From b6cbd3d7b7698922e60e2c3eadadab51a430efe1 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 15 Mar 2025 12:06:11 -0700 Subject: Progress towards no crashes Multi-part constant expansion was buggy when splitting down into functions. Improved printing for RISC multi-part constants. --- .../src/main/java/com/seaofnodes/simple/SB.java | 24 +++++----- .../com/seaofnodes/simple/node/ConstantNode.java | 2 +- .../seaofnodes/simple/node/cpus/arm/MemOpARM.java | 2 +- .../simple/node/cpus/riscv/AddIRISC.java | 11 +++-- .../seaofnodes/simple/node/cpus/riscv/ImmRISC.java | 21 ++++++-- .../com/seaofnodes/simple/node/cpus/riscv/LUI.java | 10 ++-- .../seaofnodes/simple/node/cpus/riscv/NewRISC.java | 4 +- .../simple/node/cpus/riscv/StoreRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/riscv.java | 30 +++--------- .../com/seaofnodes/simple/print/ASMPrinter.java | 56 +++++++++------------- .../java/com/seaofnodes/simple/Chapter20Test.java | 2 +- 11 files changed, 79 insertions(+), 85 deletions(-) diff --git a/chapter21/src/main/java/com/seaofnodes/simple/SB.java b/chapter21/src/main/java/com/seaofnodes/simple/SB.java index 72649a39..31fbb7d4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/SB.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/SB.java @@ -29,23 +29,25 @@ public final class SB { public SB p( int s ) { _sb.append(s); return this; } public SB p( long s ) { _sb.append(s); return this; } public SB p( boolean s) { _sb.append(s); return this; } - // 2 hex digits - public SB hex2(int s) { + // 1 byte, 2 hex digits, 8 bits + public SB hex1(int s) { int digit = (s>>4) & 0xf; _sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit)); digit = s & 0xf; _sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit)); return this; } - // 4 hex digits - public SB hex4(int s) { - assert (s>>4*4)==0; // Fits in 16 bits - for( int i=0; i<4; i++ ) { - int digit = (s>>((3-i)*4)) & 0xf; - _sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit)); - } - return this; - } + // 2 bytes, 4 hex digits, 16 bits, Big Endian + public SB hex2(int s) { return hex1(s>> 8).hex1(s); } + // 4 bytes, 8 hex digits, 32 bits, Big Endian + public SB hex4(int s) { return hex2(s>>16).hex2(s); } + //public SB hex4(int s) { + //for( int i=0; i<8; i++ ) { + // int digit = (s>>((7-i)*4)) & 0xf; + // _sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit)); + //} + //return this; + // // Fixed width field public SB fix( int sz, String s ) { for( int i=0; i>20; // Sign extend 12 bits in(1)._print0(sb.append("( "), visited); - return sb.append(String.format(" %s #%d )",glabel(),_imm12)); + return sb.append(String.format(" %s #%d )",glabel(),imm12)); } abstract int opcode(); @@ -35,6 +47,9 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ").p(glabel()).p(" #").p(_imm12); + int imm12 = (_imm12<<20)>>20; // Sign extend 12 bits + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ").p(glabel()).p(" #").p(imm12); + if( in(1) instanceof LUI lui ) + sb.p(" // #").hex4((int)(((TypeInteger)lui._con).value()) + imm12); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 38e7e4b1..df0d6b4b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -8,14 +8,14 @@ import com.seaofnodes.simple.type.TypeInteger; // Load upper 20bits. public class LUI extends ConstantNode implements MachNode { - LUI( TypeInteger ti ) { - super(ti); - assert riscv.imm20Exact(ti); + LUI( int imm20 ) { + super(TypeInteger.constant(imm20)); + assert riscv.imm20Exact((TypeInteger)_con); } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return riscv.WMASK; } @Override public boolean isClone() { return true; } - @Override public LUI copy() { return new LUI((TypeInteger)_con); } + @Override public LUI copy() { return new LUI((int)((TypeInteger)_con).value()); } @Override public String op() { return "lui"; } @Override public void encoding( Encoding enc ) { long x = ((TypeInteger)_con).value(); @@ -27,6 +27,6 @@ public class LUI extends ConstantNode implements MachNode { @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); - _con.print(sb.p(reg).p(" = #")); + sb.p(reg).p(" = #").hex4((int)(((TypeInteger)_con).value())); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index 9b6eb98e..7002e0a8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -32,8 +32,8 @@ public class NewRISC extends NewNode implements MachNode { enc.add4(body); } - // General form: "alloc #bytes" + // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(size())); + sb.p(code.reg(size())).p(" ").p(code.reg(in(nIns()-1))); } } 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 b78eac1f..383e37b5 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 @@ -23,7 +23,7 @@ public class StoreRISC extends MemOpRISC { @Override public String op() { return "st"+_sz; } @Override public RegMask regmap(int i) { // 0 - ctrl - // 1 - mem + if( i==1 ) return null; // mem if( i==2 ) return riscv.RMASK; // ptr // 2 - index if( i==4 ) return riscv.MEM_MASK; // Wide mask to store GPR and FPR 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 16b09172..fcea5e28 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 @@ -202,24 +202,6 @@ public class riscv extends Machine { }; } - public static void push_4_bytes(int value, ByteArrayOutputStream bytes) { throw Utils.TODO(); } - -// public static void print_as_hex(ByteArrayOutputStream outputStream) { -// StringBuilder hexString = new StringBuilder(); -// for (byte b : outputStream.toByteArray()) { -// hexString.append(String.format("%02X", b)); // Format as uppercase hex without space -// } -// System.out.println(hexString.toString()); -// } - -// // rs1 - rs2 -// public static int r_source(int rs1, int rs2) { -// return (rs2 << 4) | rs1; -// } -// public static int r_func7(int f) { -// return f & 7; -// } - static RegMask callInMask( TypeFunPtr tfp, int idx ) { if( idx==0 ) return RPC_MASK; if( idx==1 ) return null; @@ -363,7 +345,7 @@ public class riscv extends Machine { private Node add(AddNode add) { if( add.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && imm12(ti) ) - return new AddIRISC(add, (int)ti.value()); + return new AddIRISC(add, (int)ti.value(),true); return new AddRISC(add); } @@ -427,13 +409,15 @@ public class riscv extends Machine { return switch( con._con ) { case TypeInteger ti -> { if( imm12(ti) ) yield new IntRISC(con); - if( imm20Exact(ti) ) yield new LUI(ti); long x = ti.value(); - if( (x<<32)>>32 == x ) // Signed lower 32-bit immediate + if( imm20Exact(ti) ) yield new LUI((int)x); + if( (x<<32)>>32 == x ) { // Signed lower 32-bit immediate // Here, the low 12 bits get sign-extended, which means if // bit11 is set, the value is negative and lowers the LUI // value. Add a bit 12 to compensate - yield new AddIRISC(new LUI(((x>>11)&1)==1 ? TypeInteger.constant(x+0x1000) : ti), (int)(x & 0xFFF)); + if( ((x>>11)&1)==1 ) x += 0x1000; + yield new AddIRISC(new LUI((int)(x & ~0xFFF)), (int)(x & 0xFFF),false); + } // Need more complex sequence for larger constants... or a load // from a constant pool, which does not need an extra register throw Utils.TODO(); @@ -489,7 +473,7 @@ public class riscv extends Machine { private Node sub(SubNode sub) { return sub.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm12(ti) && imm12(ti) - ? new AddIRISC(sub, (int)(-ti.value())) + ? new AddIRISC(sub, (int)(-ti.value()),true) : new SubRISC(sub); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java index 77d891a2..55a45a32 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -48,44 +48,32 @@ public abstract class ASMPrinter { if( bb instanceof CallNode ) return iadr; final boolean postAlloc = code._phase.ordinal() > CodeGen.Phase.RegAlloc.ordinal(); - // Count Phis - int nPhi=0; - for( ; nPhi0 ) { - // Post- RegAlloc phi prints all on one line + boolean once=false; + for( Node n : bb.outs() ) { + if( !(n instanceof PhiNode phi) ) continue; + if( phi._type instanceof TypeMem || phi._type instanceof TypeRPC ) continue; // Nothing for the hidden ones + // Post-RegAlloc phi prints all on one line if( postAlloc ) { - sb.fix(4," ").p(" ").fix(encWidth,"").p(" "); - for( int i=0; i