diff options
Diffstat (limited to 'chapter21/src/main/java')
3 files changed, 55 insertions, 20 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index fb46a6a2..8f0a97c8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -343,25 +343,19 @@ public class CodeGen { // --------------------------- // Encoding public int _tEncode; - public boolean _JIT; - public Encoding _encoding; - public void preEncode() { } // overridden by M2 + public Encoding _encoding; // Encoding object + public void preEncode() { } // overridden by alternative ports public CodeGen encode(boolean jit) { assert _phase == Phase.RegAlloc; _phase = Phase.Encoding; long t0 = System.currentTimeMillis(); _encoding = new Encoding(this); - _JIT = jit; preEncode(); - _encoding.encode(); + _encoding.encode(jit); _tEncode = (int)(System.currentTimeMillis() - t0); return this; } - public CodeGen encode() { - return encode(false); - } - // Encoded binary, no relocation info - public byte[] binary() { return _encoding.bits(); } + public CodeGen encode() { return encode(false); } // --------------------------- // Exporting to external formats diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 48b9ea5f..74c128be 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -153,7 +153,7 @@ public class Encoding { _bigCons.put(relo,new Relo(relo,t,(byte)off,(byte)elf)); } - void encode() { + void encode(boolean jit) { // Basic block layout: invert branches to keep blocks in-order; insert // unconditional jumps. Attempt to keep backwards branches taken, // forwards not-taken (this is the default prediction on most @@ -171,6 +171,9 @@ public class Encoding { // Patch RIP-relative and local encodings now. patchLocalRelocations(); + // If JIT'ing (in memory execution), patch the global relocations now + if( jit ) + patchGlobalRelocations(); } // Basic block layout: invert branches to keep blocks in-order; insert @@ -416,9 +419,26 @@ public class Encoding { void patchLocalRelocations() { // Walk the local code-address relocations for( Node src : _internals.keySet() ) { + int start = _opStart[src._nid]; Node dst = _internals.get(src); int target = _opStart[dst._nid]; + ((RIPRelSize)src).patch(this, start, _opLen[src._nid], target - start); + } + } + + // A series of libc/external calls that Simple can link against in a JIT. + // Since no runtime in the JVM process, using magic numbers for the CPU + // emulators to pick up on. + public static int SENTINAL_CALLOC = -2; + + void patchGlobalRelocations() { + for( Node src : _externals.keySet() ) { int start = _opStart[src._nid]; + String dst = _externals.get(src); + int target = switch( dst ) { + case "calloc" -> SENTINAL_CALLOC; + default -> throw Utils.TODO(); + }; ((RIPRelSize)src).patch(this, start, _opLen[src._nid], target - start); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index dfa40cad..0ca76d3f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -5,14 +5,12 @@ import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.print.ASMPrinter; -public class NewRISC extends NewNode implements MachNode { +public class NewRISC extends NewNode implements MachNode, RIPRelSize { // A pre-zeroed chunk of memory. NewRISC( NewNode nnn ) { super(nnn); } @Override public String op() { return "alloc"; } - @Override public RegMask regmap(int i) { - return i==1 ? riscv.A0_MASK : null; // Size input or mem aliases - } - @Override public RegMask outregmap(int i) { return i == 1 ? riscv.A0_MASK : null; } + @Override public RegMask regmap(int i) { return i==1 ? riscv.A1_MASK : null; } + @Override public RegMask outregmap(int i) { return i==1 ? riscv.A0_MASK : null; } @Override public RegMask outregmap() { return null; } @Override public RegMask killmap() { return riscv.riscCallerSave(); } @@ -21,13 +19,36 @@ public class NewRISC extends NewNode implements MachNode { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A1, 0)); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.RPC, 0, riscv.A1, 0)); + enc.add4(riscv.i_type(riscv.OP_IMM , riscv.A0 , 0, riscv.ZERO, 1)); + enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); + enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + } + + // Patch is for running "new" in a JIT. + // Delta is from opcode start + @Override public byte encSize(int delta) { return 4*3; } + + // Patch is for running "new" in a JIT. + // Delta is from opcode start + @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { + // Odd-number patches are JIT emulator targets. + if( (delta&3)!=0 ) { + //enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, riscv.ZERO , 0, riscv.ZERO, 0)); + //enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, riscv.RPC, opStart+delta)); + + int imm20 = delta>>12; + if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension + int imm12 = delta&0xFFF; + enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + } else + throw Utils.TODO(); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { - sb.p("auipc a1=#calloc\n"); - sb.p("call a1+#calloc, a0"); + sb.p("ldi a1=#1\n"); + sb.p("auipc a2=#calloc\n"); + sb.p("call a2+#calloc, a0"); } } |
