summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'chapter21/src/main/java')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java25
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java7
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java23
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java37
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java23
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java12
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java19
8 files changed, 139 insertions, 11 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 67eeb3c2..0162bc84 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
@@ -53,6 +53,10 @@ public class Encoding {
public Encoding add1( int op ) { _bits.write(op); return this; }
+ public void add2( int op ) {
+ _bits.write(op );
+ _bits.write(op>> 8);
+ }
// Little endian write of a 32b opcode
public void add4( int op ) {
_bits.write(op );
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java
index 0ba47317..f42dae75 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java
@@ -4,9 +4,10 @@ import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.ConstantNode;
import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.cpus.riscv.riscv;
import com.seaofnodes.simple.type.TypeFunPtr;
-public class TFPARM extends ConstantNode implements MachNode {
+public class TFPARM extends ConstantNode implements MachNode, RIPRelSize {
TFPARM( ConstantNode con ) { super(con); }
@Override public String op() { return "ldx"; }
@Override public RegMask regmap(int i) { return null; }
@@ -22,6 +23,28 @@ public class TFPARM extends ConstantNode implements MachNode {
arm.imm_inst(enc,this,0b1001000100,0);
enc.add4(adrp);
}
+
+ @Override public byte encSize(int delta) {
+ if( -(1L<<12) <= delta && delta < (1L<<12) ) return 4;
+ throw Utils.TODO();
+ }
+
+ // Delta is from opcode start
+ @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
+ short rpc = enc.reg(this);
+ if(opLen ==4 ) {
+ // opstart of add
+ int next = opStart + opLen;
+ int adrp_delta = delta >> 12;
+ // patch upper 20 bits via adrp
+ enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc));
+ // low 12 bits via add
+ enc.patch4(next, arm.imm_inst_l(enc, this, 0b1001000100, delta & 0xfff));
+ } else {
+ throw Utils.TODO();
+ }
+ }
+
@Override public void asm(CodeGen code, SB sb) {
String reg = code.reg(this);
_con.print(sb.p(reg).p(" #"));
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 b35f600a..4b0781f2 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
@@ -224,6 +224,13 @@ public class arm extends Machine {
enc.add4(body);
}
+ public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) {
+ short self = enc.reg(n);
+ short reg1 = enc.reg(n.in(1));
+ int body = imm_inst(opcode, imm12&0xFFF, reg1, self);
+ return body;
+ }
+
// for normal add, reg1, reg2 cases (reg-to-reg)
// using shifted-reg form
public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) {
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java
index 873a07ce..6cb219df 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java
@@ -6,7 +6,7 @@ import com.seaofnodes.simple.node.ConstantNode;
import com.seaofnodes.simple.node.MachNode;
import com.seaofnodes.simple.type.TypeFunPtr;
-public class TFPRISC extends ConstantNode implements MachNode {
+public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize {
TFPRISC(ConstantNode con) { super(con); }
@Override public String op() { return "ldx"; }
@Override public RegMask regmap(int i) { return null; }
@@ -26,6 +26,27 @@ public class TFPRISC extends ConstantNode implements MachNode {
enc.add4(addi);
}
+ @Override public byte encSize(int delta) {
+ if( -(1L<<11) <= delta && delta < (1L<<11) ) return 4;
+ throw Utils.TODO();
+ }
+
+ // Delta is from opcode start
+ @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
+ short rpc = enc.reg(this);
+ if( opLen==4 ) {
+ // AUIPC (upper 20 bits)
+ // opstart of add
+ int next = opStart + opLen;
+ enc.patch4(opStart,riscv.u_type(0b0010111, rpc, delta));
+ // addi(low 12 bits)
+ enc.patch4(next,riscv.i_type(0b0010011, rpc, 0, rpc, delta & 0xFFF));
+ // addi
+ } else {
+ throw Utils.TODO();
+ }
+ }
+
@Override public void asm(CodeGen code, SB sb) {
_con.print(sb.p(code.reg(this)).p(" #"));
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
index 39525ed1..6dd3e3dc 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
@@ -4,6 +4,8 @@ import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.LoadNode;
import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
public class LoadX86 extends MemOpX86 {
LoadX86( LoadNode ld, Node base, Node idx, int off, int scale ) {
@@ -13,11 +15,42 @@ public class LoadX86 extends MemOpX86 {
@Override public RegMask outregmap() { return x86_64_v2.MEM_MASK; }
@Override public void encoding( Encoding enc ) {
// REX.W + 8B /r MOV r64, r/m64
+ // Zero extension for u8, u16 and u32 but sign extension i8, i16, i32
+ // Use movsx and movzx
+
short dst = enc.reg(this );
short ptr = enc.reg(ptr());
short idx = enc.reg(idx());
- enc.add1(x86_64_v2.rex(dst, ptr, idx));
- enc.add1(0x8B); // opcode
+ if (_declaredType != TypeInteger.U32) {
+ enc.add1(x86_64_v2.rex(dst, ptr, idx));
+ }
+
+ if(_declaredType == TypeInteger.I8) {
+ // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8
+ enc.add1(0x0F);
+ enc.add1(0xBE);
+ } else if(_declaredType == TypeInteger.I16) {
+ // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16
+ enc.add1(0x0F);
+ enc.add1(0xBF);
+ } else if(_declaredType == TypeInteger.I32) {
+ // sign extend: REX.W + 63 /r MOVSXD r64, r/m32
+ enc.add1(0x63);
+ } else if(_declaredType == TypeInteger.U8) {
+ // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8
+ enc.add1(0x0F);
+ enc.add1(0xB6);
+ } else if(_declaredType == TypeInteger.U16) {
+ // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16
+ enc.add1(0x0F);
+ enc.add1(0xB7);
+ } else if(_declaredType == TypeInteger.U32) {
+ // zero extend: 8B /r MOV r32, r/m32
+ enc.add1(0x8B);
+ } else if(_declaredType == TypeInteger.BOT) {
+ // REX.W + 8B /r MOV r64, r/m64
+ enc.add1(0x8B);
+ }
// includes modrm internally
x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
index 4a54663d..8c2e0612 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
@@ -2,6 +2,7 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.ConstantNode;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.StoreNode;
import java.util.BitSet;
@@ -27,13 +28,27 @@ public class StoreX86 extends MemOpX86 {
short idx = enc.reg(idx());
short src = enc.reg(val());
- enc.add1(x86_64_v2.rex(src, ptr, idx));
+ int imm_op = x86_64_v2.selectOpcodeForImmStore(_imm);
+ if(src == -1 && _imm != 0) {
+ if(imm_op == -1) {enc.add1(x86_64_v2.rex(src, ptr, idx));enc.add1(0xC7); }
+ else enc.add1(imm_op);
+ } else {
- // switch on opcode depending on instruction
- enc.add1( src == -1 ? 0xC7 : 0x89 );
+ if(_declaredType.log_size() == 0) enc.add1(0x88);
+ if(_declaredType.log_size() == 1) enc.add1(0x89);
+ if(_declaredType.log_size() == 2) enc.add1(0x89);
+ if(_declaredType.log_size() == 3) {enc.add1(x86_64_v2.rex(src, ptr, idx)); enc.add1(0x89);}
+ }
x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc);
- if( src == -1 ) enc.add4(_imm);
+ if( src == -1 ) {
+ switch (x86_64_v2.imm_size(_imm)) {
+ case 8: enc.add1(_imm); break;
+ case 16: enc.add2(_imm); break;
+ case 32: enc.add4(_imm); break;
+ case 64: enc.add8(_imm); break;
+ }
+ }
}
// General form: "stN [base + idx<<2 + 12],val"
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
index 13b9f8a3..be4d1a83 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
@@ -3,11 +3,12 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.riscv.riscv;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFunPtr;
// Function constants
-public class TFPX86 extends ConstantNode implements MachNode {
+public class TFPX86 extends ConstantNode implements MachNode, RIPRelSize {
TFPX86( ConstantNode con ) { super(con); }
@Override public String op() {
return _con == Type.NIL ? "xor" : "ldx";
@@ -42,6 +43,15 @@ public class TFPX86 extends ConstantNode implements MachNode {
enc.add4(0);
}
+ @Override public byte encSize(int delta) {
+ return 7;
+ }
+
+ // Delta is from opcode start
+ @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
+ enc.patch4(opStart + 3, delta - 7);
+ }
+
// Human-readable form appended to the SB. Things like the encoding,
// indentation, leading address or block labels not printed here.
// Just something like "ld4\tR17=[R18+12] // Load array base".
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 9d7b1a26..1d30bc4b 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
@@ -109,6 +109,20 @@ public class x86_64_v2 extends Machine {
if( 8 <= idx && idx <= 15 ) rex |= 0b00000010; // REX.X
return rex;
}
+ // return opcode for optimised immediate store
+ public static int selectOpcodeForImmStore(long imm) {
+ if(imm8(imm)) return 0xC6;
+ if(imm16(imm)) return 0xC7;
+ if(imm32(imm)) return 0xC7;
+ return -1;
+ }
+ // return the size of the immediate
+ public static int imm_size(long imm) {
+ if(imm8(imm)) return 8;
+ if(imm16(imm)) return 16;
+ if(imm32(imm)) return 32;
+ return 64;
+ }
public static int rex(int reg, int ptr, int idx) {
return rex(reg, ptr, idx, true);
@@ -410,16 +424,17 @@ public class x86_64_v2 extends Machine {
}
public static boolean imm8( long imm ) { return -128 <= imm && imm <= 127; }
+ public static boolean imm16(long imm) {return -32768 <= imm && imm <= 32767; }
public static boolean imm32( long imm ) { return (int)imm==imm; }
// Attempt a full LEA-style break down.
private Node add(AddNode add) {
Node lhs = add.in(1);
Node rhs = add.in(2);
- if( lhs instanceof LoadNode ld && ld.nOuts() == 1 )
+ if( lhs instanceof LoadNode ld && ld.nOuts() == 1 && ld._declaredType.log_size() >= 3)
return new AddMemX86(add, address(ld), ld.ptr(), idx, off, scale, imm(rhs), val);
- if(rhs instanceof LoadNode ld && ld.nOuts() == 1)
+ if(rhs instanceof LoadNode ld && ld.nOuts() == 1 && ld._declaredType.log_size() >= 3)
throw Utils.TODO(); // Swap load sides
// Attempt a full LEA-style break down.