diff options
Diffstat (limited to 'chapter19/src/main/java/com')
78 files changed, 2165 insertions, 98 deletions
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java b/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java index c48a4162..eb8dd4aa 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java @@ -204,7 +204,7 @@ public class CodeGen { // If n is a MachConcrete, then its part of a multi-node expansion. // It does not need instruction selection (already selected!) // but it does need its inputs walked. - if( n instanceof MachConcreteNode || n instanceof MemOpX86 ) { + if( n instanceof MachConcreteNode || n instanceof MemOpX86) { for( int i=0; i < n.nIns(); i++ ) n._inputs.set(i, _instSelect(n.in(i),map) ); return n; diff --git a/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java b/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java index 18055e19..efca945a 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java @@ -41,7 +41,7 @@ public abstract class ListScheduler { } private void computeSingleRDef(CFGNode bb, Node n) { - RegMaskRW rmask = n instanceof MachNode mach ? mach.outregmap().copy() : null; + RegMaskRW rmask = n instanceof MachNode mach && mach.outregmap()!=null ? mach.outregmap().copy() : null; for( Node use : n._outputs ) { // Remote use, so this is a remote def if( use!=null && use.cfg0()!=bb ) _rdef = true; @@ -205,7 +205,7 @@ public abstract class ListScheduler { for( int i=1; i<n.nIns(); i++ ) { XSched xd = XSched.get( n.in(i) ); if( xd != null && xd._n.nOuts()==1 ) - CNT[xd._single || ((MachNode)n).regmap(i).size1() ? 2 : 1]++; + CNT[xd._single || ((MachNode)n).regmap(i)!=null && ((MachNode)n).regmap(i).size1() ? 2 : 1]++; } score += 10 * Math.min( CNT[1], 2 ); score += 100 * Math.min( CNT[2], 2 ); diff --git a/chapter19/src/main/java/com/seaofnodes/simple/Parser.java b/chapter19/src/main/java/com/seaofnodes/simple/Parser.java index 61a53d68..19822738 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/Parser.java @@ -1724,6 +1724,6 @@ public class Parser { public final Lexer _loc; // file:line:charoff err //String msg = "src:"+_line_number+":"+(_position-_line_start)+" "+errorMessage; - ParseException( String msg, Lexer loc ) { super(msg); _loc = loc; assert loc!=null; } + ParseException( String msg, Lexer loc ) { super(msg); _loc = loc; } } } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java b/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java index 20be7157..073b472b 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java @@ -12,6 +12,13 @@ public class RegMask { public RegMask(long x ) { _bits = BitSet.valueOf(new long[]{x}); } public RegMask(long[] xs) { _bits = BitSet.valueOf( xs); } + + public RegMask or(RegMask other) { + BitSet resultBits = (BitSet)this._bits.clone(); + resultBits.or(other._bits); + return new RegMask(resultBits); + } + // Internal constructor RegMask() { _bits = new BitSet(); } RegMask(BitSet bs) { _bits = bs; } @@ -33,6 +40,7 @@ class RegMaskRW extends RegMask { public void clr(int r) { _bits.clear(r); } public void set(int r, boolean b) { _bits.set(r,b); } public RegMaskRW and( RegMask r ) { + if( r==null ) return this; _bits.and(r._bits); return this; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java index 6b7f2418..5a42e2e8 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java @@ -1,11 +1,9 @@ package com.seaofnodes.simple.node; +import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.type.*; - import java.util.BitSet; -import static com.seaofnodes.simple.Parser.con; - public class AddNode extends Node { public AddNode(Node lhs, Node rhs) { super(null, lhs, rhs); } @@ -46,6 +44,7 @@ public class AddNode extends Node { public Node idealize () { Node lhs = in(1); Node rhs = in(2); + if( rhs.err()!=null ) return null; Type t2 = rhs._type; // Add of 0. We do not check for (0+x) because this will already @@ -187,4 +186,10 @@ public class AddNode extends Node { @Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs); } @Override Node copyF() { return new AddFNode(null,null); } + @Override public Parser.ParseException err() { + if( in(1)._type.isHigh() || in(2)._type.isHigh() ) return null; + if( !(in(1)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(1)._type,null); + if( !(in(2)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(2)._type,null); + return null; + } } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java index 4e50c1fc..46188ed5 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java @@ -20,7 +20,7 @@ public class CallEndNode extends CFGNode implements MultiNode { @Override public boolean isMultiHead() { return true; } @Override public boolean blockHead() { return true; } - CallNode call() { return (CallNode)in(0); } + public CallNode call() { return (CallNode)in(0); } @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java index a9ca852c..25f76a71 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -48,6 +48,8 @@ public class CallNode extends CFGNode { int nargs() { return nIns()-3; } // Minus control, memory, fptr // args from input 2 to last; last is function input public Node fptr() { return _inputs.last(); } + // Error if not a TFP + public TypeFunPtr tfp() { return (TypeFunPtr)fptr()._type; } // Find the Call End from the Call public CallEndNode cend() { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java index 4fdf987d..53472994 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java @@ -78,4 +78,10 @@ public class MulNode extends Node { } @Override Node copy(Node lhs, Node rhs) { return new MulNode(lhs,rhs); } @Override Node copyF() { return new MulFNode(null,null); } + @Override public Parser.ParseException err() { + if( in(1)._type.isHigh() || in(2)._type.isHigh() ) return null; + if( !(in(1)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(1)._type,null); + if( !(in(2)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(2)._type,null); + return null; + } } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java new file mode 100644 index 00000000..bc959977 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -0,0 +1,30 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class AddFRISC extends MachConcreteNode implements MachNode{ + AddFRISC(Node addf) {super(addf);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.FMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Default on double precision for now(64 bits) + // General form: "fadd.d rd = src1 + src2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); + } + + @Override public String op() { return "addf"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java new file mode 100644 index 00000000..af4bf08d --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -0,0 +1,39 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class AddIRISC extends MachConcreteNode implements MachNode { + final TypeInteger _ti; + AddIRISC( Node add, TypeInteger ti ) { + super(add); + _inputs.pop(); + _ti = ti; + } + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { + // assert i== i; + return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "addi rd = rs1 + imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + #"); + _ti.print(sb); + } + + @Override public String op() { + return _ti.value() == 1 ? "inc" : (_ti.value() == -1 ? "dec" : "addi"); + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java new file mode 100644 index 00000000..482b7f11 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java @@ -0,0 +1,36 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + + +public class AddRISC extends MachConcreteNode implements MachNode { + + AddRISC( Node add) {super(add); } + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { + assert i== 1 || i == 2 || i == 3; + return riscv.RMASK; + } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "rd = rs1 + rs2" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); + } + + @Override public String op() { + return "add";} +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java new file mode 100644 index 00000000..29c2a686 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -0,0 +1,40 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; +import java.lang.StringBuilder; + +public class AndIRISC extends MachConcreteNode implements MachNode{ + final TypeInteger _ti; + AndIRISC(AndNode and, TypeInteger ti) { + super(and); + _inputs.pop(); + _ti = ti; + } + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { assert i==1 || i == 2; return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "andi rd = rs1 & imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #"); + _ti.print(sb); + } + + @Override public String op() { return "andi"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java new file mode 100644 index 00000000..e697de36 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java @@ -0,0 +1,41 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; +import java.lang.StringBuilder; + +public class AndRISC extends MachConcreteNode implements MachNode{ + AndRISC(Node and) { + super(and); + } + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + assert i==1 || i==2; + return riscv.RMASK; + } + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: #rd = rs1 & rs2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java new file mode 100644 index 00000000..d7e23c6d --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java @@ -0,0 +1,49 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +// Conditional branch such as: BEQ +public class CBranchRISC extends IfNode implements MachNode{ + final String _bop; + // label is obtained implicitly + CBranchRISC( IfNode iff, String bop ) { + super(iff); + _bop = bop; + } + + @Override public String label() { return op(); } + + @Override public void postSelect() { + Node set = in(1); + Node cmp = set.in(1); + // Bypass an expected Set and just reference the cmp directly + if( set instanceof SetRISC) + _inputs.set(1,cmp); + else + throw Utils.TODO(); + } + + @Override public RegMask regmap(int i) { assert i==1; return riscv.RMASK; } + @Override public RegMask outregmap() { return null; } + + // Encoding is appended into the byte array; size is returned + + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { + String src = code.reg(in(1)); + if( src!="FLAGS" ) sb.p(src); + } + + @Override public String op() { return "b"+_bop; } + + @Override public String comment() { + return "L"+cproj(1)._nid+", L"+cproj(0)._nid; + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java new file mode 100644 index 00000000..7f062104 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -0,0 +1,37 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeFunPtr; +import java.io.ByteArrayOutputStream; + +public class CallRISC extends CallNode implements MachNode{ + final TypeFunPtr _tfp; + final String _name; + CallRISC( CallNode call, TypeFunPtr tfp ) { + super(call); + _inputs.pop(); // Pop constant target + assert tfp.isConstant(); + _tfp = tfp; + _name = CodeGen.CODE.link(tfp)._name; + } + + @Override public String label() { return op(); } + @Override public RegMask regmap(int i) { + return riscv.callInMaskInt(i); // Normal argument + } + @Override public RegMask outregmap() { return riscv.RET_MASK; } + + @Override public String name() { return _name; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { + sb.p(_name); + } + + @Override public String op() { return "call"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java new file mode 100644 index 00000000..02850582 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -0,0 +1,31 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; + +import java.io.ByteArrayOutputStream; + +public class CallRRISC extends CallNode implements MachNode{ + CallRRISC( CallNode call ) { super(call); } + + @Override public String label() { return op(); } + @Override public RegMask regmap(int i) { + // Todo: float or int? + return i==_inputs._len + ? riscv.RMASK // Function call target + : riscv.callInMaskInt(i); // Normal argument + } + @Override public RegMask outregmap() { return riscv.RET_MASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(fptr())); + } + + @Override public String op() { return "callr"; } + +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java new file mode 100644 index 00000000..39fa3a29 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java @@ -0,0 +1,44 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +// Compare immediate. Sets flags.(RFLAGS) +public class CmpIRISC extends MachConcreteNode implements MachNode{ + final int _imm; + final String _bop; + CmpIRISC( BoolNode bool, TypeInteger ti ) { + super(bool); + _inputs.pop(); // Toss ideal ConstantNode away, embedded into machine op + _bop = bool.op(); // One of <,<=,== + _imm = (int)ti.value(); + assert _imm == ti.value(); + } + CmpIRISC( Node cmp, double ignore ) { + super(cmp); + _bop = "=="; + _imm = 0; + } + + @Override public RegMask regmap(int i) { assert i==1; return riscv.RMASK; } + @Override public RegMask outregmap() { return riscv.FLAGS_MASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "cmp rs1, 1" + @Override public void asm(CodeGen code, SB sb) { + String dst = code.reg(this); + if( dst!="FLAGS" ) sb.p(dst).p(" = "); + sb.p(code.reg(in(1))); + if( _imm != 0 ) sb.p(", #").p(_imm); + } + + @Override public String op() { return _imm==0 ? "test" : "cmp"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java new file mode 100644 index 00000000..3bd4008e --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java @@ -0,0 +1,28 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFunPtr; +import java.io.ByteArrayOutputStream; + +// Compare. Sets flags.(RFLAGS) +public class CmpRISC extends MachConcreteNode implements MachNode{ + CmpRISC( Node cmp ) { super(cmp); } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + + // General form: "cmp rs1, rs2" + @Override public void asm(CodeGen code, SB sb) { + String dst = code.reg(this); + if( dst!="FLAGS" ) sb.p(dst).p(" = "); + sb.p(code.reg(in(1))).p(", ").p(code.reg(in(2))); + } + + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.RMASK; } + @Override public RegMask outregmap() { return riscv.FLAGS_MASK; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java new file mode 100644 index 00000000..deb2628d --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -0,0 +1,30 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import java.io.ByteArrayOutputStream; + +public class DivFRISC extends MachConcreteNode implements MachNode{ + DivFRISC(Node divf) {super(divf);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.FMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Default on double precision for now(64 bits) + // General form: "fdiv.d rd = src1 / src2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); + } + + @Override public String op() { return "divf"; } + +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java new file mode 100644 index 00000000..98a8406f --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java @@ -0,0 +1,33 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class DivRISC extends MachConcreteNode implements MachNode{ + DivRISC(Node div) {super(div);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { + assert i==1 || i==2; + return riscv.FMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return x86_64_v2.RMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Signed division + // General form: "rd = rs1 / rs" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); + } + + @Override public String op() { return "div"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java new file mode 100644 index 00000000..e1637eec --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -0,0 +1,39 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.ConstantNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; + +import java.io.ByteArrayOutputStream; + +public class FltRISC extends ConstantNode implements MachNode{ + FltRISC(ConstantNode con) { + super(con); + } + // Register mask allowed on input i. 0 for no register. + @Override public RegMask regmap(int i) { return null; } + // General int registers + @Override public RegMask outregmap() { return riscv.FMASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Human-readable form appended to the SB. Things like the encoding, + // indentation, leading address or block labels not printed here. + // Just something like "ld4\tR17=[R18+12] // Load array base". + // General form: "op\tdst=src+src" + @Override public void asm(CodeGen code, SB sb) { + _con.print(sb.p(code.reg(this)).p(" #")); + } + + @Override public String op() { + return "flw"; // Some fancier encoding + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java new file mode 100644 index 00000000..66e32e29 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -0,0 +1,22 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.FunNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.cpus.x86_64_v2.FunX86; + +import java.io.ByteArrayOutputStream; + +public class FunRISC extends FunNode implements MachNode{ + FunRISC(FunNode fun) {super(fun);} + // Register mask allowed on input i. 0 for no register. + @Override public RegMask regmap(int i) { return null; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return null; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java new file mode 100644 index 00000000..df005e86 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -0,0 +1,29 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +// fcvt.d.w +public class I2F8RISC extends MachConcreteNode implements MachNode { + I2F8RISC(Node i2f8) {super(i2f8);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1; return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.FMASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "i2f8 (flt)int_value" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p("(flt)").p(code.reg(in(1))); + } + + @Override public String op() { return "i2f8"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java new file mode 100644 index 00000000..bf170b22 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.ConstantNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; + +import java.io.ByteArrayOutputStream; +// Integer constants +public class IntRISC extends ConstantNode implements MachNode { + IntRISC(ConstantNode con) { + super(con); + } + + // Register mask allowed on input i. 0 for no register. + @Override public RegMask regmap(int i) { return null; } + // General int registers + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Human-readable form appended to the SB. Things like the encoding, + // indentation, leading address or block labels not printed here. + // Just something like "ld4\tR17=[R18+12] // Load array base". + // General form: "op\tdst=src+src" + @Override public void asm(CodeGen code, SB sb) { + String reg = code.reg(this); + if( _con == Type.NIL || _con == TypeInteger.ZERO ) + sb.p(reg).p(",").p(reg); + else + _con.print(sb.p(reg).p(" #")); + } + + @Override public String op() { + if( _con == Type.NIL || _con == TypeInteger.ZERO ) + return "xor"; + return "ldi"; // Some fancier encoding + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java new file mode 100644 index 00000000..846e313c --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -0,0 +1,34 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class LoadRISC extends MemOpRISC{ + LoadRISC(LoadNode ld) { + super(ld, ld); + } + + @Override public RegMask regmap(int i) { + // wider mask, encode it differently, immediate handled with hard split(in RA) + return riscv.RMASK.or(riscv.FMASK); + } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { + } + + @Override public String op() { + return "lw" +_sz; + } +} + diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java new file mode 100644 index 00000000..092143d6 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java @@ -0,0 +1,36 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.*; +import java.io.ByteArrayOutputStream; +import java.lang.StringBuilder; +import java.util.BitSet; + + +public class MemOpRISC extends MemOpNode implements MachNode{ + final char _sz = (char)('0'+(1<<_declaredType.log_size())); + MemOpRISC(Node op, MemOpNode mop) { + super(op, mop); + } + @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); } + + @Override public String label() { return op(); } + @Override public Type compute() { throw Utils.TODO(); } + @Override public Node idealize() { throw Utils.TODO(); } + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { + throw Utils.TODO(); + } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { throw Utils.TODO(); } + + @Override public int encoding(ByteArrayOutputStream bytes) { throw Utils.TODO(); } + + + SB asm_address(CodeGen code, SB sb) { + return sb; + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java new file mode 100644 index 00000000..43197b50 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -0,0 +1,30 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import java.io.ByteArrayOutputStream; + +public class MulFRISC extends MachConcreteNode implements MachNode{ + MulFRISC(Node mulf) {super(mulf);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.FMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Default on double precision for now(64 bits) + // General form: "fmul.d rd = src1 * src2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); + } + + @Override public String op() { return "mulf"; } + +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java new file mode 100644 index 00000000..8735068e --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java @@ -0,0 +1,35 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class MulIRISC extends MachConcreteNode implements MachNode { + final TypeInteger _ti; + MulIRISC(Node mul, TypeInteger ti) {super(mul); _inputs.pop(); _ti = ti;} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + // General form + // General form: "muli dst * #imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * #"); + _ti.print(sb); + } + + @Override public String op() { return "muli"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java new file mode 100644 index 00000000..8713486e --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java @@ -0,0 +1,33 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + + +// mulh signed multiply instruction(no-imm form) +public class MulRISC extends MachConcreteNode implements MachNode{ + MulRISC(Node mul) {super(mul);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "rd = rs1 * rs2" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); + } + + @Override public String op() { return "mul"; } + +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java new file mode 100644 index 00000000..f050715d --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -0,0 +1,44 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; + +import java.io.ByteArrayOutputStream; + + +public class NewRISC extends NewNode implements MachNode{ + + // A pre-zeroed chunk of memory. + NewRISC( NewNode nnn ) { super(nnn); } + + // Register mask allowed on input i, the size + @Override public RegMask regmap(int i) { + // Size + if( i==1 ) return riscv.RET_MASK; + // All the memory alias edges + return null; + } + + @Override public RegMask outregmap() { throw Utils.TODO(); } + + // Register mask allowed as a result. Pointer result in standard calling + // convention. + @Override public RegMask outregmap(int i) { + if( i == 1 ) return riscv.RET_MASK; + // All the memory aliases edges + return null; + } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "alloc #bytes" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(size())); + } + + @Override public String op() { return "alloc"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java new file mode 100644 index 00000000..f3f79ed1 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; + +import java.io.ByteArrayOutputStream; + +public class OrIRISC extends MachConcreteNode implements MachNode{ + final TypeInteger _ti; + OrIRISC(Node or, TypeInteger ti) {super(or); _inputs.pop(); _ti = ti;} + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + assert i==1 || i==2; + return riscv.RMASK; + } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 0;} + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "rd = rs1 | imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" | #"); + _ti.print(sb); + } + + @Override public String op() { return "ori"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java new file mode 100644 index 00000000..8f1e9305 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import java.io.ByteArrayOutputStream; + +public class OrRISC extends MachConcreteNode implements MachNode { + OrRISC(Node or) { + super(or); + } + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + assert i==1 || i==2; + return riscv.RMASK; + } + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: # rd = rs1 | rs2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java new file mode 100644 index 00000000..2e20f96f --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java @@ -0,0 +1,25 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.ParmNode; +import com.seaofnodes.simple.node.MachNode; +import java.io.ByteArrayOutputStream; + +public class ParmRISC extends ParmNode implements MachNode{ + final RegMask _rmask; + ParmRISC(ParmNode parm) { + super(parm); + // Assume int + _rmask = riscv.callInMaskInt(_idx); + } + + // Register mask allowed on input i. 0 for no register. + @Override public RegMask regmap(int i) { return null; } + // Register mask allowed as a result. Calling convention register + @Override public RegMask outregmap() { return _rmask; } + + // Encoding is appended into the byte array. Returns size + @Override public int encoding(ByteArrayOutputStream bytes) { return 0; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java new file mode 100644 index 00000000..a1312c4c --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java @@ -0,0 +1,23 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.ProjNode; +import com.seaofnodes.simple.node.MachNode; +import java.io.ByteArrayOutputStream; + +public class ProjRISC extends ProjNode implements MachNode{ + ProjRISC(ProjNode p) {super(p);} + + // Register mask allowed on input i. 0 for no register. + @Override public RegMask regmap(int i) { return null; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return null; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java new file mode 100644 index 00000000..c92e6989 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -0,0 +1,48 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.FunNode; +import com.seaofnodes.simple.node.ReturnNode; +import com.seaofnodes.simple.node.MachNode; + +import java.io.ByteArrayOutputStream; + +public class RetRISC extends ReturnNode implements MachNode{ + RetRISC(ReturnNode ret, FunNode fun) { super(ret, fun); fun.setRet(this); } + // Todo: postSelect + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + return switch( i ) { + case 0 -> null; + case 1 -> null; + case 2 -> riscv.RET_MASK; + case 3 -> null; // RPC is always on stack + default -> throw Utils.TODO(); + }; + } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return null; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Human-readable form appended to the SB. Things like the encoding, + // indentation, leading address or block labels not printed here. + // Just something like "ld4\tR17=[R18+12] // Load array base". + // General form: "op\tdst=src+src" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(in(2))); + } + + // Correct Nodes outside the normal edges + @Override public void postSelect() { + FunNode fun = (FunNode)rpc().in(0); + _fun = fun; + fun.setRet(this); + } + + @Override public String op() { return "ret"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java new file mode 100644 index 00000000..1d8c9de8 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java @@ -0,0 +1,35 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +// corresponds to slt,sltu,slti,sltiu, seqz +// RISCV doesn't have rflags. +public class SetRISC extends MachConcreteNode implements MachNode{ + final String _bop; // One of <,<=,== + SetRISC( Node cmp, String bop ) { + super(cmp); + _inputs.setLen(1); // Pop the cmp inputs + // Replace with the matched cmp + _inputs.push(cmp); + _bop = bop; + } + @Override public RegMask regmap(int i) { assert i==1; return riscv.FLAGS_MASK; } + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)); + String src = code.reg(in(1)); + if( src!="FLAGS" ) sb.p(" = ").p(src); + } + + @Override public String op() { return "set"+_bop; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java new file mode 100644 index 00000000..8927c086 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -0,0 +1,40 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; + +public class SllIRISC extends MachConcreteNode implements MachNode{ + final TypeInteger _ti; + SllIRISC(Node sll, TypeInteger ti) {super(sll); _inputs.pop(); _ti = ti;} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + //assert i==1; + return riscv.RMASK; } + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "slli rd, rs1, imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << #"); + _ti.print(sb); + } + + @Override public String op() { return "slli"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java new file mode 100644 index 00000000..69538433 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java @@ -0,0 +1,36 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; + +public class SllRISC extends MachConcreteNode implements MachNode{ + SllRISC(Node sll) {super(sll);} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + //assert i==1; + return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "sll rd, rs1, rs2" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "sll"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java new file mode 100644 index 00000000..654dd2ae --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; +import java.lang.StringBuilder; + + +// Right Shift Arithmetic(immediate) +public class SraIRISC extends MachConcreteNode implements MachNode{ + final TypeInteger _ti; + SraIRISC(Node sra, TypeInteger ti) {super(sra); _inputs.pop(); _ti = ti;} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + // assert i==1; + return riscv.RMASK; } + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "srai rd, rs1, imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> #"); + _ti.print(sb); + } + + @Override public String op() { return "srai"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java new file mode 100644 index 00000000..2d50ceaa --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java @@ -0,0 +1,42 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.type.TypeInteger; + +import java.io.ByteArrayOutputStream; + +// Right Shift Arithmetic +public class SraRISC extends MachConcreteNode implements MachNode { + + SraRISC(Node sra) {super(sra);} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + // assert i==1; + return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "sra rd, rs1, rs2" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "sra"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java new file mode 100644 index 00000000..f7ad6c25 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; +import java.lang.StringBuilder; + + +// Right Shift Logical Immediate +public class SrlIRISC extends MachConcreteNode implements MachNode { + final TypeInteger _ti; + SrlIRISC(Node srl, TypeInteger ti) {super(srl); _inputs.pop(); _ti = ti;} + + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + // assert i==1; + return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "srli dst << #imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> #"); + _ti.print(sb); + } + + @Override public String op() { return "srli"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java new file mode 100644 index 00000000..25d62688 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java @@ -0,0 +1,38 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; +import java.util.BitSet; +import java.lang.StringBuilder; + +// Right Shift Logical +public class SrlRISC extends MachConcreteNode implements MachNode { + SrlRISC(Node srli) {super(srli);} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + // assert i==1; + return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "srl rd, rs1, rs2" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "srl"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java new file mode 100644 index 00000000..9fbd7c12 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -0,0 +1,40 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.node.StoreNode; + +import java.io.ByteArrayOutputStream; +import java.util.BitSet; + + +// sw rs2,offset(rs1) +public class StoreRISC extends MemOpRISC { + StoreRISC( StoreNode st) { + super(st, st); + } + + @Override public RegMask regmap(int i) { + return riscv.RMASK; + } + + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return null; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { + + } + + @Override public String op() { return "st"+_sz; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java new file mode 100644 index 00000000..e6a0b8e4 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -0,0 +1,30 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class SubFRISC extends MachConcreteNode implements MachNode{ + SubFRISC(Node subf) {super(subf);} + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.FMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Default on double precision for now(64 bits) + // General form: "fsub.d rd = src1 - src2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); + } + + @Override public String op() { return "subf"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java new file mode 100644 index 00000000..6fb0e0ef --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java @@ -0,0 +1,29 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +public class SubRISC extends MachConcreteNode implements MachNode { + SubRISC( Node sub ) { super(sub); } + + // Register mask allowed on input i. + @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form: "sub # rd = rs1 - rs2" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" - ").p(code.reg(in(2))); + } + + @Override public String op() { return "sub"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java new file mode 100644 index 00000000..b508541a --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.ConstantNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.cpus.x86_64_v2.TFPX86; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFunPtr; + +import java.io.ByteArrayOutputStream; + +public class TFPRISC extends ConstantNode implements MachNode{ + TFPRISC(ConstantNode con) {super(con);} + // Register mask allowed on input i. 0 for no register. + @Override public RegMask regmap(int i) { return null; } + // General int registers + @Override public RegMask outregmap() { return x86_64_v2.RMASK; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // Human-readable form appended to the SB. Things like the encoding, + // indentation, leading address or block labels not printed here. + // Just something like "ld4\tR17=[R18+12] // Load array base". + // General form: "op\tdst=src+src" + @Override public void asm(CodeGen code, SB sb) { + String reg = code.reg(this); + if( _con == Type.NIL ) + sb.p(reg).p(",").p(reg); + else + _con.print(sb.p(reg).p(" #")); + } + + @Override public String op() { + if( _con == Type.NIL ) + return "xor"; + return "ldx"; // Some fancier encoding + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java new file mode 100644 index 00000000..3d53ee64 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -0,0 +1,45 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2; +import com.seaofnodes.simple.type.TypeInteger; + +import java.io.ByteArrayOutputStream; + +public class XorIRISC extends MachConcreteNode implements MachNode{ + final TypeInteger _ti; + XorIRISC(Node xor, TypeInteger ti) {super(xor); _inputs.pop(); _ti = ti;} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + assert i==1 || i==2; + + return riscv.RMASK; } + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "rd = rs1 ^ imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #"); + _ti.print(sb); + } + + @Override public String op() { return "xori"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java new file mode 100644 index 00000000..2f34529e --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java @@ -0,0 +1,43 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.type.TypeInteger; + +import java.io.ByteArrayOutputStream; + +public class XorRISC extends MachConcreteNode implements MachNode { + + XorRISC(Node or) { + super(or); + } + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + assert i==1 || i==2; + return riscv.RMASK; + } + + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return riscv.RMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 0; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: # # rd = rs1 ^ rs2 + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java new file mode 100644 index 00000000..399eebca --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -0,0 +1,329 @@ +package com.seaofnodes.simple.node.cpus.riscv; + +import com.seaofnodes.simple.Machine; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.node.cpus.x86_64_v2.*; +import com.seaofnodes.simple.type.*; + +public class riscv extends Machine{ + @Override public String name() {return "riscv";} + + // Using ABI names instead of register names + public static int ZERO = 0, RA = 1, SP = 2, GP = 3, TP = 4, T0 = 5, T1 = 6, T2 = 7; + public static int S0 = 8, S1 = 9, A0 = 10, A1 = 11, A2 = 12, A3 = 13, A4 = 14, A5 = 15; + public static int A6 = 16, A7 = 17, S2 = 18, S3 = 19, S4 = 20, S5 = 21, S6 = 22, S7 = 23; + public static int S8 = 24, S9 = 25, S10 = 26, S11 = 27, T3 = 28, T4 = 29, T5 = 30, T6 = 31; + + // FP registers + public static int F0 = 32, F1 = 33, F2 = 34, F3 = 35, F4 = 36, F5 = 37, F6 = 38, F7 = 39; + public static int FS0 = 40, FS1 = 41, FA0 = 42, FA1 = 43, FA2 = 44, FA3 = 45, FA4 = 46, FA5 = 47; + public static int FA6 = 48, FA7 = 49, FS2 = 50, FS3 = 51, FS4 = 52, FS5 = 53, FS6 = 54, FS7 = 55; + public static int FS8 = 56, FS9 = 57, FS10 = 58, FS11 = 59, FT8 = 60, FT9 = 61, FT10 = 62, FT11 = 63; + + public static int FLAGS = 64; + + // General purpose register mask: pointers and ints, not floats + public static RegMask RMASK = new RegMask(0b11111111111111111111111111111111); + // Float mask from(ft0–ft11) + public static RegMask FMASK = new RegMask(0b11111111111111111111111111111111); + + // Return single int/ptr register + public static RegMask RET_MASK = new RegMask(A0); + + // Arguments masks + public static RegMask A0_MASK = new RegMask(1L<<A0); + public static RegMask A1_MASK = new RegMask(1L<<A1); + public static RegMask A2_MASK = new RegMask(1L<<A2); + public static RegMask A3_MASK = new RegMask(1L<<A3); + public static RegMask A4_MASK = new RegMask(1L<<A4); + public static RegMask A5_MASK = new RegMask(1L<<A5); + public static RegMask A6_MASK = new RegMask(1L<<A6); + public static RegMask A7_MASK = new RegMask(1L<<A7); + + public static RegMask FLAGS_MASK = new RegMask(1L << FLAGS); + + // Float arguments masks + public static RegMask FA0_MASK = new RegMask(1L<<FA0); + public static RegMask FA1_MASK = new RegMask(1L<<FA1); + public static RegMask FA2_MASK = new RegMask(1L<<FA2); + public static RegMask FA3_MASK = new RegMask(1L<<FA3); + public static RegMask FA4_MASK = new RegMask(1L<<FA4); + public static RegMask FA5_MASK = new RegMask(1L<<FA5); + public static RegMask FA6_MASK = new RegMask(1L<<FA6); + public static RegMask FA7_MASK = new RegMask(1L<<FA7); + + // Int arguments calling conv + static RegMask[] CALLINMASK_RISCV_INT = new RegMask[] { + null, + null, + A0_MASK, + A1_MASK, + A2_MASK, + A3_MASK, + A4_MASK, + A5_MASK, + A6_MASK, + A7_MASK + }; + + static int[] CALLINARG_RISCV_INT = new int[] { + 0, // Control, no register + 0, // Memory, no register + A0, + A1, + A2, + A3, + A4, + A5, + A6, + A7 + }; + + static int callInArgInt(int idx) { + return CALLINARG_RISCV_INT[idx]; + } + + static RegMask callInMaskInt(int idx) { + return CALLINMASK_RISCV_INT[idx]; + } + + // Float arguments + static RegMask[] CALLINMASK_RISCV_FLOAT = new RegMask[] { + null, + null, + FA0_MASK, + FA1_MASK, + FA2_MASK, + FA3_MASK, + FA4_MASK, + FA5_MASK, + FA6_MASK, + FA7_MASK + }; + + + static int[] CALLINARG_RISCV_FLOAT = new int[] { + 0, // Control, no register + 0, // Memory, no register + FA0, + FA1, + FA2, + FA3, + FA4, + FA5, + FA6, + FA7 + }; + + + static int callInArgFloat(int idx) { + return CALLINARG_RISCV_FLOAT[idx]; + } + + static RegMask callInMaskFloat(int idx) { + return CALLINMASK_RISCV_FLOAT[idx]; + } + // caller saved(riscv) + //public static final long RISCV_CALLER_SAVED= TBD + // callee saved(riscv) + public static final long RISCV_CALLEE_SAVED = + (1L << FS0) | (1L << FS1) | (1L << FS2) | (1L << FS3) | (1L << FS4) + | (1L << FS5) | (1L << FS6) | (1L << FS7) | (1L << FS8) | (1L << FS9) | (1L << FS10); + + + // Calling conv metadata + public int GPR_COUNT_CONV_RISCV = 7; // A0, A1, A2, A3, A4, A5, A6, A7 + public int FLOAT_COUNT_CONV_RISCV = 7; // FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7 + + public static final String[] REGS = new String[] { + "zero", "ra" , "sp" , "gp" , "tp" , "t0" , "t1" , "t2" , + "s0" , "s1" , "a0" , "a1" , "a2" , "a3" , "a4" , "a5" , + "a6" , "a7" , "s2" , "s3" , "s4" , "s5" , "s6" , "s7" , + "s8" , "s9" , "s10" , "s11" , "t3" , "t4" , "t5" , "t6" , + "f0" , "f1" , "f2" , "f3" , "f4" , "f5" , "f6" , "f7" , + "fs0" , "fs1" , "fa0" , "fa1" , "fa2" , "fa3" , "fa4" , "fa5" , + "fa6" , "fa7" , "fs2" , "fs3" , "fs4" , "fs5" , "fs6" , "fs7" , + "fs8" , "fs9" , "fs10", "fs11", "ft8" , "ft9" , "ft10", "ft11", + "flags" + }; + + // General purpose register mask: + @Override public String reg( int reg ) { return REGS[reg]; } + // Return a MachNode unconditional branch + @Override public CFGNode jump() { + throw Utils.TODO(); + } + + // Create a split op; any register to any register, including stack slots + @Override public Node split() { + throw Utils.TODO(); + } + + // Break an infinite loop + @Override public IfNode never( CFGNode ctrl ) { + throw Utils.TODO(); + } + + @Override public Node instSelect( Node n ) { + return switch (n) { + case AddFNode addf -> addf(addf); + case AddNode add -> add(add); + case AndNode and -> and(and); + case BoolNode bool -> cmp(bool); + case CallEndNode cend -> new CallEndNode((CallNode) cend.in(0)); + case CallNode call -> call(call); + case CProjNode c -> new CProjNode(c); + case ConstantNode con -> con(con); + case DivFNode divf -> new DivFRISC(divf); + case DivNode div -> new DivRISC(div); + case FunNode fun -> new FunRISC(fun); + case IfNode iff -> jmp(iff); + case LoadNode ld -> ld(ld); + case MemMergeNode mem -> new MemMergeNode(mem); + case MulFNode mulf -> new MulFRISC(mulf); + case MulNode mul -> mul(mul); + case NewNode nnn -> new NewRISC(nnn); + case OrNode or -> or(or); + case ParmNode parm -> new ParmRISC(parm); + case PhiNode phi -> new PhiNode(phi); + case ProjNode prj -> prj(prj); + case ReadOnlyNode read -> new ReadOnlyNode(read); + case ReturnNode ret -> new RetRISC(ret, ret.fun()); + case SarNode sar -> sra(sar); + case ShlNode shl -> sll(shl); + case ShrNode shr -> srl(shr); + case StartNode start -> new StartNode(start); + case StopNode stop -> new StopNode(stop); + case StoreNode st -> st(st); + case SubFNode subf -> new SubFRISC(subf); + case SubNode sub -> sub(sub); + case ToFloatNode tfn -> i2f8(tfn); + case XorNode xor -> xor(xor); + + case LoopNode loop -> new LoopNode(loop); + case RegionNode region -> new RegionNode(region); + default -> throw Utils.TODO(); + }; + } + + private Node addf(AddFNode addf) { + return new AddFRISC(addf); + } + + private Node add(AddNode add) { + Node rhs = add.in(2); + if( rhs instanceof ConstantNode off && off._con instanceof TypeInteger toff ) { + return new AddIRISC(add, toff); + } + return new AddRISC(add); + } + + private Node and(AndNode and) { + if( and.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) + return new AndIRISC(and, ti); + return new AndRISC(and); + } + + private Node cmp(BoolNode bool) { + Node cmp = _cmp(bool); + return new SetRISC(cmp, bool.op()); + } + + private Node call(CallNode call) { + if( call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp ) + return new CallRISC(call, tfp); + return new CallRRISC(call); + } + + private Node _cmp(BoolNode bool) { + Node rhs = bool.in(2); + + return rhs instanceof ConstantNode con && con._con instanceof TypeInteger ti + ? new CmpIRISC(bool, ti) + : new CmpRISC(bool); + } + + private Node con( ConstantNode con ) { + return switch( con._con ) { + case TypeInteger ti -> new IntRISC(con); + case TypeFloat tf -> new IntRISC(con); + case TypeFunPtr tfp -> new TFPRISC(con); + case TypeMemPtr tmp -> new ConstantNode(con); + case TypeNil tn -> throw Utils.TODO(); + // TOP, BOTTOM, XCtrl, Ctrl, etc. Never any executable code. + case Type t -> new ConstantNode(con); + }; + } + + private Node jmp( IfNode iff ) { + // If/Bool combos will match to a Cmp/Set which sets flags. + // Most general arith ops will also set flags, which the Jmp needs directly. + // Loads do not set the flags, and will need an explicit TEST + if( !(iff.in(1) instanceof BoolNode) ) + iff.setDef(1,new BoolNode.EQ(iff.in(1),new ConstantNode(TypeInteger.ZERO))); + return new CBranchRISC(iff, ((BoolNode)iff.in(1)).op()); + } + + private Node or(OrNode or) { + if(or.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) + return new OrIRISC(or, ti); + + return new OrRISC(or); + } + + private Node xor(XorNode xor) { + if(xor.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) + return new XorIRISC(xor, ti); + return new XorRISC(xor); + } + + private Node sra(SarNode sar) { + if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) + return new SraIRISC(sar, ti); + return new SraRISC(sar); + } + + private Node srl(ShrNode shr) { + if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) + return new SrlIRISC(shr, ti); + return new SrlRISC(shr); + } + + private Node sll(ShlNode sll) { + if( sll.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) + return new SllIRISC(sll, ti); + return new SllRISC(sll); + } + + private Node sub(SubNode sub) { + return sub.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti + ? new AddIRISC(sub, TypeInteger.constant(-ti.value())) + : new SubRISC(sub); + } + + private Node i2f8(ToFloatNode tfn) { + assert tfn.in(1)._type instanceof TypeInteger ti; + return new I2F8RISC(tfn); + } + + private Node prj(ProjNode prj) { + return new ProjRISC(prj); + } + + private Node ld(LoadNode ld) { + return new LoadRISC(ld); + } + + private Node st(StoreNode st) { + return new StoreRISC(st); + } + + private Node mul(MulNode mul) { + return mul.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti + ? new MulIRISC(mul, ti) + : new MulRISC(mul); + } +} + diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index 4f75edcd..4bb24fa3 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -12,7 +12,7 @@ public class AddFMemX86 extends MemOpX86 { } @Override public RegMask regmap(int i) { - if( i==1 ) return RegMask.EMPTY; // Memory + if( i==1 ) return null; // Memory if( i==2 ) return x86_64_v2.RMASK; // base if( i==3 ) return x86_64_v2.RMASK; // index if( i==4 ) return x86_64_v2.XMASK; // value diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java new file mode 100644 index 00000000..45cf2b22 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java @@ -0,0 +1,33 @@ +package com.seaofnodes.simple.node.cpus.x86_64_v2; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import java.io.ByteArrayOutputStream; + +public class AndX86 extends MachConcreteNode implements MachNode{ + AndX86(Node and) { + super(and); + } + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.WMASK; } + + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "and dst & #imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "and"; } +} + diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java new file mode 100644 index 00000000..55ab90c9 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java @@ -0,0 +1,37 @@ +package com.seaofnodes.simple.node.cpus.x86_64_v2; + +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.RegMask; +import com.seaofnodes.simple.node.CallEndNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.type.TypeFloat; +import com.seaofnodes.simple.type.TypeFunPtr; +import java.io.ByteArrayOutputStream; + +public class CallEndX86 extends CallEndNode implements MachNode { + final TypeFunPtr _tfp; + CallEndX86( CallEndNode cend ) { + super(cend); + _tfp = (TypeFunPtr)cend.call().fptr()._type; + } + + @Override public String label() { return op(); } + @Override public RegMask regmap(int i) { return null; } + @Override public RegMask outregmap() { throw Utils.TODO(); } + @Override public RegMask outregmap(int idx) { + if( idx != 2 ) return null; + return _tfp._ret instanceof TypeFloat ? x86_64_v2.RET_FMASK : x86_64_v2.RET_MASK; + } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + @Override public void asm(CodeGen code, SB sb) { } + + @Override public String op() { return "cend"; } + +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 31d303ed..99260a27 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -13,7 +13,7 @@ public class CallRX86 extends CallNode implements MachNode { @Override public RegMask regmap(int i) { return i==_inputs._len ? x86_64_v2.WMASK // Function call target - : x86_64_v2.callInMask(i); // Normal argument + : x86_64_v2.callInMask(tfp(),i); // Normal argument } @Override public RegMask outregmap() { return x86_64_v2.RET_MASK; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index 9c246c24..b3e3bbe8 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -20,11 +20,12 @@ public class CallX86 extends CallNode implements MachNode { @Override public String label() { return op(); } @Override public RegMask regmap(int i) { - return x86_64_v2.callInMask(i); // Normal argument + return x86_64_v2.callInMask(tfp(),i); // Normal argument } @Override public RegMask outregmap() { return x86_64_v2.RET_MASK; } @Override public String name() { return _name; } + @Override public TypeFunPtr tfp() { return _tfp; } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 2fa7fbb1..ea526f33 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -6,7 +6,7 @@ import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; import java.io.ByteArrayOutputStream; -// Compare immediate. Sets flags. +// Compare immediate. Sets flags.(RFLAGS) public class CmpIX86 extends MachConcreteNode implements MachNode { final int _imm; final String _bop; diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index 6b502249..d8ebb12d 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -5,6 +5,7 @@ import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; import java.io.ByteArrayOutputStream; +// Compare. Sets flags.(RFLAGS) public class CmpX86 extends MachConcreteNode implements MachNode { CmpX86( Node cmp ) { super(cmp); } @@ -16,7 +17,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { throw Utils.TODO(); } - // General form: "add dst += src" + // General form: "cmp reg1, reg2" @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); if( dst!="FLAGS" ) sb.p(dst).p(" = "); diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index 21529f7b..5e1190da 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -13,7 +13,7 @@ public class FltX86 extends ConstantNode implements MachNode { FltX86(ConstantNode con ) { super(con); } // Register mask allowed on input i. 0 for no register. - @Override public RegMask regmap(int i) { return RegMask.EMPTY; } + @Override public RegMask regmap(int i) { return null; } // General int registers @Override public RegMask outregmap() { return x86_64_v2.XMASK; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index f969fae4..8b0f016a 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -10,9 +10,9 @@ public class FunX86 extends FunNode implements MachNode { FunX86( FunNode fun ) { super(fun); } // Register mask allowed on input i. 0 for no register. - @Override public RegMask regmap(int i) { return RegMask.EMPTY; } + @Override public RegMask regmap(int i) { return null; } // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return RegMask.EMPTY; } + @Override public RegMask outregmap() { return null; } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 2cd27c14..566a7293 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -16,7 +16,7 @@ public class IntX86 extends ConstantNode implements MachNode { } // Register mask allowed on input i. 0 for no register. - @Override public RegMask regmap(int i) { return RegMask.EMPTY; } + @Override public RegMask regmap(int i) { return null; } // General int registers @Override public RegMask outregmap() { return x86_64_v2.WMASK; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index 7cf4444c..2262e847 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -26,7 +26,7 @@ public class JmpX86 extends IfNode implements MachNode { throw Utils.TODO(); } @Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.FLAGS_MASK; } - @Override public RegMask outregmap() { return RegMask.EMPTY; } + @Override public RegMask outregmap() { return null; } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index 418f63f3..a6cdbd05 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -11,7 +11,7 @@ public class MemAddX86 extends MemOpX86 { } // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return RegMask.EMPTY; } + @Override public RegMask outregmap() { return null; } // General form: "add [base + idx<<2 + 12] += src" diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java index 1e678a0b..b94ea5ae 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java @@ -59,7 +59,7 @@ public abstract class MemOpX86 extends MemOpNode implements MachNode { // Register mask allowed on input i. @Override public RegMask regmap(int i) { - if( i==1 ) return RegMask.EMPTY; // Memory + if( i==1 ) return null; // Memory if( i==2 ) return x86_64_v2.RMASK; // base if( i==3 ) return x86_64_v2.RMASK; // index if( i==4 ) return x86_64_v2.RMASK; // value diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 7508cf4c..e9eb17fc 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -12,7 +12,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { // Register mask allowed on input i. // This is the normal calling convention @Override public RegMask regmap(int i) { - // assert i==1; + assert i==1; return x86_64_v2.WMASK; } // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return x86_64_v2.WMASK; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index 4396a917..f9778845 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -14,7 +14,7 @@ public class NewX86 extends NewNode implements MachNode { // Size if( i==1 ) return x86_64_v2.RDI_MASK; // All the memory alias edges - return RegMask.EMPTY; + return null; } @Override public RegMask outregmap() { throw Utils.TODO(); } @@ -23,7 +23,7 @@ public class NewX86 extends NewNode implements MachNode { @Override public RegMask outregmap(int i) { if( i == 1 ) return x86_64_v2.RET_MASK; // All the memory aliases edges - return RegMask.EMPTY; + return null; } // Encoding is appended into the byte array; size is returned diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java index 513962c2..d3940838 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java @@ -19,7 +19,7 @@ public class OrIX86 extends MachConcreteNode implements MachNode { // Register mask allowed on input i. // This is the normal calling convention @Override public RegMask regmap(int i) { - //assert i==1; + assert i==1; return x86_64_v2.WMASK; } // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return x86_64_v2.WMASK; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java new file mode 100644 index 00000000..7c25bdae --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java @@ -0,0 +1,33 @@ +package com.seaofnodes.simple.node.cpus.x86_64_v2; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import java.io.ByteArrayOutputStream; + +public class OrX86 extends MachConcreteNode implements MachNode{ + OrX86(Node or) { + super(or); + } + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.WMASK; } + + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "and dst & #imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "or"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java index 8a439644..0fcc922d 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java @@ -1,8 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; import com.seaofnodes.simple.RegMask; -import com.seaofnodes.simple.SB; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.ParmNode; import com.seaofnodes.simple.node.MachNode; import java.io.ByteArrayOutputStream; @@ -11,11 +9,12 @@ public class ParmX86 extends ParmNode implements MachNode { final RegMask _rmask; ParmX86( ParmNode parm ) { super(parm); - _rmask = x86_64_v2.callInMask(_idx); + // default to int + _rmask = x86_64_v2.callInMask(fun().sig(),_idx); } // Register mask allowed on input i. 0 for no register. - @Override public RegMask regmap(int i) { return RegMask.EMPTY; } + @Override public RegMask regmap(int i) { return null; } // Register mask allowed as a result. Calling convention register @Override public RegMask outregmap() { return _rmask; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java index 2849b232..77fd7d34 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java @@ -12,9 +12,11 @@ public class ProjX86 extends ProjNode implements MachNode { ProjX86( ProjNode p ) { super(p); } // Register mask allowed on input i. 0 for no register. - @Override public RegMask regmap(int i) { return RegMask.EMPTY; } + @Override public RegMask regmap(int i) { return null; } // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return RegMask.EMPTY; } + @Override public RegMask outregmap() { + return ((MachNode)in(0)).outregmap(_idx); + } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index e6219ff4..21db209c 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -21,15 +21,15 @@ public class RetX86 extends ReturnNode implements MachNode { // This is the normal calling convention @Override public RegMask regmap(int i) { return switch( i ) { - case 0 -> RegMask.EMPTY; - case 1 -> RegMask.EMPTY; + case 0 -> null; + case 1 -> null; case 2 -> x86_64_v2.RET_MASK; - case 3 -> RegMask.EMPTY; // RPC is always on stack + case 3 -> null; // RPC is always on stack default -> throw Utils.TODO(); }; } // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return RegMask.EMPTY; } + @Override public RegMask outregmap() { return null; } // Encoding is appended into the byte array; size is returned @Override public int encoding(ByteArrayOutputStream bytes) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java new file mode 100644 index 00000000..f5337ee8 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -0,0 +1,37 @@ +package com.seaofnodes.simple.node.cpus.x86_64_v2; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; +import java.io.ByteArrayOutputStream; + +// Arithmetic Right Shift +public class SarIX86 extends MachConcreteNode implements MachNode { + final TypeInteger _ti; + SarIX86(Node sar, TypeInteger ti) {super(sar); _inputs.pop(); _ti = ti;} + + // Register mask allowed on input i. + // This is the normal calling convention + @Override public RegMask regmap(int i) { + // assert i==1; + return x86_64_v2.RMASK; } + // Register mask allowed as a result. 0 for no register. + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "sari dst << #imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> #"); + _ti.print(sb); + } + + @Override public String op() { return "sari"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index 3d907eef..cb0b18bf 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -8,17 +8,19 @@ import java.io.ByteArrayOutputStream; import java.util.BitSet; import java.lang.StringBuilder; - -public class SarX86 extends MachConcreteNode implements MachNode { - final TypeInteger _ti; - SarX86(Node sar, TypeInteger ti) {super(sar); _inputs.pop(); _ti = ti;} +public class SarX86 extends MachConcreteNode implements MachNode{ + SarX86(Node sar) {super(sar);} // Register mask allowed on input i. // This is the normal calling convention + + // CL register must be used for input(2) @Override public RegMask regmap(int i) { - // assert i==1; - return x86_64_v2.RMASK; } - // Register mask allowed as a result. 0 for no register. + if(i == 1) return x86_64_v2.WMASK; + if(i == 2) return x86_64_v2.RCX_MASK; + throw Utils.TODO(); + } + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } // Output is same register as input#1 @@ -30,11 +32,11 @@ public class SarX86 extends MachConcreteNode implements MachNode { } // General form - // General form: "sari dst << #imm" + // General form: "sar dst >> src" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> #"); - _ti.print(sb); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); } - @Override public String op() { return "sari"; } + @Override public String op() { return "sar"; } + } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java new file mode 100644 index 00000000..b95f9f46 --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -0,0 +1,39 @@ +package com.seaofnodes.simple.node.cpus.x86_64_v2; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import java.io.ByteArrayOutputStream; + +public class ShlX86 extends MachConcreteNode implements MachNode { + ShlX86(Node shl) { + super(shl); + }; + + // Register mask allowed on input i. + // This is the normal calling convention + + // CL register must be used for input(2) + @Override public RegMask regmap(int i) { + if(i == 1) return x86_64_v2.WMASK; + if(i == 2) return x86_64_v2.RCX_MASK; + throw Utils.TODO(); + } + + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "shl dst << src" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "shl"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 08cae93e..80115ff2 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -8,6 +8,7 @@ import java.io.ByteArrayOutputStream; import java.util.BitSet; import java.lang.StringBuilder; +// Logical Right Shift public class ShrIX86 extends MachConcreteNode implements MachNode{ final TypeInteger _ti; ShrIX86(Node shr, TypeInteger ti) {super(shr); _inputs.pop(); _ti = ti;} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java new file mode 100644 index 00000000..43fc730b --- /dev/null +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -0,0 +1,38 @@ +package com.seaofnodes.simple.node.cpus.x86_64_v2; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.node.*; +import java.io.ByteArrayOutputStream; + +public class ShrX86 extends MachConcreteNode implements MachNode { + ShrX86(Node shr) { + super(shr); + }; + // Register mask allowed on input i. + // This is the normal calling convention + + // CL register must be used for input(2) + @Override public RegMask regmap(int i) { + if(i == 1) return x86_64_v2.WMASK; + if(i == 2) return x86_64_v2.RCX_MASK; + throw Utils.TODO(); + } + + @Override public RegMask outregmap() { return x86_64_v2.WMASK; } + + // Output is same register as input#1 + @Override public int twoAddress() { return 1; } + + // Encoding is appended into the byte array; size is returned + @Override public int encoding(ByteArrayOutputStream bytes) { + throw Utils.TODO(); + } + + // General form + // General form: "shr dst >>> src" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); + } + + @Override public String op() { return "shr"; } +} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index c9191b87..734f39de 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -19,7 +19,7 @@ public class StoreX86 extends MemOpX86 { } // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return RegMask.EMPTY; } + @Override public RegMask outregmap() { return null; } // General form: "stN [base + idx<<2 + 12],val" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index bd88011f..c7edfcc4 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -12,7 +12,7 @@ import java.io.ByteArrayOutputStream; public class TFPX86 extends ConstantNode implements MachNode { TFPX86( ConstantNode con ) { super(con); } // Register mask allowed on input i. 0 for no register. - @Override public RegMask regmap(int i) { return RegMask.EMPTY; } + @Override public RegMask regmap(int i) { return null; } // General int registers @Override public RegMask outregmap() { return x86_64_v2.WMASK; } diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java index 795fa814..d71a49dc 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java @@ -11,7 +11,7 @@ import com.seaofnodes.simple.type.TypeInteger; import java.io.ByteArrayOutputStream; -public class XorIX86 extends MachConcreteNode implements MachNode { +public class XorIX86 extends MachConcreteNode implements MachNode { final TypeInteger _ti; XorIX86(Node xor, TypeInteger ti) {super(xor); _inputs.pop(); _ti = ti;} diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 45ae19dc..ddb2dcd6 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -28,7 +28,8 @@ public class x86_64_v2 extends Machine { public static RegMask FLAGS_MASK = new RegMask(1L<<FLAGS); // Return single int/ptr register - public static RegMask RET_MASK = new RegMask(RAX); + public static RegMask RET_MASK = new RegMask(1<<RAX); + public static RegMask RET_FMASK = new RegMask(1<<XMM0); public static RegMask RDI_MASK = new RegMask(1L<<RDI); public static RegMask RCX_MASK = new RegMask(1L<<RCX); @@ -37,6 +38,19 @@ public class x86_64_v2 extends Machine { public static RegMask R09_MASK = new RegMask(1L<<R09); public static RegMask RSI_MASK = new RegMask(1L<<RSI); + public static RegMask XMM0_MASK = new RegMask(1L<<XMM0); + public static RegMask XMM1_MASK = new RegMask(1L<<XMM1); + public static RegMask XMM2_MASK = new RegMask(1L<<XMM2); + public static RegMask XMM3_MASK = new RegMask(1L<<XMM3); + public static RegMask XMM4_MASK = new RegMask(1L<<XMM4); + public static RegMask XMM5_MASK = new RegMask(1L<<XMM5); + public static RegMask XMM6_MASK = new RegMask(1L<<XMM6); + public static RegMask XMM7_MASK = new RegMask(1L<<XMM7); + public static RegMask[] XMMS = new RegMask[]{ + XMM0_MASK, XMM1_MASK, XMM2_MASK, XMM3_MASK, + XMM4_MASK, XMM5_MASK, XMM6_MASK, XMM7_MASK, + }; + // Calling conv metadata public int GPR_COUNT_CONV_WIN64 = 4; // RCX, RDX, R9, R9 public int XMM_COUNT_CONV_WIN64 = 4; // XMM0L, XMM1L, XMM2L, XMM3L @@ -50,41 +64,45 @@ public class x86_64_v2 extends Machine { "r8" , "r9" , "r10" , "r11" , "r12" , "r13" , "r14" , "r15" , "xmm0", "xmm1", "xmm2" , "xmm3" , "xmm4" , "xmm5" , "xmm6" , "xmm7" , "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", + "flags", }; - @Override public String reg( int reg ) { return REGS[reg]; } + @Override public String reg( int reg ) { + return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*4+"]"; + } // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 - static int callInArg( int idx ) { - return switch( CodeGen.CODE._callingConv ) { - case CodeGen.CallingConv.SystemV -> callInArgSystemV(idx); - case CodeGen.CallingConv.Win64 -> callInArgWin64 (idx); + static int callInArg( TypeFunPtr tfp, int idx ) { + int[] cargs = switch( CodeGen.CODE._callingConv ) { + case CodeGen.CallingConv.SystemV -> CALLINARG_SYSTEMV_INT; + case CodeGen.CallingConv.Win64 -> CALLINARG_WIN64_INT; }; + if( idx < 2 ) return -1; + if( idx >= cargs.length ) + throw Utils.TODO(); // Pass on stack slot + if( tfp.arg(idx-2) instanceof TypeFloat ) + return XMM0 + (idx-2); + return cargs[idx]; } // WIN64(param passing) - static RegMask[] CALLINMASK_WIN64 = new RegMask[] { - RegMask.EMPTY, - RegMask.EMPTY, + static int[] CALLINARG_WIN64_INT = new int[] { + -1, // Control, no register + -1, // Memory, no register + RCX, + RDX, + R08, + R09, + }; + static RegMask[] CALLINARG_WIN64_MASK = new RegMask[] { + null, // Control, no register + null, // Memory, no register RCX_MASK, RDX_MASK, R08_MASK, R09_MASK, - RegMask.EMPTY, - RegMask.EMPTY }; - static int[] CALLINARG_WIN64 = new int[] { - 0, // Control, no register - 0, // Memory, no register - RCX, // - RDX, - R08, - R09, - 0, - 0, - }; - static int callInArgWin64( int idx ) { return CALLINARG_WIN64[idx]; } // caller saved(win64) public static final long WIN64_ABI_CALLER_SAVED = @@ -93,20 +111,9 @@ public class x86_64_v2 extends Machine { // callee saved(win64) public static final long WIN64_ABI_CALLEE_SAVED = ~WIN64_ABI_CALLER_SAVED; - // SystemV(param passing) - static RegMask[] CALLINMASK_SYSTEMV = new RegMask[] { - RegMask.EMPTY, - RegMask.EMPTY, - RDI_MASK, - RSI_MASK, - RDX_MASK, - RCX_MASK, - R08_MASK, - R09_MASK - }; - static int[] CALLINARG_SYSTEMV = new int[] { - 0, // Control, no register - 0, // Memory, no register + static int[] CALLINARG_SYSTEMV_INT = new int[] { + -1, // Control, no register + -1, // Memory, no register RDI, RSI, RDX, @@ -114,8 +121,16 @@ public class x86_64_v2 extends Machine { R08, R09, }; - static int callInArgSystemV( int idx ) { return CALLINARG_SYSTEMV[idx]; } - + static RegMask[] CALLINARG_SYSTEMV_MASK = new RegMask[] { + null, // Control, no register + null, // Memory, no register + RDI_MASK, + RSI_MASK, + RDX_MASK, + RCX_MASK, + R08_MASK, + R09_MASK, + }; // caller saved(systemv) // caller saved(win64) public static final long SYSTEMV_ABI_CALLER_SAVED = @@ -124,15 +139,22 @@ public class x86_64_v2 extends Machine { public static final long SYSTEMV_ABI_CALLE_SAVED = ~SYSTEMV_ABI_CALLER_SAVED; - static RegMask callInMask( int idx ) { - return switch( CodeGen.CODE._callingConv ) { - case CodeGen.CallingConv.SystemV -> CALLINMASK_SYSTEMV[idx]; - case CodeGen.CallingConv.Win64 -> CALLINMASK_WIN64 [idx]; + static RegMask callInMask( TypeFunPtr tfp, int idx ) { + RegMask[] cargs = switch( CodeGen.CODE._callingConv ) { + case CodeGen.CallingConv.SystemV -> CALLINARG_SYSTEMV_MASK; + case CodeGen.CallingConv.Win64 -> CALLINARG_WIN64_MASK; }; + if( idx < 2 ) return null; + if( idx >= cargs.length ) + throw Utils.TODO(); // Pass on stack slot + if( tfp.arg(idx-2) instanceof TypeFloat ) + return XMMS[idx-2]; + return cargs[idx]; } // Create a split op; any register to any register, including stack slots - @Override public Node split() { + @Override + public Node split() { throw Utils.TODO(); } @@ -153,7 +175,7 @@ public class x86_64_v2 extends Machine { case AddNode add -> add(add); case AndNode and -> and(and); case BoolNode bool -> cmp(bool); - case CallEndNode cend -> new CallEndNode((CallNode)cend.in(0)); + case CallEndNode cend -> new CallEndX86(cend); case CallNode call -> call(call); case CProjNode c -> new CProjNode(c); case ConstantNode con -> con(con); @@ -247,7 +269,7 @@ public class x86_64_v2 extends Machine { private Node and(AndNode and) { if( and.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) return new AndIX86(and, ti); - throw Utils.TODO(); + return new AndX86(and); } private Node call(CallNode call) { @@ -315,7 +337,7 @@ public class x86_64_v2 extends Machine { private Node or(OrNode or) { if( or.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) return new OrIX86(or, ti); - throw Utils.TODO(); + return new OrX86(or); } private Node prj( ProjNode prj ) { @@ -324,20 +346,20 @@ public class x86_64_v2 extends Machine { private Node sar( SarNode sar ) { if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti) - return new SarX86(sar, ti); - throw Utils.TODO(); + return new SarIX86(sar, ti); + return new SarX86(sar); } private Node shl( ShlNode shl ) { if( shl.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) return new ShlIX86(shl, ti); - throw Utils.TODO(); + return new ShlX86(shl); } private Node shr(ShrNode shr) { if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti ) return new ShrIX86(shr, ti); - throw Utils.TODO(); + return new ShrX86(shr); } private Node st( StoreNode st ) { |
