summaryrefslogtreecommitdiff
path: root/chapter21
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-03-30 16:12:49 -0700
committerCliff Click <cliffc@acm.org>2025-03-30 16:12:49 -0700
commita7a9069f29b112a355596756bc53cff73e597a3f (patch)
tree21b379f81fbe67969ca1365d9c2e388fdadcbbbf /chapter21
parentaea468c0b09891f89a8346de7bb37982f7767c2b (diff)
downloadSimple-a7a9069f29b112a355596756bc53cff73e597a3f.tar.gz
Simple-a7a9069f29b112a355596756bc53cff73e597a3f.zip
Pass new reg asserts
Handle -1 reg in X86 in several places. SplitARM Float spills still wrong, but less wrong. Cleanup RISC load/store handling.
Diffstat (limited to 'chapter21')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java6
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java13
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java7
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java23
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java7
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java1
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java63
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java10
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java21
10 files changed, 51 insertions, 102 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java
index bf90703a..684cc167 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java
@@ -24,6 +24,7 @@ public class SplitARM extends SplitNode {
throw Utils.TODO();
}
int off = enc._fun.computeStackSlot(dst - arm.MAX_REG)*8;
+ if( srcX ) src -= arm.D_OFFSET;
enc.add4(arm.load_str_imm(arm.OP_STORE_IMM, off, arm.RSP, src));
return;
}
@@ -31,6 +32,7 @@ public class SplitARM extends SplitNode {
if(src >= arm.MAX_REG) {
// Load from SP
int off = enc._fun.computeStackSlot(src - arm.MAX_REG) * 8;
+ if( dstX ) dst -= arm.D_OFFSET;
enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM, off, arm.RSP, dst));
return;
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java
index 8563a010..37383608 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java
@@ -4,15 +4,15 @@ 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.type.TypeFunPtr;
+import com.seaofnodes.simple.type.Type;
// Add upper 20bits to PC. Immediate comes from the relocation info.
public class AUIPC extends ConstantNode implements MachNode, RIPRelSize {
- AUIPC( TypeFunPtr tfp ) { super(tfp); }
+ AUIPC( Type tfp ) { super(tfp); }
@Override public RegMask regmap(int i) { return null; }
@Override public RegMask outregmap() { return riscv.WMASK; }
@Override public boolean isClone() { return true; }
- @Override public AUIPC copy() { return new AUIPC((TypeFunPtr)_con); }
+ @Override public AUIPC copy() { return new AUIPC(_con); }
@Override public String op() { return "auipc"; }
@Override public void encoding( Encoding enc ) {
enc.relo(this);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
index ae4a3dbe..d1bd4a94 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
@@ -18,13 +18,13 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize {
@Override public void encoding( Encoding enc ) {
enc.largeConstant(this,_con);
short dst = (short)(enc.reg(this) - riscv.F_OFFSET);
+ short tmp = (short)riscv.T6;
// AUIPC dst,#hi20_constant_pool
- enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0));
+ enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0));
// Load dst,[dst+#low12_constant_pool]
- enc.add4(riscv.i_type(riscv.OP_LOAD, dst, 0b11, dst, 0));
- // Need a GPR for AUIPC, but dst is a FPR
- throw Utils.TODO();
+ enc.add4(riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, 0));
}
+ @Override public RegMask killmap() { return new RegMask(riscv.T6); }
// Delta is from opcode start.
// TODO: always size 8?
@@ -33,10 +33,11 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize {
// Delta is from opcode start
@Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
short dst = (short)(enc.reg(this) - riscv.F_OFFSET);
+ short tmp = (short)riscv.T6;
// AUIPC dst,#hi20_constant_pool
- enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, delta));
+ enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta));
// Load dst,[dst+#low12_constant_pool]
- enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, dst, delta));
+ enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, delta));
}
@Override public void asm(CodeGen code, SB sb) {
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java
index ef953d10..7b0e9138 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java
@@ -15,10 +15,11 @@ public class LoadRISC extends MemOpRISC {
@Override public RegMask regmap(int i) { return riscv.RMASK; }
@Override public RegMask outregmap() { return riscv.MEM_MASK; }
@Override public void encoding( Encoding enc ) {
- short dst = xreg(enc);
+ short dst = enc.reg(this );
short ptr = enc.reg(ptr());
- int body = riscv.i_type(opcode(enc), dst, func3(), ptr, _off);
- enc.add4(body);
+ int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD;
+ if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET;
+ enc.add4(riscv.i_type(op, dst, func3(), ptr, _off));
}
@Override public void asm(CodeGen code, SB sb) {
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
index 239a2c5e..de8048a6 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
@@ -9,7 +9,7 @@ import java.util.BitSet;
public abstract class MemOpRISC extends MemOpNode implements MachNode {
final int _off; // Limit 12 bits
- final char _sz = (char)('0'+(1<<_declaredType.log_size()));
+ final char _sz;
MemOpRISC(MemOpNode mop, Node base, int off, Node val) {
super(mop,mop);
assert base._type instanceof TypeMemPtr;
@@ -17,6 +17,7 @@ public abstract class MemOpRISC extends MemOpNode implements MachNode {
_inputs.setX(3, null); // Never an index
_inputs.setX(4, val );
_off = off;
+ _sz = (char)('0'+(1<<_declaredType.log_size()));
}
@Override public String label() { return op(); }
@@ -54,26 +55,6 @@ public abstract class MemOpRISC extends MemOpNode implements MachNode {
return func3;
}
- // 7 bits, 00 000 11 or 00 001 11 for FP
- int opcode(Encoding enc) {
- boolean isStore = this instanceof StoreRISC;
- boolean isLoad = this instanceof LoadRISC;
- short reg = enc.reg(isStore? val(): this);
- assert reg != -1;
- boolean isFloat = enc.reg(val()) >= riscv.F_OFFSET;
-
- if (isStore) return isFloat ? 39 : 35;
- if (isLoad) return isFloat ? 7 : 3;
-
- return 0;
- }
- short xreg(Encoding enc) {
- boolean isStore = this instanceof StoreRISC;
- short xreg = enc.reg(isStore? val() : this );
- assert xreg != -1;
- return xreg < riscv.F_OFFSET ? xreg : (short)(xreg-riscv.F_OFFSET);
- }
-
// Register mask allowed on input i.
@Override public RegMask regmap(int i) {
// 0 - ctrl
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java
index 1741340e..822e67b0 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java
@@ -32,10 +32,11 @@ public class StoreRISC extends MemOpRISC {
@Override public RegMask outregmap() { return null; }
@Override public void encoding( Encoding enc ) {
- short val = xreg(enc);
+ short val = enc.reg(val());
short ptr = enc.reg(ptr());
- int body = riscv.s_type(opcode(enc), func3()&7, ptr, val, _off);
- enc.add4(body);
+ int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE;
+ if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET;
+ enc.add4(riscv.s_type(op, func3()&7, ptr, val, _off));
}
@Override public void asm(CodeGen code, SB sb) {
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 93b18a01..9ac6fe79 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
@@ -485,6 +485,7 @@ public class riscv extends Machine {
// from a constant pool, which does not need an extra register
throw Utils.TODO();
}
+ // Load from constant pool
case TypeFloat tf -> new FltRISC(con);
case TypeFunPtr tfp -> new TFPRISC(con);
case TypeMemPtr tmp -> throw Utils.TODO();
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 4afff149..71085971 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
@@ -24,56 +24,23 @@ public class LoadX86 extends MemOpX86 {
short ptr = enc.reg(ptr());
short idx = enc.reg(idx());
- if (_declaredType != TypeInteger.U32 && _declaredType != TypeFloat.F32 && _declaredType != TypeFloat.F64) {
- enc.add1(x86_64_v2.rex(dst, ptr, idx == -1 ? 0: idx));
- }
+ if( _declaredType != TypeInteger.U32 && _declaredType != TypeFloat.F32 && _declaredType != TypeFloat.F64 )
+ enc.add1(x86_64_v2.rex(dst, ptr, idx));
- if(_declaredType instanceof TypeMemPtr) {
- throw Utils.TODO();
- }
-
- else if(_declaredType == TypeFloat.F32) {
- // F3 0F 10 /r MOVSS xmm1, m32
- enc.add1(0xF3);
- enc.add1(0x0F);
- enc.add1(0x10);
- dst -= (short)x86_64_v2.XMM_OFFSET;
- }
- else if(_declaredType == TypeFloat.F64) {
- // F2 0F 10 /r MOVSD xmm1, m64
- enc.add1(0xF2);
- enc.add1(0x0F);
- enc.add1(0x10);
+ if( _declaredType.isa(TypeFloat.F64) )
dst -= (short)x86_64_v2.XMM_OFFSET;
- }
- else 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);
- } else {
- throw Utils.TODO();
- }
+
+ if( false ) ;
+ else if( _declaredType == TypeFloat.F32 ) enc.add1(0xF3).add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32
+ else if( _declaredType == TypeFloat.F64 ) enc.add1(0xF2).add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64
+ else if( _declaredType == TypeInteger.I8 ) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8
+ else if( _declaredType == TypeInteger.I16) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16
+ else if( _declaredType == TypeInteger.I32) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32
+ else if( _declaredType == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8
+ else if( _declaredType == TypeInteger.U16) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16
+ // Covers U32, I64/BOT, TMP
+ else if( _declaredType.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32
+ else throw Utils.TODO();
// 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 aa2bd9b5..52e4660d 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
@@ -30,11 +30,11 @@ public class StoreX86 extends MemOpX86 {
short idx = enc.reg(idx());
short src = enc.reg(val());
- 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);
+ if( src == -1 && _imm != 0 ) {
+ // return opcode for optimised immediate store
+ if( x86_64_v2.imm8(_imm) ) enc.add1(0xC6);
+ else if( x86_64_v2.imm32(_imm) ) enc.add1(0xC7);
+ else enc.add1(x86_64_v2.rex(-1, ptr, idx)).add1(0xC7);
} else {
if(_declaredType == TypeFloat.F32) {src -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0xF3); enc.add1(0x0F); enc.add1(0x11);}
else if(_declaredType == TypeFloat.F64) {src -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0xF2); enc.add1(0x0F); enc.add1(0x11);}
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 58f130a8..69cb59aa 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
@@ -85,6 +85,7 @@ public class x86_64_v2 extends Machine {
}
public static int modrm(MOD mod, int reg, int m_r) {
+ if( reg == -1 ) reg=0; // Missing reg in this flavor
// combine all the bits
assert 0 <= reg && reg < 16;
assert 0 <= m_r && m_r < 16;
@@ -107,23 +108,17 @@ public class x86_64_v2 extends Machine {
// 0 denotes no direct register
public static int rex(int reg, int ptr, int idx, boolean wide) {
// assuming 64 bit by default so: 0100 1000
- assert 0 <= reg && reg < 16;
- assert 0 <= ptr && ptr < 16;
+ assert -1 <= reg && reg < 16;
+ assert -1 <= ptr && ptr < 16;
assert -1 <= idx && idx < 16;
int rex = wide ? REX_W : REX;
- if( 8 <= reg && reg <= 15 ) rex |= 0b00000100; // REX.R
- if( 8 <= ptr && ptr <= 15 ) rex |= 0b00000001; // REX.B
- if( 8 <= idx && idx <= 15 ) rex |= 0b00000010; // REX.X
+ if( 8 <= reg ) rex |= 0b00000100; // REX.R
+ if( 8 <= ptr ) rex |= 0b00000001; // REX.B
+ if( 8 <= idx ) 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;
@@ -169,7 +164,7 @@ public class x86_64_v2 extends Machine {
// special encoding for [base +offset]
if( index == -1 ) {
// Case for mov reg, [disp] (load)
- enc.add1(modrm(offset == 0 ? MOD.INDIRECT_disp8 : mod, reg == -1 ? 0 : reg, x86_64_v2.RSP));
+ enc.add1(modrm(offset == 0 ? MOD.INDIRECT_disp8 : mod, reg, x86_64_v2.RSP));
enc.add1(x86_64_v2.sib(scale, x86_64_v2.RSP, base));
// special case
// still add zero it is part of SIB byte