summaryrefslogtreecommitdiff
path: root/chapter23
diff options
context:
space:
mode:
Diffstat (limited to 'chapter23')
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java6
-rw-r--r--chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java32
-rw-r--r--chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java2
3 files changed, 36 insertions, 4 deletions
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java
index 44e73d1d..94f0da0e 100644
--- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java
+++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java
@@ -28,9 +28,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize {
// Delta is from opcode start
@Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
short dst = enc.reg(this);
- // AUIPC dst,#hi20_constant_pool
- enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, delta>>12));
- // Load dst,[dst+#low12_constant_pool]
+ // Round the high part because ADDI's low 12 bits are signed.
+ enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, (delta+0x800)>>12));
+ // ADDI dst,dst,#low12_constant_pool
enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, dst, 0, dst, delta & 0xFFF));
}
diff --git a/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java
index bca06f0c..6f488c85 100644
--- a/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java
+++ b/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java
@@ -13,6 +13,38 @@ import org.junit.Test;
import static org.junit.Assert.*;
public class Chapter22Test {
+
+ @Test public void testRiscvRightShifts() {
+ // SRAI, SRLI, SRA, SRL: a0 = -32 shifted by 4.
+ int[] ops = {0x40455513,0x00455513,0x40b55533,0x00b55533};
+ for( int i=0; i<ops.length; i++ ) {
+ EvalRisc5 r5 = new EvalRisc5(new byte[1<<16],1<<15);
+ r5.st4(0,ops[i]);
+ r5.regs[riscv.A0] = -32;
+ r5.regs[riscv.A0+1] = 4;
+ assertEquals(0,r5.step(1));
+ assertEquals((i&1)==0 ? -2L : 0x0fff_ffff_ffff_fffeL,r5.regs[riscv.A0]);
+ }
+ }
+
+ @Test public void testRiscvPointerRelocation() {
+ CodeGen code = new CheckedCodeGen("return \"x\";").driver(CodeGen.Phase.Encoding,"riscv","SystemV");
+ var enc = code._encoding;
+ assertEquals(1,enc._bigCons.size());
+ var ptr = (com.seaofnodes.simple.node.cpus.riscv.TMPRISC)enc._bigCons.keySet().iterator().next();
+ int start = enc._opStart[ptr._nid];
+ for( int delta : new int[]{0x7ff,0x800,0xfff,0x1000,0x1800,-1,-0x800,-0x801} ) {
+ ptr.patch(enc,start,enc._opLen[ptr._nid],delta);
+ // Place the program above zero so backward targets are valid addresses.
+ byte[] image = new byte[1<<16];
+ System.arraycopy(enc.bits(),0,image,0x4000,enc._bits.size());
+ EvalRisc5 r5 = new EvalRisc5(image,1<<15);
+ r5._pc = 0x4000;
+ assertEquals(0,r5.step(100));
+ assertEquals(0x4000+start+delta,r5.regs[riscv.A0]);
+ }
+ }
+
@Test public void testSubZeroTypeError() {
try {
new CodeGen("return null-0;").parse().opto().typeCheck();
diff --git a/chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java
index a4cc7044..633e931e 100644
--- a/chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java
+++ b/chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java
@@ -252,7 +252,7 @@ public class EvalRisc5 {
case 2 -> (rs1 < rs2) ? 1 : 0;
case 3 -> (rs1 < rs2) ? 1 : 0;
case 4 -> rs1 ^ rs2;
- case 5 -> (ir & 0x40000000) != 0 ? (rs1 >>> (rs2 & 0x3F)) : (rs1 >> (rs2 & 0x3F));
+ case 5 -> (ir & 0x40000000) != 0 ? (rs1 >> (rs2 & 0x3F)) : (rs1 >>> (rs2 & 0x3F));
case 6 -> rs1 | rs2;
case 7 -> rs1 & rs2;
default -> rval;