summaryrefslogtreecommitdiff
path: root/chapter22/src/test/java
diff options
context:
space:
mode:
Diffstat (limited to 'chapter22/src/test/java')
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java12
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java2
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java39
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java437
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java19
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java10
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java6
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/jig.smp9
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/sieve.smp2
9 files changed, 479 insertions, 57 deletions
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
index 391bba67..2733620e 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
@@ -1,6 +1,7 @@
package com.seaofnodes.simple;
import com.seaofnodes.simple.codegen.CodeGen;
+import com.seaofnodes.simple.node.cpus.arm.arm;
import com.seaofnodes.simple.node.cpus.riscv.riscv;
import java.io.IOException;
import java.nio.file.Files;
@@ -23,10 +24,15 @@ public class BrainFuckTest {
for( int i=0; i<brain_fuck.length(); i++ )
assertEquals(brain_fuck.charAt(i), R5.ld1z(ptr+4+i));
- // TODO: replace with ARM Eval
- String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp"));
- Chapter21Test.testCPU(src,"arm", "SystemV",26,null);
+ EvalArm64 A5 = TestArm64.build("brain_fuck", 0, 28, false);
+ int trap_arm = A5.step(100000);
+ assertEquals(0,trap_arm);
+ assertEquals(0,trap);
+ int ptr_arm = (int)A5.regs[arm.X0];
+ assertEquals(brain_fuck.length(),A5.ld4s(ptr_arm));
+ for( int i=0; i<brain_fuck.length(); i++ )
+ assertEquals(brain_fuck.charAt(i), A5.ld1z(ptr+4+i));
}
}
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java
index 83902b6d..5b33d1e7 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java
@@ -84,7 +84,7 @@ return sqrt(arg) + sqrt(arg+2);
String src = "int[] !xs = new int[3]; xs[arg]=1; return xs[arg&1];";
testCPU(src,"x86_64_v2", "SystemV",-1,"return .[];");
testCPU(src,"riscv" , "SystemV", 6,"return .[];");
- testCPU(src,"arm" , "SystemV", 4,"return .[];");
+ testCPU(src,"arm" , "SystemV", 6,"return .[];");
}
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java
index 1857367b..ea23728c 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java
@@ -113,7 +113,7 @@ public class Chapter21Test {
@Test public void testSieve() throws IOException {
// The primes
- int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, };
+ int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, };
SB sb = new SB().p(primes.length).p("[");
for( int prime : primes )
sb.p(prime).p(", ");
@@ -134,15 +134,16 @@ public class Chapter21Test {
for( int i=0; i<primes.length; i++ )
assertEquals(primes[i], R5.ld4s(ary + 4 + i*4));
- //// Evaluate on ARM5 emulator; expect return of an array of primes in the simulated heap.
- //EvalArm64 A5 = TestArm64.build("sieve", 100, 160, false);
- //int trap_arm = A5.step(10000);
- //assertEquals(0, trap_arm);
- //int ary_arm = (int)A5.regs[arm.X0];
- //// Memory layout starting at ary(length,pad, prime1, primt2, prime3, prime4)
- //assertEquals(primes.length, A5.ld4s(ary_arm));
- //for(int i = 0; i<primes.length; i++)
- // assertEquals(primes[i], A5.ld4s(ary_arm + 4 + i * 4));
+ // Evaluate on ARM5 emulator; expect return of an array of primes in
+ // the simulated heap.
+ EvalArm64 A5 = TestArm64.build("sieve", 100, 160, false);
+ int trap_arm = A5.step(10000);
+ assertEquals(0, trap_arm);
+ int ary_arm = (int)A5.regs[arm.X0];
+ // Memory layout starting at ary(length,pad, prime1, primt2, prime3, prime4)
+ assertEquals(primes.length, A5.ld4s(ary_arm));
+ for( int i = 0; i<primes.length; i++ )
+ assertEquals(primes[i], A5.ld4s(ary_arm + 4 + i * 4));
}
@Test public void testFibExport() throws IOException {
@@ -168,7 +169,7 @@ public class Chapter21Test {
TestC.run("person", person, 0);
// Memory layout starting at PS:
- int ps = 1<<16; // Person array pointer
+ int ps = 1<<16; // Person array pointer starts at heap start
// Person[3] = { len,pad,P0,P1,P2 }; // sizeof = 4*8
// P0 = { age } // sizeof=8
int p0 = ps+4*8+0*8;
@@ -191,6 +192,22 @@ public class Chapter21Test {
assertEquals( 5+0,R5.ld8(p0));
assertEquals(17+1,R5.ld8(p1));
assertEquals(60+0,R5.ld8(p2));
+
+ EvalArm64 A5 = TestArm64.build("person", ps, 0, false);
+ A5.regs[arm.X1] = 1; // Index 1
+ A5.st4(ps, 3);
+ A5.st8(ps+1*8,p0);
+ A5.st8(ps+2*8,p1);
+ A5.st8(ps+3*8,p2);
+ A5.st8(p0, 5); // age= 5
+ A5.st8(p1,17); // age=17
+ A5.st8(p2,60); // age=60
+
+ int trap_arm = A5.step(100);
+ assertEquals(0,trap_arm);
+ assertEquals( 5+0, A5.ld8(p0));
+ assertEquals(17+1, A5.ld8(p1));
+ assertEquals(60+0, A5.ld8(p2));
}
@Test public void testArgCount() throws IOException {
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java
index 4a4cf25c..3ea9bea0 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java
@@ -13,10 +13,9 @@ public class EvalArm64 {
final double[] fregs;
int _pc;
-
+ int SENTINEL_CALLOC = -4;
// Start of free memory for allocation
int _heap;
-
// Cycle counters
int _cycle;
@@ -39,7 +38,8 @@ public class EvalArm64 {
public int ld1s(int x) { return _buf[x ] ; }
public int ld1z(int x) { return _buf[x ]&0xFF; }
public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; }
- public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; }
+ public int ld2z(int x) {
+ return ld1z(x) | ld1z(x+1)<< 8; }
public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; }
public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; }
@@ -52,7 +52,6 @@ public class EvalArm64 {
public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); }
public void st8(int x, long val) { st4(x,(int)val); st2(x+4,(int)(val>>32)); }
-
public int step(int maxops) {
int trap = 0;
long rval = 0;
@@ -66,7 +65,6 @@ public class EvalArm64 {
rval = 0;
frval = 0;
cycle++;
-
if( pc >= _buf.length ) {
trap = 1 + 1; // Handle access violation on instruction read.
break;
@@ -85,6 +83,7 @@ public class EvalArm64 {
int opcode1 = (ir >> 24) & 0xFF;
// [31:26]
int opcode2 = (ir >> 26) & 0x3F;
+
switch(opcode2) {
case 5: {
//b
@@ -108,13 +107,12 @@ public class EvalArm64 {
int imm26 = (ir & 0x03FFFFFF);
int imm = (imm26 << 6) >> 6;
pc = pc + (imm << 2) ;
-
- if (pc == Encoding.SENTINAL_CALLOC) {
+ if (pc == SENTINEL_CALLOC) {
long size = regs[arm.X0]*regs[arm.X1];
regs[arm.X0] = _heap;
_heap += (int)size;
// unwind pc
- pc = (int)rval - 4;
+ pc = (int)rval;
}
continue;
}
@@ -127,6 +125,136 @@ public class EvalArm64 {
rval = (ir >> 5) & 0x7FFF;
break;
}
+ case 0x38: {
+ // STRB/LDRB(register)
+ int opc = ir >> 21 & 0x7;
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ // full opcode
+ opcode1 = (ir >> 21) & 0x7FF;
+ switch(opc) {
+ case 0x1: {
+ // store
+ if(opcode1 == arm.OP_STORE_R_8) {
+ st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]);
+ }else {
+ trap = (2+1);
+ }
+ rdid = -1;
+ break;
+ }
+ case 0x3: {
+ // load
+ if(opcode1 == arm.OP_LOAD_R_8) {
+ rval = ld1s((int)regs[rn] + (int)regs[rm]);
+ } else {
+ trap = (2+1);
+ }
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+ case 0x39: {
+ // STRB/LDRB(immediate)
+ // str/ldr(immediate)
+ // rn
+ int base = ir >> 5 & 0x1F;
+ int imm = (ir >> 10) & 0xFFF;
+ rval = regs[base] + imm;
+ int opc = (ir >> 22) & 0x3;
+ // full opcode
+ opcode1 = (ir >> 22) & 0x3FF;
+
+ switch(opc) {
+ case 0x0: {
+ // store
+ if(opcode1 == arm.OP_STORE_IMM_8) {
+ st1((int)rval, (int)regs[rdid]);
+ } else trap = (2+1);
+ rdid = -1;
+
+ break;
+ }
+ case 0x1: {
+ // LDR (immediate)
+ if(opcode1 == arm.OP_LOAD_IMM_8) {
+ rval = ld1s((int)rval);
+ } else trap = (2+1);
+ rdid = -1;
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+ case 0x78: {
+ // STRH/LDRH(register)
+ int opc = ir >> 21 & 0x7;
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ // full opcode
+ opcode1 = (ir >> 21) & 0x7FF;
+ switch(opc) {
+ case 0x1: {
+ // store
+ if(opcode1 == arm.OP_STORE_R_16) {
+ st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]);
+ }else {
+ trap = (2+1);
+ }
+ rdid = -1;
+ break;
+ }
+ case 0x3: {
+ // load
+ if(opcode1 == arm.OP_LOAD_R_16) {
+ rval = ld1s((int)regs[rn] + (int)regs[rm]);
+ } else {
+ trap = (2+1);
+ }
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+
+ case 0x79: {
+ // STRH/LDRH(immediate)
+ int base = ir >> 5 & 0x1F;
+ int imm = (ir >> 10) & 0xFFF;
+ imm *= 2;
+ rval = regs[base] + imm;
+ int opc = (ir >> 22) & 0x3;
+ // full opcode
+ opcode1 = (ir >> 22) & 0x3FF;
+
+ switch(opc) {
+ case 0x0: {
+ // store
+ if(opcode1 == arm.OP_STORE_IMM_16) {
+ st2((int)rval, (int)regs[rdid]);
+ } else trap = (2+1);
+ rdid = -1;
+
+ break;
+ }
+ case 0x1: {
+ // LDR (immediate)
+ if(opcode1 == arm.OP_LOAD_IMM_16) {
+ rval = ld2s((int)rval);
+ } else trap = (2+1);
+ rdid = -1;
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+
+
case 0x5c: {
// ldr
is_f = true;
@@ -137,30 +265,276 @@ public class EvalArm64 {
frval = ld8f(pc + address);
break;
}
+ case 0xB9: {
+ // str/ldr(immediate) 32 bits
+ int base = ir >> 5 & 0x1F;
+ int imm = (ir >> 10) & 0xFFF;
+ imm *= 4;
+ rval = regs[base] + imm;
+ int opc = (ir >> 22) & 0x3;
+
+ opcode1 = (ir >> 22) & 0x3FF;
+ switch(opc) {
+ case 0x0: {
+ // store
+ if(opcode1 == arm.OP_STORE_IMM_32) {
+ st4((int)rval, (int)regs[rdid]);
+ } else trap = (2+1);
+
+ rdid = -1;
+ break;
+ }
+ case 0x1: {
+ // LDR (immediate)
+ if(opcode1 == arm.OP_LOAD_IMM_32) {
+ rval = ld4s((int) rval);
+ } else trap = (2+1);
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
case 0xF9: {
- // str
- // rn
+ // str/ldr(immediate) 64 bits
int base = ir >> 5 & 0x1F;
int imm = (ir >> 10) & 0xFFF;
+
+ imm *= 8;
+
rval = regs[base] + imm;
- switch(ir <<8 >> 30) {
+ int opc = (ir >> 22) & 0x3;
+ // full opcode
+ opcode1 = (ir >> 22) & 0x3FF;
+ switch(opc) {
case 0x0: {
// store
- _buf[(int)rval] = (byte)regs[rdid];
- if(rdid == 30) {
- System.out.print("Here");
+ if(opcode1 == arm.OP_STORE_IMM_64) {
+ st8((int)rval, regs[rdid]);
+ } else trap = (2+1);
+
+ rdid = -1;
+ break;
+ }
+ case 0x1: {
+ // LDR (immediate)
+ if(opcode1 == arm.OP_LOAD_IMM_64) {
+ rval = ld8((int)rval);
+ } else trap = (2+1);
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+ case 0xf8: {
+ // LDR/STR (register + index) 64 bits
+ int opc = ir >> 21 & 0x7;
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ // full opcode
+ opcode1 = (ir >> 21) & 0x7FF;
+ switch(opc) {
+ case 0x1: {
+ if(opcode1 == arm.OP_STORE_R_64) {
+ st8((int)regs[rn] + (int)regs[rm], regs[rdid]);
+ }else {
+ trap = (2+1);
+ }
+ // store(expected to store the length here)
+
+ rdid = -1;
+ break;
+ }
+ case 0x3: {
+ // load
+ if(opcode1 == arm.OP_LOAD_R_64) {
+ rval = ld8((int) (regs[rn] + regs[rm]));
+ } else {
+ trap = (2+1);
+ }
+ break;
+ }
+ default: trap = (2+1);
+ }
+
+ break;
+ }
+
+ case 0xB8: {
+ // LDR/STR (register + index) 32 bits
+ int opc = ir >> 21 & 0x7;
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ // full opcode
+ opcode1 = (ir >> 21) & 0x7FF;
+ switch(opc) {
+ case 0x1: {
+ if(opcode1 == arm.OP_STORE_R_32) {
+ st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]);
+ }else {
+ trap = (2+1);
}
+ // store(expected to store the length here)
+
rdid = -1;
break;
}
+ case 0x3: {
+ // load
+ if( opcode1 == arm.OP_LOAD_R_32) {
+ rval = ld4s((int) (regs[rn] + regs[rm]));
+ } else {
+ trap = (2+1);
+ }
+ break;
+ }
+ default: trap = (2+1);
+ }
+
+ break;
+ }
+
+ case 0xFC: {
+ // LDR/STR (register + index) float 64 bits
+ int opc = ir >> 21 & 0x7;
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ is_f = true;
+ // full opcode
+ opcode1 = (ir >> 21) & 0x7FF;
+ switch(opc) {
case 0x1: {
+ if(opcode1 == arm.OPF_STORE_R_64) {
+ st8((int)regs[rn] + (int)regs[rm], (int)regs[rdid]);
+ }else {
+ trap = (2+1);
+ }
+ // store(expected to store the length here)
+
+ rdid = -1;
+ break;
+ }
+ case 0x3: {
// load
- rval = _buf[(int)rval];
+ if(opcode1 == arm.OPF_LOAD_R_64) {
+ frval = ld8f((int) (regs[rn] + regs[rm]));
+ } else {
+ trap = (2+1);
+ }
break;
}
default: trap = (2+1);
}
+
+ break;
+ }
+
+ case 0xBC: {
+ // LDR/STR (register + index) float 32 bits
+ int opc = ir >> 21 & 0x7;
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ is_f = true;
+ // full opcode
+ opcode1 = (ir >> 21) & 0x7FF;
+ switch(opc) {
+ case 0x1: {
+ if(opcode1 == arm.OPF_STORE_R_32) {
+ st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]);
+ }else {
+ trap = (2+1);
+ }
+ // store(expected to store the length here)
+
+ rdid = -1;
+ break;
+ }
+ case 0x3: {
+ // load
+ if(opcode1 == arm.OPF_LOAD_R_32) {
+ frval = ld4f((int) (regs[rn] + regs[rm]));
+ } else {
+ trap = (2+1);
+ }
+ break;
+ }
+ default: trap = (2+1);
+ }
+
+ break;
+ }
+
+ case 0xBD: {
+ // LDR/STR(immediate) 32 bits floats
+ int base = ir >> 5 & 0x1F;
+ int imm = (ir >> 10) & 0xFFF;
+
+ imm *= 4;
+ is_f = true;
+ rval = regs[base] + imm;
+ int opc = (ir >> 22) & 0x3;
+ // full opcode
+ opcode1 = (ir >> 22) & 0x3FF;
+ switch(opc) {
+ case 0x0: {
+ // store
+ if(opcode1 == arm.OPF_STORE_IMM_32) {
+ st4((int)rval, (int)regs[rdid]);
+ } else trap = (2+1);
+
+ rdid = -1;
+ break;
+ }
+ case 0x1: {
+ // LDR (immediate)
+ if(opcode1 == arm.OPF_LOAD_IMM_32) {
+ frval = ld4s((int)rval);
+ } else trap = (2+1);
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+ case 0xFD: {
+ // LDR/STR(immediate) 64 bits floats
+ int base = ir >> 5 & 0x1F;
+ int imm = (ir >> 10) & 0xFFF;
+
+ imm *= 4;
+ is_f = true;
+ rval = regs[base] + imm;
+ int opc = (ir >> 22) & 0x3;
+ // full opcode
+ opcode1 = (ir >> 22) & 0x3FF;
+ switch(opc) {
+ case 0x0: {
+ // store
+ if(opcode1 == arm.OPF_STORE_IMM_64) {
+ st8((int)rval, regs[rdid]);
+ } else trap = (2+1);
+
+ rdid = -1;
+ break;
+ }
+ case 0x1: {
+ // LDR (immediate)
+ if(opcode1 == arm.OPF_LOAD_IMM_64) {
+ frval = ld8((int)rval);
+ } else trap = (2+1);
+ break;
+ }
+ default: trap = (2+1);
+ }
+ break;
+ }
+ case 0x9b: {
+ // mul
+ int rn = (ir >> 5) & 0x1F;
+ int rm = (ir >> 16) & 0x1F;
+ rval = regs[rn] * regs[rm];
break;
}
case 0x54: {
@@ -209,17 +583,17 @@ public class EvalArm64 {
case 0xD: if(Z || N != V) rval = regs[rm]; break; // le
case 0xE: rval = regs[rm]; break; // always executed(al)
default: {
- rval = regs[(ir >> 5) & 0x1F];
+ rval = regs[(ir >> 5) & 0x1F];
}
}
break;
}
case 0xeb: {
// subs(shifted register)
- int rn = (ir >> 5) & 0x1F;
+ int rn = (ir >> 5) & 0x1F;
int rm = (ir >> 16) & 0x1F;
- int lhs = (int)regs[rn];
- int rhs = (int)regs[rm];
+ long lhs = regs[rn];
+ long rhs = regs[rm];
rval = lhs - rhs;
// set flags as a side effect
@@ -238,7 +612,7 @@ public class EvalArm64 {
// subs(immediate)
int rn = (ir >> 5) & 0x1F;
int immediate = ir << 10 >> 20;
- int lhs = (int)regs[rn];
+ long lhs = regs[rn];
rval = lhs - immediate;
@@ -267,13 +641,30 @@ public class EvalArm64 {
// add(immediate)
int rn = (ir >> 5) & 0x1F;
int immediate = ir << 10 >> 20;
+ // only hit it twice
rval = regs[rn] + immediate;
break;
}
case 0xD3: {
- // lsl
- int immr = ir << 10 >> 26;
- rval = 64 - immr;
+ // lsl(immediate)
+ int imm = (ir >> 16) & 0x3F;
+ int rn = (ir >> 5) & 0x1F;
+ rval = regs[rn] << (64 - imm);
+ break;
+ }
+ case 0x93: {
+ // asr(immediate)
+ int imm = (ir >> 16) & 0x3F;
+ int rn = (ir >> 5) & 0x1F;
+ rval = regs[rn] >> (imm);
+ break;
+ }
+ case 0x92: {
+ // and(immediate)
+ int imm12 = (ir >> 10) & 0x1FFF;
+ long immediate = arm.decodeImm12(imm12);
+ int rn = (ir >> 5) & 0x1F;
+ rval = regs[rn] & immediate;
break;
}
case 0xAA: {
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java
index bad22d52..fd953342 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java
@@ -54,7 +54,7 @@ import java.util.Arrays;
public void st1(int x, int val) { _buf[x] = (byte)val; }
public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); }
- public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); }
+ public void st4(int x, int val) {st2(x,val); st2(x+2,val>>16); }
public void st8(int x, long val) { st4(x,(int)val); st2(x+4,(int)(val>>32)); }
// Note: only a few bits are used. (Machine = 3, User = 0)
@@ -84,7 +84,6 @@ import java.util.Arrays;
trap = 1; // Handle PC-misaligned access
break;
}
-
// Load instruction from image buffer at PC
ir = ld4s( pc );
int rdid = (ir >> 7) & 0x1f;
@@ -104,13 +103,11 @@ import java.util.Arrays;
break;
}
case 0x67: { // JALR (0b1100111)
- int imm = ir >> 20;
-
- int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0);
+ int imm_se = ir >> 20; // Sign extend 12 bits
rval = pc + 4;
- pc = ( ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1) - 4;
+ pc = ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1;
// Return from top-level ; exit sim
- if( pc+4==0 ) {
+ if( pc==0 ) {
if( rdid!=0 ) regs[rdid] = rval; // Write PC into register before exit
break outer;
}
@@ -122,7 +119,8 @@ import java.util.Arrays;
// Arrays.fill(_buf,_heap,_heap+size, (byte) 0 );
_heap += size;
pc = (int)(rval - 4); // Unwind PC, as-if returned from calloc
- }
+ } else
+ pc -= 4;
break;
}
case 0x63: { // Branch (0b1100011)
@@ -195,7 +193,6 @@ import java.util.Arrays;
if( (addy & 0x800)!=0 ) addy |= 0xfffff000;
addy += rs1;
rdid = 0;
-
if( addy >= _buf.length-3 ) {
trap = (7+1); // Store access fault.
rval = addy;
@@ -218,6 +215,10 @@ import java.util.Arrays;
boolean is_reg = (ir & 0x20)!=0;
long rs2 = is_reg ? regs[imm & 0x1f] : imm;
+ // Insert the detection here
+ int rs1id = (ir >> 15) & 0x1f;
+ int funct3 = (ir >> 12) & 0x7;
+
if( is_reg && ( ir & 0x02000000 )!=0 ) {
switch( (ir>>12)&7 ) { //0x02000000 = RV32M
case 0: rval = rs1 * rs2; break; // MUL
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java
index 739f5b1e..5d7d1361 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java
@@ -13,21 +13,21 @@ import static org.junit.Assert.assertEquals;
// Runs 32-bit ARM code in an emulator
public class TestArm64 {
- public static EvalArm64 build(String file, int arg, int spills, boolean print) throws IOException {
+ public static EvalArm64 build( String file, int arg, int spills, boolean print ) throws IOException {
return build("src/test/java/com/seaofnodes/simple/progs",file, arg, spills, print);
}
// Compile and run a simple program
- public static EvalArm64 build(String dir, String file, int arg, int spills, boolean print) throws IOException {
+ public static EvalArm64 build( String dir, String file, int arg, int spills, boolean print ) throws IOException {
// Compile and export Simple
String src = Files.readString(Path.of(dir+"/"+file+".smp"));
CodeGen code = new CodeGen(src).driver("arm", "SystemV",null);
- if(print) {code.print_as_hex(); System.out.print(code.asm());}
+ if( print ) { code.print_as_hex(); System.out.print(code.asm()); }
// Allocation quality not degraded
int delta = spills>>3;
- if(delta == 0) delta =1;
- if(spills != -1) assertEquals("Expect spills:", spills, code._regAlloc._spillScaled, delta);
+ if( delta == 0 ) delta =1;
+ if( spills != -1 ) assertEquals("Expect spills:", spills, code._regAlloc._spillScaled, delta);
// Image
byte[] image = new byte[1<<20]; // A megabyte (1024*1024 bytes)
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java
index b7642540..041ed833 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java
@@ -12,16 +12,16 @@ import static org.junit.Assert.*;
// Runs 32-bit R5 code in an emulator
public abstract class TestRisc5 {
- public static EvalRisc5 build( String file, int arg, int spills, boolean print) throws IOException {
+ public static EvalRisc5 build( String file, int arg, int spills, boolean print ) throws IOException {
return build("src/test/java/com/seaofnodes/simple/progs",file, null, arg, spills, print);
}
// Compile and run a simple program
- public static EvalRisc5 build( String dir, String file, String main, int arg, int spills, boolean print) throws IOException {
+ public static EvalRisc5 build( String dir, String file, String main, int arg, int spills, boolean print ) throws IOException {
// Compile and export Simple
String src = Files.readString(Path.of(dir+"/"+file+".smp"));
CodeGen code = new CodeGen(src).driver("riscv", "SystemV",null);
- if(print) {code.print_as_hex(); System.out.print(code.asm());}
+ if( print ) { code.print_as_hex(); System.out.print(code.asm()); }
// Allocation quality not degraded
int delta = spills>>3;
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/jig.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/jig.smp
index 64c15dd7..00c2a161 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/progs/jig.smp
+++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/jig.smp
@@ -1,2 +1,9 @@
// -*- mode: java; -*-
-val allocIA = { int N -> return new u32[N]; };
+struct s0 {
+ i16 v1;
+ u8 v2;
+};
+s0 !l4Hi9BCnsd = new s0;
+if( new s0.v2+arg )
+ while(1) l4Hi9BCnsd=new s0;
+while(new s0.v2+new s0.v1<=0) {}
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/sieve.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/sieve.smp
index 6d160b1e..569dbb96 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/progs/sieve.smp
+++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/sieve.smp
@@ -1,6 +1,6 @@
// -*- mode: java; -*-
-// The main Sieve array
val sieve = { int N ->
+ // The main Sieve array
bool[] !ary = new bool[N];
// The primes less than N
u32[] !primes = new u32[N>>1];