diff options
Diffstat (limited to 'chapter21/src')
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 |
