diff options
Diffstat (limited to 'chapter21/src')
48 files changed, 365 insertions, 149 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index eb6d96f9..1e778aa7 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -296,30 +296,36 @@ public class CodeGen { return this; } - //public static void print_as_hex(ByteArrayOutputStream outputStream) { - // byte[] encodedBytes = outputStream.toByteArray(); - // for (byte b : encodedBytes) { - // System.out.print(String.format("%02X", b)); - // } - // System.out.println(); - //} - // + public static void print_as_hex(Encoding enc) { + for (byte b : enc._bits.toByteArray()) { + System.out.print(String.format("%02X", b)); + } + System.out.println(); + } + + public void print_as_hex() { + for (byte b : _encoding._bits.toByteArray()) { + System.out.print(String.format("%02X", b)); + } + System.out.println(); + } + //// Debug purposes for now - //public CodeGen printENCODING() { - // ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - // - // for(Node bb : CodeGen.CODE._cfg) { - // for(Node n: bb.outs()) { - // if(n instanceof MachNode) { - // ((MachNode) n).encoding(outputStream); - // } - // } - // } - // - // print_as_hex(outputStream); - // // Get the raw bytes from the output stream - // return this; - //} +// public CodeGen printENCODING() { +// ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); +// +// for(Node bb : CodeGen.CODE._cfg) { +// for(Node n: bb.outs()) { +// if(n instanceof MachNode) { +// ((MachNode) n).encoding(E); +// } +// } +// } +// +// print_as_hex(outputStream); +// // Get the raw bytes from the output stream +// return this; +// } public String reg(Node n) { if( _phase.ordinal() >= Phase.RegAlloc.ordinal() ) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index b95e3719..a65b9553 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -9,7 +9,9 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public String op() { return "add"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,139); } + + // ADD (shifted register) + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,0b10001011); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index 35d1eef1..6e1930ed 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -9,10 +9,12 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @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,10); } + + //FADD (scalar) + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,0b00011110); } // Default on double precision for now(64 bits) - // General form: "vadd.32 rd = src1 + src2 + // General form: "addf rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index b37fadee..fab40b1d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -16,7 +16,8 @@ public class AddIARM extends MachConcreteNode implements MachNode { } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,580,_imm); } + //ADD (immediate) + @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,0b1001000100,_imm); } // General form: "addi rd = rs1 + 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index 8e95628c..c107e87f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -12,7 +12,8 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "&"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,138); } + // AND (shifted register) + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,0b10001010); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java new file mode 100644 index 00000000..ce270356 --- /dev/null +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -0,0 +1,22 @@ +package com.seaofnodes.simple.node.cpus.arm; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.node.*; + +public class AndIARM extends MachConcreteNode implements MachNode { + final int _imm; + AndIARM(Node and, int imm) { + super(and); + _inputs.pop(); + _imm = imm; + } + @Override public String op() { return "andi"; } + @Override public RegMask regmap(int i) { return arm.RMASK; } + @Override public RegMask outregmap() { return arm.RMASK; } + @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,0b100100100,_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(_imm); + } +}
\ No newline at end of file diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index d91a18ab..23776896 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -10,7 +10,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.RMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,10); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,0b1010); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java new file mode 100644 index 00000000..e5636bc3 --- /dev/null +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -0,0 +1,31 @@ +package com.seaofnodes.simple.node.cpus.arm; + +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.Encoding; +import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; + +public class AsrIARM extends MachConcreteNode implements MachNode { + final int _imm; + AsrIARM(Node asr, int imm) { + super(asr); + _inputs.pop(); + _imm = imm; + } + @Override public String op() { return "asri"; } + @Override public RegMask regmap(int i) { return arm.RMASK; } + @Override public RegMask outregmap() { return arm.RMASK; } + @Override public void encoding( Encoding enc ) { + short rd = enc.reg(this); + short rn = enc.reg(in(1)); + assert _imm > 0; + enc.add4(arm.imm_shift(0b100100110,_imm, 0b111111, rn, rd)); + } + // General form: "asri rd = rs1 >> imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> #").p(_imm); + } +}
\ No newline at end of file diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index a7cbd1aa..6b87a2a5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -34,16 +34,8 @@ public class BranchARM extends IfNode implements MachNode{ enc.jump(this,cproj(0)); // Assuming that condition flags are already set. These flags are set // by comparison (or sub). No need for regs because it uses flags - arm.COND cond = switch (_bop) { - case "==" -> arm.COND.EQ; - case "!=" -> arm.COND.NE; - case "<" -> arm.COND.LE; - case "<=" -> arm.COND.LT; - case ">=" -> arm.COND.GT; - case ">" -> arm.COND.GE; - default -> throw Utils.TODO(); - }; - int body = arm.b_cond(84, 0, cond); + // B.cond + int body = arm.b_cond(0b01010100, 0, arm.make_condition(_bop)); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 2a815f37..1d3d4d3d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -24,10 +24,10 @@ public class CallARM extends CallNode implements MachNode { @Override public RegMask regmap(int i) { return arm.callInMask(_tfp,i); } @Override public RegMask outregmap() { return null; } - // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { enc.relo(this,_tfp); // Record relo info - enc.add4(arm.b(37,0)); + // BL + enc.add4(arm.b(0B100101,0)); // Target patched at link time } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index 1d76b621..b5c3ecac 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -16,9 +16,10 @@ public class CallRRARM extends CallNode implements MachNode { @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - //enc.add4(arm.b(37, 0)); // Needs a register, typically a jump-and-link-register opcode - throw Utils.TODO(); + // blr + short self = enc.reg(this); + enc.add4(arm.blr(0b1101011000111111000000, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index f97fdeda..7b61baf7 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -9,7 +9,9 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public String op() { return "cmp"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.FLAGS_MASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,235); } + + // SUBS (shifted register) + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,0b11101011); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpFARM.java index f2880078..e82a2ee3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpFARM.java @@ -10,7 +10,8 @@ public class CmpFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "cmpf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.FLAGS_MASK; } - // Encoding is appended into the byte array; size is returned + + // FCMP @Override public void encoding( Encoding enc ) { arm.f_cmp(enc,this); } // General form: "cmp d0, d1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpMemARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpMemARM.java deleted file mode 100644 index 47f68ccc..00000000 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpMemARM.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.seaofnodes.simple.node.cpus.arm; - -public class CmpMemARM { -} diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index 62ce9827..4e1f9d5d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -9,7 +9,8 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public String op() { return "div"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,1238,3); } + // SDIV + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,0b10011010110,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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 8ffb14ec..9d8e064b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -9,7 +9,9 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "divf"; } @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,6); } + + // FDIV (scalar) + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,0b000110); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java index be837f04..517d0831 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java @@ -20,7 +20,6 @@ public class FloatARM extends ConstantNode implements MachNode { @Override public boolean isClone() { return true; } @Override public FloatARM copy() { return new FloatARM(this); } - // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); double d = ((TypeFloat)_con).value(); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index f1286630..f10e636a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -10,9 +10,10 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } @Override public void encoding( Encoding enc ) { + // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(158, 1, reg1, self); + int body = arm.float_cast(0b10011110, 1, reg1, self); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index d44e108e..f9b53f6b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -17,7 +17,6 @@ public class IntARM extends ConstantNode implements MachNode { @Override public boolean isClone() { return true; } @Override public IntARM copy() { return new IntARM(this); } - // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { short self = enc.reg(this); long x = ((TypeInteger)_con).value(); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 4fa16a74..7dd4d929 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -17,7 +17,8 @@ public class LoadARM extends MemOpARM{ } @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return arm.MEM_MASK; } - @Override public void encoding( Encoding enc ) { arm.ldst_encode(enc,this,1986,this); } + // ldr(immediate - unsigned offset) | ldr(register) + @Override public void encoding( Encoding enc ) { arm.ldst_encode(enc,this,this); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(","); asm_address(code,sb); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index c97608d5..24790f9d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -10,7 +10,8 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public String op() { return "shr"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,8); } + + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,0b1000); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java new file mode 100644 index 00000000..d6633e51 --- /dev/null +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -0,0 +1,33 @@ +package com.seaofnodes.simple.node.cpus.arm; + +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.Encoding; +import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.node.Node; + +public class LslIARM extends MachConcreteNode implements MachNode { + final int _imm; + LslIARM(Node lsl, int imm) { + super(lsl); + _inputs.pop(); + _imm = imm; + } + @Override public String op() { return "lsli"; } + @Override public RegMask regmap(int i) { return arm.RMASK; } + @Override public RegMask outregmap() { return arm.RMASK; } + @Override public void encoding( Encoding enc ) { + short rd = enc.reg(this); + short rn = enc.reg(in(1)); + assert _imm > 0; + // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) + // immr must be (-<shift> MOD 64) = 64 - shift + enc.add4(arm.imm_shift(0b110100110, 64 - _imm, (64 - _imm) - 1, rn, rd)); + } + // General form: "lsli rd = rs1 << imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << #").p(_imm); + } +}
\ No newline at end of file diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index 848f96f9..cdc0f301 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -10,7 +10,8 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "shr"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,9); } + + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,0b1001); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java new file mode 100644 index 00000000..8bf2b9ce --- /dev/null +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -0,0 +1,29 @@ +package com.seaofnodes.simple.node.cpus.arm; + + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.node.*; + +// logical right shift immediate +public class LsrIARM extends MachConcreteNode implements MachNode { + final int _imm; + LsrIARM(Node lsr, int imm) { + super(lsr); + _inputs.pop(); + _imm = imm; + } + @Override public String op() { return "lsri"; } + @Override public RegMask regmap(int i) { return arm.RMASK; } + @Override public RegMask outregmap() { return arm.RMASK; } + @Override public void encoding( Encoding enc ) { + short rd = enc.reg(this); + short rn = enc.reg(in(1)); + assert _imm > 0; + enc.add4(arm.imm_shift(0b110100110,_imm, 0b111111, rn,rd)); + } + // General form: "lsri rd = rs1 >>> imm" + @Override public void asm(CodeGen code, SB sb) { + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> #").p(_imm); + } +}
\ No newline at end of file diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index 706922a7..5decb4de 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -10,7 +10,8 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public String op() { return "mul"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,1240,31); } + + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,0b10011011000,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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 0e59bd96..a4862db5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -9,7 +9,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,2); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,0b10); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulIARM.java deleted file mode 100644 index e617ee13..00000000 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulIARM.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.seaofnodes.simple.node.cpus.arm; - -import com.seaofnodes.simple.*; -import com.seaofnodes.simple.codegen.CodeGen; -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.codegen.RegMask; -import com.seaofnodes.simple.node.*; -import com.seaofnodes.simple.type.TypeInteger; - -public class MulIARM extends MachConcreteNode implements MachNode{ - final TypeInteger _ti; - MulIARM(Node mul, TypeInteger ti) { - super(mul); - _inputs.pop(); - _ti = ti; - } - - // Register mask allowed on input i. - // This is the normal calling convention - @Override public RegMask regmap(int i) { - // assert i==1; - return arm.RMASK; } - - // Register mask allowed as a result. 0 for no register. - @Override public RegMask outregmap() { return arm.RMASK; } - - // Output is same register as input#1 - @Override public int twoAddress() { return 1; } - - // Encoding is appended into the byte array; size is returned - @Override public void encoding( Encoding enc ) { - throw Utils.TODO(); - } - - // General form - // General form: "muli dst * #imm" - @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * #"); - _ti.print(sb); - } - - @Override public String op() { return "muli"; } -} diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index cdac48a3..8ddf1bd6 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -15,7 +15,8 @@ public class NewARM extends NewNode implements MachNode { @Override public void encoding( Encoding enc ) { enc.relo(this); - enc.add4(arm.b(37, 0)); + // bl + enc.add4(arm.b(0b100101, 0)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index 1092c931..c492d334 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -18,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(964, 0, reg1, self); + int subs = arm.imm_inst(0b1111000100, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(1236, 31, arm.COND.EQ, 63, reg1); + int cset = arm.cond_set(0b10011010100, 31, arm.COND.EQ, 63, reg1); enc.add4(cset); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index 19631f35..860546d2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -11,7 +11,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.RMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,170); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,0b10101010); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index 3f72f026..bb28acdb 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -14,7 +14,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public String op() { return "ori"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,0xC8,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,0b101100100,_imm); } // General form: "ori rd = rs1 | 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 9066925e..2a702247 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -15,7 +15,8 @@ public class RetARM extends ReturnNode implements MachNode { } @Override public RegMask regmap(int i) { return arm.retMask(_fun.sig(),i); } @Override public RegMask outregmap() { return null; } - @Override public void encoding( Encoding enc ) { enc.add4(arm.ret(3512256)); } + // RET + @Override public void encoding( Encoding enc ) { enc.add4(arm.ret(0b1101011001011111000000)); } @Override public void asm(CodeGen code, SB sb) { // Post code-gen, just print the "ret" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index 0f958e38..5c187239 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -21,8 +21,8 @@ public class SetARM extends MachConcreteNode implements MachNode { // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { - //arm.cond_set(???); - Utils.TODO(); + int body = arm.cset(0b1001101010011111, arm.make_condition(_bop), 0b0111111, enc.reg(this)); + enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index defb4f92..f3ef7f7b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -9,11 +9,10 @@ public class SplitARM extends SplitNode { @Override public RegMask regmap(int i) { return arm.SPLIT_MASK; } @Override public RegMask outregmap() { return arm.SPLIT_MASK; } - // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int body = arm.r_reg(170, 0, reg1, 0, 31, self); + int body = arm.r_reg(0b10101010, 0, reg1, 0, 31, self); enc.add4(body); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index ae7e88d9..03a39f06 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -21,7 +21,7 @@ public class StoreARM extends MemOpARM { } @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - @Override public void encoding( Encoding enc ) { arm.ldst_encode(enc,this,1984,val()); } + @Override public void encoding( Encoding enc ) { arm.ldst_encode(enc,this,val()); } @Override public void asm(CodeGen code, SB sb) { asm_address(code,sb).p(","); if( val()==null ) sb.p("#").p(_imm); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index df85199c..072bbf46 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -9,7 +9,8 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sub"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,203); } + + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,0b11001011); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index b5aacc52..903c7947 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -9,7 +9,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,14); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,0b1110); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index bda6681e..0334fa78 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -17,8 +17,8 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public String op() { return _imm == -1 ? "dec" : "subi"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.RMASK; } - // Encoding is appended into the byte array; size is returned - @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,836,_imm); } + + @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,0b1101000100,_imm); } // General form: "subi rd = rs1 - imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 36125048..eb06a4e0 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -16,11 +16,11 @@ public class TFPARM extends ConstantNode implements MachNode { @Override public void encoding( Encoding enc ) { enc.relo(this,(TypeFunPtr)_con); short self = enc.reg(this); - // Limit of 16bit address for function constants??? - int body = arm.load_adr(1986,0,0,self); - enc.add4(body); - // Surely need to split into 2 ops? - throw Utils.TODO(); + // adrp x0, 0 + int adrp = arm.adrp(1,0, 0b10000, 0,self); + // add x0, x0, 0 + arm.imm_inst(enc,this,0b1001000100,0); + enc.add4(adrp); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index 8c4f65f9..9fdf0619 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -10,7 +10,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.RMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,202); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,0b11001010); } // 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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java new file mode 100644 index 00000000..4814a7cc --- /dev/null +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -0,0 +1,27 @@ +package com.seaofnodes.simple.node.cpus.arm; + +import com.seaofnodes.simple.node.MachConcreteNode; +import com.seaofnodes.simple.node.MachNode; + +import com.seaofnodes.simple.*; +import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.node.*; + +public class XorIARM extends MachConcreteNode implements MachNode { + final int _imm; + XorIARM(Node xor, int imm) { + super(xor); + _inputs.pop(); + _imm = imm; + } + + @Override public String op() { return "xori"; } + @Override public RegMask regmap(int i) { return arm.RMASK; } + @Override public RegMask outregmap() { return arm.RMASK; } + + // General form: "xori rd = rs1 ^ imm" + @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,0b110100100,_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/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index add609fc..04569476 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -116,6 +116,10 @@ public class arm extends Machine { SXTX, } + static public int cset(int opcode, COND cond, int rn, int rd) { + return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; + } + public enum STORE_LOAD_OPTION { UXTW, // base+ u32 index [<< logsize] UXTX, // base+ u64 index [<< logsize] @@ -169,16 +173,42 @@ public class arm extends Machine { // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { if( !ti.isConstant() ) return -1; - // TODO: THE REAL THING - // INVARIANT: always a positive thing - 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 + while (val < 0 || (val & 1)==0) { + val = (val >>> 63) | (val << 1); + immr++; + } + 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 opcdoe public static int imm_inst(int opcode, int imm12, int rn, int rd) { assert opcode >=0 && imm12 >= 0 && rn >=0 && rd>=0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; + return (opcode << 23) | (imm12 << 10) | (rn << 5) | rd; + } + + public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { + return (opcode << 23) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; } + public static void imm_inst(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); @@ -206,7 +236,7 @@ public class arm extends Machine { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(1238, reg2, op2, reg1, self); + int body = shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } @@ -243,12 +273,20 @@ public class arm extends Machine { 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(30, 1, reg2, op, reg1, self); + int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } + public static int load_pc(int opcode, int offset, int rt) { + return (opcode << 24) | (offset << 5) | rt; + } + // int l + public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { + return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; + } + public static int load_adr(int opcode, int offset, int base, int rt) { - return (opcode << 21) | (offset << 12) | (3 << 10) | (base << 5) | rt; + return (opcode << 22) | (offset << 10) | (base << 5) | rt; } // [Rptr+Roff] @@ -259,13 +297,14 @@ public class arm extends Machine { public static int load_str_imm(int opcode, int imm9, int ptr, int rt) { return (opcode << 21) | (imm9 << 12) |(1 << 10) |(ptr << 5) | rt; } - public static void ldst_encode( Encoding enc, MemOpARM n, int op, Node xval ) { + // Todo: provide op as binary here + public static void ldst_encode( Encoding enc, MemOpARM n, Node xval ) { short ptr = enc.reg(n.ptr()); short off = enc.reg(n.off()); short val = enc.reg(xval) ; int body = n.off() == null - ? load_str_imm(op, off, ptr, val) - : indr_adr(op+1, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? load_str_imm(0b1111100101, off, ptr, val) + : indr_adr(0b11111000011, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } @@ -291,10 +330,21 @@ public class arm extends Machine { public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-arm.D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-arm.D_OFFSET); - int body = f_cmp(30, 3, reg1, reg2); + int body = f_cmp(0b00011110, 3, reg1, reg2); enc.add4(body); } + public static COND make_condition(String bop) { + return switch (bop) { + case "==" -> arm.COND.EQ; + case "!=" -> arm.COND.NE; + case "<" -> arm.COND.LE; + case "<=" -> arm.COND.LT; + case ">=" -> arm.COND.GT; + case ">" -> arm.COND.GE; + default -> throw Utils.TODO(); + }; + } // Todo: maybe missing zero here after label << 5 public static int b_cond(int opcode, int label, COND cond) { return (opcode << 24) | (label << 5) | cond.ordinal(); @@ -304,6 +354,10 @@ public class arm extends Machine { 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) { + return opcode << 10 | rd << 5; + } public static int b(int opcode, int imm26) { return (opcode << 26) | imm26; } @@ -389,7 +443,7 @@ public class arm extends Machine { return switch( n ) { case AddFNode addf -> new AddFARM(addf); case AddNode add -> add(add); - case AndNode and -> new AndARM(and); + case AndNode and -> and(and); case BoolNode bool -> cmp(bool); case CallNode call -> call(call); case CastNode cast -> new CastNode(cast); @@ -412,16 +466,16 @@ public class arm extends Machine { case ProjNode prj -> new ProjARM(prj); case ReadOnlyNode read -> new ReadOnlyNode(read); case ReturnNode ret -> new RetARM(ret,ret.fun()); - case SarNode sar -> new AsrARM(sar); - case ShlNode shl -> new LslARM(shl); - case ShrNode shr -> new LsrARM(shr); + case SarNode sar -> asr(sar); + case ShlNode shl -> lsl(shl); + case ShrNode shr -> lsr(shr); case StartNode start -> new StartNode(start); case StopNode stop -> new StopNode(stop); case StoreNode st -> st(st); case SubFNode subf -> new SubFARM(subf); case SubNode sub -> sub(sub); case ToFloatNode tfn-> new I2F8ARM(tfn); - case XorNode xor -> new XorARM(xor); + case XorNode xor -> xor(xor); case LoopNode loop -> new LoopNode(loop); case RegionNode region-> new RegionNode(region); @@ -431,7 +485,7 @@ public class arm extends Machine { private Node cmp(BoolNode bool){ Node cmp = _cmp(bool); - return new SetARM(cmp, bool.op()); + return new SetARM(cmp, invert(bool.op())); } private Node _cmp(BoolNode bool) { if( bool instanceof BoolNode.EQF || @@ -494,6 +548,38 @@ public class arm extends Machine { : new OrARM(or); } + private Node xor(XorNode xor) { + int imm12; + return xor.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && (imm12 = imm12Logical(ti)) != -1 + ? new XorIARM(xor, imm12) + : new XorARM(xor); + } + + private Node and(AndNode and) { + int imm12; + return and.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && (imm12 = imm12Logical(ti)) != -1 + ? new AndIARM(and, imm12) + : new AndARM(and); + } + + private Node asr(SarNode asr) { + return asr.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && ti.value() >= 0 && ti.value() < 63 + ? new AsrIARM(asr, (int)ti.value()) + : new AsrARM(asr); + } + + private Node lsl(ShlNode lsl) { + return lsl.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && ti.value() >= 0 && ti.value() < 63 + ? new LslIARM(lsl, (int)ti.value()) + : new LslARM(lsl); + } + + private Node lsr(ShrNode lsr) { + return lsr.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && ti.value() >= 0 && ti.value() < 63 + ? new LsrIARM(lsr, (int)ti.value()) + : new LsrARM(lsr); + } + private static int off; private static Node idx; diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index d209ad5f..0adfe716 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -15,7 +15,6 @@ public class CallRRISC extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } - // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index 7ce82ec7..2d253ff3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -14,12 +14,12 @@ public class FltRISC extends ConstantNode implements MachNode{ @Override public RegMask outregmap() { return riscv.FMASK; } @Override public boolean isClone() { return true; } @Override public FltRISC copy() { return new FltRISC(this); } - // Encoding is appended into the byte array; size is returned + @Override public void encoding( Encoding enc ) { enc.largeConstant(this,_con); short dst = (short)(enc.reg(this) - riscv.F_OFFSET); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(0x17, dst, 0)); + enc.add4(riscv.u_type(0b0010111, dst, 0)); // Load dst,[dst+#low12_constant_pool] enc.add4(riscv.i_type(0x07, dst, 0x03, dst, 0)); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index 4e73aeab..5374eae8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -37,7 +37,6 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { abstract int opcode(); abstract int func3(); - // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index ac2eac39..d2bdcb8a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -17,10 +17,12 @@ public class TFPRISC extends ConstantNode implements MachNode { enc.relo(this,(TypeFunPtr)_con); short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; - //int body = riscv.i_type(riscv.I_TYPE, dst, 0, riscv.ZERO, (int)(ti.value() & 0xFFF)); - //enc.add4(body); - // Surely need to split into 2 ops? - throw Utils.TODO(); + // auipc t0,0 + int auipc = riscv.u_type(0b0010111, dst, 0); + // addi t1,t0 + #0 + int addi = riscv.i_type(0b0010011, dst, 0, dst, 0); + enc.add4(auipc); + enc.add4(addi); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 4eac27a8..b9d4fa8d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -16,7 +16,8 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // 0xFF/2 + // 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.INDIRECT,2,src)); diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java index e2a79b8f..f3075a68 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -62,4 +62,22 @@ return sqrt(farg) + sqrt(farg+2.0); testCPU(src,"riscv" , "SystemV",17,null); testCPU(src,"arm" , "SystemV",18,null); } + + @Test + public void testArray1() { + String src = + """ + int[] !ary = new int[arg]; + // Fill [0,1,2,3,4,...] + for( int i=0; i<ary#; i++ ) + ary[i] = i; + // Fill [0,1,3,6,10,...] + for( int i=0; i<ary#-1; i++ ) + ary[i+1] += ary[i]; + return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6 + """; + testCPU(src,"x86_64_v2", "SystemV",3,"return .[];"); + testCPU(src,"riscv" , "SystemV",1,"return (add,.[],(mul,.[],1000));"); + testCPU(src,"arm" , "SystemV",1,"return (add,.[],(muli,.[]));"); + } } |
