summaryrefslogtreecommitdiff
path: root/chapter21
diff options
context:
space:
mode:
Diffstat (limited to 'chapter21')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java7
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java56
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java5
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java3
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java35
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java36
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java31
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java35
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp12
11 files changed, 175 insertions, 51 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
index 64ea8201..f5d32dd2 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
@@ -308,16 +308,21 @@ public class CodeGen {
// ---------------------------
// Encoding
public int _tEncode;
+ public boolean _JIT;
public Encoding _encoding;
- public CodeGen encode() {
+ public CodeGen encode(boolean jit) {
assert _phase == Phase.RegAlloc;
_phase = Phase.Encoding;
long t0 = System.currentTimeMillis();
_encoding = new Encoding(this);
+ _JIT = jit;
_encoding.encode();
_tEncode = (int)(System.currentTimeMillis() - t0);
return this;
}
+ public CodeGen encode() {
+ return encode(false);
+ }
// Encoded binary, no relocation info
public byte[] binary() { return _encoding.bits(); }
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 223911ba..62bcfcde 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
@@ -228,6 +228,30 @@ public class ElfFile {
}
}
+ public final HashMap<Type, Symbol> _bigCons = new HashMap<>();
+ private void encodeConstants(SymbolSection symbols, DataSection rdata) {
+ int cnt = 0;
+ for (Map.Entry<Node,Type> e : _code._encoding._bigCons.entrySet()) {
+ if (_bigCons.get(e.getValue()) != null) {
+ continue;
+ }
+
+ Symbol glob = new Symbol("GLOB$"+cnt, rdata._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
+ glob._value = rdata._contents.size();
+ symbols.push(glob);
+
+ Type t = e.getValue();
+ if ( t instanceof TypeFloat tf ) {
+ write8(rdata._contents, Double.doubleToLongBits(tf._con));
+ } else {
+ throw Utils.TODO();
+ }
+
+ glob._size = rdata._contents.size() - glob._value;
+ _bigCons.put(e.getValue(), glob);
+ cnt++;
+ }
+ }
public void export(String fname) throws IOException {
DataSection strtab = new DataSection(".strtab", 3 /* SHT_SYMTAB */);
// first byte is reserved for an empty string
@@ -253,6 +277,8 @@ public class ElfFile {
// populate function symbols
encodeFunctions(symbols, text);
+ // populate big constants
+ encodeConstants(symbols, rdata);
int idx = 1;
for( Section s : _sections ) {
@@ -267,8 +293,9 @@ public class ElfFile {
int num = 1;
for( Symbol s : symbols._loc )
s._index = num++;
+ // extra space for .rela.text
int start_global = symbols._loc.size();
- for(Symbol a: symbols._symbols)
+ for(Symbol a: symbols._symbols) {
a._index = start_global++;
// create .text relocations
@@ -276,16 +303,31 @@ public class ElfFile {
for( Node n : _code._encoding._externals.keySet()) {
int nid = n._nid;
String extern = _code._encoding._externals.get(n);
- if(!extern.isEmpty()) throw Utils.TODO();
- // Todo: fix this up later when external functions will be in TU
- //int sym_id = _funcs.get(extern)._index;
- int sym_id = 0;
+
+ Symbol sym = new Symbol(extern, 0, SYM_BIND_GLOBAL, SYM_TYPE_NOTYPE);
+ sym._index = start_global++;
+ symbols.push(sym);
+
+ int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4;
+
+ // u64 offset
+ write8(text_rela._contents, offset);
+ // u64 info
+ write8(text_rela._contents, ((long)sym._index << 32L) | 4L /* PLT32 */);
+ // i64 addend
+ write8(text_rela._contents, -4);
+ }
+
+ // relocations to constants
+ for (Map.Entry<Node,Type> e : _code._encoding._bigCons.entrySet()) {
+ int nid = e.getKey()._nid;
+ int sym_id = _bigCons.get(e.getValue())._index;
int offset = _code._encoding._opStart[nid] + _code._encoding._opLen[nid] - 4;
// u64 offset
write8(text_rela._contents, offset);
// u64 info
- write8(text_rela._contents, ((long)sym_id << 32L) | 4L /* PLT32 */);
+ write8(text_rela._contents, ((long)sym_id << 32L) | 2L /* PC32 */);
// i64 addend
write8(text_rela._contents, -4);
}
@@ -295,7 +337,7 @@ public class ElfFile {
text_rela._info = text._index;
pushSection(text_rela);
- Symbol sym = new Symbol(text_rela._name, idx++, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
+ Symbol sym = new Symbol(text_rela._name, num, SYM_BIND_LOCAL, SYM_TYPE_SECTION);
sym._name_pos = text_rela._name_pos;
sym._size = text_rela.size();
symbols.push(sym);
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 0f9aac89..f90ce96a 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
@@ -151,9 +151,14 @@ public class Encoding {
// Record opcode start and length.
writeEncodings();
+ // ELF handles big constants, they
+ // are accessed by RIP-relative addressing.
+
+ if(_code._JIT) writeConstantPool(true);
// Short-form RIP-relative support: replace long encodings with short
// encodings and compact the code, changing all the offsets.
compactShortForm();
+
}
// Basic block layout: invert branches to keep blocks in-order; insert
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java
index 636c5a5f..8d4a2f71 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java
@@ -4,7 +4,7 @@ import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.*;
-// corresponds to slt (and NOT sltu, slti, sltiu)
+// corresponds to slt sltu
public class SetRISC extends MachConcreteNode implements MachNode {
final boolean _unsigned;
public SetRISC( Node cmp, boolean unsigned ) { super(cmp); _unsigned=unsigned; }
@@ -12,7 +12,7 @@ public class SetRISC extends MachConcreteNode implements MachNode {
@Override public RegMask regmap(int i) { return riscv.RMASK; }
@Override public RegMask outregmap() { return riscv.WMASK; }
@Override public void encoding( Encoding enc ) {
- riscv.r_type(enc,this,_unsigned ? 0b011 : 0x010,0);
+ riscv.r_type(enc,this,_unsigned ? 0b011 : 0b010,0);
}
@Override public void asm(CodeGen code, SB sb) {
sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" < ").p(code.reg(in(2)));
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
index f6f3474f..921fa336 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
@@ -15,13 +15,14 @@ public class CmpMemX86 extends MemOpX86 {
@Override public void encoding( Encoding enc ) {
// REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64
// CMP [mem], imm32
+
short ptr = enc.reg(ptr());
short idx = enc.reg(idx());
short src = enc.reg(val());
enc.add1(x86_64_v2.rex(src, ptr, idx));
// opcode varies by immediate
- enc.add1( src == -1 ? 0x39 : 0x81 );
+ enc.add1( src == -1 ? 0x81 : 0x39);
// includes modrm
x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 7 : src, enc);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
index 708269bd..c9df7b99 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
@@ -4,7 +4,7 @@ import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.*;
-public class FltX86 extends ConstantNode implements MachNode, RIPRelSize {
+public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{
private byte _encSize;
FltX86(ConstantNode con ) { super(con); }
@Override public String op() { return "ld8"; }
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java
index d6c977a5..6d6aa89c 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java
@@ -1,12 +1,39 @@
package com.seaofnodes.simple.node.cpus.x86_64_v2;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.codegen.CodeGen;
+import com.seaofnodes.simple.codegen.Encoding;
+import com.seaofnodes.simple.codegen.RegMask;
+import com.seaofnodes.simple.node.MachNode;
import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.*;
+
// Arithmetic Right Shift
-public class SarIX86 extends ImmX86 {
- SarIX86( Node add, int imm ) { super(add,imm); assert x86_64_v2.imm8(imm); }
+public class SarIX86 extends MachConcreteNode implements MachNode {
+ final int _imm;
+ SarIX86( Node sari, int imm ) { super(sari); assert x86_64_v2.imm8(imm); _inputs.pop(); _imm = imm; }
@Override public String op() { return "sari"; }
@Override public String glabel() { return ">>"; }
- @Override int opcode() { return 0xC1; }
- @Override int mod() { return 7; }
+ int opcode() { return 0xC1; }
+ int mod() { return 7; }
+
+ @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; }
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ @Override public void encoding(Encoding enc) {
+ short dst = enc.reg(this); // Also src1
+ enc.add1(x86_64_v2.rex(0, dst, 0));
+ enc.add1( opcode());
+
+ enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) );
+
+ // immediate(4 bytes) 32 bits or (1 byte)8 bits
+ if( x86_64_v2.imm8(_imm) ) enc.add1(_imm);
+ else enc.add4(_imm);
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm);
+ }
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java
index 35818a91..c53e0ea9 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java
@@ -2,10 +2,38 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.node.Node;
-public class ShlIX86 extends ImmX86 {
- ShlIX86( Node add, int imm ) { super(add,imm); }
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.*;
+
+public class ShlIX86 extends MachConcreteNode implements MachNode {
+ final int _imm;
+ ShlIX86( Node shli, int imm ) {
+ super(shli);
+ assert x86_64_v2.imm8(imm);
+ _inputs.pop(); // Pop constant input off
+ _imm = imm;
+ }
+ public int opcode() { return 0xC1; }
+ public int mod() { return 4; }
+
+ @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; }
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
@Override public String op() { return "shli"; }
@Override public String glabel() { return "<<"; }
- @Override int opcode() { return 0xC1; }
- @Override int mod() { return 4; }
+ @Override public void encoding(Encoding enc) {
+ short dst = enc.reg(this); // Also src1
+ enc.add1(x86_64_v2.rex(0, dst, 0));
+ enc.add1( opcode());
+
+ enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) );
+
+ // immediate(4 bytes) 32 bits or (1 byte)8 bits
+ if( x86_64_v2.imm8(_imm) ) enc.add1(_imm);
+ else enc.add4(_imm);
+ }
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm);
+ }
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java
index 0e96962b..c79b8817 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java
@@ -2,10 +2,33 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.node.Node;
-public class ShrIX86 extends ImmX86 {
- ShrIX86( Node add, int imm ) { super(add,imm); }
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.codegen.*;
+import com.seaofnodes.simple.node.*;
+
+public class ShrIX86 extends MachConcreteNode implements MachNode {
+ final int _imm;
+ ShrIX86( Node shri, int imm ) { super(shri); assert x86_64_v2.imm8(imm); _inputs.pop(); _imm = imm; }
@Override public String op() { return "shri"; }
@Override public String glabel() { return ">>>"; }
- @Override int opcode() { return 0xC1; }
- @Override int mod() { return 5; }
+ int opcode() { return 0xC1; }
+ int mod() { return 5; }
+
+ @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; }
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ @Override public void encoding(Encoding enc) {
+ short dst = enc.reg(this); // Also src1
+ enc.add1(x86_64_v2.rex(0, dst, 0));
+ enc.add1( opcode());
+
+ enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) );
+
+ // immediate(4 bytes) 32 bits or (1 byte)8 bits
+ if( x86_64_v2.imm8(_imm) ) enc.add1(_imm);
+ else enc.add4(_imm);
+ }
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm);
+ }
}
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 39048f2d..bf8f92ad 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
@@ -146,31 +146,24 @@ public class x86_64_v2 extends Machine {
public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) {
// Assume indirect
assert 0 <= base && base < 16;
- assert index != RSP;
+ assert -1 <= index && index < 16 && index != RSP;
MOD mod = MOD.INDIRECT;
// is 1 byte enough or need more?
if( offset != 0 )
mod = imm8(offset)
- ? MOD.INDIRECT_disp8
- : MOD.INDIRECT_disp32;
+ ? MOD.INDIRECT_disp8
+ : MOD.INDIRECT_disp32;
- // needs to pick optimal displacement mod if we want to encode base
- // when we only have base = RSP then we still need displacement added so ti becomes: [RSP+RSP*1+0x0]
- // RSP as index in this case is special and refers to: [base + disp8]
- if( mod == MOD.INDIRECT && (base == RBP || base == R13) )
+ if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) {
mod = MOD.INDIRECT_disp8;
+ } else if( index == -1 && (base == RSP || base == R12) ) {
+ index = RSP;
+ }
- // special encoding for [base +offset]
if( index == -1 ) {
- // Case for mov reg, [disp] (load)
- enc.add1(modrm(offset == 0 ? MOD.INDIRECT_disp8 : mod, reg, x86_64_v2.RSP));
- enc.add1(sib(scale, x86_64_v2.RSP, base));
- // special case
- // still add zero it is part of SIB byte
- if(offset == 0) enc.add1(offset);
+ enc.add1(modrm(mod, reg, base));
} else {
- // rsp is hard-coded here(0x04)
enc.add1(modrm(mod, reg, x86_64_v2.RSP));
enc.add1(sib(scale, index, base));
}
@@ -592,20 +585,20 @@ public class x86_64_v2 extends Machine {
}
private Node sar(SarNode sar) {
- if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
- return new SarIX86(sar, (int)(ti.value() & 0x03f) );
+ if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm8(ti.value()))
+ return new SarIX86(sar, (int)(ti.value() & 0xff) );
return new SarX86(sar);
}
private Node shl(ShlNode shl) {
- if( shl.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
- return new ShlIX86(shl, (int)(ti.value() & 0x03f) );
+ if( shl.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm8(ti.value()))
+ return new ShlIX86(shl, (int)(ti.value() & 0xff) );
return new ShlX86(shl);
}
private Node shr( ShrNode shr ) {
- if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
- return new ShrIX86(shr, (int)(ti.value() & 0x03f) );
+ if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm8(ti.value()) )
+ return new ShrIX86(shr, (int)(ti.value() & 0xff) );
return new ShrX86(shr);
}
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp
index b41fc26e..50419959 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp
+++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/newtonFloat.smp
@@ -1,11 +1,11 @@
// -*- mode: java; -*-
// Newtons approximation to the square root
-val sqrt = { flt x ->
- flt epsilon = 1e-57;
- flt guess = x;
- while( 1 ) {
+val test_sqrt = { flt x ->
+ flt epsilon = 1e-57;
+ flt guess = x;
+ while( 1 ) {
flt next = (x/guess + guess)/2;
if( guess-epsilon <= next & next <= guess+epsilon ) return guess;
guess = next;
- }
-};
+ }
+}; \ No newline at end of file