summaryrefslogtreecommitdiff
path: root/chapter21
diff options
context:
space:
mode:
Diffstat (limited to 'chapter21')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java1
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java15
-rw-r--r--chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java21
3 files changed, 26 insertions, 11 deletions
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 746ecfed..d1d20919 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/ElfFile.java
@@ -221,6 +221,7 @@ public class ElfFile {
i++;
int end = _code._encoding._opStart[ret._nid] + _code._encoding._opLen[ret._nid];
+ if( fun._name==null ) continue; // Anonymous addresses are relocated within .text.
Symbol func = new Symbol(fun._name, text._index, SYM_BIND_GLOBAL, SYM_TYPE_FUNC);
func._value = _code._encoding._opStart[fun._nid];
func._size = end - func._value;
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 17613009..a4355e17 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
@@ -26,22 +26,15 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize {
enc.add4(addi);
}
- @Override public byte encSize(int delta) {
- if( -(1L<<11) <= delta && delta < (1L<<11) ) return 4;
- throw Utils.TODO();
- }
+ @Override public byte encSize(int delta) { return 8; }
// Delta is from opcode start
@Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
short rpc = enc.reg(this);
if( opLen==8 ) {
- // AUIPC (upper 20 bits)
- // opstart of add
- int next = opStart + opLen;
- enc.patch4(opStart,riscv.u_type(riscv.OP_AUIPC, rpc, delta));
- // addi(low 12 bits)
- enc.patch4(next,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, delta & 0xFFF));
- // addi
+ // ADDI sign-extends its low 12 bits, so round the AUIPC high part.
+ enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, (delta+0x800)>>12));
+ enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, delta & 0xFFF));
} else {
// should not happen as one instruction is 4 byte, and TFP arm encodes 2.
throw Utils.TODO();
diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
index 0cabcfbc..72041bd7 100644
--- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
+++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java
@@ -11,6 +11,27 @@ import org.junit.Test;
import static org.junit.Assert.*;
public class Chapter21Test {
+ @Test public void testReturnedFunctionEncoding() throws IOException {
+ String src = "if(arg) return {->42;}; return {->43;};";
+ CodeGen code = new CodeGen(src).driver("riscv","SystemV",null);
+ for( int arg : new int[]{0,1} ) {
+ byte[] image = new byte[1<<16];
+ byte[] bits = code._encoding.bits();
+ System.arraycopy(bits,0,image,0,bits.length);
+ EvalRisc5 cpu = new EvalRisc5(image,1<<15);
+ cpu._pc = code._encoding._opStart[code.link(code._main)._nid];
+ cpu.regs[riscv.A0] = arg;
+ assertEquals(0,cpu.step(100));
+ assertEquals(0,cpu._pc);
+ cpu._pc = (int)cpu.regs[riscv.A0];
+ assertEquals(0,cpu.step(100));
+ assertEquals(0,cpu._pc);
+ assertEquals(arg==0 ? 43 : 42,cpu.regs[riscv.A0]);
+ }
+ // Anonymous bodies need code, but no exported ELF name.
+ new CodeGen(src).driver(TestC.CPU_PORT,TestC.CALL_CONVENTION,"build/objs/anonymous.o");
+ }
+
@Test public void testArmFloatMemory() throws IOException {
for( String type : new String[]{"f32","f64"} ) {
String src = type+"[] !a=new "+type+"[3]; a[arg]=1.25; return a[1];";