diff options
| author | Cliff Click <cliffc@acm.org> | 2025-04-15 19:41:55 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-04-15 19:41:55 -0700 |
| commit | 2a3b2d4d4bc6099ab9fead00cfaa3f0a8e6aeb9f (patch) | |
| tree | 6a94bfc5734ba84497083d233281a569ffe0c67f /chapter21 | |
| parent | 2fb0ec312d76f22534331023c86e68b7a62b98e6 (diff) | |
| download | Simple-2a3b2d4d4bc6099ab9fead00cfaa3f0a8e6aeb9f.tar.gz Simple-2a3b2d4d4bc6099ab9fead00cfaa3f0a8e6aeb9f.zip | |
R5 fcmp, flt load from pool
exportELF(null) now patches the cpool entries as well as globals.
Repeated cpool entries folded.
Fixed FltRISC, FCMP encoding.
Diffstat (limited to 'chapter21')
10 files changed, 90 insertions, 96 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 146c016a..2e1a4709 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -379,17 +379,16 @@ public class CodeGen { public int _tEncode; public Encoding _encoding; // Encoding object public void preEncode() { } // overridden by alternative ports - public CodeGen encode(boolean jit) { + public CodeGen encode() { assert _phase == Phase.RegAlloc; _phase = Phase.Encoding; long t0 = System.currentTimeMillis(); _encoding = new Encoding(this); preEncode(); - _encoding.encode(jit); + _encoding.encode(); _tEncode = (int)(System.currentTimeMillis() - t0); return this; } - public CodeGen encode() { return encode(false); } // --------------------------- // Exporting to external formats 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 118ca47c..395b3d46 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -153,7 +153,7 @@ public class Encoding { _bigCons.put(relo,new Relo(relo,t,(byte)off,(byte)elf)); } - void encode(boolean jit) { + void encode() { // Basic block layout: invert branches to keep blocks in-order; insert // unconditional jumps. Attempt to keep backwards branches taken, // forwards not-taken (this is the default prediction on most @@ -170,10 +170,6 @@ public class Encoding { // Patch RIP-relative and local encodings now. patchLocalRelocations(); - - // If JIT'ing (in memory execution), patch the global relocations now - if( jit ) - patchGlobalRelocations(); } // Basic block layout: invert branches to keep blocks in-order; insert @@ -382,14 +378,10 @@ public class Encoding { // Write the constant pool into the BAOS and optionally patch locally void writeConstantPool( BAOS bits, boolean patch ) { - HashSet<Relo> ts = new HashSet<>(); - for( Relo t : _bigCons.values() ) { - if( ts.contains(t) ) - throw Utils.TODO(); // Dup! Compress! - ts.add(t); - } padN(16,bits); + HashMap<Type,Integer> targets = new HashMap<>(); + // By log size for( int log = 3; log >= 0; log-- ) { // Write the 8-byte constants @@ -397,17 +389,21 @@ public class Encoding { Relo relo = _bigCons.get(op); if( relo._t.log_size()==log ) { // Map from relo to constant start and patch - relo._target = bits.size(); + Integer target = targets.get(relo._t); + if( target==null ) { + targets.put(relo._t,target = bits.size()); + // Put constant into code space. + if( relo._t instanceof TypeTuple tt ) // Constant tuples put all entries + for( Type tx : tt._types ) + addN(log,tx,bits); + else + addN(log,relo._t,bits); + } + relo._target = target; relo._opStart= _opStart[op._nid]; // Go ahead and locally patch in-memory if( patch ) ((RIPRelSize)op).patch(this, relo._opStart, _opLen[op._nid], relo._target - relo._opStart); - // Put constant into code space. - if( relo._t instanceof TypeTuple tt ) // Constant tuples put all entries - for( Type tx : tt._types ) - addN(log,tx,bits); - else - addN(log,relo._t,bits); } } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java index 07a5dd12..e1e849e6 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/LinkMem.java @@ -1,14 +1,22 @@ package com.seaofnodes.simple.codegen; +import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.node.Node; + // In-memory linking public class LinkMem { final CodeGen _code; LinkMem( CodeGen code ) { _code = code; } public CodeGen link() { + Encoding enc = _code._encoding; + + // Patch external calls internally + enc.patchGlobalRelocations(); + // Write any large constants into a constant pool; they // are accessed by RIP-relative addressing. - _code._encoding.writeConstantPool(_code._encoding._bits,true); + enc.writeConstantPool(enc._bits,true); return _code; } 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 0a7b02e3..35de7e04 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 @@ -22,7 +22,7 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { // AUIPC dst,#hi20_constant_pool 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, tmp, 0)); + enc.add4(riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -35,9 +35,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { 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, tmp, delta)); + enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, delta)); + enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 64440536..9ee19e42 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -23,7 +23,7 @@ public class SetFRISC extends MachConcreteNode implements MachNode { short dst = enc.reg(this ); short src1 = (short)(enc.reg(in(1))-riscv.F_OFFSET); short src2 = (short)(enc.reg(in(2))-riscv.F_OFFSET); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0); + int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } 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 902aa3c2..8f3c9bb2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -6,6 +6,7 @@ import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; +import java.util.HashSet; public abstract class ASMPrinter { @@ -26,11 +27,15 @@ public abstract class ASMPrinter { // constant pool Encoding enc = code._encoding; if( enc!=null && !enc._bigCons.isEmpty() ) { + iadr = (iadr+15)&-16; // pad to 16 + HashSet<Type> targets = new HashSet<>(); sb.p("--- Constant Pool ------").nl(); // By log size for( int log = 3; log >= 0; log-- ) { for( Node op : enc._bigCons.keySet() ) { Encoding.Relo relo = enc._bigCons.get(op); + if( targets.contains(relo._t) ) continue; + targets.add(relo._t); if( relo._t.log_size()==log ) { sb.hex2(iadr).p(" "); if( relo._t instanceof TypeTuple tt ) { diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java index faf21b4f..cf088835 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -101,13 +101,14 @@ public class Chapter21Test { 8 2.828427 9 3.000000 """; - TestC.run("newtonFloat",result); + //TestC.run("newtonFloat",result); + EvalRisc5 R5 = TestRisc5.build("newtonFloat", 0); - R5.fregs[riscv.FA0 - riscv.F_OFFSET] = 4.0; - int trap = R5.step(100); + R5.fregs[riscv.FA0 - riscv.F_OFFSET] = 3.0; + int trap = R5.step(1000); assertEquals(0,trap); // Return register A0 holds fib(8)==55 - assertEquals(2.0,R5.fregs[riscv.FA0 - riscv.F_OFFSET], 0.00001); + assertEquals(1.732051,R5.fregs[riscv.FA0 - riscv.F_OFFSET], 0.00001); } @Test public void testSieve() throws IOException { diff --git a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java index 50e52095..e48dd34c 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java @@ -47,6 +47,10 @@ import java.util.Arrays; public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } + public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } + public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } + + public void st1(int x, int val) { _buf[x] = (byte)val; } public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } @@ -85,17 +89,6 @@ import java.util.Arrays; int rdid = (ir >> 7) & 0x1f; switch( ir & 0x7f ) { - // floats - case 0x7: { - is_f = true; - // does not handle rsp case - - long rs1 = (ir >> 15) & 0x1f; - // Todo: look for stack case - if (rs1 == 2) break; - frval = ir & 0x7FF000; - break; - } case 0x37: // LUI (0b0110111) rval = ( ir & 0xfffff000 ); break; @@ -174,6 +167,27 @@ import java.util.Arrays; } break; } + // floats + case 0x7: { + is_f = true; + int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b + int imm = ir >> 20; + int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); + int rsval = rs1 + imm_se; + + if( rsval >= _buf.length-3 ) { + trap = (5+1); + rval = rsval; + } else { + switch( ( ir >> 12 ) & 0x7 ) { + case 2: frval = ld4f( rsval ); break; + case 3: frval = ld8f( rsval ); break; + default: trap = (2+1); + } + } + break; + } + case 0x23: { // Store 0b0100011 int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b long rs2 = regs[(ir >> 20) & 0x1f]; @@ -279,66 +293,37 @@ import java.util.Arrays; } case 0x53: { - // differentiate between fcvt.d.w and fadd.d is_f = true; - int rs1; - int rs1_int; - int rs2; - int func5 = (ir >> 27) & 0x1F;; + int rs1 = (ir >> 15) & 0x1F; + int rs2 = (ir >> 20) & 0x1F; + double lhs = fregs[rs1]; + double rhs = fregs[rs2]; + int func5 = (ir >> 27) & 0x1F; int func2 = (ir >> 25) & 0x3; -// if(func5 == 0 && func2 == 1) { -// } - if(func5 == 0) { - // fadd.d - rs1 = (ir >> 15) & 0x1F; - rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - frval = lhs + rhs; + if( func2 != 1 ) throw Utils.TODO(); // 1==double + switch( func5 ) { + case 0: frval = lhs + rhs; break; // fadd.d + case 1: frval = lhs - rhs; break; // fsub.d + case 2: frval = lhs * rhs; break; // fmul.d + case 3: frval = lhs / rhs; break; // fdiv.d + case 5: frval = Math.min(lhs,rhs); break; // fmin.d, also used for move + case 20: + is_f = false; // Output into a GPR + rval = switch( (ir >> 12) & 7 ) { + case 0 -> lhs <= rhs ? 1 : 0; + case 1 -> lhs == rhs ? 1 : 0; + case 2 -> lhs < rhs ? 1 : 0; + default -> throw Utils.TODO(); + }; break; - } else if(func5 == 26) { - //fcvt.d.w - rs1_int = (ir >> 15) & 0x1F; - long value = regs[rs1_int]; - frval = (double)value; - break; - } else if (func5 == 5) { - // fmin.d - rs1 = (ir >> 15) & 0x1F; - rs2 = (ir >> 20) & 0x1F; - // just pick one as they are the same - frval = fregs[rs1]; - break; - } else if(func5 == 3) { - // fdiv.d - rs1 = (ir >> 15) & 0x1F; - rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - frval = lhs / rhs; - break; - } else if(func5 == 2) { - // fmul.d - rs1 = (ir >> 15) & 0x1F; - rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - frval = lhs * rhs; - break; - - } else if(func5 == 1) { - // fsub.d - rs1 = (ir >> 15) & 0x1F; - rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - frval = lhs - rhs; - break; - } else { + case 26: frval = (double)regs[rs1]; break; // fcvt.w.d + default: trap = (2+1); // Fault: Invalid opcode. throw Utils.TODO(); } + break; } + default: trap = (2+1); // Fault: Invalid opcode. } diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java index 96aa5b74..1325f1e1 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -19,7 +19,7 @@ public class TestArm64 { public static EvalArm64 build(String dir, String file, int arg) throws IOException { // Compile and export Simple String src = Files.readString(Path.of(dir+"/"+file+".smp")); - CodeGen code = new CodeGen(src).driver(CodeGen.Phase.RegAlloc,"arm", "SystemV").encode(true); + CodeGen code = new CodeGen(src).driver("arm", "SystemV",null); // Image byte[] image = new byte[1<<20]; // A megabyte (1024*1024 bytes) diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java index 8b9b8884..a72dbd1d 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -18,7 +18,7 @@ public abstract class TestRisc5 { public static EvalRisc5 build( String dir, String file, int arg ) throws IOException { // Compile and export Simple String src = Files.readString(Path.of(dir+"/"+file+".smp")); - CodeGen code = new CodeGen(src).driver(CodeGen.Phase.RegAlloc,"riscv", "SystemV").encode(true); + CodeGen code = new CodeGen(src).driver("riscv", "SystemV",null); // Image byte[] image = new byte[1<<20]; // A megabyte (1024*1024 bytes) |
