summaryrefslogtreecommitdiff
path: root/chapter21/src/test/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'chapter21/src/test/java/com')
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java35
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java67
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java90
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java34
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/TestC.java3
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp6
6 files changed, 226 insertions, 9 deletions
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
index f3b2c26d..faf21b4f 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
+++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
@@ -102,6 +102,12 @@ public class Chapter21Test {
9 3.000000
""";
TestC.run("newtonFloat",result);
+ EvalRisc5 R5 = TestRisc5.build("newtonFloat", 0);
+ R5.fregs[riscv.FA0 - riscv.F_OFFSET] = 4.0;
+ int trap = R5.step(100);
+ assertEquals(0,trap);
+ // Return register A0 holds fib(8)==55
+ assertEquals(2.0,R5.fregs[riscv.FA0 - riscv.F_OFFSET], 0.00001);
}
@Test public void testSieve() throws IOException {
@@ -173,9 +179,36 @@ public class Chapter21Test {
assertEquals(17+1,R5.ld8(p1));
assertEquals(60+0,R5.ld8(p2));
}
-
@Test public void testArgCount() throws IOException {
String arg_count = "191.000000\n";
TestC.run("arg_count", arg_count);
+
+ EvalRisc5 R5 = TestRisc5.build("no_stack_arg_count", 0);
+
+ // Todo: handle stack(imaginary stack in emulator)
+ // pass in float arguments
+ R5.fregs[riscv.FA0 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA1 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA2 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA3 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA4 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA5 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA6 - riscv.F_OFFSET] = 1.1;
+ R5.fregs[riscv.FA7 - riscv.F_OFFSET] = 1.1;
+
+ R5.regs[riscv.A1] = 2;
+ R5.regs[riscv.A2] = 2;
+ R5.regs[riscv.A3] = 2;
+ R5.regs[riscv.A4] = 2;
+ R5.regs[riscv.A5] = 2;
+ R5.regs[riscv.A6] = 2;
+ R5.regs[riscv.A7] = 2;
+
+ int trap = R5.step(100);
+ assertEquals(0,trap);
+
+ double result = R5.fregs[riscv.FA0 - riscv.F_OFFSET];
+ // missing a float
+ assertEquals(22.8, result, 0.00001);
}
}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java
new file mode 100644
index 00000000..55a16f84
--- /dev/null
+++ b/chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java
@@ -0,0 +1,67 @@
+package com.seaofnodes.simple;
+
+public class EvalArm64 {
+ // Memory image, always 0-based
+ public final byte[] _buf;
+
+ // GPRs
+ final long[] regs;
+ // FRs
+ final double[] fregs;
+
+ int _pc;
+
+ // Start of free memory for allocation
+ int _heap;
+
+ // Cycle counters
+ int _cycle;
+
+ EvalArm64(byte[] buf, int stackSize) {
+ _buf = buf;
+ regs = new long[32];
+ fregs = new double[32];
+ // Stack grows down, heap grows up
+ regs[2/*RSP*/] = _heap = stackSize;
+ _pc = 0;
+ }
+
+ public int step(int maxops) {
+ int trap = 0;
+ long rval = 0;
+ double frval = 0;
+ int pc = _pc;
+ int cycle = _cycle;
+ boolean is_f = false;
+ outer:
+ for(int icount = 0; icount < maxops; icount++) {
+ int ir = 0;
+ rval = 0;
+ cycle++;
+
+ if( pc >= _buf.length ) {
+ trap = 1 + 1; // Handle access violation on instruction read.
+ break;
+ }
+
+ if( (pc & 3)!=0 ) {
+ trap = 1; // Handle PC-misaligned access
+ break;
+ }
+
+ // Load instruction from image buffer at PC
+ //ir = ld4s( pc );
+
+ //int rdid = ir & 0x1f;
+ //switch(ir & )
+ }
+ if(trap != 0) {
+ return trap;
+ }
+ _cycle = _cycle;
+ _pc = pc;
+ return 0;
+ }
+
+
+}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java
index eed596e8..50e52095 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java
+++ b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java
@@ -19,7 +19,8 @@ import java.util.Arrays;
// GPRs
final long[] regs;
-
+ // FRs
+ final double[] fregs;
// PC
int _pc;
@@ -30,8 +31,9 @@ import java.util.Arrays;
int _cycle;
EvalRisc5( byte[] buf, int stackSize ) {
- _buf = buf;
- regs = new long[32];
+ _buf = buf;
+ regs = new long[32];
+ fregs = new double[32];
// Stack grows down, heap grows up
regs[2/*RSP*/] = _heap = stackSize;
_pc = 0;
@@ -59,9 +61,10 @@ import java.util.Arrays;
public int step( int maxops ) {
int trap = 0;
long rval = 0;
+ double frval = 0;
int pc = _pc;
int cycle = _cycle;
-
+ boolean is_f = false;
outer:
for( int icount = 0; icount < maxops; icount++ ) {
int ir = 0;
@@ -82,6 +85,17 @@ import java.util.Arrays;
int rdid = (ir >> 7) & 0x1f;
switch( ir & 0x7f ) {
+ // floats
+ case 0x7: {
+ is_f = true;
+ // does not handle rsp case
+
+ long rs1 = (ir >> 15) & 0x1f;
+ // Todo: look for stack case
+ if (rs1 == 2) break;
+ frval = ir & 0x7FF000;
+ break;
+ }
case 0x37: // LUI (0b0110111)
rval = ( ir & 0xfffff000 );
break;
@@ -263,6 +277,68 @@ import java.util.Arrays;
}
break;
}
+
+ case 0x53: {
+ // differentiate between fcvt.d.w and fadd.d
+ is_f = true;
+ int rs1;
+ int rs1_int;
+ int rs2;
+ int func5 = (ir >> 27) & 0x1F;;
+ int func2 = (ir >> 25) & 0x3;
+// if(func5 == 0 && func2 == 1) {
+// }
+ if(func5 == 0) {
+ // fadd.d
+ rs1 = (ir >> 15) & 0x1F;
+ rs2 = (ir >> 20) & 0x1F;
+ double lhs = fregs[rs1];
+ double rhs = fregs[rs2];
+ frval = lhs + rhs;
+ break;
+ } else if(func5 == 26) {
+ //fcvt.d.w
+ rs1_int = (ir >> 15) & 0x1F;
+ long value = regs[rs1_int];
+ frval = (double)value;
+ break;
+ } else if (func5 == 5) {
+ // fmin.d
+ rs1 = (ir >> 15) & 0x1F;
+ rs2 = (ir >> 20) & 0x1F;
+ // just pick one as they are the same
+ frval = fregs[rs1];
+ break;
+ } else if(func5 == 3) {
+ // fdiv.d
+ rs1 = (ir >> 15) & 0x1F;
+ rs2 = (ir >> 20) & 0x1F;
+ double lhs = fregs[rs1];
+ double rhs = fregs[rs2];
+ frval = lhs / rhs;
+ break;
+ } else if(func5 == 2) {
+ // fmul.d
+ rs1 = (ir >> 15) & 0x1F;
+ rs2 = (ir >> 20) & 0x1F;
+ double lhs = fregs[rs1];
+ double rhs = fregs[rs2];
+ frval = lhs * rhs;
+ break;
+
+ } else if(func5 == 1) {
+ // fsub.d
+ rs1 = (ir >> 15) & 0x1F;
+ rs2 = (ir >> 20) & 0x1F;
+ double lhs = fregs[rs1];
+ double rhs = fregs[rs2];
+ frval = lhs - rhs;
+ break;
+ } else {
+ trap = (2+1); // Fault: Invalid opcode.
+ throw Utils.TODO();
+ }
+ }
default: trap = (2+1); // Fault: Invalid opcode.
}
@@ -272,8 +348,10 @@ import java.util.Arrays;
break;
}
- if( rdid!=0 )
- regs[rdid] = rval; // Write back register.
+ if( rdid!=0 || is_f) {
+ if(is_f) {fregs[rdid] = frval; is_f = false;} // Write back register.
+ else regs[rdid] = rval; // Write back register.
+ }
pc += 4;
}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java
new file mode 100644
index 00000000..96aa5b74
--- /dev/null
+++ b/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java
@@ -0,0 +1,34 @@
+package com.seaofnodes.simple;
+
+
+import com.seaofnodes.simple.codegen.CodeGen;
+import com.seaofnodes.simple.node.cpus.arm.arm;
+import junit.framework.Assert;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.io.IOException;
+
+// Runs 32-bit ARM code in an emulator
+
+public class TestArm64 {
+ public static EvalArm64 build(String file, int arg) throws IOException {
+ return build("src/test/java/com/seaofnodes/simple/progs",file, arg);
+ }
+
+ // Compile and run a simple program
+ public static EvalArm64 build(String dir, String file, int arg) throws IOException {
+ // Compile and export Simple
+ String src = Files.readString(Path.of(dir+"/"+file+".smp"));
+ CodeGen code = new CodeGen(src).driver(CodeGen.Phase.RegAlloc,"arm", "SystemV").encode(true);
+
+ // Image
+ byte[] image = new byte[1<<20]; // A megabyte (1024*1024 bytes)
+ EvalArm64 ARM = new EvalArm64(image, 1<<16);
+ // Code at offset 0
+ System.arraycopy(code._encoding.bits(), 0, image, 0, code._encoding.bits().length);
+ // Initial incoming int arg
+ ARM.regs[arm.D0] = arg;
+ // malloc memory starts at 64K and goes up
+ return ARM;
+ }
+}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestC.java b/chapter21/src/test/java/com/seaofnodes/simple/TestC.java
index 4294606c..8398c673 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/TestC.java
+++ b/chapter21/src/test/java/com/seaofnodes/simple/TestC.java
@@ -43,7 +43,6 @@ public abstract class TestC {
String obj = bin+".o";
// Compile simple, emit ELF
CodeGen code = new CodeGen(src).driver( CPU_PORT, simple_conv, obj);
-
// Compile the C program
var params = new String[] {
//if (USE_WSL) "wsl.exe";
@@ -77,6 +76,6 @@ public abstract class TestC {
System.err.println(result);
}
assertEquals( 0, error );
- assertEquals(expected,result);
+ assertEquals(expected,result.replace("\r",""));
}
}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp
new file mode 100644
index 00000000..20a05445
--- /dev/null
+++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/no_stack_arg_count.smp
@@ -0,0 +1,6 @@
+// -*- mode: java; -*-
+val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15 ->
+ return
+ i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 +
+ i10+f11+i12+f13+i14+f15;
+};