summaryrefslogtreecommitdiff
path: root/chapter21/src
diff options
context:
space:
mode:
Diffstat (limited to 'chapter21/src')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java6
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java45
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java4
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java9
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c17
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp46
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/progs/fib.c15
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/progs/fib.smp4
13 files changed, 139 insertions, 20 deletions
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 a66fc579..679329f7 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
@@ -337,6 +337,11 @@ public class Encoding {
slide += (newStart+15 & -16)-newStart;
}
_opStart[bb._nid] += slide;
+ for( Node n : bb._outputs ) {
+ if( n instanceof MachNode && !(n instanceof CFGNode) ) {
+ _opStart[n._nid] += slide;
+ }
+ }
if( bb instanceof RIPRelSize riprel ) {
CFGNode target = ((CFGNode)bb.out(0)).uctrlSkipEmpty();
// Delta is from opStart to opStart. X86 at least counts
@@ -355,7 +360,6 @@ public class Encoding {
}
}
-
// Copy/slide the bits to make space for all the longer branches
int grow = _opStart[_code._cfg.at(len-1)._nid] - oldStarts[len-1];
if( grow > 0 ) { // If no short-form ops, nothing to do here
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java
index e429a967..209f24f4 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java
@@ -11,7 +11,7 @@ public class AddFARM extends MachConcreteNode implements MachNode {
@Override public RegMask outregmap() { return arm.DMASK; }
//FADD (scalar)
- @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_ADD); }
+ @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);}
// Default on double precision for now(64 bits)
// General form: "addf rd = src1 + src2
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
index 6b2b03c3..e3d2de47 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
@@ -93,9 +93,10 @@ public class arm extends Machine {
// major opcode: OP
public static int OP_ADD = 0b10_001_011;
public static int OPF_ADD = 0b00_011_110;
+ public static int OPF_OP_ADD = 0b00_101_0;
public static int OPI_ADD = 0b10_010_00100;
- public static int OP_UJMP = 0b01010100;
+ public static int OP_UJMP = 0b000101;
public static int OP_ADRP = 0b10000;
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
index a97c6d10..e82a6f24 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
@@ -124,7 +124,7 @@ public class riscv extends Machine {
public static int OP_JAL = 0b11_011_11;
- // Since riscv instructions are fixed we can just or them togehter
+ // Since riscv instructions are fixed we can just or them together
public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) {
assert 0 <= rs1 && rs1 < 32;
assert 0 <= rs2 && rs2 < 32;
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
index 921fa336..f9cd597b 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
@@ -3,6 +3,8 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
public class CmpMemX86 extends MemOpX86 {
final boolean _invert; // Op switched LHS, RHS
@@ -20,16 +22,43 @@ public class CmpMemX86 extends MemOpX86 {
short idx = enc.reg(idx());
short src = enc.reg(val());
- enc.add1(x86_64_v2.rex(src, ptr, idx));
- // opcode varies by immediate
- enc.add1( src == -1 ? 0x81 : 0x39);
-
- // includes modrm
- x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 7 : src, enc);
-
- if( src == -1 ) enc.add4(_imm);
+ if(src == -1) {
+ int log = _declaredType.log_size();
+ x86_64_v2.rexF(-1, ptr, idx, log==3, enc);
+ switch(log) {
+ case 0: enc.add1(0x80); break;
+ case 1: enc.add1(0x66).add1(0x81); break;
+ case 2: enc.add1(0x81); break;
+ case 3: enc.add1(0x81); break;
+ }
+ x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc);
+ switch(log) {
+ case 0: enc.add1(_imm); break;
+ case 1: enc.add2(_imm); break;
+ case 2: enc.add4(_imm); break;
+ case 3: enc.add8(_imm); break;
+ }
+ } else {
+ encVal(enc, _declaredType, ptr, idx, src, _off, _scale);
+ }
}
+ static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale) {
+ if(decl instanceof TypeFloat) {
+ src -= (short)x86_64_v2.XMM_OFFSET;
+ enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2);
+ } else {
+ int log = decl.log_size();
+ x86_64_v2.rexF(src, ptr, idx, log == 3, enc);
+ switch(log) {
+ case 0: enc.add1(0x38); break;
+ case 1: enc.add1(0x66).add1(0x3B); break;
+ case 2: enc.add1(0x3B); break;
+ case 3: enc.add1(0x3B); break;
+ }
+ }
+ x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc);
+ }
// General form: "cmp dst = src, [base + idx<<2 + 12]"
@Override public void asm(CodeGen code, SB sb) {
String dst = code.reg(this);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java
index 906d0ce9..a97f3d9f 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java
@@ -23,7 +23,7 @@ public class MemAddX86 extends MemOpX86 {
enc.add1(x86_64_v2.rex(src, ptr, idx));
// opcode
- enc.add1( src == -1 ? 0x01 : 0x81 );
+ enc.add1( src == -1 ? 0x81: 0x01);
// includes modrm
x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
index cb2e58f9..8e3112cd 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
@@ -26,7 +26,7 @@ public class SplitX86 extends SplitNode {
// push rcx
// popf (Pop the top of the stack into the FLAGS register)
// 50+rd PUSH r64
- if( src >= 8 ) enc.add1(x86_64_v2.rexF(0,src,0,true, enc));
+ x86_64_v2.rexF(0,src,0,false,enc);
enc.add1(0x50 + src);
// popf
enc.add1(0x9D);
@@ -37,7 +37,7 @@ public class SplitX86 extends SplitNode {
// pushf; pop reg
enc.add1(0x9C);
// 58+ rd POP r64
- if( dst >= 8 ) enc.add1(x86_64_v2.rexF(0,dst,0,true, enc));
+ x86_64_v2.rexF(0,dst,0,false, enc);
enc.add1(0x58 + dst);
return;
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
index 4770bfbb..ea0ab27b 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
@@ -514,10 +514,10 @@ public class x86_64_v2 extends Machine {
Node rhs = bool.in(2);
// Vs memory
- if( lhs instanceof LoadNode ld && ld.nOuts() == 1 && ld._declaredType.log_size() >= 3 )
+ if( lhs instanceof LoadNode ld && ld.nOuts() == 1 && rhs._type.isa(ld._declaredType) )
return new CmpMemX86(bool, address(ld), ld.ptr(), idx, off, scale, imm(rhs), val, false);
- if( rhs instanceof LoadNode ld && ld.nOuts() == 1 && ld._declaredType.log_size() >= 3 )
+ if( rhs instanceof LoadNode ld && ld.nOuts() == 1 && lhs._type.isa(ld._declaredType))
return new CmpMemX86(bool, address(ld), ld.ptr(), idx, off, scale, imm(lhs), val, true );
// Vs immediate
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
index 170a7674..b3eb7679 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
+++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
@@ -93,4 +93,13 @@ public class Chapter21Test {
TestC.run("sieve",primes);
}
+ @Test public void testFibExport() throws IOException {
+ String fib = "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]";
+ TestC.run("fib", fib);
+ }
+
+ @Test public void testBrainFuck() throws IOException {
+ String brain_fuck = "Hello World!\n";
+ TestC.run("brain_fuck", brain_fuck);
+ }
}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c
new file mode 100644
index 00000000..9efc7d5b
--- /dev/null
+++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef struct AryInt {
+ unsigned int len;
+ unsigned char data[];
+} AryInt;
+
+extern AryInt* brain_fuck();
+
+int main() {
+ AryInt* ps = brain_fuck();
+
+ printf("%.*s", ps->len, ps->data);
+
+ return 0;
+} \ No newline at end of file
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp
new file mode 100644
index 00000000..69e63ba3
--- /dev/null
+++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.smp
@@ -0,0 +1,46 @@
+val brain_fuck = { ->
+u8[] !program = new u8[106];program[0] = 43;program[1] = 43;program[2] = 43;program[3] = 43;program[4] = 43;program[5] = 43;program[6] = 43;program[7] = 43;program[8] = 91;program[9] = 62;program[10] = 43;program[11] = 43;program[12] = 43;program[13] = 43;program[14] = 91;program[15] = 62;program[16] = 43;program[17] = 43;program[18] = 62;program[19] = 43;program[20] = 43;program[21] = 43;program[22] = 62;program[23] = 43;program[24] = 43;program[25] = 43;program[26] = 62;program[27] = 43;program[28] = 60;program[29] = 60;program[30] = 60;program[31] = 60;program[32] = 45;program[33] = 93;program[34] = 62;program[35] = 43;program[36] = 62;program[37] = 43;program[38] = 62;program[39] = 45;program[40] = 62;program[41] = 62;program[42] = 43;program[43] = 91;program[44] = 60;program[45] = 93;program[46] = 60;program[47] = 45;program[48] = 93;program[49] = 62;program[50] = 62;program[51] = 46;program[52] = 62;program[53] = 45;program[54] = 45;program[55] = 45;program[56] = 46;program[57] = 43;program[58] = 43;program[59] = 43;program[60] = 43;program[61] = 43;program[62] = 43;program[63] = 43;program[64] = 46;program[65] = 46;program[66] = 43;program[67] = 43;program[68] = 43;program[69] = 46;program[70] = 62;program[71] = 62;program[72] = 46;program[73] = 60;program[74] = 45;program[75] = 46;program[76] = 60;program[77] = 46;program[78] = 43;program[79] = 43;program[80] = 43;program[81] = 46;program[82] = 45;program[83] = 45;program[84] = 45;program[85] = 45;program[86] = 45;program[87] = 45;program[88] = 46;program[89] = 45;program[90] = 45;program[91] = 45;program[92] = 45;program[93] = 45;program[94] = 45;program[95] = 45;program[96] = 45;program[97] = 46;program[98] = 62;program[99] = 62;program[100] = 43;program[101] = 46;program[102] = 62;program[103] = 43;program[104] = 43;program[105] = 46;
+int d = 0;
+u8[] !output = new u8[0];
+u8[] !data = new u8[100];
+
+for( int pc = 0; pc < program#; pc++ ) {
+ var command = program[pc];
+ if (command == 62) {
+ d++;
+ } else if (command == 60) {
+ d--;
+ } else if (command == 43) {
+ data[d]++;
+ } else if (command == 45) {
+ data[d]--;
+ } else if (command == 46) {
+ // Output a byte; increase the output array size
+ var old = output;
+ output = new u8[output# + 1];
+ for( int i = 0; i < old#; i++ )
+ output[i] = old[i];
+ output[old#] = data[d]; // Add the extra byte on the end
+ } else if (command == 44) {
+ data[d] = 42;
+ } else if (command == 91) {
+ if (data[d] == 0) {
+ for( int d = 1; d > 0; ) {
+ command = program[++pc];
+ if (command == 91) d++;
+ if (command == 93) d--;
+ }
+ }
+ } else if (command == 93) {
+ if (data[d]) {
+ for( int d = 1; d > 0; ) {
+ command = program[--pc];
+ if (command == 93) d++;
+ if (command == 91) d--;
+ }
+ }
+ }
+}
+return output;
+};
+
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.c b/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.c
new file mode 100644
index 00000000..c18b5c23
--- /dev/null
+++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+
+extern int fib(int x);
+
+int main() {
+ printf("[");
+ for (int i = 0; i < 10; i++) {
+ printf("%d", fib(i));
+ if (i < 9) printf(", ");
+ }
+ printf("]");
+ return 0;
+} \ No newline at end of file
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.smp
index fd6ed218..1512541b 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.smp
+++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/fib.smp
@@ -8,6 +8,4 @@ val fib = {int n ->
f2=temp;
}
return f2;
-};
-
-fib(10);
+}; \ No newline at end of file