summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-03-18 11:22:07 -0700
committerCliff Click <cliffc@acm.org>2025-03-18 11:22:07 -0700
commite625a921d8fc9540a277e5becc8fe49b557c49fc (patch)
tree54d972fa23f15217009a190d57be11be1fbfb34d /chapter21/src/main/java/com
parentefc53c6d4b8d11cb08ba84800d85bc725b2f2d5b (diff)
downloadSimple-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')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/SB.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java6
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java54
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Machine.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/MachNode.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java5
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java11
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java10
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java27
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java1
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java51
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;
+ }
+
}