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