summaryrefslogtreecommitdiff
path: root/chapter22/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'chapter22/src/main/java/com')
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/Parser.java51
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/LoopNode.java14
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java4
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java4
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java16
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java8
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NegARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java16
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java4
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java16
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java6
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java186
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java8
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java8
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java2
33 files changed, 246 insertions, 135 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
index 219c3c44..78807884 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
@@ -24,7 +24,7 @@ public class Parser {
public final CodeGen _code;
// The Lexer. Thin wrapper over a byte[] buffer with a cursor.
- private final Lexer _lexer;
+ private Lexer _lexer;
/**
* Current ScopeNode - ScopeNodes change as we parse code, but at any point of time
@@ -92,7 +92,6 @@ public class Parser {
public Parser(CodeGen code, TypeInteger arg) {
_code = code;
- _lexer = new Lexer(code._src);
_scope = new ScopeNode();
_continueScope = _breakScope = null;
ZERO = con(TypeInteger.ZERO).keep();
@@ -132,8 +131,13 @@ public class Parser {
private Node ctrl() { return _scope.ctrl(); }
private <N extends Node> N ctrl(N n) { return _scope.ctrl(n); }
- public void parse() { parse(false); }
- public void parse(boolean show) {
+ public void parse() {
+ _parse(com.seaofnodes.simple.sys.sys.SYS);
+ _parse(_code._src);
+ }
+
+ private void _parse(String src) {
+ _lexer = new Lexer(src);
_xScopes.push(_scope);
_scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer);
_scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer);
@@ -173,7 +177,6 @@ public class Parser {
init.unkeep().kill();
INITS.clear();
stop.peephole();
- if( show ) showGraph();
}
/**
@@ -694,7 +697,9 @@ public class Parser {
boolean xfinal = false;
Node expr;
if( match("=") ) {
- expr = parseAsgn();
+ expr = isExternDecl()
+ ? externDecl(name,t)
+ : parseAsgn();
// TOP means val and val is always final
xfinal = (t==Type.TOP) ||
// BOTTOM is var and var is always not-final
@@ -1437,6 +1442,19 @@ public class Parser {
return new ProjNode(cend,2,"#2").peephole();
}
+ // Just after parsing "type foo = " can parse `"C"`
+ private boolean isExternDecl( ) {
+ int old = pos();
+ String s = parseString();
+ if( "C".equals(s) ) return true;
+ pos(old);
+ return false;
+ }
+ // External linked constant
+ private Node externDecl( String ex, Type t ) {
+ return new ExternNode(t,ex).peephole();
+ }
+
/**
* Parse integer literal
*
@@ -1453,6 +1471,18 @@ public class Parser {
return _scope.upcastGuard(n.peephole());
}
+ // Parse a string or null
+ private String parseString() {
+ if( !peek('"') ) return null;
+ _lexer.inc();
+ int start = pos();
+ while( !_lexer.isEOF() && _lexer.nextChar()!= '"' ) ;
+ if( _lexer.isEOF() )
+ throw error("Unclosed string");
+ return new String(_lexer._input,start,pos()-start-1);
+ }
+
+
//////////////////////////////////
// Utilities for lexical analysis
@@ -1596,7 +1626,14 @@ public class Parser {
_input[_position ] == '/' &&
_input[_position+1] == '/') {
inc(); inc();
- while( !isEOF() && _input[_position] != '\n' ) inc();
+ while( !isEOF() && _input[_position] != '\n' )
+ inc();
+ } else if( _position+2 < _input.length &&
+ _input[_position ] == '/' &&
+ _input[_position+1] == '*') {
+ while( !isEOF() && !(_input[_position-1] == '*' && _input[_position] == '/'))
+ inc();
+ inc();
} else break;
}
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/LoopNode.java
index 1ba182b9..cacf9c99 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/LoopNode.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/LoopNode.java
@@ -58,20 +58,10 @@ public class LoopNode extends RegionNode {
// XCtrl or a bunch of prior NeverNode exits.
Node top = new ConstantNode(Type.TOP).peephole();
Node memout = new MemMergeNode(false);
- memout.addDef(null); // placeholder for control
+ memout.addDef(f); // placeholder for control
for( Node u : _outputs )
if( u instanceof PhiNode phi && phi._type.isa(TypeMem.BOT) )
memout.addDef(phi);
- if( memout.nIns()>2 )
- memout.setDef(0, ret.cfg0());
- else {
- if( memout.nIns()==1 ) memout=top;
- else {
- Node tmp=memout;
- memout=memout.in(1);
- tmp.setDef(1, null);
- }
- }
Node ctrl = ret.ctrl(), mem = ret.mem(), expr = ret.expr();
if( ctrl!=null && ctrl._type != Type.XCONTROL ) {
@@ -81,7 +71,7 @@ public class LoopNode extends RegionNode {
expr instanceof PhiNode prez && prez.region()==r ) ) {
// Nope, insert an aligned exit layer
RegionNode r = new RegionNode(_loc,null,ctrl).init();
- ctrl = r; r._ltree = _ltree;
+ ctrl = r; r._ltree = stop._ltree;
mem = new PhiNode(r,mem ).init();
expr = new PhiNode(r,expr).init();
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index ed46c8f9..0579ecd0 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -122,7 +122,9 @@ public class PhiNode extends Node {
if( in(1).getClass() != op.getClass() || op.in(0)!=null || in(1).nIns() != op.nIns() )
return false; // Wrong class or CFG bound or mismatched inputs
if( op.nOuts() > 1 ) { // Too many users, but addDep in case lose users
- for( Node out : op._outputs ) if( out!=null ) addDep(out);
+ for( Node out : op._outputs )
+ if( out!=null && out!=this )
+ addDep(out);
return false;
}
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java
index 205ab6e4..f37738bf 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java
@@ -8,7 +8,7 @@ public class AddARM extends MachConcreteNode implements MachNode {
AddARM( Node add) { super(add); }
@Override public String op() { return "add"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
// ADD (shifted register)
@Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); }
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java
index fe4ecead..a1cd8306 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java
@@ -15,7 +15,7 @@ public class AddIARM extends MachConcreteNode implements MachNode {
return _imm == 1 ? "inc" : (_imm == -1 ? "dec" : "addi");
}
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @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);
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java
index d125174b..ad76ca4c 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java
@@ -11,7 +11,7 @@ public class AndARM extends MachConcreteNode implements MachNode {
@Override public String op() { return "and"; }
@Override public String glabel() { return "&"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { 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); }
// General form: #rd = rs1 & rs2
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java
index 76f5fa39..1f12ef13 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java
@@ -13,12 +13,12 @@ public class AndIARM extends MachConcreteNode implements MachNode {
}
@Override public String op() { return "andi"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { 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);
}
// 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);
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm));
}
} \ No newline at end of file
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java
index b1603338..342b7519 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java
@@ -9,7 +9,7 @@ public class AsrARM extends MachConcreteNode implements MachNode {
AsrARM(Node asr) {super(asr);}
@Override public String op() { return "sar"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { 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 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/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java
index eb535201..a1775dde 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java
@@ -17,7 +17,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode {
}
@Override public String op() { return "asri"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) {
short rd = enc.reg(this);
short rn = enc.reg(in(1));
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java
index 8b8af5c3..40bd8387 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java
@@ -8,7 +8,7 @@ public class DivARM extends MachConcreteNode implements MachNode {
DivARM( Node div ) { super(div); }
@Override public String op() { return "div"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { 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); }
// General form: "div dst /= src"
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java
index daf221f3..44c13321 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java
@@ -18,13 +18,19 @@ public class LoadARM extends MemOpARM {
}
@Override public String op() { return "ld"+_sz; }
@Override public RegMask outregmap() { return arm.MEM_MASK; }
+
+ 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 int imm_op() {
+ return _declaredType == TypeFloat.F32 ? arm.OPF_LOAD_IMM_32
+ : _declaredType == TypeFloat.F64 ? arm.OPF_LOAD_IMM_64
+ : OP_LOADS[_declaredType.log_size()];
+ }
+
+ 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, };
+
// ldr(immediate - unsigned offset) | ldr(register)
@Override public void encoding( Encoding enc ) {
- if(_declaredType == TypeFloat.F32 || _declaredType == TypeFloat.F64) {
- ldst_encode(enc, arm.OPF_LOAD_IMM, arm.OPF_LOAD_R, this, true);
- } else {
- ldst_encode(enc, arm.OP_LOAD_IMM, arm.OP_LOAD_R, this, false);
- }
+ ldst_encode(enc, imm_op(), OP_LOAD_RS[_declaredType.log_size()], this, size());
}
@Override public void asm(CodeGen code, SB sb) {
sb.p(code.reg(this)).p(",");
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java
index 5c664c40..055d6dcc 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java
@@ -9,7 +9,7 @@ public class LslARM extends MachConcreteNode implements MachNode {
LslARM(Node asr) {super(asr);}
@Override public String op() { return "shr"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { 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 asm(CodeGen code, SB sb) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java
index 5e35b4c0..94d3e25b 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java
@@ -17,7 +17,7 @@ public class LslIARM extends MachConcreteNode implements MachNode {
}
@Override public String op() { return "lsli"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) {
short rd = enc.reg(this);
short rn = enc.reg(in(1));
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java
index f22c1264..a691e0fe 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java
@@ -9,7 +9,7 @@ public class LsrARM extends MachConcreteNode implements MachNode {
LsrARM(Node asr) {super(asr);}
@Override public String op() { return "shr"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { 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 asm(CodeGen code, SB sb) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java
index e349d46f..094cd30f 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java
@@ -15,7 +15,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode {
}
@Override public String op() { return "lsri"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) {
short rd = enc.reg(this);
short rn = enc.reg(in(1));
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java
index d0ae385a..6d8344a2 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java
@@ -29,7 +29,7 @@ public abstract class MemOpARM extends MemOpNode implements MachNode {
_inputs.setX(4,val);
}
- @Override public String label() { return op(); }
+ @Override public String label() { return op();}
Node val() { return in(4); } // Only for stores
@Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); }
@@ -37,6 +37,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode {
@Override public Type compute() { throw Utils.TODO(); }
@Override public Node idealize() { throw Utils.TODO(); }
+ int size() { return 1<<_declaredType.log_size(); }
+
// Wider mask to store both GPRs and FPRs
@Override public RegMask regmap(int i) {
// 0 - ctrl
@@ -48,12 +50,12 @@ public abstract class MemOpARM extends MemOpNode implements MachNode {
}
// Shared encoding for loads and stores(int and float)
- public void ldst_encode( Encoding enc, int opcode_imm, int opcode_reg, Node xval, boolean float_type ) {
+ public void ldst_encode( Encoding enc, int opcode_imm, int opcode_reg, Node xval, int size) {
short ptr = enc.reg(ptr());
short off = enc.reg(off());
short val = enc.reg(xval);
int body = off() == null
- ? arm.load_str_imm(opcode_imm, _off, ptr, val)
+ ? arm.load_str_imm(opcode_imm, _off, ptr, val, size)
: arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val);
enc.add4(body);
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java
index 261327cb..3514db9b 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java
@@ -9,7 +9,7 @@ public class MulARM extends MachConcreteNode implements MachNode {
MulARM(Node mul) {super(mul);}
@Override public String op() { return "mul"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); }
// General form: "rd = rs1 * rs2"
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NegARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NegARM.java
index 74289797..b7c3c803 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NegARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NegARM.java
@@ -13,7 +13,7 @@ public class NegARM extends MachConcreteNode implements MachNode {
}
@Override public String op() { return "neg"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) {
// reverse subtract with immediate 0
arm.imm_inst(enc,this, in(1), 0b00100110, 0);
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java
index 967847a9..cb51eea2 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java
@@ -9,20 +9,28 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize {
NewARM(NewNode nnn) { super(nnn); }
@Override public void encoding( Encoding enc ) {
// BL(branch with link)
- enc.external(this,"calloc").add4(arm.b(arm.OP_CALL, 0));
+ enc.external(this,"calloc").
+ add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1
+ add4(arm.b(arm.OP_CALL, 0));
}
// Patch is for running "new" in a JIT.
// Delta is from opcode start
- @Override public byte encSize(int delta) { return 4; }
+ @Override public byte encSize(int delta) { return 4*2; }
// Patch is for running "new" in a JIT.
// Delta is from opcode start
@Override public void patch(Encoding enc, int opStart, int opLen, int delta ) {
- if((delta & 3) != 0) {
- enc.patch4(opStart, arm.b_calloc(arm.OP_CALL, delta));
+ // Negative patches are JIT emulator targets.
+ if( opStart+delta < 0 ) {
+ enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4));
} else {
throw Utils.TODO();
}
}
+ // General form: "alloc #bytes PC"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p("ldi x0=#1\n");
+ sb.p("call #calloc");
+ }
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java
index 7efae38d..5a8d882d 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java
@@ -10,7 +10,7 @@ public class NotARM extends MachConcreteNode implements MachNode{
NotARM(NotNode not) {super(not);}
@Override public String op() { return "not"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public RegMask killmap() { return arm.FLAGS_MASK; }
@Override public void encoding( Encoding enc ) {
// subs xzr, rs, #0
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java
index 593c0c6c..b5cfa8cf 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java
@@ -10,7 +10,7 @@ public class OrARM extends MachConcreteNode implements MachNode {
@Override public String op() { return "or"; }
@Override public String glabel() { return "|"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); }
// General form: #rd = rs1 & rs2
@Override public void asm(CodeGen code, SB sb) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java
index f6f4e472..2a2d199a 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java
@@ -13,7 +13,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 RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) {
arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm);
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java
index 52f448df..246e482a 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java
@@ -17,7 +17,7 @@ public class SetARM extends MachConcreteNode implements MachNode {
}
@Override public String op() { return "set"+_bop; }
@Override public RegMask regmap(int i) { assert i==1; return arm.FLAGS_MASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) {
int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop), 0b011111, enc.reg(this));
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java
index ba39eead..62bb75aa 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java
@@ -27,7 +27,7 @@ public class SplitARM extends SplitNode {
}
int off = enc._fun.computeStackOffset(enc._code,dst);
if( srcX ) src -= arm.D_OFFSET;
- enc.add4(arm.load_str_imm(arm.OP_STORE_IMM, off, arm.RSP, src));
+ enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8));
return;
}
@@ -35,7 +35,7 @@ public class SplitARM extends SplitNode {
// Load from SP
int off = enc._fun.computeStackOffset(enc._code,src);
if( dstX ) dst -= arm.D_OFFSET;
- enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM, off, arm.RSP, dst));
+ enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8));
return;
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java
index ffeac3eb..688d8731 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java
@@ -22,12 +22,18 @@ 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 int imm_op() {
+ return _declaredType == TypeFloat.F32 ? arm.OPF_STORE_IMM_32
+ : _declaredType == TypeFloat.F64 ? arm.OPF_STORE_IMM_64
+ : OP_STORES[_declaredType.log_size()];
+ }
+
+ 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, };
+
@Override public void encoding( Encoding enc ) {
- if(_declaredType == TypeFloat.F32 || _declaredType == TypeFloat.F64) {
- ldst_encode(enc, arm.OPF_STORE_IMM,arm.OPF_STORE_R, val(), true);
- } else {
- ldst_encode(enc, arm.OP_STORE_IMM, arm.OP_STORE_R, val(), false);
- }
+ ldst_encode(enc, imm_op(), OP_STORE_RS[_declaredType.log_size()], val(), size());
}
@Override public void asm(CodeGen code, SB sb) {
asm_address(code,sb).p(",");
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java
index feb59853..552b46df 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java
@@ -8,7 +8,7 @@ public class SubARM extends MachConcreteNode implements MachNode {
SubARM(Node sub) { super(sub); }
@Override public String op() { return "sub"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); }
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java
index 29ce71b6..b882c5a4 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java
@@ -16,9 +16,11 @@ 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; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
- @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this, in(1), 0b1101000100,_imm); }
+ @Override public void encoding( Encoding enc ) {
+ arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm);
+ }
// General form: "subi rd = rs1 - imm"
@Override public void asm(CodeGen code, SB sb) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java
index 9afd2e5d..ec86cfa5 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java
@@ -9,7 +9,7 @@ public class XorARM extends MachConcreteNode implements MachNode{
@Override public String op() { return "xor"; }
@Override public String glabel() { return "^"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @Override public RegMask outregmap() { return arm.WMASK; }
@Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); }
// General form: "rd = x1 ^ x2"
@Override public void asm(CodeGen code, SB sb) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java
index 95e2c932..e2582d22 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java
@@ -17,7 +17,7 @@ public class XorIARM extends MachConcreteNode implements MachNode {
@Override public String op() { return "xori"; }
@Override public RegMask regmap(int i) { return arm.RMASK; }
- @Override public RegMask outregmap() { return arm.RMASK; }
+ @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); }
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
index fabfe2fe..104929f4 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
@@ -31,15 +31,15 @@ public class arm extends Machine {
public static final int D_OFFSET = 32;
static final String[] REGS = new String[] {
- "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7",
- "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15",
- "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23",
- "X24", "X25", "X26", "X27", "X28", "X29", "RPC", "RSP",
- "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
- "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
- "D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
- "D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
- "flags"
+ "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7",
+ "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15",
+ "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23",
+ "X24", "X25", "X26", "X27", "X28", "X29", "RPC", "RSP",
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
+ "D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
+ "D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
+ "flags"
};
@Override public String[] regs() { return REGS; }
@@ -60,8 +60,6 @@ public class arm extends Machine {
static final RegMask SPLIT_MASK = new RegMask(WR_BITS | FP_BITS, -2L/*skip flags*/);
static final RegMask FLAGS_MASK = new RegMask(FLAGS);
- // x30 (LR): Procedure link register, used to return from subroutines.
- //static final RegMask RPC_MASK = new RegMask(1L << X30);
// Arguments masks
static final RegMask X0_MASK = new RegMask(X0);
@@ -89,6 +87,7 @@ public class arm extends Machine {
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;
@@ -140,17 +139,39 @@ public class arm extends Machine {
public static int OP_RET = 0b1101011001011111000000;
// Store/load opcodes
- public static int OP_LOAD_R = 0b11111000011;
- public static int OP_LOAD_IMM = 0b1111100101;
+ 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 OPF_LOAD_R = 0b11111100011;
- public static int OPF_LOAD_IMM = 0b1111110101;
+ 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;
- public static int OP_STORE_R = 0b11111000001;
- public static int OP_STORE_IMM = 0b1111100100;
+ // 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 = 0b1111110100;
+ public static int OPF_STORE_IMM_64 = 0b1111110100;
- public static int OPF_STORE_R = 0b11111100001;
- public static int OPF_STORE_IMM = 0b1111110100;
public static int OP_FMOV = 0b10011110;
public static int OP_FMOV_REG = 0b00011110;
@@ -160,24 +181,24 @@ public class arm extends Machine {
// for incoming argument idx.
// index 0 for control, 1 for memory, real args start at index 2
static final RegMask[] CALLINMASK = new RegMask[] {
- X0_MASK,
- X1_MASK,
- X2_MASK,
- X3_MASK,
- X4_MASK,
- X5_MASK,
- X6_MASK,
- X7_MASK,
+ X0_MASK,
+ X1_MASK,
+ X2_MASK,
+ X3_MASK,
+ X4_MASK,
+ X5_MASK,
+ X6_MASK,
+ X7_MASK,
};
static final RegMask[] XMMS = new RegMask[] {
- D0_MASK,
- D1_MASK,
- D2_MASK,
- D3_MASK,
- D4_MASK,
- D5_MASK,
- D6_MASK,
- D7_MASK,
+ D0_MASK,
+ D1_MASK,
+ D2_MASK,
+ D3_MASK,
+ D4_MASK,
+ D5_MASK,
+ D6_MASK,
+ D7_MASK,
};
// ARM ENCODING
@@ -251,10 +272,16 @@ public class arm extends Machine {
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?
@@ -289,6 +316,7 @@ public class arm extends Machine {
public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) {
short self = enc.reg(n);
short reg1 = enc.reg(n2);
+
int body = imm_inst(opcode, imm12&0xFFF, reg1, self);
enc.add4(body);
}
@@ -309,7 +337,6 @@ public class arm extends Machine {
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);
enc.add4(body);
}
@@ -325,7 +352,7 @@ public class arm extends Machine {
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) {
@@ -342,14 +369,14 @@ public class arm extends Machine {
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);
- enc.add4(body);
- }
+ }
+ 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);
+ enc.add4(body);
+ }
public static void r_reg_subs(Encoding enc, Node n, int opcode) {
short reg1 = enc.reg(n.in(1));
@@ -447,10 +474,15 @@ public class arm extends Machine {
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) {
+ 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;
- return (opcode << 22) | (imm12 << 10) |(ptr << 5) | rt;
+
+ 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
@@ -523,7 +555,7 @@ public class arm extends Machine {
delta &= (1L<<26)-1; // Zero extend
return (opcode << 26) | delta;
}
- // no aligned assert
+ // 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;
@@ -551,6 +583,30 @@ public class arm extends Machine {
}
throw Utils.TODO(); // Pass on stack slot
}
+
+ 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;
+ }
+
// Return the max stack slot used by this signature, or 0
@Override public short maxArgSlot( TypeFunPtr tfp ) {
int icnt=0, fcnt=0; // Count of ints, floats
@@ -639,8 +695,8 @@ public class arm extends Machine {
if( bool.isFloat() )
return new CmpFARM(bool);
return bool.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti
- ? new CmpIARM(bool, (int)ti.value())
- : new CmpARM(bool);
+ ? new CmpIARM(bool, (int)ti.value())
+ : new CmpARM(bool);
}
private Node ld(LoadNode ld) {
@@ -660,40 +716,40 @@ public class arm extends Machine {
private Node add(AddNode add) {
return add.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && imm12(ti)
- ? new AddIARM(add, (int)ti.value())
- : new AddARM(add);
+ ? new AddIARM(add, (int)ti.value())
+ : new AddARM(add);
}
private Node sub(SubNode sub) {
return sub.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm12(ti)
- ? new AddIARM(sub, (int)(-ti.value()))
- : new SubARM(sub);
+ ? new SubIARM(sub, (int)(ti.value()))
+ : new SubARM(sub);
}
private Node con( ConstantNode con ) {
if( !con._con.isConstant() ) return new ConstantNode( con ); // Default unknown caller inputs
return switch( con._con ) {
- case TypeInteger ti -> new IntARM(con);
- case TypeFloat tf -> new FloatARM(con);
- case TypeFunPtr tfp -> new TFPARM(con);
- case TypeMemPtr tmp -> new ConstantNode(con);
- case TypeNil tn -> throw Utils.TODO();
- // TOP, BOTTOM, XCtrl, Ctrl, etc. Never any executable code.
- case Type t -> t==Type.NIL ? new IntARM(con) : new ConstantNode(con);
+ case TypeInteger ti -> new IntARM(con);
+ case TypeFloat tf -> new FloatARM(con);
+ case TypeFunPtr tfp -> new TFPARM(con);
+ case TypeMemPtr tmp -> new ConstantNode(con);
+ case TypeNil tn -> throw Utils.TODO();
+ // TOP, BOTTOM, XCtrl, Ctrl, etc. Never any executable code.
+ case Type t -> t==Type.NIL ? new IntARM(con) : new ConstantNode(con);
};
}
private Node call(CallNode call){
return call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp
- ? new CallARM(call, tfp)
- : new CallRRARM(call);
+ ? new CallARM(call, tfp)
+ : new CallRRARM(call);
}
private Node or(OrNode or) {
int imm12;
return or.in(2) instanceof ConstantNode off && off._con instanceof TypeInteger ti && (imm12 = imm12Logical(ti)) != -1
- ? new OrIARM(or, imm12)
- : new OrARM(or);
+ ? new OrIARM(or, imm12)
+ : new OrARM(or);
}
private Node xor(XorNode xor) {
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java
index 3b0018c2..e395a811 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java
@@ -25,11 +25,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize {
// Patch is for running "new" in a JIT.
// Delta is from opcode start
@Override public void patch( Encoding enc, int opStart, int opLen, int delta ) {
- // Odd-number patches are JIT emulator targets.
- if( (delta&3)!=0 ) {
- //enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, riscv.ZERO , 0, riscv.ZERO, 0));
- //enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, riscv.RPC, opStart+delta));
-
+ // Negative patches are JIT emulator targets.
+ if( opStart+delta < 0 ) {
+ delta -= 4; // Offset from the AUIPC start
int imm20 = delta>>12;
if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension
int imm12 = delta&0xFFF;
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java
index 170fc8c5..0439adfd 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java
@@ -10,12 +10,16 @@ public class NewX86 extends NewNode implements MachNode {
NewX86( NewNode nnn ) { super(nnn); }
@Override public void encoding( Encoding enc ) {
enc.external(this,"calloc");
- // This has to call the *native* ABI, regardless of how Simple is
- // being compiled, because it links against the native 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
}
+ // General form: "alloc #bytes PC"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p("ldi rcx = #1\n");
+ sb.p("call #calloc");
+ }
+
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
index cf3bdde3..da269d31 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
@@ -235,7 +235,7 @@ public abstract class ASMPrinter {
for( int i=0; i<len; i++ )
sb.hex1(code._encoding._bits.buf()[iadr++]);
off += len;
- for( int i=size-off; i<dopz; i++ ) sb.p(" ");
+ for( int i=len; i<dopz; i++ ) sb.p(" ");
sb.p(" ");
int x = isMultiOp.indexOf('\n');
if( x== -1 ) { // Last line