summaryrefslogtreecommitdiff
path: root/chapter21/src/main/java/com
diff options
context:
space:
mode:
authorTamás Hadházy <85063808+Hels15@users.noreply.github.com>2025-03-30 21:33:48 +0100
committerGitHub <noreply@github.com>2025-03-30 13:33:48 -0700
commitf9710b82df0eb51090514c56e64e743d32d06b12 (patch)
treed0cd65d1e6270ac13d0b73222760081b1b73651b /chapter21/src/main/java/com
parentfe08995cca0196850855c0f81619d264cf66b716 (diff)
downloadSimple-f9710b82df0eb51090514c56e64e743d32d06b12.tar.gz
Simple-f9710b82df0eb51090514c56e64e743d32d06b12.zip
Extra assert for reg numbering (#188)
* x86 addressing modes during inst select Drop New taking inits; just follow with initializing stores. Simplifies inst selelection which otherwise needs to undo this optimization and emit following init stores. Basic load/store for now, op-to-mem comes later add same becomes Shl by 1. Drop DivF-immiedate * call setup * extended ch13, 14,15,16 (#153) * merge2 * merge3 * Fix a few minor fuzzer bugs * Force array layout ld/st get size (but not signed/unsigned) Add unsigned LT for later range checks. * Fix a bunch of float issues was deleting required inputs * simpler invariant defensive copy inputs for simpler invariant in complex sharing patterns inc/dec form (just the opcode now). * Call & CallR X86 instructions * merge2 * Add-from-memory op Remove FP immediate forms. * Remove name from TFP Never shoulda been there (but was convenient for awhile). Moved into FunNode, found by checking the linker table with a TFP. * remove debug prints add check for bad call convention fix 3 tests (bad merge?) * cleanup call convention abi Needs more love at some point... * one more cleanup ABI * New (#154) * merge2 * merge3 * GCM for float ops fixed, other cleanup - small extensions * call setup * merge2 * remove debug prints add check for bad call convention fix 3 tests (bad merge?) * cleanup call convention abi Needs more love at some point... * one more cleanup ABI --------- Co-authored-by: Cliff Click <cliffc@acm.org> * Add CmpMem form Common addressing mode print LEA can skip a base * Add a AddFMemX86 A bunch of mem op patterns are missing, hopefully they are just cut-n-paste from the existing patterns. * Docs * XMM reg mask fix Minor README updates * Allow inverted cmp/mem narrowing stores can bypass an AndMask Array length loads do not need control Some missing print info * Support "*ptr op= val" at least for MemAdd * missed golden rule update * Array len is u32 load-after-store zero/sign-extends if the store is truncating * One more missed case * READMEs * Update README.md * Update README.md * Move printing into print dir * Move codegen into codegen * Framework for Reg Alloc * riscv init * added not imm form bitwise shifts and ops plus test cases * addressing modes(high chance it'll get deleted) * First cut BuildLRG RegMask.EMPTY -> null * fix minor bug * Setup for first simple split * First cut split code for mismatch regs * delete non existing matches * replace RegMask.Empty with null * Live Ranges U-F BuildLRG for Phi Add CmpFX86 * FPR return CallEndX86 needed to tell fp return from gpr ret Call has no output regs. * riscv handle store and load, fltRisch uses risc reg now * load float into GPR and then later in RA do hard split. * minor changes * Next cut regalloc Building IFG. Coloring. Some nested spilling Optimize divf/con -> mul times inverse * turn off ch20 tests * Update Chapter20Test.java * RISC-V basic isel (#156) * Initial push Major CodeGen cleanup; most static globals move into the CodeGen object. * Minor progress bug with mutual recursion * Add test from pr#148 * First cut x86 "port" Only "return 0;", no registers, no encoding, but yah gotta start somewhere * Update README.md * Update README.md * Update ListScheduler.java * command line launcher for simple Parser bug fref in args Some new test cases. * Add basic RegMask for more than 64 bits of register mask. Add calling convention basics to X86; con+ret RegMasks. GCM computes CFG for all users. Drop unused MultiUse. Pick up reg-pressure aware ListScheduler. Re-layout CodeGen file to get code & data chunks nearer each other. minor Ary extension * ASM Printer InstSel handles folding 2+ ideal ops into 1 machine op * handle instSel for some control flow Bool,If,CProj,Region,Phi Handle 2-op expansions Shuffle instSel graph walk back again. * Basic if-block inst selects and asm prints * Add mul-by-coinstant to shift * left shift codegen basic * exclude RSP from *write* mask * 2-arg add (not immediate) mul-by-small constant opt. Some utilities. * Handle first loop Change inst sel walk again to pre-order, to set an early visit bit to stop cycles. CFGNode copies dom/loop info. Cmp not-immediate form. Ret/Fun lazy updates * inst select for new struct allocation * Float, bitwise and arithmetic operands codegen x86-64 (#150) * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * Remove non-exsting FP+imm ops * Handle first loop Change inst sel walk again to pre-order, to set an early visit bit to stop cycles. CFGNode copies dom/loop info. Cmp not-immediate form. Ret/Fun lazy updates * float ops without imm values * merge * merge * inst select for new struct allocation * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * Remove non-exsting FP+imm ops * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * float ops without imm values * merge * merge * Rebased on ch 19 * Update tests --------- Co-authored-by: Cliff Click <cliffc@acm.org> * cleanup after merge alpha-sort helper fcns implicit test vs zero/null * Add LEA op asm print works on ideal nodes for all tests * Minor cleanup lea * merge2 * merge3 * GCM for float ops fixed, other cleanup - small extensions * x86 addressing modes during inst select Drop New taking inits; just follow with initializing stores. Simplifies inst selelection which otherwise needs to undo this optimization and emit following init stores. Basic load/store for now, op-to-mem comes later add same becomes Shl by 1. Drop DivF-immiedate * call setup * extended ch13, 14,15,16 (#153) * merge2 * merge3 * Fix a few minor fuzzer bugs * Force array layout ld/st get size (but not signed/unsigned) Add unsigned LT for later range checks. * Fix a bunch of float issues was deleting required inputs * simpler invariant defensive copy inputs for simpler invariant in complex sharing patterns inc/dec form (just the opcode now). * Call & CallR X86 instructions * merge2 * Add-from-memory op Remove FP immediate forms. * Remove name from TFP Never shoulda been there (but was convenient for awhile). Moved into FunNode, found by checking the linker table with a TFP. * remove debug prints add check for bad call convention fix 3 tests (bad merge?) * cleanup call convention abi Needs more love at some point... * one more cleanup ABI * New (#154) * merge2 * merge3 * GCM for float ops fixed, other cleanup - small extensions * call setup * merge2 * remove debug prints add check for bad call convention fix 3 tests (bad merge?) * cleanup call convention abi Needs more love at some point... * one more cleanup ABI --------- Co-authored-by: Cliff Click <cliffc@acm.org> * Add CmpMem form Common addressing mode print LEA can skip a base * Add a AddFMemX86 A bunch of mem op patterns are missing, hopefully they are just cut-n-paste from the existing patterns. * Docs * XMM reg mask fix Minor README updates * Allow inverted cmp/mem narrowing stores can bypass an AndMask Array length loads do not need control Some missing print info * Support "*ptr op= val" at least for MemAdd * missed golden rule update * Array len is u32 load-after-store zero/sign-extends if the store is truncating * One more missed case * riscv init * added not imm form bitwise shifts and ops plus test cases * addressing modes(high chance it'll get deleted) * fix minor bug * delete non existing matches * replace RegMask.Empty with null * riscv handle store and load, fltRisch uses risc reg now * load float into GPR and then later in RA do hard split. * minor changes * turn off ch20 tests * Update Chapter20Test.java --------- Co-authored-by: Cliff Click <cliffc@acm.org> * Bring pr/154 to ch 20 RISC5 changes. Some missing x86 ops. Still needs some calling convention love. * First cut regalloc working Biased coloring; tracking splits around a LRG. Separate split for self-conflicts. postColor to remove junk splits. Some minor riscv fixes. * Compile some riscv codes If SplitEmptyMask does not apply, fall back to normal split. Missing CmpFRISC. Renamed riscv flags. RetRISC handls FPR remove extra RegMask constructurs * add riscv port to readme * arm init * Progress reg alloc Handle multi-node projections. A little smarter about 2-addr scheduling RegAlloc must-have single registers removes from other masks instead of interfering; had the mask removal backwards in a few cases. LRG/RegMask COW expand masks before mutating. Clone small constants instead of spilling. Alloc & ProjX86 get output reg masks. Full print large reg masks with sp+offset * UF LRGs can be null during coloring * Finish UF find * work in progress * README updates * Fix ch19 mis-merge? * x86 call args, risc5 load/store regs * arm2 bs * Push RISC WMASK avoid writing to RSP * work in progress * clearnup arm * Progress calling convention allocations Call unlinks before reg alloc. CallEnd tracks RPC CallX86 requires TFP for correct ABI Bias Color tracks 2-addr. RPC gets a mask/stack-slot Clean up call/fun ABI Fix mask RET, RET_F Fix print stack slot Remove isMultiHead, isMultiTail Better all-asm print * Beef up Newton test * fixed main pr problems * regmask extra comments * Clean pass normal tests New fcn print upgrades several golden rule tests. Move the unlink-all from the walk::err call (which IS used during IterPeeps) to GCM. CallEnd upgrades return type based on constant call. Fix unlink to also unlink CallEnd Constant TFP print checks constant Tested an untested Load * Arm basics, minor changes in riscv (#160) * Initial push Major CodeGen cleanup; most static globals move into the CodeGen object. * Minor progress bug with mutual recursion * Add test from pr#148 * First cut x86 "port" Only "return 0;", no registers, no encoding, but yah gotta start somewhere * Update README.md * Update README.md * Update ListScheduler.java * command line launcher for simple Parser bug fref in args Some new test cases. * Add basic RegMask for more than 64 bits of register mask. Add calling convention basics to X86; con+ret RegMasks. GCM computes CFG for all users. Drop unused MultiUse. Pick up reg-pressure aware ListScheduler. Re-layout CodeGen file to get code & data chunks nearer each other. minor Ary extension * ASM Printer InstSel handles folding 2+ ideal ops into 1 machine op * handle instSel for some control flow Bool,If,CProj,Region,Phi Handle 2-op expansions Shuffle instSel graph walk back again. * Basic if-block inst selects and asm prints * Add mul-by-coinstant to shift * left shift codegen basic * exclude RSP from *write* mask * 2-arg add (not immediate) mul-by-small constant opt. Some utilities. * Handle first loop Change inst sel walk again to pre-order, to set an early visit bit to stop cycles. CFGNode copies dom/loop info. Cmp not-immediate form. Ret/Fun lazy updates * inst select for new struct allocation * Float, bitwise and arithmetic operands codegen x86-64 (#150) * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * Remove non-exsting FP+imm ops * Handle first loop Change inst sel walk again to pre-order, to set an early visit bit to stop cycles. CFGNode copies dom/loop info. Cmp not-immediate form. Ret/Fun lazy updates * float ops without imm values * merge * merge * inst select for new struct allocation * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * Remove non-exsting FP+imm ops * left shift codegen basic * sar codegen basic * merge * some basic ops * addf * divf, subf, mulf * rsp allowed in bitwise input, not output * formatting * float ops without imm values * merge * merge * Rebased on ch 19 * Update tests --------- Co-authored-by: Cliff Click <cliffc@acm.org> * cleanup after merge alpha-sort helper fcns implicit test vs zero/null * Add LEA op asm print works on ideal nodes for all tests * Minor cleanup lea * merge2 * merge3 * GCM for float ops fixed, other cleanup - small extensions * x86 addressing modes during inst select Drop New taking inits; just follow with initializing stores. Simplifies inst selelection which otherwise needs to undo this optimization and emit following init stores. Basic load/store for now, op-to-mem comes later add same becomes Shl by 1. Drop DivF-immiedate * call setup * extended ch13, 14,15,16 (#153) * merge2 * merge3 * Fix a few minor fuzzer bugs * Force array layout ld/st get size (but not signed/unsigned) Add unsigned LT for later range checks. * Fix a bunch of float issues was deleting required inputs * simpler invariant defensive copy inputs for simpler invariant in complex sharing patterns inc/dec form (just the opcode now). * Call & CallR X86 instructions * merge2 * Add-from-memory op Remove FP immediate forms. * Remove name from TFP Never shoulda been there (but was convenient for awhile). Moved into FunNode, found by checking the linker table with a TFP. * remove debug prints add check for bad call convention fix 3 tests (bad merge?) * cleanup call convention abi Needs more love at some point... * one more cleanup ABI * New (#154) * merge2 * merge3 * GCM for float ops fixed, other cleanup - small extensions * call setup * merge2 * remove debug prints add check for bad call convention fix 3 tests (bad merge?) * cleanup call convention abi Needs more love at some point... * one more cleanup ABI --------- Co-authored-by: Cliff Click <cliffc@acm.org> * Add CmpMem form Common addressing mode print LEA can skip a base * Add a AddFMemX86 A bunch of mem op patterns are missing, hopefully they are just cut-n-paste from the existing patterns. * Docs * XMM reg mask fix Minor README updates * Allow inverted cmp/mem narrowing stores can bypass an AndMask Array length loads do not need control Some missing print info * Support "*ptr op= val" at least for MemAdd * missed golden rule update * Array len is u32 load-after-store zero/sign-extends if the store is truncating * One more missed case * riscv init * added not imm form bitwise shifts and ops plus test cases * addressing modes(high chance it'll get deleted) * fix minor bug * delete non existing matches * replace RegMask.Empty with null * riscv handle store and load, fltRisch uses risc reg now * load float into GPR and then later in RA do hard split. * minor changes * turn off ch20 tests * Update Chapter20Test.java * add riscv port to readme * arm init * work in progress * arm2 bs * work in progress * clearnup arm * fixed main pr problems * regmask extra comments --------- Co-authored-by: Cliff Click <cliffc@acm.org> * Update Chapter20Test.java * Weaken range-check test since no range checks... test cannot fail (pass) * Fix issue #161 Error adding 'null' and '5' * bug fixs, cloning constants Fix bug missing Find. Fix bug setDef does unordered removal from basic blocks. Use cloned constants for spilling. * RA fixes SplitSelfConflict MUST split before uses and after defs. Split global constants across functions Missing find in union; Inserting split after new inserted wrong place Pre-remove null LRGs before color. Bias color hunts through Phis Shorten InstructionSelection. Rename !unified() to leader() AddMemX86 is 2-addr Add CastXXX to preserve register across cast. * encoding init * encoding init 2 * rex fix * indirect addressing modes * setop change opcode, rename FLOAT_OFFSET * mask sib and modrm with 3 bits, 4th bit goes into rex. * sign extend div with cqo * idiv input is fixed to rax and RMASK, grab input from second slot when encoding * encoding of newx86 * tfp and CallEndNode encoding * sib improvement * more cleanups * more cleanups * Allow a killMap to kill regs. Bugfix scheduler. Bugfix spiller - self-conflict order depended on hashtable iteration order, which depended on System.hashCode which would vary run to run. Improvements to coloring Improvements to spill quality testing * Added flags-kill for XOR * Missing add-deps from fuzzer * Update Chapter14Test.java * fixed order of operands * base rex fixup * more bug fix * remove jukn files * minimal "make release" * further fixes * minor fixes * minor fixes * minor fixes * base != -1 check, precedence fix * Add regkills in IFG building Fix bug LRG union stats Adjust self-conflict splits to be slightly less aggressive In every use-side split, dont split-after-split same block. NewNode is a multi, does not define a register * 64 bit encoding for gpr(s) load * RA improvements Attempt to commute to keep reg-masks compatible. Clones with kills (x86 XOR killing flags to zero) fail before the flag-def. Bugfix failed to color last lrg. More smarts on picking trivial LRGs during coloring Drop isSplit, add SplitNode Pass regalloc round to all splits for debugging Self-conflict no split on loop backedge. Handle split that gets made goes dead No-reg-mask spilling handles case with many def/uses. Add DivIX86 BrainFuck, MergeSort now allocate as testing * 8 bit imm support * conditional jump fix * Push l,ast change, unbreak branch * XOR remove extra opcode, imm size supports 8 bit. * Finally pass the `new [u8]` double-copy test * Fix several ARM reg setup problems Finish Split bypass check ARM: rsp is also a fixed zero, in R31. R0 is a valid register. CallArm prints args, passes TFP for arg selection. Does not return a register. All CallEndARM which DOES return a register. Parms missing tfp for float args. ProjARM after a New missing regs. RetARM missing RPC. Remove hopeful DivIX86 * 64 bit imm for alu ops encoded in extra reg then use it in Op as an operand * Bunch of minor arm, risc fixes small constants not cloning * jump invert encoding * warning comment * Much ARM fixage One More Go-Round with Better Biased Colors Fix bug picking deepest spills to bias. ARM: remove default 2-address. Fix regmask overflow. Rename some ops to be canonical. * Fixes to release Port does not have to be in a Simple named directory. Call convention is just a string, no enum Missed some tests running RISC, ARM. * Minor release change to allow another foreign port * better split encoding and fix CallInMask * notNode * fix callInMask * riscv init * riscv basic ALU ops and types of instructions * Allowing non-Simple repo ports Expanding public API slightly so alternative (non-Simple repo) ports can happen. RegMask supports single-bit-set and a long bitmask. Bugfix GCM splitting multiple global constants. Bugfix LCM grabbing a projection vs multi Bugfix RegAlloc when avoiding splitting a clonable Source code in release More timing in CodeGen * riscv indirect addressing and function calls * Cleanup call ABI presentation Everybody uses the same names, same code shapes * Caller save regs ...not callee save yet * Expose caller save regs * Store Risc adjustments, no imm in MemOpRISC * specific print encoding for cpus * merge fixup * More x86,risc,arm call convention fixes Collect callee and caller save masks (inverts of each other, except for spills). Reorg layout to be closer to each other; remove dead mask definitions; add final keyword * lui fix up with 32 bit immediates * Callee-save registers Callee-save registers and masks and inserting LRGs for same and spilling and picking good spills. Insert CalleeSaveNodes and edges to RetXXXs and RegMasks for those edges. Iterators for regmask. Better printing post-allocation * RegMask supports 128 bits All regs available arm, risc. MergeSort compiles & runs * added flags splitting * Fix risc5 compares No flags on risc5. Branch takes 2 inputs (one can be imm12). Float compare only sets a GPR to 0/1. Bool has a isFloat Common risc5 imm-form handling * extend test cases * imm encoding, flags fixed * grep for Todo: relocs * float riscv fixed * flags for set * lui fix for small bits [0, 12] * arm init * arm last touches * fmov still needs fix * minor fixes * minor fixes(2) * got rid of unnecessary stuff * create ch21 * remove encodings from chapter20 dir * 1/2 pass cleaning up ARM encoding API * ARM encoding compiles * Risc R_TYPE and I_TYPE * Progress RISC encodings Missing lots of stuff still * progress risc encoding * risc encodings compile * Update README.md * Fold up redundant OP/OP-FP risc5 encoding * x86 mem opcodes first cut break out MemOp encodings into parts; change x86 indirectAdr to use Encoding class, remove redundant asserts & code * x86 mem op encodings * x86 reg+imm forms * most reg-reg forms * More x86 encodings * Last few encodings * switch to binary literals over decimals for opcodes * logical immediates fixed, bitwise ops imm forms * tfp and setArm fixed * PC relative float for riscv * readme init * Merged pr/169 * Fixed the array1 test encodings Clean up branch invert logic during BB layout Cleanup branch target printing for RISC,ARM ImmRISC ops mask imm12 to 12 bits Fix NewRISC; hardcode RPC as part of call Fix RISC inverting branchs >,>= * floatarm encoding * tfparm and intarm * uncontional jump encoding for arm and riscv * smarter IntARM, Intx86 does not always include rex. * REX after PREFIX * fixup load and store indirect * updated rex prefix, if its 0x40 then its not needed * Rex fix for floats, got rid of unnecessary stuff. * rename to camel case, better param name * add test export * merged * store opt * store and load optimised forms handled * tfp patch * Store/load float arm/riscv/x64 * got rid of debug print * splits for x86, riscv and arm * readme fixups * fix global symbol numbering for constants * fix TFP pathc on arm and riscv, keep symbols in good order. * fix opcode for store and loads, memOpRisc for Store and splitting * replace hard coded opcodes with major opcodes * replace hard coded opcodes with major opcodes * add asserts and fix reg numbering * add asserts and fix reg numbering --------- Co-authored-by: Cliff Click <cliffc@acm.org>
Diffstat (limited to 'chapter21/src/main/java/com')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java16
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java83
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java16
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java1
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java18
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java22
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java1
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java4
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java1
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java18
17 files changed, 136 insertions, 58 deletions
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 3a3e78d4..fe4ecead 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
@@ -18,7 +18,7 @@ public class AddIARM extends MachConcreteNode implements MachNode {
@Override public RegMask outregmap() { return arm.RMASK; }
//ADD (immediate)
@Override public void encoding( Encoding enc ) {
- arm.imm_inst(enc,this,arm.OPI_ADD,_imm);
+ arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm);
}
// General form: "addi rd = rs1 + imm"
@Override public void asm(CodeGen code, SB sb) {
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
index e7f45843..76f5fa39 100644
--- 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
@@ -15,7 +15,7 @@ public class AndIARM 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_n(enc,this,arm.OPI_AND,_imm);
+ 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) {
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java
index 1196add9..fe36390c 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java
@@ -28,7 +28,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode {
@Override public boolean isClone() { return true; }
@Override public Node copy() { return new CmpIARM(this); }
// Encoding is appended into the byte array; size is returned
- @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this,arm.OPI_CMP,_imm); }
+ @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,in(1),in(1), arm.OPI_CMP,_imm); }
// General form: "cmp rs1, 1"
@Override public void asm(CodeGen code, SB sb) {
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 fe58a299..f6f4e472 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
@@ -15,7 +15,7 @@ public class OrIARM 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_n(enc, this, arm.OPI_OR, _imm);
+ arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm);
}
// General form: "ori rd = rs1 | imm"
@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 a92f7f59..bf90703a 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
@@ -24,13 +24,15 @@ public class SplitARM extends SplitNode {
throw Utils.TODO();
}
int off = enc._fun.computeStackSlot(dst - arm.MAX_REG)*8;
- enc.add4(arm.load_str_imm(arm.OP_STORE_IMM, off, src, dst));
+ enc.add4(arm.load_str_imm(arm.OP_STORE_IMM, off, arm.RSP, src));
+ return;
}
if(src >= arm.MAX_REG) {
// Load from SP
int off = enc._fun.computeStackSlot(src - arm.MAX_REG) * 8;
- enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM, off, src, dst));
+ enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM, off, arm.RSP, dst));
+ return;
}
// pick opcode based on regs
@@ -40,15 +42,15 @@ public class SplitARM extends SplitNode {
} else if(dstX && srcX) {
// FPR->FPR
// fmov reg
- enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src,dst));
- } else if(dstX && !srcX) {
+ enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET));
+ } else if(!srcX && dstX) {
// GPR->FPR
// FMOV(general) 64 bits to DOUBLE-PRECISION
- enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst));
- } else if(!dstX && srcX) {
+ enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET));
+ } else if( srcX && !dstX) {
//FPF->GPR
// FMOV(general) DOUBLE-PRECISION to 64 bits
- enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src, dst));
+ enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst));
}
}
}
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 0334fa78..29ce71b6 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
@@ -18,7 +18,7 @@ public class SubIARM 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,0b1101000100,_imm); }
+ @Override public void encoding( Encoding enc ) { arm.imm_inst(enc,this, in(1), 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/XorIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java
index be28fb28..95e2c932 100644
--- 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
@@ -20,7 +20,7 @@ public class XorIARM extends MachConcreteNode implements MachNode {
@Override public RegMask outregmap() { return arm.RMASK; }
// General form: "xori rd = rs1 ^ imm"
- @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this,arm.OPI_XOR,_imm); }
+ @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); }
@Override public void asm(CodeGen code, SB sb) {
sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm);
}
diff --git a/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 21d6aa98..f070a526 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
@@ -199,10 +199,15 @@ public class arm extends Machine {
}
static public int cset(int opcode, int rm, COND cond, int rn, int rd) {
+ assert 0 <= rm && rm < 32;
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
return (opcode << 21) | (rm << 15) | (cond.ordinal() << 12) | (rn << 5) | rd;
}
static public int cset(int opcode, COND cond, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd;
}
@@ -287,17 +292,21 @@ public class arm extends Machine {
// 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
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
+ assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits
return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd;
}
public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) {
- return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd;
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
+ return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd;
}
- public static void imm_inst(Encoding enc, Node n, int opcode, int imm12) {
+ public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) {
short self = enc.reg(n);
- short reg1 = enc.reg(n.in(1));
+ short reg1 = enc.reg(n2);
int body = imm_inst(opcode, imm12&0xFFF, reg1, self);
enc.add4(body);
}
@@ -308,9 +317,9 @@ public class arm extends Machine {
enc.add4(body);
}
- public static void imm_inst_n(Encoding enc, Node n, int opcode, int imm13) {
+ 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(n.in(1));
+ short reg1 = enc.reg(n2);
int body = imm_inst_n(opcode, imm13, reg1, self);
enc.add4(body);
@@ -318,14 +327,16 @@ public class arm extends Machine {
// nth bit comes from immediate and not opcode
public static int imm_inst_n(int opcode, int imm13, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
assert 0 <= imm13 && imm13 <= 0x1FFF;
return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd;
}
- public static int imm_inst_l(int opcode, int imm12, int self) {
+ 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) {
@@ -338,17 +349,23 @@ public class arm extends Machine {
// for normal add, reg1, reg2 cases (reg-to-reg)
// using shifted-reg form
public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) {
+ assert 0 <= rm && rm < 32;
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) << (rn << 5) | rd;
- }
- public static void r_reg(Encoding enc, Node n, int opcode) {
- short self = enc.reg(n);
- short reg1 = enc.reg(n.in(1));
- short reg2 = enc.reg(n.in(2));
- int body = r_reg(opcode, 0, reg2, 0, reg1, self);
- 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 int shift_reg(int opcode, int rm, int op2, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rm && rm < 32;
+ assert 0 <= rd && rd < 32;
return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd;
}
public static void shift_reg(Encoding enc, Node n, int op2) {
@@ -361,6 +378,9 @@ public class arm extends Machine {
// MUL can be considered an alias for MADD with the third operand Ra being set to 0
public static int madd(int opcode, int rm, int ra, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
+ assert 0 <= rm && rm < 32;
return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd;
}
public static void madd(Encoding enc, Node n, int opcode, int ra) {
@@ -373,11 +393,13 @@ public class arm extends Machine {
// encodes movk, movn, and movz
public static int mov(int opcode, int shift, int imm16, int rd) {
+ assert 0 <= rd && rd < 32;
return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd;
}
- public static int mov_reg(int opcode, int src, int dst) {
- return (opcode << 21) | (src << 16) | 0b11111 << 5 | dst;
+ public static int mov_reg(int opcode, int src, int rd) {
+ assert 0 <= rd && rd < 32;
+ return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd;
}
public static int ret(int opcode) {
@@ -385,18 +407,21 @@ public class arm extends Machine {
}
// FMOV (scalar, immediate)
- public static int f_mov(int opcode, int ftype, int imm8, int rd) {
- return (opcode << 24) | (ftype << 21) |(imm8 << 13) | (128 << 5) | rd;
- }
-
public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
+ assert 0 <= rm && rm < 32;
return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd;
}
public static int f_mov_reg(int opcode, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd;
}
public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rd && rd < 32;
return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd;
}
public static void f_scalar(Encoding enc, Node n, int op ) {
@@ -413,19 +438,20 @@ public class arm extends Machine {
}
// int l
public static int adrp(int op, int imlo,int opcode, int imhi, int rd) {
+ assert 0 <= rd && rd < 32;
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 << 22) | (offset << 10) | (base << 5) | rt;
- }
-
// [Rptr+Roff]
public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) {
+ assert 0 <= ptr && ptr < 32;
+ assert 0 <= rt && rt < 32;
return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt;
}
// [Rptr+imm9]
public static int load_str_imm(int opcode, int imm12, int ptr, int rt) {
+ assert 0 <= ptr && ptr < 32;
+ assert 0 <= rt && rt < 32;
return (opcode << 22) | (imm12 << 10) |(ptr << 5) | rt;
}
@@ -440,12 +466,16 @@ public class arm extends Machine {
(vd << 12) | (0x01100010 << 4) | vm;
}
public static int float_cast(int opcode, int ftype, int rn, int rd) {
+ assert 0 <= rd && rd < 32;
+ assert 0 <= rn && rn < 32;
return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd;
}
// ftype = 3
public static int f_cmp(int opcode, int ftype, int rm, int rn) {
+ assert 0 <= rn && rn < 32;
+ assert 0 <= rm && rm < 32;
return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5) | 8;
}
public static void f_cmp(Encoding enc, Node n) {
@@ -475,11 +505,14 @@ public class arm extends Machine {
}
public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) {
+ assert 0 <= rd && rd < 32;
+ assert 0 <= rn && rn < 32;
return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd;
}
// Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4.
public static int blr(int opcode, int rd) {
+ assert 0 <= rd && rd < 32;
return opcode << 10 | rd << 5;
}
public static int b(int opcode, int delta) {
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
index 16d5da3a..56da1811 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
@@ -135,6 +135,9 @@ public class riscv extends Machine {
// Since riscv instructions are fixed we can just or them togehter
public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) {
+ assert 0 <= rs1 && rs1 < 32;
+ assert 0 <= rs2 && rs2 < 32;
+ assert 0 <= rd && rd < 32;
return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode;
}
public static void r_type(Encoding enc, Node n, int func3, int func7) {
@@ -155,11 +158,13 @@ public class riscv extends Machine {
public static int u_type(int opcode, int rd, int imm20) {
+ assert 0 <= rd && rd < 32;
return (imm20 << 12) | (rd << 7) | opcode;
}
public static int j_type(int opcode, int rd, int delta) {
assert -(1L<<20) <= delta && delta < (1L<<20);
+ assert 0 <= rd && rd < 32;
// Messy branch offset encoding
// 31 30-21 20 19-12 11-7 6-0
// 20 10- 1 11 19-12 rpc JAL
@@ -174,16 +179,17 @@ public class riscv extends Machine {
public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) {
- assert opcode >= 0 && rd >=0 && func3 >=0 && rs1 >=0 && imm12 >= 0; // Zero-extend by caller
+ assert 0 <= rd && rd < 32;
+ assert 0 <= rs1 && rs1 < 32;
+ assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller
return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode;
}
// S-type instructions(store)
- public static int s_type(int opcode, int offset1, int func3, int rs1, int rs2, int offset2) {
- return (offset2 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (offset1 << 7) | opcode;
- }
public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) {
+ assert 0 <= rs1 && rs1 < 32;
+ assert 0 <= rs2 && rs2 < 32;
assert imm12 >= 0; // Masked to high zero bits by caller
int imm_lo = imm12 & 0x1F;
int imm_hi = imm12 >> 5;
@@ -192,6 +198,8 @@ public class riscv extends Machine {
// BRANCH
public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) {
+ assert 0 <= rs1 && rs1 < 32;
+ assert 0 <= rs2 && rs2 < 32;
assert -4*1024 <= delta && delta < 4*1024;
assert (delta&1)==0; // Low bit is always zero, not encoded
// Messy branch offset encoding
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java
index 6271afcd..d274875a 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java
@@ -31,7 +31,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode {
@Override public Node copy() { return new CmpIX86(this); }
@Override public final void encoding( Encoding enc ) {
- short dst = enc.reg(this); // Also src1
+ short dst = enc.reg(in(1)); // Also src1
enc.add1(x86_64_v2.rex(0, dst, 0));
// opcode; 0x81 or 0x83; 0x69 or 0x6B
enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) );
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
index b6aa5e97..f6f3474f 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java
@@ -25,6 +25,7 @@ public class CmpMemX86 extends MemOpX86 {
// includes modrm
x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 7 : src, enc);
+
if( src == -1 ) enc.add4(_imm);
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java
index 4c03e07a..06a36d99 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java
@@ -1,15 +1,23 @@
package com.seaofnodes.simple.node.cpus.x86_64_v2;
-import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.*;
-import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.*;
-public class CmpX86 extends RegX86 {
+public class CmpX86 extends MachConcreteNode implements MachNode {
CmpX86( Node add ) { super(add); }
@Override public String op() { return "cmp"; }
- @Override int opcode() { return 0x3B; }
+ @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; }
@Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; }
- @Override public int twoAddress() { return 0; }
+
+ @Override public void encoding( Encoding enc ) {
+ short dst = enc.reg(in(1));
+ short src = enc.reg(in(2));
+
+ enc.add1(x86_64_v2.rex(dst, src, 0));
+ enc.add1(0x3B);
+ enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src));
+ }
@Override public void asm(CodeGen code, SB sb) {
String dst = code.reg(this);
if( dst!="flags" ) sb.p(dst).p(" = ");
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
index 9471ccdf..b8e63780 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
@@ -5,7 +5,10 @@ import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.LoadNode;
import com.seaofnodes.simple.node.Node;
-import com.seaofnodes.simple.type.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.type.TypeMemPtr;
public class LoadX86 extends MemOpX86 {
LoadX86( LoadNode ld, Node base, Node idx, int off, int scale ) {
@@ -18,29 +21,34 @@ public class LoadX86 extends MemOpX86 {
// Zero extension for u8, u16 and u32 but sign extension i8, i16, i32
// Use movsx and movzx
+ CodeGen.print_as_hex(enc);
short dst = enc.reg(this );
short ptr = enc.reg(ptr());
short idx = enc.reg(idx());
if (_declaredType != TypeInteger.U32 && _declaredType != TypeFloat.F32 && _declaredType != TypeFloat.F64) {
- enc.add1(x86_64_v2.rex(dst, ptr, idx));
+ enc.add1(x86_64_v2.rex(dst, ptr, idx == -1 ? 0: idx));
}
- if(_declaredType == TypeFloat.F32) {
+ if(_declaredType instanceof TypeMemPtr) {
+ throw Utils.TODO();
+ }
+
+ else if(_declaredType == TypeFloat.F32) {
// F3 0F 10 /r MOVSS xmm1, m32
enc.add1(0xF3);
enc.add1(0x0F);
enc.add1(0x10);
dst -= (short)x86_64_v2.XMM_OFFSET;
}
- if(_declaredType == TypeFloat.F64) {
+ else if(_declaredType == TypeFloat.F64) {
// F2 0F 10 /r MOVSD xmm1, m64
enc.add1(0xF2);
enc.add1(0x0F);
enc.add1(0x10);
dst -= (short)x86_64_v2.XMM_OFFSET;
}
- if(_declaredType == TypeInteger.I8) {
+ else if(_declaredType == TypeInteger.I8) {
// sign extend: REX.W + 0F BE /r MOVSX r64, r/m8
enc.add1(0x0F);
enc.add1(0xBE);
@@ -59,10 +67,10 @@ public class LoadX86 extends MemOpX86 {
// zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16
enc.add1(0x0F);
enc.add1(0xB7);
- } else if(_declaredType == TypeInteger.U32 ) {
+ } else if(_declaredType == TypeInteger.U32) {
// zero extend: 8B /r MOV r32, r/m32
enc.add1(0x8B);
- } else if(_declaredType == TypeInteger.BOT || _declaredType instanceof TypeMemPtr) {
+ } else if(_declaredType == TypeInteger.BOT) {
// REX.W + 8B /r MOV r64, r/m64
enc.add1(0x8B);
} else {
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java
index 334791cc..0997644d 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java
@@ -14,6 +14,7 @@ public abstract class RegX86 extends MachConcreteNode {
// REX.W + 01 /r
short dst = enc.reg(in(1)); // src1
short src = enc.reg(in(2)); // src2
+
enc.add1(x86_64_v2.rex(dst, src, 0));
enc.add1(opcode()); // opcode
enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src));
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
index a718ee51..270d2acc 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java
@@ -18,7 +18,9 @@ public class SplitX86 extends SplitNode {
// REX.W + 8B /r MOV r64, r/m64
short dst = enc.reg(this );
short src = enc.reg(in(1));
-
+ if(_nid == 69) {
+ CodeGen.print_as_hex(enc);
+ }
if( dst == x86_64_v2.FLAGS ) {
// mov reg, flags
// push rcx
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
index 6be21c47..aa2bd9b5 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
@@ -31,6 +31,7 @@ public class StoreX86 extends MemOpX86 {
short src = enc.reg(val());
int imm_op = x86_64_v2.selectOpcodeForImmStore(_imm);
+
if(src == -1 && _imm != 0) {
if(imm_op == -1) {enc.add1(x86_64_v2.rex(src, ptr, idx));enc.add1(0xC7); }
else enc.add1(imm_op);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
index f51e0c75..d0056920 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
@@ -86,12 +86,16 @@ public class x86_64_v2 extends Machine {
public static int modrm(MOD mod, int reg, int m_r) {
// combine all the bits
+ assert 0 <= reg && reg < 16;
+ assert 0 <= m_r && m_r < 16;
return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07;
}
// 00 000 000
// same bit-layout as modrm
public static int sib(int scale, int index, int base) {
+ assert 0 <= base && base < 16;
+ assert 0 <= index && index < 16;
return (scale << 6) | ((index & 0x07) << 3) | base & 0x07;
}
@@ -103,6 +107,10 @@ public class x86_64_v2 extends Machine {
// 0 denotes no direct register
public static int rex(int reg, int ptr, int idx, boolean wide) {
// assuming 64 bit by default so: 0100 1000
+ assert 0 <= reg && reg < 16;
+ assert 0 <= ptr && ptr < 16;
+ assert 0 <= idx && idx < 16;
+
int rex = wide ? REX_W : REX;
if( 8 <= reg && reg <= 15 ) rex |= 0b00000100; // REX.R
if( 8 <= ptr && ptr <= 15 ) rex |= 0b00000001; // REX.B
@@ -153,16 +161,22 @@ public class x86_64_v2 extends Machine {
: MOD.INDIRECT_disp32;
// needs to pick optimal displacement mod if we want to encode base
+ // when we only have base = RSP then we still need displacement added so ti becomes: [RSP+RSP*1+0x0]
+ // RSP as index in this case is special and refers to: [base + disp8]
if( mod == MOD.INDIRECT && (base == RBP || base == R13) )
mod = MOD.INDIRECT_disp8;
// special encoding for [base +offset]
if( index == -1 ) {
// Case for mov reg, [disp] (load)
- enc.add1(modrm(mod, reg == -1 ? 0 : reg, base));
+ enc.add1(modrm(offset == 0 ? MOD.INDIRECT_disp8 : mod, reg == -1 ? 0 : reg, x86_64_v2.RSP));
+ enc.add1(x86_64_v2.sib(scale, x86_64_v2.RSP, base));
+ // special case
+ // still add zero it is part of SIB byte
+ if(offset == 0) enc.add1(offset);
} else {
// rsp is hard-coded here(0x04)
- enc.add1(modrm(mod, reg, 0x04));
+ enc.add1(modrm(mod, reg, x86_64_v2.RSP));
enc.add1(sib(scale, index, base));
}