From a7a9069f29b112a355596756bc53cff73e597a3f Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 30 Mar 2025 16:12:49 -0700 Subject: 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. --- .../seaofnodes/simple/node/cpus/arm/SplitARM.java | 2 + .../seaofnodes/simple/node/cpus/riscv/AUIPC.java | 6 +-- .../seaofnodes/simple/node/cpus/riscv/FltRISC.java | 13 ++--- .../simple/node/cpus/riscv/LoadRISC.java | 7 +-- .../simple/node/cpus/riscv/MemOpRISC.java | 23 +------- .../simple/node/cpus/riscv/StoreRISC.java | 7 +-- .../seaofnodes/simple/node/cpus/riscv/riscv.java | 1 + .../simple/node/cpus/x86_64_v2/LoadX86.java | 63 ++++++---------------- .../simple/node/cpus/x86_64_v2/StoreX86.java | 10 ++-- .../simple/node/cpus/x86_64_v2/x86_64_v2.java | 21 +++----- 10 files changed, 51 insertions(+), 102 deletions(-) (limited to 'chapter21') 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 -- cgit v1.2.3