summaryrefslogtreecommitdiff
path: root/chapter19
diff options
context:
space:
mode:
Diffstat (limited to 'chapter19')
-rw-r--r--chapter19/README.md97
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java4
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/Parser.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/RegMask.java8
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java11
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java6
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java39
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java36
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java40
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java41
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java49
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java37
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java31
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java44
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java28
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java39
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java22
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java29
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java34
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java36
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java35
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java44
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java25
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java23
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java48
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java35
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java40
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java36
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java42
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java38
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java40
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java29
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java45
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java329
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java37
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java3
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java3
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java4
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java4
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java7
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java6
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java8
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java37
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java24
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java39
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java1
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java38
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java122
-rw-r--r--chapter19/src/test/java/com/seaofnodes/simple/Chapter13Test.java13
-rw-r--r--chapter19/src/test/java/com/seaofnodes/simple/Chapter19Test.java33
81 files changed, 2307 insertions, 99 deletions
diff --git a/chapter19/README.md b/chapter19/README.md
index 1e2074cf..87a4c3a6 100644
--- a/chapter19/README.md
+++ b/chapter19/README.md
@@ -90,4 +90,99 @@ the `Cmp/SetXX` opcode sequence. The X86 `Jxx` takes in `FLAGS` and not a
`0/1`, so the `Jxx` will skip the `SetXX` and directly use the `Cmp`. Using
the ideal `Bool` directly will require the `SetXX`. i.e. `return a==3` will
match to a `CmpX86 RAX,#3; SetEQ RAX; ret;` whereas a `if( a==3 )` will match
-to a `CmpX86 RAX,#3; jeq;` \ No newline at end of file
+to a `CmpX86 RAX,#3; jeq;`
+
+## RISC-V port
+
+In the `node/cpus/riscv` directory is a `riscv.java` port to a RISC-V.
+This port supports 32 64-bit GPRs, and 32 floating-point registers.
+There is a pattern matcher for matching riscv ops from idealized Simple
+Sea-of-Nodes. Currently, we are targeting `RVA23U64`.
+
+### Normal instruction selection
+
+Works the same way as **X86_64_V2**, since riscv doesn't have *complex* addressing modes, greedy
+pattern matching doesn't apply to most of the cases. Ops without any special behavior simply do the lookup.
+
+### Restricted ISA
+RISC-V is a restricted ISA with simple addressing modes and overloads.
+E.g `lea` is not present.
+
+
+### Branching
+In `x86_64_v2`, branching requires a comparison instruction to set flags,
+followed by a jump instruction that uses those flags.
+In contrast, RISC-V includes all necessary operands within the
+branch instruction itself, eliminating the need for a separate
+comparison step.
+
+E.g
+```
+beq x10, x11, some_label
+```
+
+`CBranchRISC` implements this behavior.
+### No R-Flags
+No R-flags exist in RiSC-V. To obtain similar functionality:
+
+We can set the value of registers based on the result of the comparison this way explicitly.
+```
+xor a0, a0, a1
+seqz a0, a0
+```
+After the first `xor` - `a0` will be zero if `a0` and `a1` are equal.
+The `seqz` instruction will set `a0` to 1 if `a0` is zero from the previous operation.
+This matches `SetRISC` in the `nodes/cpus/riscv` port.
+
+### Fixed instruction length
+RISC-V instructions have fixed length of 32 bits(in most cases) which means that we can benefit
+from displacements in the encoding side.
+
+E.g
+```
+flw fa5, 0(a0)
+flw fa4, 12(a0)
+fadd.s fa0, fa5, fa4
+```
+(No load is needed prior to `flw`)
+
+### ABI names(registers)
+In `RISC-V`, general-purpose registers (`GPRs`) range from `x0` to `x31`, and floating-point registers range
+from `f0` to `f31`.
+
+To enhance readability and align with calling conventions, RISC-V defines ABI names for registers, providing more intuitive aliases
+instead of raw register numbers.
+
+
+
+| Register | Alias | Usage | Saved By |
+|----------|-------|------------------------------|----------|
+| x10 | a0 | Function arguments/return values | Caller |
+| x11 | a1 | Function arguments/return values | Caller |
+| x12 | a2 | Function arguments | Caller |
+| x13 | a3 | Function arguments | Caller |
+| x14 | a4 | Function arguments | Caller |
+| x15 | a5 | Function arguments | Caller |
+| x16 | a6 | Function arguments | Caller |
+| x17 | a7 | Function arguments | Caller |
+
+When passing in arguments to a function, the first 8 arguments from the caller are passed in registers `a0` to `a7`.
+
+### Load floats
+Currently, floating-point constants are first loaded into an `integer GPR` before being converted into a floating-point register.
+This process is rewritten in the RA stage as:
+
+
+````
+lui a0, 262144
+fmv.w.x fa0, a0
+````
+For non-constant values, we use a broader register mask that
+supports both GPRs and FPRs. This implementation can be found in:
+`nodes/cpus/riscv/LoadRISC`.
+
+
+
+
+
+
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 ) {
diff --git a/chapter19/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter19/src/test/java/com/seaofnodes/simple/Chapter13Test.java
index d05fd7d8..005a3dd4 100644
--- a/chapter19/src/test/java/com/seaofnodes/simple/Chapter13Test.java
+++ b/chapter19/src/test/java/com/seaofnodes/simple/Chapter13Test.java
@@ -128,6 +128,19 @@ return n.i;
}
@Test
+ public void testNullRef4() {
+ CodeGen code = new CodeGen("-null-5/null-5;");
+ try { code.parse().opto().typeCheck(); fail(); }
+ catch( Exception e ) { assertEquals("Cannot 'Add' null",e.getMessage()); }
+ }
+
+ @Test public void testNullRef5() {
+ CodeGen code = new CodeGen("return null+42;");
+ try { code.parse().opto().typeCheck(); fail(); }
+ catch( Exception e ) { assertEquals("Cannot 'Add' null",e.getMessage()); }
+ }
+
+ @Test
public void testEmpty() {
CodeGen code = new CodeGen(
"""
diff --git a/chapter19/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/chapter19/src/test/java/com/seaofnodes/simple/Chapter19Test.java
index a4857a01..990c4c32 100644
--- a/chapter19/src/test/java/com/seaofnodes/simple/Chapter19Test.java
+++ b/chapter19/src/test/java/com/seaofnodes/simple/Chapter19Test.java
@@ -180,6 +180,39 @@ return arg1 * arg;
}
@Test
+ public void testBasic18() {
+ CodeGen code = new CodeGen(
+ """
+ int arg1 = arg + 1;
+ return arg1 << arg;
+ """);
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (shl,(inc,arg),arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic19() {
+ CodeGen code = new CodeGen(
+ """
+ int arg1 = arg + 1;
+ return arg1 >> arg;
+ """);
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (sar,(inc,arg),arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic20() {
+ CodeGen code = new CodeGen(
+ """
+ int arg1 = arg + 1;
+ return arg1 >>> arg;
+ """);
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (shr,(inc,arg),arg);", code._stop.toString());
+ }
+
+ @Test
public void testToFloat() {
CodeGen code = new CodeGen("""
int a = arg;