diff options
| author | Cliff Click <cliffc@acm.org> | 2026-10-01 14:58:31 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-10-01 14:58:31 -0700 |
| commit | 5dd5b7a2d03885cb767bbf2b609d56f8ef897301 (patch) | |
| tree | f524a9d000c588fa99fc3808e0d37012885cdf7e /chapter25/src | |
| parent | 154dd8b03010a96a48d7903e69394bcc4606c027 (diff) | |
| download | Simple-5dd5b7a2d03885cb767bbf2b609d56f8ef897301.tar.gz Simple-5dd5b7a2d03885cb767bbf2b609d56f8ef897301.zip | |
Move much of the ISA support to shared code
The ISA shared handlers here are required for a proper compiler, but contain only trivial bit-massaging operations.
Diffstat (limited to 'chapter25/src')
135 files changed, 388 insertions, 2491 deletions
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 215fd694..7cb92884 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -17,7 +17,7 @@ import java.util.*; * There are also a bunch of generic utilities for managing bits and bytes * common in all encodings. */ -public class Encoding { +public class Encoding implements com.seaofnodes.isa.CodeSink { // Top-level program graph structure public final CodeGen _code; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index 1c865254..76e47ca2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // ADD (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_ADD); } // General form: "rd = rs1 + rs2" @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index eb75c1a0..67a10b48 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } //FADD (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);} + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_OP_ADD);} // Default on double precision for now(64 bits) // General form: "addf rd = src1 + src2 diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index 93c9e8c3..4c635d07 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class AddIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } //ADD (immediate) @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_ADD,_imm); } // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index 77115d54..1a0365ad 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -13,7 +14,7 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // AND (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_AND); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_AND); } // General form: #rd = rs1 & rs2 @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java index 5b739cd3..6292e98e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,10 +16,10 @@ public class AndIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc,this, in(1), arm.OPI_AND,_imm); + arm.imm_inst_n(enc,this, in(1), Arm64.OPI_AND,_imm); } // General form: "andi rd = rs1 & imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm)); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(Arm64.decodeImm12(_imm)); } }
\ No newline at end of file diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index b83fb3cb..77f14d4c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sar"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_ASR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_ASR); } @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java index 38373e67..7cb42eec 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,7 +23,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_ASR,_imm, 0b111111, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_ASR,_imm, 0b111111, rn, rd)); } // General form: "asri rd = rs1 >> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index 5cf8a89c..31bbde86 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -37,10 +38,10 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // by comparison (or sub). No need for regs because it uses flags if( in(1)!=null ) { // B.cond - enc.add4( arm.b_cond(arm.OP_BRANCH, 0, arm.make_condition(_bop, _fp)) ); + enc.add4( Arm64.b_cond(Arm64.OP_BRANCH, 0, Arm64.make_condition(_bop, _fp)) ); } else { if( _bop=="!=" ) return; // Inverted, no code - enc.add4(arm.b(arm.OP_UJMP, 0)); + enc.add4(Arm64.b(Arm64.OP_UJMP, 0)); } enc.jump(this,cproj(0)); } @@ -57,7 +58,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( opLen==4 ) { - enc.patch4(opStart,arm.b_cond(arm.OP_BRANCH, delta, arm.make_condition(_bop, _fp))); + enc.patch4(opStart,Arm64.b_cond(Arm64.OP_BRANCH, delta, Arm64.make_condition(_bop, _fp))); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 8f070525..4de28f3a 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -29,7 +30,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); // BL - enc.add4(arm.b(arm.OP_CALL,0)); // Target patched at link time + enc.add4(Arm64.b(Arm64.OP_CALL,0)); // Target patched at link time } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -37,7 +38,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - enc.patch4(opStart,arm.b(arm.OP_CALL,delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_CALL,delta)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index c84aa9e5..1949ae46 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class CallRRARM extends CallNode implements MachNode { // Needs a register, typically a jump-and-link-register opcode // blr short self = enc.reg(this); - enc.add4(arm.blr(arm.OP_CALLRARM, self)); + enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index 794ff0c9..1bd9c372 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.FLAGS_MASK; } // SUBS (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,arm.OP_CMP); } + @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,Arm64.OP_CMP); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java index f84a1649..cd4dd9cf 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -28,7 +29,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public Node copy() { return new CmpIARM(this); } - @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), arm.OPI_CMP,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), Arm64.OPI_CMP,_imm); } // General form: "cmp rs1, 1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index de254eeb..e94b6491 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // SDIV - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_DIV,3); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_DIV,3); } // General form: "div dst /= src" @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 813bebe4..68ad6047 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } // FDIV (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_DIV); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_DIV); } // General form: "VDIF = dst /= src" @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java index 26a237d0..814a82c2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,7 +23,7 @@ public class ExtendARM extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); // SBFM/UBFM aliases: sign/zero extend the low byte, short or int. - enc.add4(arm.imm_shift(_signed ? arm.OPI_ASR : arm.OPI_LSR,0,_bits-1,src,dst)); + enc.add4(Arm64.imm_shift(_signed ? Arm64.OPI_ASR : Arm64.OPI_LSR,0,_bits-1,src,dst)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java index 42553868..db2540f7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class FltARM extends ConstantNode implements MachNode, RIPRelSize { if( _ext!=null ) throw Utils.TODO(); enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/); short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.add4(arm.load_pc(arm.OPF_ARM, 0, dst)); + enc.add4(Arm64.load_pc(Arm64.OPF_ARM, 0, dst)); } // Delta is from opcode start. @@ -30,7 +31,7 @@ public class FltARM extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.patch4(opStart, arm.load_pc(arm.OPF_ARM, delta, dst)); + enc.patch4(opStart, Arm64.load_pc(Arm64.OPF_ARM, delta, dst)); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java index b9e85202..17cafcde 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -16,6 +17,6 @@ public class FunARM extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(arm.imm_inst(arm.OPI_SUB, sz, arm.RSP, arm.RSP)); + enc.add4(Arm64.imm_inst(Arm64.OPI_SUB, sz, arm.RSP, arm.RSP)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index f1fa162f..b1c30afc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,7 +14,7 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(arm.OP_FLOAT_C, 1, reg1, self); + int body = Arm64.float_cast(Arm64.OP_FLOAT_C, 1, reg1, self); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index dbed9487..72b76edd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -24,39 +25,7 @@ public class IntARM extends ConstantNode implements MachNode { if( _ext!=null ) throw Utils.TODO(); short self = enc.reg(this); long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); - int nb0 = 0; - int nb1 = 0; - // Count number of 0000 and FFFF blocks - for (int i=0; i<64; i+=16) { - int block = (int)(x >> i) & 0xFFFF; - if (block == 0) nb0++; - if (block == 0xFFFF) nb1++; - } - int pattern; - int op; - if(nb0 >= nb1) { - // More 0 blocks then F blocks, use movz - pattern = 0; - op = arm.OP_MOVZ; - } else { - // More F blocks then 0 blocks, use movn - pattern = 0xFFFF; - op = arm.OP_MOVN; - } - int invert = pattern; - for (int i=0; i<4; i++) { - int block = (int)x & 0xFFFF; - x >>= 16; - if (block != pattern) { - enc.add4(arm.mov(op, i, block ^ invert, self)); - op = arm.OP_MOVK; - invert = 0; - } - } - if (op != arm.OP_MOVK) { - // All blocks are the same, special case - enc.add4(arm.mov(op, 0, 0, self)); - } + Arm64.constant(enc,self,x); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 827db545..4fbd6840 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -18,9 +19,9 @@ public class LoadARM extends MemOpARM { @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } - private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; + private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, }; - private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; + private static final int[] OP_LOAD_RS = new int[]{ Arm64.OP_LOAD_R_8 , Arm64.OP_LOAD_R_16 , Arm64.OP_LOAD_R_32 , Arm64.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index 80ce493f..954cfac2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSL); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSL); } @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java index 7fe16cbe..b32153ab 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -24,7 +25,7 @@ public class LslIARM extends MachConcreteNode implements MachNode { assert _imm > 0; // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) // immr must be (-<shift> MOD 64) = 64 - shift - enc.add4(arm.imm_shift(arm.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); } // General form: "lsli rd = rs1 << imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index fc005e04..91be34e3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSR); } @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java index 78844b0a..243ce968 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_LSR,_imm, 0b111111, rn,rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSR,_imm, 0b111111, rn,rd)); } // General form: "lsri rd = rs1 >>> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index a26f385a..14eaf510 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -66,8 +67,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { val -= arm.D0; } int body = off() == null - ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) - : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? Arm64.load_str_imm(opcode_imm, _off, ptr, val, size) + : Arm64.indr_adr(opcode_reg, off, Arm64.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index a23ec75b..f598cefb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_MUL,31); } // General form: "rd = rs1 * rs2" @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 73ebbf00..a4f81fd4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class MulFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_MUL); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_MUL); } // Default on double precision for now(64 bits) // General form: "VMUL.f32 rd = src1 * src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index df2a6bc9..8bb8983e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,8 +12,8 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { // BL(branch with link) enc.external(this,"calloc"). - add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1 - add4(arm.b(arm.OP_CALL, 0)); + add4(Arm64.mov(Arm64.OP_MOVZ, 0, 1, 0)). // movz x0,#1 + add4(Arm64.b(Arm64.OP_CALL, 0)); } // Patch is for running "new" in a JIT. @@ -24,7 +25,7 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void patch(Encoding enc, int opStart, int opLen, int delta ) { // Negative patches are JIT emulator targets. if( opStart+delta < 0 ) { - enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4)); + enc.patch4(opStart+4, Arm64.b_calloc(Arm64.OP_CALL, delta-4)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index d78421ca..ac21c706 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -17,9 +18,9 @@ public class NotARM extends MachConcreteNode implements MachNode{ // subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int subs = arm.imm_inst(arm.OP_SUBS, 0, reg1, self); + int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(arm.OP_CSET, 31, arm.COND.EQ, 31, reg1); + int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 31, reg1); enc.add4(cset); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index e8245749..5b7264ec 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class OrARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "|"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_OR); } // General form: #rd = rs1 & rs2 @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index a48caa51..86d07bee 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,7 +16,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm); + arm.imm_inst_n(enc, this, in(1), Arm64.OPI_OR, _imm); } // General form: "ori rd = rs1 | imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 4597666b..a7ed5073 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class RetARM extends ReturnNode implements MachNode { @Override public void encoding( Encoding enc ) { int frameAdjust = ((FunARM)fun())._frameAdjust; if( frameAdjust > 0 ) - enc.add4(arm.imm_inst(arm.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); - enc.add4(arm.ret(arm.OP_RET)); + enc.add4(Arm64.imm_inst(Arm64.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); + enc.add4(Arm64.ret(Arm64.OP_RET)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index c597b9dd..e5b06c39 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -23,7 +24,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { // Using RM==RN==31 implies a *zero* value, not R31. - int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop, _fp), 0b011111, enc.reg(this)); + int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop, _fp), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index be975fb6..dcfeb5d8 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -26,7 +27,7 @@ public class SplitARM extends SplitNode { } int off = fun(enc).computeStackOffset(enc._code,dst); if( srcX ) src -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_STORE_IMM_64, off, arm.RSP, src, 8)); return; } @@ -34,26 +35,26 @@ public class SplitARM extends SplitNode { // Load from SP int off = fun(enc).computeStackOffset(enc._code,src); if( dstX ) dst -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); return; } // pick opcode based on regs if(!dstX && !srcX) { // GPR->GPR - enc.add4(arm.mov_reg(arm.OP_MOV, src, dst)); + enc.add4(Arm64.mov_reg(Arm64.OP_MOV, src, dst)); } else if(dstX && srcX) { // FPR->FPR // fmov reg - enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_reg(Arm64.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); } else if(!srcX && dstX) { // GPR->FPR // FMOV(general) 64 bits to DOUBLE-PRECISION - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); } else if( srcX && !dstX) { //FPF->GPR // FMOV(general) DOUBLE-PRECISION to 64 bits - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); } } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 36b6bcdb..0b90ac8b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.StoreNode; @@ -22,9 +23,9 @@ public class StoreARM extends MemOpARM { @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; + private static final int[] OP_STORES = new int[]{ Arm64.OP_STORE_IMM_8, Arm64.OP_STORE_IMM_16, Arm64.OP_STORE_IMM_32, Arm64.OP_STORE_IMM_64, }; - private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; + private static final int[] OP_STORE_RS = new int[]{ Arm64.OP_STORE_R_8, Arm64.OP_STORE_R_16, Arm64.OP_STORE_R_32, Arm64.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[Integer.numberOfTrailingZeros(_bytes)], val(), size()); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index e3b95e50..fd5cd4de 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_SUB); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index a252e542..1a751434 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class SubFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_SUB); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_SUB); } // Default on double precision for now(64 bits) // General form: "vsub.f32 rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index b50107c9..b2c0b2ed 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -18,7 +19,7 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_SUB,_imm); } // General form: "subi rd = rs1 - imm" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 9d490c8b..a053ba46 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -22,9 +23,9 @@ public class TFPARM extends FunPtrNode implements MachNode, RIPRelSize { else enc.external(this,_ext); // ELF-file external patch short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java index 8209eb4b..b2531f97 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,9 +22,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { else enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java index ce4f523c..aecd02bb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,7 +20,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - int body = arm.b(arm.OP_UJMP, 0); + int body = Arm64.b(Arm64.OP_UJMP, 0); enc.add4(body); } @@ -33,7 +34,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,arm.b(arm.OP_UJMP, delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_UJMP, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index 52bda021..d56397a3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class XorARM extends MachConcreteNode implements MachNode{ @Override public String glabel() { return "^"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_XOR); } // General form: "rd = x1 ^ x2" @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java index 23b29644..12143ccd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -19,7 +20,7 @@ public class XorIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // General form: "xori rd = rs1 ^ imm" - @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), Arm64.OPI_XOR,_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 044d0352..2ba2d62e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; +import static com.seaofnodes.isa.Arm64.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -81,102 +83,6 @@ public class arm extends Machine { static final RegMask D6_MASK = new RegMask(D6); static final RegMask D7_MASK = new RegMask(D7); - // major opcode: OP - public static int OP_ADD = 0b10_001_011; - public static int OPF_ADD = 0b00_011_110; - public static int OPF_OP_ADD = 0b00_101_0; - public static int OPI_ADD = 0b10_010_00100; - - public static int OPI_SUB = 0b11_010_00100; - public static int OP_UJMP = 0b000101; - - public static int OP_ADRP = 0b10000; - - public static int OP_ASR = 0b1010; - public static int OPI_ASR = 0b10_0100_1101; - - public static int OP_LSL = 0b1000; - public static int OPI_LSL =0b1101001101; - - public static int OP_LSR = 0b1001; - public static int OPI_LSR = 0b1101001101; - - public static int OP_BRANCH = 0b01_0101_00; - public static int OP_CALL = 0b10_010_1; - - public static int OP_CALLRARM = 0b1101011000111111000000; - - public static int OP_SUBS = 0b1111000100; - public static int OP_CSET = 0b10011010100; - public static int OP_CMP = 0b11101011; - public static int OPI_CMP = 0b1111000100; - - public static int OP_DIV = 0b10011010110; - public static int OPF_DIV = 0b000110; - - public static int OP_MUL = 0b10011011000; - public static int OPF_MUL = 0b10; - - public static int OPF_ARM = 0b01011100; - - public static int OP_FLOAT_C = 0b10011110; - - public static int OP_XOR = 0b11001010; - public static int OPI_XOR = 0b110100100; - - public static int OP_AND = 0b10_0010_10; - public static int OPI_AND = 0b10_0100_100; - - public static int OP_OR = 0b10101010; - public static int OPI_OR = 0b101100100; - - public static int OP_SUB = 0b11001011; - public static int OPF_SUB = 0b1110; - - public static int OP_MOVK = 0b111100101; - public static int OP_MOVN = 0b100100101; - public static int OP_MOVZ = 0b110100101; - - public static int OP_RET = 0b1101011001011111000000; - // Store/load opcodes - public static int OP_LOAD_R_64 = 0b11111000011; - public static int OP_LOAD_R_32 = 0b10111000011; - public static int OP_LOAD_R_16 = 0b01111000010; - public static int OP_LOAD_R_8 = 0b00111000011; - - public static int OP_LOAD_IMM_64 = 0b1111100101; - public static int OP_LOAD_IMM_32 = 0b1011100101; - public static int OP_LOAD_IMM_16 = 0b0111100101; - public static int OP_LOAD_IMM_8 = 0b0011100101; - - // load - public static int OPF_LOAD_R_64 = 0b11111100011; - public static int OPF_LOAD_R_32 = 0b10111100011; - - public static int OPF_LOAD_IMM_64 = 0b1111110101; - public static int OPF_LOAD_IMM_32 = 0b1011110101; - - public static int OP_STORE_R_64 = 0b11111000001; - public static int OP_STORE_R_32 = 0b10111000001; - public static int OP_STORE_R_16 = 0b01111000001; - public static int OP_STORE_R_8 = 0b00111000001; - - public static int OP_STORE_IMM_64 = 0b1111100100; - public static int OP_STORE_IMM_32 = 0b1011100100; - public static int OP_STORE_IMM_16 = 0b0111100100; - public static int OP_STORE_IMM_8 = 0b0011100100; - - public static int OPF_STORE_R_64 = 0b11111100001; - public static int OPF_STORE_R_32 = 0b10111100001; - - public static int OPF_STORE_IMM_32 = 0b1011110100; - public static int OPF_STORE_IMM_64 = 0b1111110100; - - - public static int OP_FMOV = 0b10011110; - public static int OP_FMOV_REG = 0b00011110; - // https://docsmirror.github.io/A64/2023-06/mov_orr_log_shift.html - public static int OP_MOV = 0b10101010000; // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 @@ -202,56 +108,6 @@ public class arm extends Machine { }; // ARM ENCODING - public enum OPTION { - UXTB, - UXTH, - UXTX, - SXTB, - SXTH, - SXTW, - SXTX, - } - - static public int cset(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - // Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least significant bit inverted. - int actualCond = cond.ordinal() ^ 1; - return (opcode << 21) | (rm << 16) | (actualCond << 12) | (0b01 << 10) | (rn << 5) | rd; - } - - static public int cset(int opcode, COND cond, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - public enum STORE_LOAD_OPTION { - UXTW, // base+ u32 index [<< logsize] - UXTX, // base+ u64 index [<< logsize] - SXTW, // base+ s32 index [<< logsize] - SXTX, // base+ s64 index [<< logsize] - } - - public enum COND { - EQ, - NE, - CS, - CC, - MI, - PL, - VS, - VC, - HI, - LS, - GE, - LT, - GT, - LE, - AL, - NV - } // True if signed 9-bit immediate private static boolean imm9(TypeInteger ti) { @@ -264,55 +120,10 @@ public class arm extends Machine { return ti.isConstant() && ((ti.value()<<52)>>52) == ti.value(); } - // Can we encode this in ARM's 12-bit LOGICAL immediate form? // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { - if( !ti.isConstant() ) return -1; - if( !ti.isConstant() ) return -1; - long val = ti.value(); - if (val == 0 || val == -1) return -1; // Special cases are not allowed - int immr = 0; - // Rotate until we have 0[...]1 - - // Rotate until: - // The number is negative (MSB is 1) - // Or the LSB is not 1 - while (val < 0 || (val & 1)==0) { - // circular rotation - val = (val >>> 63) | (val << 1); - immr++; - } - // Start by assuming that val might be made of two 32-bit chunks that repeat. - int size = 32; - long pattern = val; - // Is upper half of pattern the same as the lower? - while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { - // Then only take one half - pattern >>= size; - size >>= 1; - } - size <<= 1; - int imms = Long.bitCount(pattern); - // Pattern should now be zeros followed by ones 0000011111 - if (pattern != (1L<<imms)-1) return -1; - imms--; - if (size == 64) return 0x1000 | immr << 6 | imms; - return (32-size)<<1 | immr << 6 | imms; - } - - // sh is encoded in opcode - public static int imm_inst(int opcode, int imm12, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; - } - - public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + return ti.isConstant() ? Arm64.logicalImmediate(ti.value()) : -1; } public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) { @@ -324,64 +135,46 @@ public class arm extends Machine { opcode ^= OPI_ADD ^ OPI_SUB; imm12 = -imm12; } - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); enc.add4(body); } public static void imm_inst_subs(Encoding enc, Node n,Node n2, int opcode, int imm12) { short reg1 = enc.reg(n2); // 31 = 11111 - int body = imm_inst(opcode, imm12&0xFFF, reg1, 31); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, 31); enc.add4(body); } // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static void imm_inst(Encoding enc, int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, self, self); enc.add4(body); } public static void imm_inst_n(Encoding enc, Node n, Node n2, int opcode, int imm13) { short self = enc.reg(n); short reg1 = enc.reg(n2); - int body = imm_inst_n(opcode, imm13, reg1, self); + int body = Arm64.imm_inst_n(opcode, imm13, reg1, self); enc.add4(body); } - // nth bit comes from immediate and not opcode - public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= imm13 && imm13 <= 0x1FFF; - return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; - } - - public static int imm_inst_l(int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); - return body; - } - // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); return body; } // for normal add, reg1, reg2 cases (reg-to-reg) // using shifted-reg form - public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; - } + public static void r_reg(Encoding enc, Node n, int opcode) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); enc.add4(body); } @@ -389,232 +182,51 @@ public class arm extends Machine { short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); // 31 = 11111 - int body = r_reg(opcode, 0, reg2, 0, reg1, 31); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, 31); enc.add4(body); } - public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; - } public static void shift_reg(Encoding enc, Node n, int op2) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(0b10011010110, reg2, op2, reg1, self); + int body = Arm64.shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } // MUL can be considered an alias for MADD with the third operand Ra being set to 0 - public static int madd(int opcode, int rm, int ra, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; - } + public static void madd(Encoding enc, Node n, int opcode, int ra) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = madd(opcode, reg2, ra, reg1, self); + int body = Arm64.madd(opcode, reg2, ra, reg1, self); enc.add4(body); } - // encodes movk, movn, and movz - public static int mov(int opcode, int shift, int imm16, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; - } - - public static int mov_reg(int opcode, int src, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; - } - - public static int ret(int opcode) { - return (opcode << 10) | (X30 << 5); - } - - // FMOV (scalar, immediate) - public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; - } - - public static int f_mov_reg(int opcode, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; - } - public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; - } public static void f_scalar(Encoding enc, Node n, int op ) { short self = (short)(enc.reg(n) -D_OFFSET); short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); + int body = Arm64.f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } - // share same encoding with LDR (literal, SIMD&FP) flavour - public static int load_pc(int opcode, int offset, int rt) { - offset>>=2; - return (opcode << 24) | (offset << 5) | rt; - } - // int l - public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= imlo && imlo <= 0x3; // 2 bits - assert 0 <= imhi && imhi <= 0x7FFFF; // 19 bits - return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; - } - public static void patch_adrp_add(Encoding enc, int opStart, int delta, int rd) { int target = opStart + delta; int pageDelta = ((target & ~0xFFF) - (opStart & ~0xFFF)) >> 12; int imm21 = pageDelta & 0x1FFFFF; - enc.patch4(opStart , adrp(1, imm21 & 3, OP_ADRP, imm21 >>> 2, rd)); - enc.patch4(opStart+4, imm_inst_l(OPI_ADD, target & 0xFFF, rd)); - } - - // [Rptr+Roff] - public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; - } - // [Rptr+imm9] - public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - - if(size == 8) imm12 = imm12 >> 3; - if(size == 4) imm12 = imm12 >> 2; - if(size == 2) imm12 = imm12 >> 1; - // size == 1 imm12 = imm12 - return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; - } - - // encoding for vcvt, size is encoded in operand - // <Qd>, <Qm> - // F32.S32 - //encoded as op = 0b00, size = 0b10. - // VCVT<c>.<Td>.<Tm> <Dd>, <Dm> - // opcode is broken down into 4 pieces - public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { - return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | - (vd << 12) | (0x01100010 << 4) | vm; - } - public static int float_cast(int opcode, int ftype, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; + enc.patch4(opStart , Arm64.adrp(1, imm21 & 3, OP_ADRP, imm21 >>> 2, rd)); + enc.patch4(opStart+4, Arm64.imm_inst_l(OPI_ADD, target & 0xFFF, rd)); } - - // ftype = 3 - public static int f_cmp(int opcode, int ftype, int rm, int rn) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - // Todo: |8 is not needed - return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); - } public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_cmp(0b00011110, 3, reg2, reg1); + int body = Arm64.f_cmp(0b00011110, 3, reg2, reg1); enc.add4(body); } - public static COND make_condition(String bop, boolean fp) { - // One of {N,Z,C} and !V - // OR { !N, !Z, C, V } - return fp - ? switch (bop) { // FP uses unsigned encodings - case "==" -> COND.EQ; // Z - case "!=" -> COND.NE; // !Z - case "<" -> COND.MI; // N - case "<=" -> COND.LS; // Z || !C - case ">=" -> COND.PL; // !N - case ">" -> COND.HI; // !Z && C - default -> throw Utils.TODO(); - } - : switch (bop) { - case "==" -> COND.EQ; // Z - case "!=" -> COND.NE; // !Z - case "<" -> COND.LT; // N != V - case "<=" -> COND.LE; // Z || N != V - case ">=" -> COND.GE; // N == V - case ">" -> COND.GT; // !Z && N == V - default -> throw Utils.TODO(); - }; - } - - public static int b_cond(int opcode, int delta, COND cond) { - // 24-5 == 19bits offset range - assert -(1<<19) <= delta && delta < (1<<19); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<19)-1; // Zero extend - return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); - } - - public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - // Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4. - public static int blr(int opcode, int rd) { - assert 0 <= rd && rd < 32; - return opcode << 10 | rd << 5; - } - public static int b(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - // no aligned assert(assert (delta&3)==0;) - public static int b_calloc(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - - public static long decodeImm12(int imm12) { - int immr = (imm12 >> 6) & 0x3F; - int imms = imm12 & 0x3F; - int size; - if ((imm12 & 0x1000) != 0) { - size = 64; - } else { - size = 31-(imms >> 1); - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size++; - imms &= ~((32-size) << 1); - } - long val = (2L << imms)-1; - while (size < 64) { - val |= val << size; - size <<= 1; - } - val = (val >>> immr) | val << (64-immr); - return val; - } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; @@ -851,7 +463,6 @@ public class arm extends Machine { return prj.in(0) instanceof StartNode ? new ProjNode(prj) : new ProjARM(prj); } - private static int off; private static Node idx; private Node st(StoreNode st) { @@ -877,5 +488,4 @@ public class arm extends Machine { return mop; } - } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 1c157bc1..59bad64e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachNode; import com.seaofnodes.simple.node.FunPtrNode; @@ -18,7 +19,7 @@ public class AUIPC extends FunPtrNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); short dst = enc.reg(this); - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -29,7 +30,7 @@ public class AUIPC extends FunPtrNode implements MachNode, RIPRelSize { //short rpc = enc.reg(this); //// High half is where the TFP constant used to be, the last input //short auipc = enc.reg(in(_inputs._len-1)); - //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + //enc.patch4(opStart,RiscV.i_type(0x67, rpc, 0, auipc, delta)); throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java index 8636df9f..d87e49b9 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AddFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,1); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,1); } @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java index 511b0583..8012b61e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -8,7 +9,7 @@ public class AddIRISC extends ImmRISC { public AddIRISC( Node add, int imm12, boolean pop ) { super(add,imm12,pop); } @Override public String op() { return "addi"; } @Override public String glabel() { return "+"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 0;} @Override public AddIRISC copy() { // Clone the AddI, using the same inputs-only code used during inst select. diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java index 842c8bdc..9fd65e7d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,6 +8,6 @@ public class AndIRISC extends ImmRISC { public AndIRISC( Node and, int imm) { super(and,imm); } @Override public String op() { return "andi"; } @Override public String glabel() { return "&"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 7;} } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java index b8664679..a9d03da5 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -46,12 +47,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { if( in(1)==null && _bop=="!=" ) return; // Inverted never-node, no code enc.jump(this,cproj(0)); if( in(1)==null ) // Never node - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); else { // Todo: relocs (for offset - immf) short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); - enc.add4(riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, 0)); + enc.add4(RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, 0)); } } @@ -67,12 +68,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( in(1)==null ) { // Never node - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); if( opLen==4 ) { - enc.patch4(opStart,riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, delta)); + enc.patch4(opStart,RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index 8e1b4a48..b1426a3f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -32,7 +33,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); short rpc = enc.reg(this); - enc.add4(riscv.j_type(riscv.OP_JAL, rpc, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, rpc, 0)); } // Delta is from opcode start @@ -46,7 +47,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short rpc = enc.reg(this); if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, rpc, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, rpc, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index 7369f9f5..cda4bc79 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -18,7 +19,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(riscv.OP_JALR, rpc, 0, src, 0); + int body = RiscV.i_type(RiscV.OP_JALR, rpc, 0, src, 0); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java index 68ed6f6c..8eb4fb3b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivFRISC extends MachConcreteNode implements MachNode{ @Override public String op() { return "divf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RUP,13); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RUP,13); } // Default on double precision for now(64 bits) // General form: "fdiv.d rd = src1 / src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java index 22ac2a69..5bd3ec1c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,8 +23,8 @@ public class ExtendRISC extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); int shift = 64-_bits; - enc.add4(riscv.i_type(riscv.OP_IMM,dst,1,src,shift)); - enc.add4(riscv.i_type(riscv.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,1,src,shift)); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index c1a9b018..a110d156 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,9 +22,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.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOADFP, 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 +36,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>>12)); + 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_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); + 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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java index 6fce6244..d3d64b06 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -17,6 +18,6 @@ public class FunRISC extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java index db0547fe..1b53ab0f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,7 +15,7 @@ public class I2F8RISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this )-riscv.F_OFFSET); short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.RM.RNE.ordinal(),src1,0,0x69); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.RM.RNE.ordinal(),src1,0,0x69); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index b4c87872..ee247c3e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -41,7 +42,7 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); + enc.add4(RiscV.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); } // General form: "addi rd = rs1 + imm" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java index e6b4c4ed..dd4a02a3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -25,9 +26,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short tmp = (short)riscv.T6; enc.largeConstant(this,_con, 0, -1); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + 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_LOAD, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -36,9 +37,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + 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 & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index b795ba96..35d2bc65 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class IntRISC extends ConstantNode implements MachNode { int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 7333f2b7..aedd8b47 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class LUI extends ConstantNode implements MachNode { long x = ((TypeInteger)_con).value(); int imm20 = (int)(x>>12) & 0xFFFFF; short dst = enc.reg(this); - int lui = riscv.u_type(riscv.OP_LUI, dst, imm20); + int lui = RiscV.u_type(RiscV.OP_LUI, dst, imm20); enc.add4(lui); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index 592cdb84..e9f3ec02 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -19,9 +20,9 @@ public class LoadRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short ptr = enc.reg(ptr()); - int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dst >= riscv.F_OFFSET ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, func3(), ptr, _off)); + enc.add4(RiscV.i_type(op, dst, func3(), ptr, _off)); } @Override int func3() { int func3 = -1; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java index 5cc40079..dacec2b5 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class MulFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,9); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,9); } @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java index d8183d09..3070c56c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,7 +13,7 @@ public class NegRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - riscv.r_type(riscv.OP,dst,0,0,src,0x20); + RiscV.r_type(RiscV.OP,dst,0,0,src,0x20); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = -").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index 4a6583ce..40d0359c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.print.ASMPrinter; @@ -14,9 +15,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.i_type(riscv.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); - enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); } // Patch is for running "new" in a JIT. @@ -32,8 +33,8 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { int imm20 = delta>>12; if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension int imm12 = delta&0xFFF; - enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); - enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + enc.patch4(opStart+4,RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); } else throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java index 1369ee76..dbe9ceb0 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -14,7 +15,7 @@ public class NotRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 2, src, 1)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java index 963b9d50..937595a3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class OrIRISC extends ImmRISC { public OrIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 6; } @Override public String glabel() { return "|"; } @Override public String op() { return "ori"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 7e4631d3..33143c6b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -14,8 +15,8 @@ public class RetRISC extends ReturnNode implements MachNode { int sz = fun()._frameAdjust; if( sz >= 1L<<12 ) throw Utils.TODO(); if( sz != 0 ) - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); short rpc = enc.reg(rpc()); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.ZERO, 0, rpc, 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR, riscv.ZERO, 0, rpc, 0)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 3424cd01..d037dd5c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.BoolNode; import com.seaofnodes.simple.node.MachConcreteNode; @@ -23,7 +24,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,0b1010001/*FCMP*/); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java index 12c0ddec..1425caa2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SllIRISC extends ImmRISC { public SllIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 1; } @Override public String glabel() { return "<<"; } @Override public String op() { return "slli"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 58fa8a4b..d455337b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -25,36 +26,36 @@ public class SplitRISC extends SplitNode { throw Utils.TODO(); // Very rare stack-stack move } int off = fun(enc).computeStackOffset(enc._code,dst); - int op = srcX ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = srcX ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( srcX ) src -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, 0b011, riscv.RSP, src, off)); + enc.add4(RiscV.s_type(op, 0b011, riscv.RSP, src, off)); return; } if( src >= riscv.MAX_REG ) { // Load from SP int off = fun(enc).computeStackOffset(enc._code,src); - int op = dstX ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dstX ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dstX ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, 0b011, riscv.RSP, off)); + enc.add4(RiscV.i_type(op, dst, 0b011, riscv.RSP, off)); return; } // pick opcode based on regs if( !dstX && !srcX ) { // GPR->GPR - enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + enc.add4(RiscV.r_type(RiscV.OP,dst,0,src,riscv.ZERO,0)); } else if( dstX && srcX ) { // FPR->FPR src -= riscv.F_OFFSET; dst -= riscv.F_OFFSET; - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) } else if(!srcX && dstX) { //GPR->FPR // fmv.d.x - enc.add4(riscv.r_type(riscv.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); } else if(srcX && !dstX) { //FPR->GPR //fmv.x.d - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); } } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java index fcfa0774..b316b303 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,7 +8,7 @@ public class SraIRISC extends ImmRISC { public SraIRISC( Node and, int imm) { super(and,imm | (0x20 << 5)); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5;} @Override public String glabel() { return ">>"; } @Override public String op() { return "srai"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java index 2f73e139..d0ea6b18 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SrlIRISC extends ImmRISC { public SrlIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5; } @Override public String glabel() { return ">>>"; } @Override public String op() { return "srli"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index 100bbd2a..c3fcf4d3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.node.*; @@ -37,9 +38,9 @@ public class StoreRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short val = enc.reg(val()); short ptr = enc.reg(ptr()); - int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = val >= riscv.F_OFFSET ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); + enc.add4(RiscV.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); } // func3 is based on load/store size and extend diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java index da3e92f4..044820cf 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,5); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,5); } @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/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index 1f269152..44ef1a95 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -23,9 +24,9 @@ public class TFPRISC extends FunPtrNode implements MachNode, RIPRelSize { // TODO: 1 op encoding, plus a TODO if it does not fit short dst = enc.reg(this); // auipc t0,0 - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi t1,t0 + #0 - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -38,9 +39,9 @@ public class TFPRISC extends FunPtrNode implements MachNode, RIPRelSize { int lo12 = delta - (hi20 << 12); // AUIPC (upper 20 bits) // opstart of add - enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, hi20)); + enc.patch4(opStart ,RiscV.u_type(RiscV.OP_AUIPC, rpc, hi20)); // addi(low 12 bits) - enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, lo12 & 0xFFF)); + enc.patch4(opStart+4,RiscV.i_type(RiscV.OP_IMM, rpc, 0, rpc, lo12 & 0xFFF)); // addi } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java index 45c3eed2..a5ff3753 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -20,9 +21,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { else enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -31,9 +32,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, (delta+0x800)>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, dst, (delta+0x800)>>12)); // ADDI's low 12 bits are signed; round the AUIPC page accordingly. - enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, dst, 0, dst, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java index 160895df..448d9ec3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -21,7 +22,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.jump(this,uctrl()); - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); } // Delta is from opcode start @@ -34,7 +35,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 19ea6bc7..f4323cae 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -1,12 +1,13 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } public XorIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } @Override public String op() { return "xori"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 03f7371b..808ad82e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; +import static com.seaofnodes.isa.RiscV.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -67,7 +69,6 @@ public class riscv extends Machine { static final RegMask SPLIT_MASK = new RegMask( WR_BITS | FP_BITS, -1L ); - // Arguments masks public static RegMask A0_MASK = new RegMask(A0); public static RegMask A1_MASK = new RegMask(A1); @@ -113,40 +114,13 @@ public class riscv extends Machine { FA7_MASK }; - // major opcode: OP - public static int OP_LOAD = 0b00_000_11; - public static int OP_LOADFP = 0b00_001_11; - public static int OP_CUSTOM0 = 0b00_010_11; - public static int OP_IMM = 0b00_100_11; - public static int OP_AUIPC = 0b00_101_11; - - public static int OP_STORE = 0b01_000_11; - public static int OP_STOREFP = 0b01_001_11; - public static int OP_CUSTOM1 = 0b01_010_11; - public static int OP = 0b01_100_11; - public static int OP_LUI = 0b01_101_11; - - public static int OP_CUSTOM2 = 0b10_010_11; - public static int OP_FP = 0b10_100_11; - - public static int OP_BRANCH = 0b11_000_11; - public static int OP_JALR = 0b11_001_11; - public static int OP_RESERVED= 0b11_010_11; - public static int OP_JAL = 0b11_011_11; - - // Since riscv instructions are fixed we can just or them together - public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= rd && rd < 32; - return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } + public static void r_type(Encoding enc, Node n, int func3, int func7) { short dst = enc.reg(n); short src1 = enc.reg(n.in(1)); short src2 = enc.reg(n.in(2)); - int body = r_type(OP,dst,func3,src1,src2,func7); + int body = RiscV.r_type(OP,dst,func3,src1,src2,func7); enc.add4(body); } @@ -154,103 +128,10 @@ public class riscv extends Machine { short dst = (short)(enc.reg(n )-F_OFFSET); short src1 = (short)(enc.reg(n.in(1))-F_OFFSET); short src2 = (short)(enc.reg(n.in(2))-F_OFFSET); - int body = r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); + int body = RiscV.r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); enc.add4(body); } - - public static int u_type(int opcode, int rd, int imm20) { - assert 0 <= rd && rd < 32; - return (imm20 << 12) | (rd << 7) | opcode; - } - - public static int j_type(int opcode, int rd, int delta) { - assert -(1L<<20) <= delta && delta < (1L<<20); - assert 0 <= rd && rd < 32; - // Messy branch offset encoding - // 31 30-21 20 19-12 11-7 6-0 - // 20 10- 1 11 19-12 rpc JAL - assert (delta&1)==0; // Low bit is always zero, not encoded - int imm10_01 = (delta>> 1) & 0x3FF; - int imm11 = (delta>>11) & 1; - int imm12_19 = (delta>>12) & 0xFF; - int imm20 = (delta>>19) & 1; - int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; - return bits << 12 | rd << 7 | opcode; - } - - - public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { - assert 0 <= rd && rd < 32; - assert 0 <= rs1 && rs1 < 32; - assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller - return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } - - // S-type instructions(store) - public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= func3; - - assert imm12 >= 0; // Masked to high zero bits by caller - int imm_lo = imm12 & 0x1F; - int imm_hi = imm12 >> 5; - return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; - } - - // BRANCH - public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert -4*1024 <= delta && delta < 4*1024; - assert (delta&1)==0; // Low bit is always zero, not encoded - // Messy branch offset encoding - // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 - // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP - int imm4_1 = (delta>> 1) & 0xF; - int imm10_5= (delta>> 5) &0x3F; - int imm11 = (delta>>11) & 1; - int imm12 = (delta>>12) & 1; - int imm5 = imm4_1<<1 | imm11; - int imm7 = imm12<<6 | imm10_5; - return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; - } - - public enum RM { - RNE, // Round to Nearest, ties to Even - RTZ, // Round towards Zero - RDN, // Round Down - RUP, // Round Up - DIRECT, // Round to Nearest, ties to Max Magnitude - RESERVED1, // Reserved for futue use - RESERVED2, // Reserved for future use - DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved - } - - // Since opcode is the same just return back func3 - static public int jumpop(String op) { - return switch(op) { - case "==" -> 0x0; - case "!=" -> 0x1; - case "<" -> 0x4; - case ">=" -> 0x5; - case "u<" -> 0x6; - case "u<=" -> 0x7; - default -> throw Utils.TODO(); - }; - } - - // Since opcode is the same just return back func3 - static public int fsetop(String op) { - return switch(op) { - case "<" -> 1; - case "<=" -> 0; - case "==" -> 2; - default -> throw Utils.TODO(); - }; - } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; @@ -309,7 +190,6 @@ public class riscv extends Machine { } @Override public int rpc() { return RPC; } - // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index 093e2bd2..74af9266 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -20,19 +21,7 @@ public class AddFMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // addsd xmm0, DWORD PTR [rdi+0xc] - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - // F opcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, ptr, idx, false, enc); - - // FP ADD - enc.add1(0x0F).add1(0x58); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst = src + [base + idx<<2 + 12]" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index 02e0c7ea..c7d0cf9c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,17 +14,7 @@ public class AddFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 58 /r ADDSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x58); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "addf dst += src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java index 0ba390c6..0e652a93 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.SB; @@ -16,9 +17,7 @@ public class AddIX86 extends ImmX86 { @Override public final void encoding( Encoding enc ) { if( _imm== 1 || _imm== -1 ) { short dst = enc.reg(this); // Also src1 - enc.add1( x86_64_v2.rex(0,dst,0)); - enc.add1(0xFF); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, _imm==1 ? 0 : 1, dst) ); + X86.unary(enc,0xFF,_imm==1 ? 0 : 1,dst); } else super.encoding(enc); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java index 3ee721e3..ed65b0a8 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class AddMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // add something to register from memory - // add eax,DWORD PTR [rdi+0xc] - // REX.W + 03 /r ADD r64, r/m64 - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - // opcode - enc.add1(0x03); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0,0x03,true,enc.reg(this),enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst += [base + idx<<2 + 12]" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 14b8e4da..f97163eb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; import com.seaofnodes.simple.node.MachNode; @@ -16,11 +17,7 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // FF /2 CALL r/m64 - // calls the function in the register - short src = enc.reg(fptr()); - enc.add1(0xFF); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,2,src)); + X86.callRegister(enc,enc.reg(fptr())); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index 989895b2..6bafbf37 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -34,7 +35,7 @@ public class CallX86 extends CallNode implements MachNode, RIPRelSize { FunNode fun = CodeGen.CODE.link(_tfp); if( fun==null ) enc.external(this,_name); else enc.relo(this); - enc.add1(0xe8).add4(0); + X86.call(enc); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java index 5b97ef63..5ef7a476 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,16 +12,7 @@ public class CmpFX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // UCOMISD - short src1 = (short)(enc.reg(in(1)) - x86_64_v2.XMM_OFFSET); - short src2 = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // float opcode - enc.add1(0x66); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(src1, src2, 0, false, enc); - - enc.add1(0x0F).add1(0x2E); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src1, src2)); + X86.sse(enc,0x66,0x0F2E,false,enc.reg(in(1))-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "cmp src1,src2" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 8b8318eb..151f8ca8 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -26,14 +27,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode { @Override public Node copy() { return new CmpIX86(this); } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,0x81,7,enc.reg(in(1)),_imm); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index 9d131fc6..4014045b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -16,51 +17,16 @@ public class CmpMemX86 extends MemOpX86 { @Override public String op() { return ((val()==null && _imm==0) ? "test" : "cmp") + _sz; } @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @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()); - - if(src == -1) { + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) { assert !_swap; - int log = _con.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch(log) { - case 0: enc.add1(0x80); break; - case 1: enc.add1(0x66).add1(0x81); break; - case 2: enc.add1(0x81); break; - case 3: enc.add1(0x81); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc); - switch(log) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; - } - } else { - encVal(enc, _con, ptr, idx, src, _off, _scale, _swap); - } + X86.cmpImm(enc,_con.log_size(),_imm,ptr,idx,_off,_scale); + } else encVal(enc,_con,ptr,idx,src,_off,_scale,_swap); } static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale, boolean _swap) { - if(decl instanceof TypeFloat) { - src -= (short)x86_64_v2.XMM_OFFSET; - enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2); - } else { - int log = decl.log_size(); - x86_64_v2.rexF(src, ptr, idx, log == 3, enc); - int swap = _swap ? 2 : 0; - switch(log) { - case 0: enc.add1(0x38+swap); break; - case 1: enc.add1(0x66).add1(0x39+swap); break; - case 2: enc.add1(0x39+swap); break; - case 3: enc.add1(0x39+swap); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + assert !(decl instanceof TypeFloat); // Selected separately as CmpFX86. + X86.cmpMem(enc,decl.log_size(),src,ptr,idx,off,scale,_swap); } // General form: "cmp dst = src, [base + idx<<2 + 12]" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index e7305cdf..7faea17b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,12 +18,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); - short src = enc.reg(in(2)); - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x3B); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x3B,enc.reg(in(1)),enc.reg(in(2))); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index 3427aea5..7bbb5102 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class DivFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5E /r DIVSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5E); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5E,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java index b5904a7f..9f375a80 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,16 +15,7 @@ public class DivX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.RDX_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + F7 /7 IDIV r/m64 - short src = enc.reg(in(2)); - // sign extend rax before 128/64 bits division - // sign extend rax to rdx:rax - enc.add1(x86_64_v2.REX_W); - enc.add1(0x99); - enc.add1(x86_64_v2.rex(0, src, 0)); - // divide - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x07, src)); + X86.divide(enc,enc.reg(in(2))); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java index e905e2e3..1a6ae123 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -20,12 +21,7 @@ public class ExtendX86 extends MachConcreteNode { @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), src = enc.reg(in(1)); - // MOVSX/MOVZX for bytes and shorts; MOVSXD/MOV r32 for ints. - enc.add1(x86_64_v2.rex(dst,src,0,_signed || _bits<32)); - if( _bits==32 ) enc.add1(_signed ? 0x63 : 0x8b); - else enc.add1(0x0f).add1((_signed ? 0xbe : 0xb6) + (_bits==16 ? 1 : 0)); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,dst,src)); + X86.extend(enc,_bits,_signed,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index 15e95374..59f06341 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,20 +18,8 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { if( _ext!=null ) throw Utils.TODO(); - // Load the constant into a FPR - // movsd xmm, [rip + 0] - // F2 0F 10 /r MOVSD xmm1, m64 - _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - _encSize += x86_64_v2.rexF(dst, 0, 0, false, enc); - enc.add1(0x0F).add1(0x10); - // hard-code rip here - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); - enc.add4(0); - enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); + _encSize=X86.rip(enc,0xF2,0x0F10,false,enc.reg(this)-x86_64_v2.XMM_OFFSET); + enc.largeConstant(this,_con,_encSize-4,2/*ELF PC32*/); } // Delta is from opcode start diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index 1724109a..0e44aee7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.FunNode; @@ -25,11 +26,7 @@ public class FunX86 extends FunNode implements MachNode { @Override public void encoding( Encoding enc ) { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust - // opcode: 0x83, addi rsp with immediate 8 - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b101, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); + X86.imm(enc,0x81,5,x86_64_v2.RSP,sz); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java index 9f3d7905..ee357901 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,18 +12,7 @@ public class I2f8X86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public void encoding( Encoding enc ) { - // F2 0F 2A /r CVTSI2SD xmm1, r32/m32 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = enc.reg(in(1)); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, true, enc); - - enc.add1(0x0F).add1(0x2A); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F2A,true,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java index 5e406911..5a4ff4b2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -21,14 +22,7 @@ public abstract class ImmX86 extends MachConcreteNode implements MachNode { abstract int mod(); @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( opcode() + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - 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); + X86.imm(enc,opcode(),mod(),enc.reg(this),_imm); } // General form: "addi dst += #imm" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 1973ea4e..2ffaa3d1 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -24,45 +25,8 @@ public class IntX86 extends ConstantNode implements MachNode { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL || _con==TypeInteger.ZERO ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - if( _ext!=null ) throw Utils.TODO(); - // Simply move the constant into a GPR - // Conditional encoding based on 64 or 32 bits - //REX.W + C7 /0 id MOV r/m64, imm32 - - long imm = ((TypeInteger)_con).value(); - if (Integer.MIN_VALUE <= imm && imm < 0) { - // We need sign extension, so use imm32 into 64 bit register - // REX.W + C7 /0 id MOV r/m64, imm32 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xC7); // 32 bits encoding - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x00, dst)); - enc.add4((int)imm); - } else if (0 <= imm && imm <= 0xFFFFFFFFL) { - // We want zero extension into 64 bit register - // so move 32 bit into 32 bit register which zeros - // the upper bits in the 64 bit register. - // B8+ rd id MOV r32, imm32 - if (dst >= 8) enc.add1(0x41); - enc.add1(0xB8 + (dst & 0x07)); - enc.add4((int)imm); - } else { - // Just write the full 64 bit constant - // REX.W + B8+ rd io MOV r64, imm64 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xB8 + (dst & 0x07)); - enc.add8(imm); // 64 bits encoding - } + X86.constant(enc,enc.reg(this),_con==Type.NIL ? 0 : ((TypeInteger)_con).value()); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index de27aa5c..10cee059 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -30,38 +31,21 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { @Override public void negate() { _bop = negate(_bop); } @Override public void encoding( Encoding enc ) { - if( in(1)!=null ) { - int op = x86_64_v2.jumpop(_bop); - enc.add1(op-16).add1(0); // Short form jump - } else { - if( _bop=="!=" ) return; // Inverted, no code - enc.add1(0xEB).add1(0); // Never-node - } + if( in(1)==null && _bop=="!=" ) return; + X86.branch(enc,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); enc.jump(this,cproj(0)); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding @Override public byte encSize(int delta) { - if( in(1)==null && _bop=="!=" ) return 0; // Inverted never-node, no code - return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 6); + if( in(1)==null && _bop=="!=" ) return 0; + return X86.branchSize(delta,in(1)!=null); } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 6; // Offset from opcode END - bits[opStart] = 0x0F; - bits[opStart+1] = (byte)(in(1)==null ? 0xE9 : x86_64_v2.jumpop(_bop)); - enc.patch4(opStart+2,delta); - } + assert !(in(1)==null && _bop=="!="); + X86.patchBranch(enc.bits(),opStart,opLen,delta,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java index 2cd6018f..4b00e4dd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -23,25 +24,7 @@ public class LeaX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 8D /r LEA r64,m - short dst = enc.reg(this); - short ptr = enc.reg(in(1)); - short idx = enc.reg(in(2)); - // ptr is null - // just do: [(index * s) + disp32] - if( ptr == -1 ) { - enc.add1(x86_64_v2.rex(dst, 0, idx)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x04)); - enc.add1(x86_64_v2.sib(_scale, idx, x86_64_v2.RBP)); - enc.add4(_offset); - return; - } - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - enc.add1(0x8D); // opcode - // rsp is hard-coded here(0x04) - x86_64_v2.indirectAdr(_scale, idx, ptr, _offset, dst, enc); + X86.lea(enc,enc.reg(this),enc.reg(in(1)),enc.reg(in(2)),_offset,_scale); } // General form: "lea dst = base + 4*idx + 12" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java index aca0eea1..5c472dbe 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -24,33 +25,14 @@ public class LoadX86 extends MemOpX86 { } static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) { - // Allocation may put a full-width integer in an XMM register (or a - // floating value in a GPR). Move its bits using the selected register bank. - if( dst>=x86_64_v2.XMM_OFFSET && decl.log_size()==3 ) decl=TypeFloat.F64; - else if( dst<x86_64_v2.XMM_OFFSET && decl instanceof TypeFloat ) - decl = decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; - if( decl == TypeFloat.F32) enc.add1(0xF3); - if( decl == TypeFloat.F64) enc.add1(0xF2); - - if( decl.isa(TypeFloat.F64) ) - dst -= (short)x86_64_v2.XMM_OFFSET; - - x86_64_v2.rexF(dst, ptr, idx, decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64, enc); - - if( false ) ; - else if( decl == TypeFloat.F32 ) enc.add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32 - else if( decl == TypeFloat.F64 ) enc.add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64 - else if( decl.isa(TypeInteger.I8)) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8 - else if( decl == TypeInteger.I16 ) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16 - else if( decl == TypeInteger.I32 ) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32 - else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8 - else if( decl == TypeInteger.U16 ) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16 - // Covers U32, I64/BOT, TMP - else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32 - else throw Utils.TODO(); - - // includes modrm internally - x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc); + // The chapter chooses the register bank and extension from its own type facts. + boolean xmm=dst>=x86_64_v2.XMM_OFFSET; + if( xmm && decl.log_size()==3 ) decl=TypeFloat.F64; + else if( !xmm && decl instanceof TypeFloat ) + decl=decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; + boolean signed=decl.isa(TypeInteger.I8) || decl==TypeInteger.I16 || decl==TypeInteger.I32; + X86.load(enc,decl.log_size(),signed,xmm, + xmm ? dst-x86_64_v2.XMM_OFFSET : dst,ptr,idx,off,scale); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index bd56d022..2e18a058 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,20 +16,7 @@ public class MemAddX86 extends MemOpX86 { @Override public RegMask outregmap() { return null; } @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // add something to memory - // REX.W + 01 /r | REX.W + 81 /0 id - // ADD [mem], imm32/reg - 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 - enc.add1( src == -1 ? (_imm==1 ? 0xFF : 0x81): 0x01); - - // includes modrm - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc); - if( src == -1 && _imm!=1 ) enc.add4(_imm); + X86.addMem(enc,enc.reg(val()),_imm,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add [base + idx<<2 + 12] += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index 7932c893..74616db7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,16 +14,7 @@ public class MulFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 59 /r MULSD xmm1,xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x59).add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F59,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "mulf dst *= src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 1e9e708f..5dcb253d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,15 +18,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } // Rare 3-address form @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // Also src1 - short src = enc.reg(in(1)); - enc.add1(x86_64_v2.rex(dst, src, 0)); - // opcode; 0x69 or 0x6B - enc.add1( 0x69 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imul(enc,enc.reg(this),enc.reg(in(1)),_imm); } // General form: "addi dst += #imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java index 4d2a11ed..6f3fcdeb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,13 +14,7 @@ public class MulX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // REX.W + 0F AF /r IMUL r64, r/m64 - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xAF); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x0FAF,enc.reg(this),enc.reg(in(2))); } // General form: "mul dst *= src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java index 0c2baced..86610f6d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,10 +14,7 @@ public class NegX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 3, dst)); + X86.unary(enc,0xF7,3,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index 40a38809..d6a06c2f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -10,11 +11,8 @@ public class NewX86 extends NewNode implements MachNode { NewX86( NewNode nnn ) { super(nnn); } @Override public void encoding( Encoding enc ) { enc.external(this,"calloc"); - // ldi rcx,#1 // number of elements to calloc - enc.add1(0xB8 + _arg2Reg).add4(1); - // E8 cd CALL rel32; - enc.add1(0xE8); - enc.add4(0); // offset + X86.constant(enc,_arg2Reg,1); + X86.call(enc); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java index 7db80299..1e4e7c26 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,25 +13,9 @@ public class NotX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - assert !(in(1) instanceof NotNode); // Cleared out by peeps - assert !(in(1) instanceof BoolNode); // Cleared out by peeps - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - - // test rdi,rdi - enc.add1(x86_64_v2.rex(src, src, 0)); - enc.add1(0x85); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src, src)); - - // setz dstb; then zero-extend the low byte into the full register. - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0x94); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0xB6); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + assert !(in(1) instanceof NotNode); // Cleared out by peeps + assert !(in(1) instanceof BoolNode); + X86.not(enc,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java index 5a475efe..06755143 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,13 +13,7 @@ public abstract class RegX86 extends MachConcreteNode { @Override public int twoAddress() { return 1; } abstract int opcode(); @Override public void encoding( Encoding enc ) { - // REX.W + 01 /r - short dst = enc.reg(in(1)); // src1 - short src = enc.reg(in(2)); // src2 - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); } // General form: "add dst += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index a35d43a2..e4467bb4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -8,12 +9,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public void encoding( Encoding enc ) { int sz = fun()._frameAdjust; - if( sz != 0 ) { - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b000, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); - } - enc.add1(0xC3); + if( sz!=0 ) X86.imm(enc,0x81,0,x86_64_v2.RSP,sz); + X86.ret(enc); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index 95e0c336..cf6275dc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,15 +23,7 @@ public class SarIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @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); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index 4cc8b558..92493712 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class SarX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst)); + X86.unary(enc,opcode(),7,enc.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 177e35ab..864c1b55 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -24,27 +25,15 @@ public class SetX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX + 0F 94 - short dst = enc.reg(this ); - - // Optional rex, for dst - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(switch (_bop) { + int op=switch (_bop) { case "==" -> 0x94; // SETE case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE case ">" -> _unsigned ? 0x97 : 0x9F; // SETA /SETG default -> throw Utils.TODO(); - }); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - - // low 8 bites are set, now zero extend for next instruction - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(0xB6); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + }; + X86.set(enc,op&15,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index f7b2f28a..1e62243e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -23,15 +24,7 @@ public class ShlIX86 extends MachConcreteNode implements MachNode { @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } @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); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java index 5fee72d9..768d97e7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShlX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 4, dst)); + X86.unary(enc,opcode(),4,enc.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 7e0378b1..8a0d1b58 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -18,15 +19,7 @@ public class ShrIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @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); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java index 67dcf055..1ba20fee 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShrX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 5, dst)); + X86.unary(enc,opcode(),5,enc.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index bc3d421d..b2b643d3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -18,44 +19,17 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. @Override public void encoding( Encoding enc ) { - // REX.W + 8B /r MOV r64, r/m64 - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - if( dst == x86_64_v2.FLAGS ) { - // mov reg, flags - // push rcx - // popf (Pop the top of the stack into the FLAGS register) - // 50+rd PUSH r64 - x86_64_v2.rexF(0,src,0,false,enc); - enc.add1(0x50 + src); - // popf - enc.add1(0x9D); - return; - } - if( src == x86_64_v2.FLAGS ) { - // mov flags, reg - // pushf; pop reg - enc.add1(0x9C); - // 58+ rd POP r64 - x86_64_v2.rexF(0,dst,0,false, enc); - enc.add1(0x58 + dst); - return; - } - - // Flag for being either XMM or stack - boolean dstX = dst >= x86_64_v2.XMM_OFFSET; - boolean srcX = src >= x86_64_v2.XMM_OFFSET; - + short dst=enc.reg(this), src=enc.reg(in(1)); + if( dst==x86_64_v2.FLAGS ) { X86.flags(enc,src,true); return; } + if( src==x86_64_v2.FLAGS ) { X86.flags(enc,dst,false); return; } + boolean dstX=dst>=x86_64_v2.XMM_OFFSET, srcX=src>=x86_64_v2.XMM_OFFSET; // Stack spills if( dst >= x86_64_v2.MAX_REG ) { int off = fun(enc).computeStackOffset(enc._code,dst); if( src >= x86_64_v2.MAX_REG ) { // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] int soff = fun(enc).computeStackOffset(enc._code,src); - enc.add1(0xFF); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); - enc.add1(0x8F); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + X86.stackCopy(enc,soff,off); return; } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); @@ -67,34 +41,7 @@ public class SplitX86 extends SplitNode { return; } - // reg-reg move. Adjust numbering for GPR vs FPR reg set - if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; - if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; - - // 0x66 if moving between register classes - if( dstX ^ srcX ) enc.add1(0x66); - if( !dstX && srcX ) - { short tmp=src; src=dst; dst=tmp; } - enc.add1(x86_64_v2.rex(dst, src, 0)); - - // pick opcode based on regs - if( !dstX && !srcX ) { - // reg->reg (MOV r64, r/m64) - enc.add1(0x8B); - } else if( dstX && srcX ) { - // xmm->xmm (NP 0F 28 /r MOVAPS xmm1, xmm2/m128) - enc.add1(0x0F); - enc.add1(0x28); - } else if( dstX && !srcX ) { - // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) - enc.add1(0x0F); - enc.add1(0x6E); - } else if( !dstX && srcX ) { - // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) - enc.add1(0x0F); - enc.add1(0x7E); - } - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.move(enc,dstX,srcX,dstX ? dst-x86_64_v2.XMM_OFFSET : dst, + srcX ? src-x86_64_v2.XMM_OFFSET : src); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index 7133e824..9ffa25fc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -25,55 +26,16 @@ public class StoreX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // REX.W + C7 /0 id MOV r/m64, imm32 | - // REX.W + 89 /r MOV r/m64, r64 - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if( src == -1 ) { - int log = Integer.numberOfTrailingZeros(_sz-'0'); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch( log ) { - case 0: enc .add1(0xC6); break; - case 1: enc.add1(0x66).add1(0xC7); break; - case 2: enc .add1(0xC7); break; - case 3: enc .add1(0xC7); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc); - switch( log ) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate - } - } else { - encVal(enc,_con,ptr,idx,src,_off,_scale); - } + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) X86.storeImm(enc,Integer.numberOfTrailingZeros(_sz-'0'),_imm,ptr,idx,_off,_scale); + else encVal(enc,_con,ptr,idx,src,_off,_scale); } // Non-immediate encoding static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) { - int log = decl.log_size(); - // Float reg being stored - if( src >= x86_64_v2.XMM_OFFSET ) { - src -= (short)x86_64_v2.XMM_OFFSET; - assert log == 2 || log == 3; - enc.add1( log==2 ? 0xF3 : 0xF2 ); - x86_64_v2.rexF(src,ptr,idx,false,enc); - enc.add1(0x0F).add1(0x11); - } else { - // byte stores from sil, dil, bpl, spl need a rex - if( log == 0 && src >= x86_64_v2.RSP ) enc.add1(x86_64_v2.rex(src,ptr,idx,false)); - else x86_64_v2.rexF(src,ptr,idx,log==3,enc); - switch( log ) { - case 0: enc .add1(0x88); break; - case 1: enc.add1(0x66).add1(0x89); break; - case 2: enc .add1(0x89); break; - case 3: enc .add1(0x89); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + boolean xmm=src>=x86_64_v2.XMM_OFFSET; + X86.store(enc,decl.log_size(),xmm, + xmm ? src-x86_64_v2.XMM_OFFSET : src,ptr,idx,off,scale); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index b6530a87..29f0033a 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,16 +13,7 @@ public class SubFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5C /r SUBSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5C); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5C,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "subf dst -= src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index fe2060ba..e3563713 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -25,17 +26,9 @@ public class TFPX86 extends FunPtrNode implements MachNode, RIPRelSize { @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - if( _ext==null ) enc.relo(this); // Internal patch - else enc.external(this,_ext); // ELF-file external patch - // lea to load function pointer address - // lea rax, [rip+disp32] - short dst = enc.reg(this); - // 0 or 1 for REX depending on the dst. - // Zero/sign extend should be fine, so not wide. - _opLen = (byte)(6+ x86_64_v2.rexF(dst, 0, 0, true, enc)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); - enc.add4(0); + if( _ext==null ) enc.relo(this); + else enc.external(this,_ext); + _opLen=X86.rip(enc,0,0x8D,true,enc.reg(this)); } @Override public byte encSize(int delta) { return _opLen; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java index fbd79dd7..682597f4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeMemPtr; @@ -18,8 +19,7 @@ public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { short dst = enc.reg(this); // 0 or 1 for REX depending on the dst. - _opLen = (byte)(6+ x86_64_v2.rexF(dst, 0, 0, true, enc)); - enc.add1(0x8D).add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)).add4(0); + _opLen = X86.rip(enc,0,0x8D,true,dst); if( _ext!=null ) enc.externalData(this,_ext); else enc.largeConstant(this,((TypeMemPtr)_con)._obj, _opLen-4, 2/*ELF encoding PC32*/); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java index 6f538d27..591a51c3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,29 +20,17 @@ public class UJmpX86 extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - // Short-form jump - enc.add1(0xEB).add1(0); - //// E9 cd JMP rel32 - //enc.add1(0xE9).add4(0); + X86.branch(enc,-1); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding - @Override public byte encSize(int delta) { return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 5); } + @Override public byte encSize(int delta) { + return X86.branchSize(delta,false); + } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert bits[opStart] == (byte)0xEB; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert bits[opStart] == (byte)0xEB; - bits[opStart] = (byte)0xE9; // Long form - delta -= 5; // Offset from opcode END - enc.patch4(opStart+1,delta); - } + X86.patchBranch(enc.bits(),opStart,opLen,delta,-1); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 99010ffd..f006411e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -69,13 +69,6 @@ public class x86_64_v2 extends Machine { public static int REX_WRB= 0x4D; public static int REX_WB = 0x49; - public enum MOD { - INDIRECT, // [mem] - INDIRECT_disp8, // [mem + 0x12] - INDIRECT_disp32, // [mem + 0x12345678] - DIRECT, // mem - }; - // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -95,90 +88,6 @@ public class x86_64_v2 extends Machine { }; } - public static int modrm(MOD mod, int reg, int m_r) { - if( reg == -1 ) reg=0; // Missing reg in this flavor - // combine all the bits - assert 0 <= reg && reg < 16; - assert 0 <= m_r && m_r < 16; - return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07; - } - - // 00 000 000 - // same bit-layout as modrm - public static int sib(int scale, int index, int base) { - assert 0 <= base && base < 16; - assert 0 <= index && index < 16; - return (scale << 6) | ((index & 0x07) << 3) | base & 0x07; - } - - // reg1 is reg(R) - // reg2 is r/mem(B) - // reg3 is X(index) - // reg4 is X(base) - - // 0 denotes no direct register - public static int rex(int reg, int ptr, int idx, boolean wide) { - // assuming 64 bit by default so: 0100 1000 - assert -1 <= reg && reg < 16; - assert -1 <= ptr && ptr < 16; - assert -1 <= idx && idx < 16; - - int rex = wide ? REX_W : REX; - if( 8 <= reg ) rex |= 0b00000100; // REX.R - if( 8 <= ptr ) rex |= 0b00000001; // REX.B - if( 8 <= idx ) rex |= 0b00000010; // REX.X - return rex; - } - - public static int rex(int reg, int ptr, int idx) { - return rex(reg, ptr, idx, true); - } - - // rex for floats. Return size (0 or 1) - // don't need to use REX if 0x40. - public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { - int rex = rex(reg, ptr, idx, wide); - if (rex == REX) return 0; - enc.add1(rex); - return 1; - } - // Function used for encoding indirect memory addresses - // Does not always generate SIB byte e.g index == -1. - // -1 denotes empty value, not set - note 0 is different from -1 as it can represent rax. - // Looks for best mod locally - public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { - // Assume indirect - assert 0 <= base && base < 16; - 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; - - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { - mod = MOD.INDIRECT_disp8; - } else if( index == -1 && (base == RSP || base == R12) ) { - index = RSP; - } - - if( index == -1 ) { - enc.add1(modrm(mod, reg, base)); - } else { - enc.add1(modrm(mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, index, base)); - } - - if( mod == MOD.INDIRECT_disp8 ) { - enc.add1(offset); - } else if( mod == MOD.INDIRECT_disp32 ) { - enc.add4(offset); - } - } - - // Limit of float args passed in registers static RegMask[] XMMS8 = new RegMask[]{ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3), diff --git a/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index f3da1592..c2713e4f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import java.io.IOException; import org.junit.Test; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java index a400dc5f..c3d93188 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java index 35e0144a..82211985 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.util.Utils; import com.seaofnodes.simple.codegen.CodeGen; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java index 2f0490a5..dad1dde4 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java index a94f36f2..05dfe1c2 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java index 7158ace0..c05c13f1 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.ElfReader; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java deleted file mode 100644 index 1503adb5..00000000 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ /dev/null @@ -1,767 +0,0 @@ -package com.seaofnodes.simple; - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.arm.arm; -import com.seaofnodes.simple.util.Utils; -import java.io.ByteArrayOutputStream; - -public class EvalArm64 { - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - // flags - boolean N = false; - boolean Z = false; - boolean C = false; - boolean V = false; - - EvalArm64(byte[] buf, int stackSize) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[arm.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - 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); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - public int step(int maxops) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - outer: - for(int icount = 0; icount < maxops; icount++) { - boolean is_f = false; - int ir = 0; - rval = 0; - frval = 0; - cycle++; - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - - // Load instruction from image buffer at PC - ir = ld4s( pc ); - - int rdid = ir & 0x1f; - // [31:24] - int opcode1 = (ir >> 24) & 0xFF; - - // for the opcode we just match for bits[31:24]; - switch( opcode1 ) { - case 0x14, 0x15, 0x16, 0x17: { //b - int imm26 = ir << 6 >> 6; - pc = pc + (imm26 * 4) - 4; - rdid = -1; - break; - } - case 0x1E: { // floats - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - int rs2 = (ir >> 16) & 0x1F; - - int op = (ir >> 10) & 0x3F; - switch(op) { - case 16: frval = fregs[rs1]; break; // fmov - case 10: frval = fregs[rs1] + fregs[rs2]; break; // fadd - - case 6: if (fregs[rs2] == 0) frval = 0; else frval = fregs[rs1] / fregs[rs2]; break; // fdiv - case 8: { - // fcmp - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - - Z = (lhs == rhs); - N = (lhs < rhs); - C = (lhs > rhs); - V = Double.isNaN(lhs) || Double.isNaN(rhs); - rdid = -1; - break; - } - case 2: frval = fregs[rs1] * fregs[rs2]; break; // fmul - case 14: frval = fregs[rs1] - fregs[rs2]; break; // fsub - default: trap = (2+1); - } - break; - } - - case 0x38: { - // STRB/LDRB(register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch( ir >> 21 & 0x7 ) { - case 0x1 -> { // store - if( opcode1 == arm.OP_STORE_R_8 ) st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - else trap = (2+1); - rdid = -1; - } - case 0x3 -> { // load - if( opcode1 == arm.OP_LOAD_R_8 ) rval = ld1s((int)regs[rn] + (int)regs[rm]); - else trap = (2+1); - } - default -> trap = (2+1); - } - break; - } - case 0x39: { - // STRB/LDRB(immediate) - // str/ldr(immediate) - // rn - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_8) { - st1((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_8) { - rval = ld1s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - case 0x54: { - // b.cond - int imm19 = ir << 8 >> 13; - imm19 = pc + (imm19 * 4) - 4; - rdid = -1; - - switch(ir & 0xF) { - case 0x0: if(Z) pc = imm19; break; // eq - case 0x1: if(!Z) pc = imm19; break; // ne - case 0x2: if(C) pc = imm19; break; // cs - case 0x3: if(!C) pc = imm19; break; - case 0x4: if(N) pc = imm19; break; // mi - case 0x5: if(!N) pc = imm19; break; // pl - case 0x6: if(V) pc = imm19; break; // vs - case 0x7: if(!V) pc = imm19; break; // vc - case 0x8: if(C && !Z) pc = imm19; break; // hi - case 0x9: if(!C || Z) pc = imm19; break; // ls - case 0xA: if(N == V) pc = imm19; break; // ge - case 0xB: if(N != V) pc = imm19; break; // lt - case 0xC: if(!Z && N == V) pc = imm19; break; // gt - case 0xD: if(Z || N != V) pc = imm19; break; // le - case 0xE: pc = imm19; break; // always executed(al) - default: trap = (2+1); - } - break; - } - - case 0x5c: { - // ldr - is_f = true; - // address = delta - int address = ir << 8 >> 13; - address *= 4; - if(address >= _buf.length-3) trap = (5 + 1); - frval = ld8f(pc + address); - break; - } - - case 0x78: { - // STRH/LDRH(register) - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - // store - if(opcode1 == arm.OP_STORE_R_16) { - st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_16) { - rval = ld1s((int)regs[rn] + (int)regs[rm]); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - break; - } - - case 0x79: { - // STRH/LDRH(immediate) - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 2; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_16) { - st2((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_16) { - rval = ld2s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - - case 0x8A: { // AND - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] & regs[rm]; - break; - } - - case 0x8B, 0xCB: { - // add/sub(register), unshifted form emitted by Simple - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = opcode1==0x8B ? lhs + rhs : lhs - rhs; - break; - } - - case 0x90, 0xB0, 0xD0, 0xF0: { // adrp - int immhi = ( ir << 8 ) >>> (8+5); - int immlo = (ir>>29)& 3; - int imm = ((immhi<<2) | immlo); - imm = (imm << 11) >> 11; - imm <<= 12; - rval = (pc & ~0xFFF) + imm; - break; - } - - case 0x91, 0xD1: { // ADD/SUB (immediate), unsigned imm12, optional LSL #12 - int rn = (ir >> 5) & 0x1F; - long immediate = (ir >>> 10) & 0xFFF; - if( (ir & (1<<22))!=0 ) immediate <<= 12; - rval = opcode1==0x91 ? regs[rn] + immediate : regs[rn] - immediate; - break; - } - case 0x92: { // and(immediate) - int imm12 = (ir >> 10) & 0x1FFF; - long immediate = arm.decodeImm12(imm12); - int rn = (ir >> 5) & 0x1F; - rval = regs[rn] & immediate; - break; - } - case 0x93, 0xD3: { // SBFM/UBFM: shifts and signed/unsigned extracts - int immr = (ir >>> 16) & 63; - int imms = (ir >>> 10) & 63; - int rn = (ir >>> 5) & 31; - boolean signed = (ir & 0x40000000)==0; - long value = regs[rn] << (63-imms); - value = signed ? value >> (63-imms) : value >>> (63-imms); - rval = immr > imms ? value << (64-immr) - : signed ? value >> immr : value >>> immr; - break; - } - - case 0x94, 0x95, 0x96, 0x97: { // bl - rdid = -1; // BL writes only X30, not a displacement-selected register. - rval = pc + 4; - regs[arm.X30] = rval; - int imm26 = (ir & 0x03FFFFFF); - int imm = (imm26 << 6) >> 6; - pc = pc + (imm << 2) ; - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - long size = regs[arm.X0]*regs[arm.X1]; - size = (size+7) & -8; // 8-byte aligned - regs[arm.X0] = _heap; - _heap += (int)size; - pc = (int)rval; - } - if( pc == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[0]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[1],(int)regs[2]); - regs[0] = regs[2]; - pc = (int)rval; - } - pc -= 4; - rdid = -1; - break; - } - - case 0x9A: { - int encodedCond = (ir >> 12) & 0xF; - int decodedCond = encodedCond ^ 1; - // conditional select(csel) - boolean cond = switch (decodedCond) { - case 0x0 -> Z ; // eq - case 0x1 -> !Z ; // ne - case 0x2 -> C ; // cs - case 0x3 -> !C ; // cc - case 0x4 -> N ; // mi - case 0x5 -> !N ; // pl - case 0x6 -> V ; // vs - case 0x7 -> !V ; // vc - case 0x8 -> ( C && !Z ) ; // hi - case 0x9 -> (!C || Z ) ; // ls - case 0xA -> ( N == V) ; // ge - case 0xB -> ( N != V) ; // lt - case 0xC -> (!Z && N == V) ; // gt - case 0xD -> ( Z || N != V ); // le - case 0xE -> true ; // always - case 0xF -> false ; // never - default -> throw Utils.TODO(); - }; - if( cond ) rval = 1; - break; - } - case 0x9B: { // mul - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] * regs[rm]; - break; - } - case 0x9E: { - // scvtf - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - frval = (double)regs[rs1]; - break; - } - - case 0xAA: { - // MOV(register) - int rm = (ir >> 16) & 0x1F; - rval = regs[rm]; - break; - } - - case 0xB8: { - // LDR/STR (register + index) 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if( opcode1 == arm.OP_LOAD_R_32) { - rval = ld4s((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xB9: { - // str/ldr(immediate) 32 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 4; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_32) { - rval = ld4s((int) rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xBC: { - // LDR/STR (register + index) float 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_32) { - frval = ld4f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xBD: { - // LDR/STR(immediate) 32 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 4; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xD2: // MOVZ - case 0xF2: { // MOVK preserves the other halfwords - // movz - // get immediate - int shift = ((ir >> 21) & 3)*16; - rval = ((ir >> 5) & 0xFFFFL) << shift; - if( opcode1==0xF2 ) rval |= regs[rdid] & ~(0xFFFFL << shift); - break; - } - - case 0xEB: { - // subs(shifted register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = lhs - rhs; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= rhs; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (rhs >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - - case 0xD6: { - int op = ir & 0xFFFFFC1F; - int rn = (ir >>> 5) & 31; - int target = (int)regs[rn]; // Read before BLR overwrites X30. - rdid = -1; - if( op==0xD63F0000 ) regs[arm.X30] = pc+4; // BLR - else if( op!=0xD65F0000 ) { trap = 3; break; } // RET - pc = target; - if( op==0xD65F0000 && pc==0 ) break outer; - pc -= 4; - break; - } - - case 0xF1: { - // subs(immediate) - int rn = (ir >> 5) & 0x1F; - int immediate = ir << 10 >> 20; - long lhs = regs[rn]; - - rval = lhs - immediate; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= immediate; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (immediate >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - case 0xF8: { - // LDR/STR (register + index) 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_64) { - rval = ld8((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xF9: { - // str/ldr(immediate) 64 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_64) { - st8((int)rval, regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_64) { - rval = ld8((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xFC: { - // LDR/STR (register + index) float 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_64) { - frval = ld8f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xFD: { - // LDR/STR(immediate) 64 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - default: trap = (2+1); - } - - if(trap != 0) { - _pc = pc; - break; - } - if(rdid != -1) { - if(is_f) fregs[rdid] = frval; - else regs[rdid] = rval; - } - - pc += 4; - } - // Handle traps and interrupts. - if(trap != 0) - return trap; - _cycle = cycle; - _pc = pc; - return 0; - } - - -} diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java deleted file mode 100644 index 633e931e..00000000 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ /dev/null @@ -1,368 +0,0 @@ - package com.seaofnodes.simple; - -/** Simple RISC5 CPU Emulator - * - * Original works credit Charles Lohr. - * This is a complete rewrite in Java. - * - * Load code into memory and go! - */ - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.riscv.riscv; -import com.seaofnodes.simple.util.Utils; -import java.io.ByteArrayOutputStream; -import java.util.Arrays; - -public class EvalRisc5 { - - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - // PC - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - EvalRisc5( byte[] buf, int stackSize ) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[riscv.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - 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); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - // Note: only a few bits are used. (Machine = 3, User = 0) - // Bits 0..1 = privilege. - // Bit 2 = WFI (Wait for interrupt) - // Bit 3+ = Load/Store reservation LSBs. - int _extraflags; - - public int step( int maxops ) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for( int icount = 0; icount < maxops; icount++ ) { - int ir = 0; - rval = 0; - cycle++; - - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - // Load instruction from image buffer at PC - ir = ld4s( pc ); - int rdid = (ir >> 7) & 0x1f; - - switch( ir & 0x7f ) { - case 0x37: // LUI (0b0110111) - rval = ( ir & 0xfffff000 ); - break; - case 0x17: // AUIPC (0b0010111) - rval = pc + ( ir & 0xfffff000 ); - break; - case 0x6F: { // JAL (0b1101111) - int reladdy = ((ir & 0x80000000)>>11) | ((ir & 0x7fe00000)>>20) | ((ir & 0x00100000)>>9) | ((ir&0x000ff000)); - if( (reladdy & 0x00100000)!=0 ) reladdy |= 0xffe00000; // Sign extension. - rval = pc + 4; - pc = pc + reladdy - 4; - if( pc+4 == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[10]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[11],(int)regs[12]); - regs[10] = regs[12]; - rdid = 0; - pc = (int)(rval - 4); // Unwind PC, as-if returned from write - } - break; - } - case 0x67: { // JALR (0b1100111) - int imm_se = ir >> 20; // Sign extend 12 bits - rval = pc + 4; - pc = ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1; - // Return from top-level ; exit sim - if( pc==0 ) { - if( rdid!=0 ) regs[rdid] = rval; // Write PC into register before exit - break outer; - } - // Inline CALLOC effect - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - int size = (int)(regs[10]*regs[11]); - size = (size+7) & -8; // 8-byte aligned - regs[10] = _heap; // Return next free address - _heap += size; - pc = (int)(rval - 4); // Unwind PC, as-if returned from calloc - } else - pc -= 4; - break; - } - case 0x63: { // Branch (0b1100011) - int immm4 = ((ir & 0xf00)>>7) | ((ir & 0x7e000000)>>20) | ((ir & 0x80) << 4) | ((ir >> 31)<<12); - if( (immm4 & 0x1000)!=0 ) immm4 |= 0xffffe000; - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - immm4 = pc + immm4 - 4; - rdid = 0; - if( switch( (ir >> 12) & 0x7 ) { - case 0 -> rs1 == rs2; - case 1 -> rs1 != rs2; - case 4 -> rs1 < rs2; - case 5 -> rs1 >= rs2; - case 6 -> Long.compareUnsigned(rs1,rs2) < 0; //BLTU - case 7 -> Long.compareUnsigned(rs1,rs2) >= 0; //BGEU - default -> { trap = (2+1); yield false; } - } ) pc = immm4; - break; - } - case 0x03: { // Load (0b0000011) - 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 ) { - //LB, LH, LW, LBU, LHU - case 0: rval = ld1s( rsval ); break; - case 1: rval = ld2s( rsval ); break; - case 2: rval = ld4s( rsval ); break; - case 3: rval = ld8 ( rsval ); break; - case 4: rval = ld1z( rsval ); break; - case 5: rval = ld2z( rsval ); break; - case 6: rval = ld4s( rsval ); break; - default: trap = (2+1); - } - } - 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]; - int addy = ( ( ir >> 7 ) & 0x1f ) | ( ( ir & 0xfe000000 ) >> 20 ); - if( (addy & 0x800)!=0 ) addy |= 0xfffff000; - addy += rs1; - rdid = 0; - if( addy >= _buf.length-3 ) { - trap = (7+1); // Store access fault. - rval = addy; - } else { - switch( ( ir >> 12 ) & 0x7 ) { //SB, SH, SW - case 0: st1( addy, (int)rs2 ); break; - case 1: st2( addy, (int)rs2 ); break; - case 2: st4( addy, (int)rs2 ); break; - case 3: st8( addy, rs2 ); break; - default: trap = (2+1); - } - } - break; - } - case 0x13: // Op-immediate 0b0010011 - case 0x33: { // Op 0b0110011 - int imm = ir >> 20; - imm = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); - long rs1 = regs[(ir >> 15) & 0x1f]; - boolean is_reg = (ir & 0x20)!=0; - long rs2 = is_reg ? regs[imm & 0x1f] : imm; - - // Insert the detection here - int rs1id = (ir >> 15) & 0x1f; - int funct3 = (ir >> 12) & 0x7; - - if( is_reg && ( ir & 0x02000000 )!=0 ) { - switch( (ir>>12)&7 ) { //0x02000000 = RV32M - case 0: rval = rs1 * rs2; break; // MUL - case 1: rval = (int)((long)((int)rs1) * (long)((int)rs2)) >> 32; break; // MULH - case 2: rval = (int)((long)((int)rs1) * (long)rs2) >> 32; break; // MULHSU - case 3: rval = (int)((long)rs1 * (long)rs2) >> 32; break; // MULHU - case 4: if( rs2 == 0 ) rval = -1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? rs1 : ((int)rs1 / (int)rs2); break; // DIV - case 5: if( rs2 == 0 ) rval = 0xffffffff; else rval = rs1 / rs2; break; // DIVU - case 6: if( rs2 == 0 ) rval = rs1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? 0 : ((int)((int)rs1 % (int)rs2)); break; // REM - case 7: if( rs2 == 0 ) rval = rs1; else rval = rs1 % rs2; break; // REMU - } - } else { - rval = switch( (ir >> 12) & 7 ) { // These could be either op-immediate or op commands. Be careful. - case 0 -> (is_reg && (ir & 0x40000000) != 0) ? (rs1 - rs2) : (rs1 + rs2); - case 1 -> rs1 << (rs2 & 0x3F); - case 2 -> (rs1 < rs2) ? 1 : 0; - case 3 -> (rs1 < rs2) ? 1 : 0; - case 4 -> rs1 ^ rs2; - case 5 -> (ir & 0x40000000) != 0 ? (rs1 >> (rs2 & 0x3F)) : (rs1 >>> (rs2 & 0x3F)); - case 6 -> rs1 | rs2; - case 7 -> rs1 & rs2; - default -> rval; - }; - } - break; - } - case 0x0f: // 0b0001111 - rdid = 0; // fencetype = (ir >> 12) & 0b111; We ignore fences in this impl. - break; - case 0x73: // Zifencei+Zicsr (0b1110011) - trap = (2+1); // Note micrrop 0b100 == undefined. - break; - - case 0x2f: { // RV32A (0b00101111) - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - int irmid = ( ir>>27 ) & 0x1f; - - // We don't implement load/store from UART or CLNT with RV32A here. - if( rs1 >= _buf.length-3 ) { - trap = (7+1); //Store/AMO access fault - rval = rs1; - } else { - rval = ld4s( (int)rs1 ); - - // Referenced a little bit of https://github.com/franzflasch/riscv_em/blob/master/src/core/core.c - boolean dowrite = true; - switch( irmid ) { - case 2: //LR.W (0b00010) - dowrite = false; - _extraflags = (_extraflags & 0x07) | (int)(rs1<<3); - break; - case 3: { //SC.W (0b00011) (Make sure we have a slot, and, it's valid) - boolean xflag = _extraflags >> 3 != ( rs1 & 0x1fffffff ); - rval = xflag ? 1 : 0; // Validate that our reservation slot is OK. - dowrite = !xflag; // Only write if slot is valid. - break; - } - case 0: rs2 += rval; break; // AMOADD.W (0b00000) - case 1: break; // AMOSWAP.W (0b00001) - case 4: rs2 ^= rval; break; // AMOXOR.W (0b00100) - case 8: rs2 |= rval; break; // AMOOR.W (0b01000) - case 12: rs2 &= rval; break; // AMOAND.W (0b01100) - case 16: rs2 = Math.min( rs2, rval ); break; //AMOMIN.W (0b10000) - case 20: rs2 = Math.max( rs2, rval ); break; //AMOMAX.W (0b10100) - case 24: rs2 = Math.min( rs2, rval ); break; //AMOMINU.W (0b11000) - case 28: rs2 = Math.max( rs2, rval ); break; //AMOMAXU.W (0b11100) - default: trap = (2+1); dowrite = false; break; //Not supported. - } - if( dowrite ) st4( (int)rs1, (int)rs2 ); - } - break; - } - - case 0x53: { - is_f = true; - 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( 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; - 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. - } - - // If there was a trap, do NOT allow register writeback. - if( trap!=0 ) { - _pc = pc; - break; - } - - if( rdid!=0 || is_f) { - if(is_f) {fregs[rdid] = frval; is_f = false;} // Write back register. - else regs[rdid] = rval; // Write back register. - } - - pc += 4; - } - - // Handle traps and interrupts. - if( trap!=0 ) - return trap; - - _cycle = cycle; - _pc = pc; - return 0; - } -} diff --git a/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java index ca33438a..ba8fc178 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.node.cpus.riscv.riscv; import com.seaofnodes.simple.util.SB; import java.io.IOException; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java index d2c6cde4..f1089cf0 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.FunNode; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java index 1de5e3bc..10c75d3f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; |
