summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'chapter21/src/main/java/com')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java14
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java22
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java39
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");
}
}