diff options
| author | Cliff Click <cliffc@acm.org> | 2025-03-18 11:22:07 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-03-18 11:22:07 -0700 |
| commit | e625a921d8fc9540a277e5becc8fe49b557c49fc (patch) | |
| tree | 54d972fa23f15217009a190d57be11be1fbfb34d /chapter21/src/main/java/com | |
| parent | efc53c6d4b8d11cb08ba84800d85bc725b2f2d5b (diff) | |
| download | Simple-e625a921d8fc9540a277e5becc8fe49b557c49fc.tar.gz Simple-e625a921d8fc9540a277e5becc8fe49b557c49fc.zip | |
changed relo ABI
Missing patch/merge from ARM ldst-encoding
Explicit external calls.
Better printing for multi-op template encodings
Diffstat (limited to 'chapter21/src/main/java/com')
20 files changed, 115 insertions, 78 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/SB.java b/chapter21/src/main/java/com/seaofnodes/simple/SB.java index 31fbb7d4..af49e52b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/SB.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/SB.java @@ -54,6 +54,7 @@ public final class SB { _sb.append( i < s.length() ? s.charAt(i) : ' '); return this; } + public char at(int idx ) { return _sb.charAt(idx); } // Not spelled "p" on purpose: too easy to accidentally say "p(1.0)" and // suddenly call the autoboxed version. @@ -93,6 +94,8 @@ public final class SB { // public SB unchar() { return unchar(1); } public SB unchar(int x) { _sb.setLength(_sb.length()-x); return this; } + public SB setLen(int len) { _sb.setLength(len); return this; } + public String subString(int start, int end ) { return _sb.substring(start,end); } public SB clear() { _sb.setLength(0); return this; } public int len() { return _sb.length(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java index c01eadd1..c39c5dc2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java @@ -284,10 +284,10 @@ public class ElfFile { // create .text relocations DataSection text_rela = new DataSection(".rela.text", 4 /* SHT_RELA */); - for( Node n : _code._encoding._externals) { + for( Node n : _code._encoding._externals.keySet()) { int nid = n._nid; - TypeFunPtr tfp = n instanceof CallNode call ? call.tfp() : (TypeFunPtr)n._type; - int sym_id = _funcs.get(tfp)._index; + String extern = _code._encoding._externals.get(n); + int sym_id = _funcs.get(extern)._index; int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4; // u64 offset 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 7cdbf1c8..56e5960a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -82,17 +82,31 @@ public class Encoding { // Nodes need "relocation" patching; things done after code is placed. - private final Ary<Node> _internals = new Ary<>(Node.class); - public final Ary<Node> _externals = new Ary<>(Node.class); + // Record src and dst Nodes. + private final HashMap<Node,CFGNode> _internals = new HashMap<>(); + // Source is a Call, destination in the Fun. public Encoding relo( CallNode call ) { - (call.external() ? _externals : _internals).add(call); + _internals.put(call,_code.link(call.tfp())); return this; } - public Encoding reloTFP( ConstantNode con ) { _internals.add(con); return this; } + public Encoding relo( ConstantNode con ) { + TypeFunPtr tfp = (TypeFunPtr)con._con; + _internals.put(con,_code.link(tfp)); + return this; + } + public void jump( CFGNode jmp, CFGNode dst ) { + while( dst.nOuts() == 1 ) // Skip empty blocks + dst = dst.uctrl(); + _internals.put(jmp,dst); + } - public void relo( NewNode nnn ) { - // TODO: record alloc relocation info + + final HashMap<Node,String> _externals = new HashMap<>(); + public Encoding external( Node call, String extern ) { + _externals.put(call,extern); + return this; } + // Store t as a 32/64 bit constant in the code space; generate RIP-relative // addressing to load it @@ -103,10 +117,6 @@ public class Encoding { // TODO: } - // Local relocation info for patching local jumps, once targets are known. - private final HashMap<CFGNode,CFGNode> _jmps = new HashMap<>(); - public void jump( CFGNode jmp, CFGNode target ) { _jmps.put(jmp,target); } - void encode() { // Basic block layout: invert branches to keep blocks in-order; insert // unconditional jumps. Attempt to keep backwards branches taken, @@ -286,27 +296,11 @@ public class Encoding { // Patch local encodings now private void patchLocalRelocations() { - // Walk all the jumps. Re-patch them all now with but with the Real Offset - for( CFGNode jmp : _jmps.keySet() ) { - CFGNode target = jmp instanceof IfNode iff ? iff.cproj(0) : jmp.uctrl(); - while( target.nOuts() == 1 ) // Skip empty blocks - target = target.uctrl(); - int start = _opStart[jmp._nid]; - ((RIPRelSize)jmp).patch(this, start, _opLen[jmp._nid], _opStart[target._nid] - start); - } - - // Walk the local code-address relocations - for( Node n : _internals ) { - TypeFunPtr tfp = n instanceof CallNode call ? call.tfp() : (TypeFunPtr)n._type; - FunNode fun = _code.link(tfp); - int start = _opStart[n._nid]; - ((RIPRelSize)n).patch(this, start, _opLen[n._nid], _opStart[fun._nid] - start); - } - - // Walk the external call relocations - for( Node call : _externals ) { - throw Utils.TODO(); + for( Node src : _internals.keySet() ) { + Node dst = _internals.get(src); + int start = _opStart[src._nid]; + ((RIPRelSize)src).patch(this, start, _opLen[src._nid], _opStart[dst._nid] - start); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java index 13d7abc1..fbc3f6c2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java @@ -7,6 +7,8 @@ abstract public class Machine { public abstract String name(); // Human-readable name for a register number, e.g. "RAX" or "R0" public abstract String reg( int reg ); + // Default opcode size for printing; 4 bytes for most 32-bit risc chips + public int defaultOpSize() { return 4; } // Create a split op; any register to any register, including stack slots public abstract SplitNode split( String kind, byte round, LRG lrg); // List of caller-save registers diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java index 5486b1c1..3fc6e031 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java @@ -52,6 +52,9 @@ public interface MachNode { // Just something like "R17=[R18+12] // Load array base". // General form: "dst=src+src". default void asm(CodeGen code, SB sb) { throw Utils.TODO(); } + // Multi-op encodings, printing 1 op per line. Template-style, + // no RA, no scheduling. + default void asm(CodeGen code, SB sb, int multiN) { } // Human readable opcode; e.g. "ld4" or "call". default String op() { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index b3384f21..c9f47ba5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -30,12 +30,11 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { - enc.jump(this,cproj(0)); // Assuming that condition flags are already set. These flags are set // by comparison (or sub). No need for regs because it uses flags + enc.jump(this,cproj(0)); // B.cond - int body = arm.b_cond(0b01010100, 0, arm.make_condition(_bop)); - enc.add4(body); + enc.add4( arm.b_cond(0b01010100, 0, arm.make_condition(_bop)) ); } // Delta is from opcode start diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index f09d208a..800ad34c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -18,7 +18,7 @@ public class LoadARM extends MemOpARM{ @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return arm.MEM_MASK; } // ldr(immediate - unsigned offset) | ldr(register) - @Override public void encoding( Encoding enc ) { arm.ldst_encode(enc,0b11111000010, this,this); } + @Override public void encoding( Encoding enc ) { ldst_encode(enc,0b11111000010,this); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(","); asm_address(code,sb); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index 922276d4..0987b7bf 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -47,6 +47,17 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { throw Utils.TODO(); } + // Shared encoding for loads and stores + public void ldst_encode( Encoding enc, int opcode, Node xval ) { + short ptr = enc.reg(ptr()); + short off = enc.reg(off()); + short val = enc.reg(xval ); + int body = off() == null + ? arm.load_str_imm(0b1111100101, off, ptr, val) + : arm.indr_adr(0b11111000011, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + enc.add4(body); + } + SB asm_address(CodeGen code, SB sb) { sb.p("[").p(code.reg(ptr())).p("+"); if( off() != null ) sb.p(code.reg(off())); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index 8ddf1bd6..8a465b66 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -14,9 +14,8 @@ public class NewARM extends NewNode implements MachNode { @Override public RegMask killmap() { return arm.armCallerSave(); } @Override public void encoding( Encoding enc ) { - enc.relo(this); // bl - enc.add4(arm.b(0b100101, 0)); + enc.external(this,"calloc").add4(arm.b(0b100101, 0)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 094348ce..e1fb592c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -21,7 +21,7 @@ public class StoreARM extends MemOpARM { } @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - @Override public void encoding( Encoding enc ) { arm.ldst_encode(enc,0b11111000000, this,val()); } + @Override public void encoding( Encoding enc ) { ldst_encode(enc,0b11111000000, val()); } @Override public void asm(CodeGen code, SB sb) { asm_address(code,sb).p(","); if( val()==null ) sb.p("#").p(_imm); 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 429148d2..0ba47317 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 @@ -14,7 +14,7 @@ public class TFPARM extends ConstantNode implements MachNode { @Override public boolean isClone() { return true; } @Override public TFPARM copy() { return new TFPARM(this); } @Override public void encoding( Encoding enc ) { - enc.reloTFP(this); + enc.relo(this); short self = enc.reg(this); // adrp x0, 0 int adrp = arm.adrp(1,0, 0b10000, 0,self); 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 a3f08730..d90ea15e 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 @@ -298,16 +298,6 @@ public class arm extends Machine { public static int load_str_imm(int opcode, int imm9, int ptr, int rt) { return (opcode << 21) | (imm9 << 12) |(1 << 10) |(ptr << 5) | rt; } - // Todo: provide op as binary here - public static void ldst_encode( Encoding enc, int opcode, MemOpARM n, Node xval ) { - short ptr = enc.reg(n.ptr()); - short off = enc.reg(n.off()); - short val = enc.reg(xval) ; - int body = n.off() == null - ? load_str_imm(0b1111100101, off, ptr, val) - : indr_adr(0b11111000011, off, STORE_LOAD_OPTION.SXTX, 0, ptr, val); - enc.add4(body); - } // encoding for vcvt, size is encoded in operand // <Qd>, <Qm> 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 244e0456..59075190 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 @@ -15,7 +15,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { @Override public AUIPC copy() { return new AUIPC((TypeFunPtr)_con); } @Override public String op() { return "auipc"; } @Override public void encoding( Encoding enc ) { - enc.reloTFP(this); + enc.relo(this); short dst = enc.reg(this); enc.add4(riscv.u_type(0x17, dst, 0)); } 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 2bdfc262..7d43e1ec 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 @@ -3,20 +3,14 @@ package com.seaofnodes.simple.node.cpus.riscv; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.print.ASMPrinter; public class NewRISC extends NewNode implements MachNode { // A pre-zeroed chunk of memory. - NewRISC( NewNode nnn, AUIPC auipc ) { - super(nnn); - _inputs.add(auipc); // Add high-half address - } + NewRISC( NewNode nnn ) { super(nnn); } @Override public String op() { return "alloc"; } - @Override public RegMask regmap(int i) { - if( i == 1 ) return riscv.A0_MASK; // Size input - // Last call input is AUIPC - if( i == nIns()-1 ) return riscv.RMASK; - // In-between are mem aliases? - return null; + @Override public RegMask regmap(int i) { + return i==1 ? riscv.A0_MASK : null; // Size input or mem aliases } @Override public RegMask outregmap(int i) { return i == 1 ? riscv.A0_MASK : null; } @Override public RegMask outregmap() { return null; } @@ -24,15 +18,16 @@ public class NewRISC extends NewNode implements MachNode { // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { - enc.relo(this); - // High half is where the TFP constant used to be, the last input - short auipc = enc.reg(in(nIns()-1)); - int body = riscv.i_type(0x67, riscv.RPC, 0, auipc, 0); - enc.add4(body); + // Generic external encoding; 2 ops. + enc.external(this,"calloc"); + // A1 is a caller-save, allowed to crush building external address + enc.add4(riscv.u_type(0x17, riscv.A1, 0)); + enc.add4(riscv.i_type(0x67, riscv.RPC, riscv.I_JALR, riscv.A1, 0)); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(size())).p(" ").p(code.reg(in(nIns()-1))); + sb.p("auipc a1=#calloc\n"); + sb.p("call a1+#calloc, a0"); } } 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 4b096e7b..873a07ce 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 @@ -14,7 +14,8 @@ public class TFPRISC extends ConstantNode implements MachNode { @Override public boolean isClone() { return true; } @Override public TFPRISC copy() { return new TFPRISC(this); } @Override public void encoding( Encoding enc ) { - enc.reloTFP(this); + enc.relo(this); + // TODO: 1 op encoding, plus a TODO if it does not fit short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; // auipc t0,0 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 e3cc8724..285b4583 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 @@ -384,7 +384,7 @@ public class riscv extends Machine { } private Node nnn(NewNode nnn) { // TODO: pass in the TFP for alloc - return new NewRISC(nnn, new AUIPC(null)); + return new NewRISC(nnn); } private Node cmp(BoolNode bool) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index 19ebcbcf..c846f341 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -17,7 +17,7 @@ public class NewX86 extends NewNode implements MachNode { // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { - enc.relo(this); + enc.external(this,"calloc"); // E8 cd CALL rel32; enc.add1(0xE8); enc.add4(0); // offset 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 6131fea6..13b9f8a3 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 @@ -35,7 +35,7 @@ public class TFPX86 extends ConstantNode implements MachNode { // lea to load function pointer address // lea rax, [rip+disp32] - enc.reloTFP(this); + enc.relo(this); enc.add1(x86_64_v2.rex(dst, 0, 0)); enc.add1(0x8D); // opcode enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); 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 ee0f89d6..20abb4e8 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 @@ -10,6 +10,7 @@ import java.io.ByteArrayOutputStream; public class x86_64_v2 extends Machine { // X86-64 V2. Includes e.g. SSE4.2 and POPCNT. @Override public String name() { return "x86_64_v2"; } + @Override public int defaultOpSize() { return 5; } public static int RAX = 0, RCX = 1, RDX = 2, RBX = 3, RSP = 4, RBP = 5, RSI = 6, RDI = 7; public static int R08 = 8, R09 = 9, R10 = 10, R11 = 11, R12 = 12, R13 = 13, R14 = 14, R15 = 15; 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 d511d8ad..9b0074c5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -1,7 +1,8 @@ package com.seaofnodes.simple.print; -import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeMem; import com.seaofnodes.simple.type.TypeRPC; @@ -38,10 +39,10 @@ public abstract class ASMPrinter { return iadr; } - static private final int encWidth = 10; static private final int opWidth = 5; static private final int argWidth = 30; static int doBlock(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) { + final int encWidth = code._mach.defaultOpSize()*2; CFGNode bb = code._cfg.at(cfgidx); if( bb != fun && !(bb instanceof IfNode) && !(bb instanceof CallEndNode) && !(bb instanceof CallNode) && !(bb instanceof CProjNode && bb.in(0) instanceof CallEndNode )) sb.p(label(bb)).p(":").nl(); @@ -84,6 +85,7 @@ public abstract class ASMPrinter { if( postAlloc && n instanceof CalleeSaveNode ) return iadr; if( postEncode && n instanceof ProjNode ) return iadr; if( n instanceof MemMergeNode ) return iadr; + final int encWidth = code._mach.defaultOpSize()*2; // All blocks ending in a Region will need to either fall into or jump // to this block. Until the post-reg-alloc block layout cleanup, we @@ -127,14 +129,16 @@ public abstract class ASMPrinter { sb.p(" "); // Op; generally "ld4" or "call" - sb.fix(opWidth, n instanceof MachNode mach ? mach.op() : n.label()); - sb.p(" "); + sb.fix(opWidth, n instanceof MachNode mach ? mach.op() : n.label()).p(" "); // General asm args + String isMultiOp = null; if( n instanceof MachNode mach ) { int old = sb.len(); mach.asm(code,sb); - sb.fix(argWidth-(sb.len()-old),""); // Pad out + int len = sb.len(); + isMultiOp = isMultiOp(sb,old,len); + sb.fix(argWidth-len,""); // Pad out } else if( !(n._type instanceof TypeMem) ) { // Room for some inputs @@ -155,8 +159,33 @@ public abstract class ASMPrinter { sb.nl(); + // Printing more op bits than fit + if( isMultiOp != null ) { + // Multiple ops, template style, no RA, no scheduling. Print out + // one-line-per-newline, with encoding bits up front. + int size = code._encoding._opLen[n._nid]; + int off = code._mach.defaultOpSize(); + while( isMultiOp!=null ) { + sb.hex2(iadr).p(" "); + int len = Math.min(off,size); + for( int i=0; i<len; i++ ) + sb.hex1(code._encoding._bits.buf()[iadr++]); + off += code._mach.defaultOpSize(); + sb.p(" "); + int x = isMultiOp.indexOf('\n'); + if( x== -1 ) { // Last line + sb.p(isMultiOp).nl(); + isMultiOp = null; + } else { + sb.p(isMultiOp.substring(0,x+1)); // Includes the newline + isMultiOp = isMultiOp.substring(x+1); + } + + } - if( fatEncoding > 0 ) { + } else if( fatEncoding > 0 ) { + // Extra bytes past the default encoding width, all put on a line by + // themselves. X86 special for super long encodings sb.hex2(iadr).p(" "); for( int i=0; i<fatEncoding; i++ ) sb.hex1(code._encoding._bits.buf()[iadr++]); @@ -179,4 +208,14 @@ public abstract class ASMPrinter { return (bb instanceof LoopNode ? "LOOP" : "L")+bb._nid; } + private static String isMultiOp(SB sb, int old, int len) { + for( int i=old; i<len; i++ ) + if( sb.at(i)=='\n' ) { + String s = sb.subString(i+1,len); + sb.setLen(i); + return s; + } + return null; + } + } |
