summaryrefslogtreecommitdiff
path: root/chapter19/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-03-08 09:59:31 -0800
committerGitHub <noreply@github.com>2025-03-08 09:59:31 -0800
commit2370fb29d4538479af9eb94fc666a5ce09fcb492 (patch)
treef21ed94228e23c6786a175741b785ab85888fadb /chapter19/src/main/java/com
parent53452331d8e69dc3bcd40a56a4f00f9380140e73 (diff)
downloadSimple-2370fb29d4538479af9eb94fc666a5ce09fcb492.tar.gz
Simple-2370fb29d4538479af9eb94fc666a5ce09fcb492.zip
Ch20 reg (#166)
* READMEs * Update README.md * Update README.md * Move printing into print dir * Move codegen into codegen * Framework for Reg Alloc * First cut BuildLRG RegMask.EMPTY -> null * Setup for first simple split * First cut split code for mismatch regs * 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. * Next cut regalloc Building IFG. Coloring. Some nested spilling Optimize divf/con -> mul times inverse * 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 * 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 * README updates * Fix ch19 mis-merge? * x86 call args, risc5 load/store regs * Push RISC WMASK avoid writing to RSP * 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 * 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. * 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 * remove jukn files * minimal "make release" * 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 * 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 * Push l,ast change, unbreak branch * 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 * Bunch of minor arm, risc fixes small constants not cloning * 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 * 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 * Cleanup call ABI presentation Everybody uses the same names, same code shapes * Caller save regs ...not callee save yet * Expose caller save regs * 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 * 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 * 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 * yank MulIRISC * fix arg flags reg Arm split op can spill flags bugfix RegAlloc 1st real >=64bit reg num * Update Chapter20Test.java * Turn off transpile tests which are broken for some time now * A lot more readme * better flags ListScheduler stalls cmp/jmp in the same block; avoids some flags spills. Make CmpIX86/ARM rematieralize. Bugfix: remove some include x86/risc/arm in other dirs. Canonicalize boilerplate fcn order * regalloc improves Use FltRISC, not clonable requires a spill from int->flt regs. new splits track origin LRG, so later splits in the same pass know what lrg a spilled input is. * RA improvements & fixes Bugfix on split loop-depth computation. Track killmask kills, which are always capacity kills and require more spilling. Rename the riscv registers canonically, so I can tell them part! Definitely no GP or TP in Simple. Node insertAfter bypass a little more conservative. * RA bugfix remove unified failed live ranges * easier access for remote ports debug support * Lots more comments * bugfix infinite peep cycle on (17 ^ 3.14), i.e. bad program * Fix imm12 shift --------- Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com>
Diffstat (limited to 'chapter19/src/main/java/com')
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java4
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/Parser.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/RegMask.java8
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java11
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java6
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java39
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java36
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java40
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java41
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java49
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java37
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java31
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java44
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java28
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java39
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java22
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java29
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java34
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java36
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java35
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java44
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java25
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java23
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java48
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java35
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java40
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java36
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java42
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java38
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java40
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java30
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java29
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java45
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java43
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java329
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java37
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java3
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java3
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java4
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java4
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java33
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java7
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java6
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java8
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java37
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java24
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java39
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java1
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java38
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java2
-rw-r--r--chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java122
78 files changed, 2165 insertions, 98 deletions
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java b/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java
index c48a4162..eb8dd4aa 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/CodeGen.java
@@ -204,7 +204,7 @@ public class CodeGen {
// If n is a MachConcrete, then its part of a multi-node expansion.
// It does not need instruction selection (already selected!)
// but it does need its inputs walked.
- if( n instanceof MachConcreteNode || n instanceof MemOpX86 ) {
+ if( n instanceof MachConcreteNode || n instanceof MemOpX86) {
for( int i=0; i < n.nIns(); i++ )
n._inputs.set(i, _instSelect(n.in(i),map) );
return n;
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java b/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java
index 18055e19..efca945a 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/ListScheduler.java
@@ -41,7 +41,7 @@ public abstract class ListScheduler {
}
private void computeSingleRDef(CFGNode bb, Node n) {
- RegMaskRW rmask = n instanceof MachNode mach ? mach.outregmap().copy() : null;
+ RegMaskRW rmask = n instanceof MachNode mach && mach.outregmap()!=null ? mach.outregmap().copy() : null;
for( Node use : n._outputs ) {
// Remote use, so this is a remote def
if( use!=null && use.cfg0()!=bb ) _rdef = true;
@@ -205,7 +205,7 @@ public abstract class ListScheduler {
for( int i=1; i<n.nIns(); i++ ) {
XSched xd = XSched.get( n.in(i) );
if( xd != null && xd._n.nOuts()==1 )
- CNT[xd._single || ((MachNode)n).regmap(i).size1() ? 2 : 1]++;
+ CNT[xd._single || ((MachNode)n).regmap(i)!=null && ((MachNode)n).regmap(i).size1() ? 2 : 1]++;
}
score += 10 * Math.min( CNT[1], 2 );
score += 100 * Math.min( CNT[2], 2 );
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/Parser.java b/chapter19/src/main/java/com/seaofnodes/simple/Parser.java
index 61a53d68..19822738 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/Parser.java
@@ -1724,6 +1724,6 @@ public class Parser {
public final Lexer _loc;
// file:line:charoff err
//String msg = "src:"+_line_number+":"+(_position-_line_start)+" "+errorMessage;
- ParseException( String msg, Lexer loc ) { super(msg); _loc = loc; assert loc!=null; }
+ ParseException( String msg, Lexer loc ) { super(msg); _loc = loc; }
}
}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java b/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java
index 20be7157..073b472b 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/RegMask.java
@@ -12,6 +12,13 @@ public class RegMask {
public RegMask(long x ) { _bits = BitSet.valueOf(new long[]{x}); }
public RegMask(long[] xs) { _bits = BitSet.valueOf( xs); }
+
+ public RegMask or(RegMask other) {
+ BitSet resultBits = (BitSet)this._bits.clone();
+ resultBits.or(other._bits);
+ return new RegMask(resultBits);
+ }
+
// Internal constructor
RegMask() { _bits = new BitSet(); }
RegMask(BitSet bs) { _bits = bs; }
@@ -33,6 +40,7 @@ class RegMaskRW extends RegMask {
public void clr(int r) { _bits.clear(r); }
public void set(int r, boolean b) { _bits.set(r,b); }
public RegMaskRW and( RegMask r ) {
+ if( r==null ) return this;
_bits.and(r._bits);
return this;
}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java
index 6b7f2418..5a42e2e8 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -1,11 +1,9 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.*;
-
import java.util.BitSet;
-import static com.seaofnodes.simple.Parser.con;
-
public class AddNode extends Node {
public AddNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@@ -46,6 +44,7 @@ public class AddNode extends Node {
public Node idealize () {
Node lhs = in(1);
Node rhs = in(2);
+ if( rhs.err()!=null ) return null;
Type t2 = rhs._type;
// Add of 0. We do not check for (0+x) because this will already
@@ -187,4 +186,10 @@ public class AddNode extends Node {
@Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs); }
@Override Node copyF() { return new AddFNode(null,null); }
+ @Override public Parser.ParseException err() {
+ if( in(1)._type.isHigh() || in(2)._type.isHigh() ) return null;
+ if( !(in(1)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(1)._type,null);
+ if( !(in(2)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(2)._type,null);
+ return null;
+ }
}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
index 4e50c1fc..46188ed5 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
@@ -20,7 +20,7 @@ public class CallEndNode extends CFGNode implements MultiNode {
@Override public boolean isMultiHead() { return true; }
@Override public boolean blockHead() { return true; }
- CallNode call() { return (CallNode)in(0); }
+ public CallNode call() { return (CallNode)in(0); }
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java
index a9ca852c..25f76a71 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/CallNode.java
@@ -48,6 +48,8 @@ public class CallNode extends CFGNode {
int nargs() { return nIns()-3; } // Minus control, memory, fptr
// args from input 2 to last; last is function input
public Node fptr() { return _inputs.last(); }
+ // Error if not a TFP
+ public TypeFunPtr tfp() { return (TypeFunPtr)fptr()._type; }
// Find the Call End from the Call
public CallEndNode cend() {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 4fdf987d..53472994 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -78,4 +78,10 @@ public class MulNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new MulNode(lhs,rhs); }
@Override Node copyF() { return new MulFNode(null,null); }
+ @Override public Parser.ParseException err() {
+ if( in(1)._type.isHigh() || in(2)._type.isHigh() ) return null;
+ if( !(in(1)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(1)._type,null);
+ if( !(in(2)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(2)._type,null);
+ return null;
+ }
}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java
new file mode 100644
index 00000000..bc959977
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java
@@ -0,0 +1,30 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class AddFRISC extends MachConcreteNode implements MachNode{
+ AddFRISC(Node addf) {super(addf);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.FMASK; }
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Default on double precision for now(64 bits)
+ // General form: "fadd.d 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)));
+ }
+
+ @Override public String op() { return "addf"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java
new file mode 100644
index 00000000..af4bf08d
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java
@@ -0,0 +1,39 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class AddIRISC extends MachConcreteNode implements MachNode {
+ final TypeInteger _ti;
+ AddIRISC( Node add, TypeInteger ti ) {
+ super(add);
+ _inputs.pop();
+ _ti = ti;
+ }
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) {
+ // assert i== i;
+ return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // 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(" + #");
+ _ti.print(sb);
+ }
+
+ @Override public String op() {
+ return _ti.value() == 1 ? "inc" : (_ti.value() == -1 ? "dec" : "addi");
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java
new file mode 100644
index 00000000..482b7f11
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddRISC.java
@@ -0,0 +1,36 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+
+public class AddRISC extends MachConcreteNode implements MachNode {
+
+ AddRISC( Node add) {super(add); }
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) {
+ assert i== 1 || i == 2 || i == 3;
+ return riscv.RMASK;
+ }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // 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)));
+ }
+
+ @Override public String op() {
+ return "add";}
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java
new file mode 100644
index 00000000..29c2a686
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java
@@ -0,0 +1,40 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+import java.lang.StringBuilder;
+
+public class AndIRISC extends MachConcreteNode implements MachNode{
+ final TypeInteger _ti;
+ AndIRISC(AndNode and, TypeInteger ti) {
+ super(and);
+ _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 || i == 2; return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // 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(" & #");
+ _ti.print(sb);
+ }
+
+ @Override public String op() { return "andi"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java
new file mode 100644
index 00000000..e697de36
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndRISC.java
@@ -0,0 +1,41 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+import java.lang.StringBuilder;
+
+public class AndRISC extends MachConcreteNode implements MachNode{
+ AndRISC(Node and) {
+ super(and);
+ }
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ assert i==1 || i==2;
+ return riscv.RMASK;
+ }
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: #rd = rs1 & rs2
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java
new file mode 100644
index 00000000..d7e23c6d
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CBranchRISC.java
@@ -0,0 +1,49 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+// Conditional branch such as: BEQ
+public class CBranchRISC extends IfNode implements MachNode{
+ final String _bop;
+ // label is obtained implicitly
+ CBranchRISC( IfNode iff, String bop ) {
+ super(iff);
+ _bop = bop;
+ }
+
+ @Override public String label() { return op(); }
+
+ @Override public void postSelect() {
+ Node set = in(1);
+ Node cmp = set.in(1);
+ // Bypass an expected Set and just reference the cmp directly
+ if( set instanceof SetRISC)
+ _inputs.set(1,cmp);
+ else
+ throw Utils.TODO();
+ }
+
+ @Override public RegMask regmap(int i) { assert i==1; return riscv.RMASK; }
+ @Override public RegMask outregmap() { return null; }
+
+ // Encoding is appended into the byte array; size is returned
+
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+ String src = code.reg(in(1));
+ if( src!="FLAGS" ) sb.p(src);
+ }
+
+ @Override public String op() { return "b"+_bop; }
+
+ @Override public String comment() {
+ return "L"+cproj(1)._nid+", L"+cproj(0)._nid;
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java
new file mode 100644
index 00000000..7f062104
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java
@@ -0,0 +1,37 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeFunPtr;
+import java.io.ByteArrayOutputStream;
+
+public class CallRISC extends CallNode implements MachNode{
+ final TypeFunPtr _tfp;
+ final String _name;
+ CallRISC( CallNode call, TypeFunPtr tfp ) {
+ super(call);
+ _inputs.pop(); // Pop constant target
+ assert tfp.isConstant();
+ _tfp = tfp;
+ _name = CodeGen.CODE.link(tfp)._name;
+ }
+
+ @Override public String label() { return op(); }
+ @Override public RegMask regmap(int i) {
+ return riscv.callInMaskInt(i); // Normal argument
+ }
+ @Override public RegMask outregmap() { return riscv.RET_MASK; }
+
+ @Override public String name() { return _name; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(_name);
+ }
+
+ @Override public String op() { return "call"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java
new file mode 100644
index 00000000..02850582
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java
@@ -0,0 +1,31 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+
+import java.io.ByteArrayOutputStream;
+
+public class CallRRISC extends CallNode implements MachNode{
+ CallRRISC( CallNode call ) { super(call); }
+
+ @Override public String label() { return op(); }
+ @Override public RegMask regmap(int i) {
+ // Todo: float or int?
+ return i==_inputs._len
+ ? riscv.RMASK // Function call target
+ : riscv.callInMaskInt(i); // Normal argument
+ }
+ @Override public RegMask outregmap() { return riscv.RET_MASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(fptr()));
+ }
+
+ @Override public String op() { return "callr"; }
+
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java
new file mode 100644
index 00000000..39fa3a29
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpIRISC.java
@@ -0,0 +1,44 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+// Compare immediate. Sets flags.(RFLAGS)
+public class CmpIRISC extends MachConcreteNode implements MachNode{
+ final int _imm;
+ final String _bop;
+ CmpIRISC( BoolNode bool, TypeInteger ti ) {
+ super(bool);
+ _inputs.pop(); // Toss ideal ConstantNode away, embedded into machine op
+ _bop = bool.op(); // One of <,<=,==
+ _imm = (int)ti.value();
+ assert _imm == ti.value();
+ }
+ CmpIRISC( Node cmp, double ignore ) {
+ super(cmp);
+ _bop = "==";
+ _imm = 0;
+ }
+
+ @Override public RegMask regmap(int i) { assert i==1; return riscv.RMASK; }
+ @Override public RegMask outregmap() { return riscv.FLAGS_MASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form: "cmp rs1, 1"
+ @Override public void asm(CodeGen code, SB sb) {
+ String dst = code.reg(this);
+ if( dst!="FLAGS" ) sb.p(dst).p(" = ");
+ sb.p(code.reg(in(1)));
+ if( _imm != 0 ) sb.p(", #").p(_imm);
+ }
+
+ @Override public String op() { return _imm==0 ? "test" : "cmp"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java
new file mode 100644
index 00000000..3bd4008e
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CmpRISC.java
@@ -0,0 +1,28 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFunPtr;
+import java.io.ByteArrayOutputStream;
+
+// Compare. Sets flags.(RFLAGS)
+public class CmpRISC extends MachConcreteNode implements MachNode{
+ CmpRISC( Node cmp ) { super(cmp); }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+
+ // General form: "cmp rs1, rs2"
+ @Override public void asm(CodeGen code, SB sb) {
+ String dst = code.reg(this);
+ if( dst!="FLAGS" ) sb.p(dst).p(" = ");
+ sb.p(code.reg(in(1))).p(", ").p(code.reg(in(2)));
+ }
+
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.RMASK; }
+ @Override public RegMask outregmap() { return riscv.FLAGS_MASK; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java
new file mode 100644
index 00000000..deb2628d
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java
@@ -0,0 +1,30 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import java.io.ByteArrayOutputStream;
+
+public class DivFRISC extends MachConcreteNode implements MachNode{
+ DivFRISC(Node divf) {super(divf);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.FMASK; }
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Default on double precision for now(64 bits)
+ // General form: "fdiv.d 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)));
+ }
+
+ @Override public String op() { return "divf"; }
+
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java
new file mode 100644
index 00000000..98a8406f
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivRISC.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class DivRISC extends MachConcreteNode implements MachNode{
+ DivRISC(Node div) {super(div);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) {
+ assert i==1 || i==2;
+ return riscv.FMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return x86_64_v2.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Signed division
+ // General form: "rd = rs1 / rs"
+ @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)));
+ }
+
+ @Override public String op() { return "div"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
new file mode 100644
index 00000000..e1637eec
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java
@@ -0,0 +1,39 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.ConstantNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+
+import java.io.ByteArrayOutputStream;
+
+public class FltRISC extends ConstantNode implements MachNode{
+ FltRISC(ConstantNode con) {
+ super(con);
+ }
+ // Register mask allowed on input i. 0 for no register.
+ @Override public RegMask regmap(int i) { return null; }
+ // General int registers
+ @Override public RegMask outregmap() { return riscv.FMASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Human-readable form appended to the SB. Things like the encoding,
+ // indentation, leading address or block labels not printed here.
+ // Just something like "ld4\tR17=[R18+12] // Load array base".
+ // General form: "op\tdst=src+src"
+ @Override public void asm(CodeGen code, SB sb) {
+ _con.print(sb.p(code.reg(this)).p(" #"));
+ }
+
+ @Override public String op() {
+ return "flw"; // Some fancier encoding
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java
new file mode 100644
index 00000000..66e32e29
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java
@@ -0,0 +1,22 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.FunNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.FunX86;
+
+import java.io.ByteArrayOutputStream;
+
+public class FunRISC extends FunNode implements MachNode{
+ FunRISC(FunNode fun) {super(fun);}
+ // Register mask allowed on input i. 0 for no register.
+ @Override public RegMask regmap(int i) { return null; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return null; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java
new file mode 100644
index 00000000..df005e86
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java
@@ -0,0 +1,29 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+// fcvt.d.w
+public class I2F8RISC extends MachConcreteNode implements MachNode {
+ I2F8RISC(Node i2f8) {super(i2f8);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1; return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.FMASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form: "i2f8 (flt)int_value"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p("(flt)").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "i2f8"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java
new file mode 100644
index 00000000..bf170b22
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.ConstantNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.io.ByteArrayOutputStream;
+// Integer constants
+public class IntRISC extends ConstantNode implements MachNode {
+ IntRISC(ConstantNode con) {
+ super(con);
+ }
+
+ // Register mask allowed on input i. 0 for no register.
+ @Override public RegMask regmap(int i) { return null; }
+ // General int registers
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Human-readable form appended to the SB. Things like the encoding,
+ // indentation, leading address or block labels not printed here.
+ // Just something like "ld4\tR17=[R18+12] // Load array base".
+ // General form: "op\tdst=src+src"
+ @Override public void asm(CodeGen code, SB sb) {
+ String reg = code.reg(this);
+ if( _con == Type.NIL || _con == TypeInteger.ZERO )
+ sb.p(reg).p(",").p(reg);
+ else
+ _con.print(sb.p(reg).p(" #"));
+ }
+
+ @Override public String op() {
+ if( _con == Type.NIL || _con == TypeInteger.ZERO )
+ return "xor";
+ return "ldi"; // Some fancier encoding
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java
new file mode 100644
index 00000000..846e313c
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java
@@ -0,0 +1,34 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class LoadRISC extends MemOpRISC{
+ LoadRISC(LoadNode ld) {
+ super(ld, ld);
+ }
+
+ @Override public RegMask regmap(int i) {
+ // wider mask, encode it differently, immediate handled with hard split(in RA)
+ return riscv.RMASK.or(riscv.FMASK);
+ }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+ }
+
+ @Override public String op() {
+ return "lw" +_sz;
+ }
+}
+
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
new file mode 100644
index 00000000..092143d6
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
@@ -0,0 +1,36 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.*;
+import java.io.ByteArrayOutputStream;
+import java.lang.StringBuilder;
+import java.util.BitSet;
+
+
+public class MemOpRISC extends MemOpNode implements MachNode{
+ final char _sz = (char)('0'+(1<<_declaredType.log_size()));
+ MemOpRISC(Node op, MemOpNode mop) {
+ super(op, mop);
+ }
+ @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); }
+
+ @Override public String label() { return op(); }
+ @Override public Type compute() { throw Utils.TODO(); }
+ @Override public Node idealize() { throw Utils.TODO(); }
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) {
+ throw Utils.TODO();
+ }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { throw Utils.TODO(); }
+
+ @Override public int encoding(ByteArrayOutputStream bytes) { throw Utils.TODO(); }
+
+
+ SB asm_address(CodeGen code, SB sb) {
+ return sb;
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java
new file mode 100644
index 00000000..43197b50
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java
@@ -0,0 +1,30 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import java.io.ByteArrayOutputStream;
+
+public class MulFRISC extends MachConcreteNode implements MachNode{
+ MulFRISC(Node mulf) {super(mulf);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.FMASK; }
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Default on double precision for now(64 bits)
+ // General form: "fmul.d 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)));
+ }
+
+ @Override public String op() { return "mulf"; }
+
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java
new file mode 100644
index 00000000..8735068e
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulIRISC.java
@@ -0,0 +1,35 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class MulIRISC extends MachConcreteNode implements MachNode {
+ final TypeInteger _ti;
+ MulIRISC(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) {
+ return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ 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/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java
new file mode 100644
index 00000000..8713486e
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulRISC.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+
+// mulh signed multiply instruction(no-imm form)
+public class MulRISC extends MachConcreteNode implements MachNode{
+ MulRISC(Node mul) {super(mul);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // 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)));
+ }
+
+ @Override public String op() { return "mul"; }
+
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java
new file mode 100644
index 00000000..f050715d
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java
@@ -0,0 +1,44 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+
+import java.io.ByteArrayOutputStream;
+
+
+public class NewRISC extends NewNode implements MachNode{
+
+ // A pre-zeroed chunk of memory.
+ NewRISC( NewNode nnn ) { super(nnn); }
+
+ // Register mask allowed on input i, the size
+ @Override public RegMask regmap(int i) {
+ // Size
+ if( i==1 ) return riscv.RET_MASK;
+ // All the memory alias edges
+ return null;
+ }
+
+ @Override public RegMask outregmap() { throw Utils.TODO(); }
+
+ // Register mask allowed as a result. Pointer result in standard calling
+ // convention.
+ @Override public RegMask outregmap(int i) {
+ if( i == 1 ) return riscv.RET_MASK;
+ // All the memory aliases edges
+ return null;
+ }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form: "alloc #bytes"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(size()));
+ }
+
+ @Override public String op() { return "alloc"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java
new file mode 100644
index 00000000..f3f79ed1
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.MachConcreteNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.io.ByteArrayOutputStream;
+
+public class OrIRISC extends MachConcreteNode implements MachNode{
+ final TypeInteger _ti;
+ OrIRISC(Node or, TypeInteger ti) {super(or); _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 || i==2;
+ return riscv.RMASK;
+ }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0;}
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "rd = rs1 | 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 "ori"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java
new file mode 100644
index 00000000..8f1e9305
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.node.MachConcreteNode;
+import com.seaofnodes.simple.node.MachNode;
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import java.io.ByteArrayOutputStream;
+
+public class OrRISC extends MachConcreteNode implements MachNode {
+ OrRISC(Node or) {
+ super(or);
+ }
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ assert i==1 || i==2;
+ return riscv.RMASK;
+ }
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: # rd = rs1 | rs2
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java
new file mode 100644
index 00000000..2e20f96f
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ParmRISC.java
@@ -0,0 +1,25 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.ParmNode;
+import com.seaofnodes.simple.node.MachNode;
+import java.io.ByteArrayOutputStream;
+
+public class ParmRISC extends ParmNode implements MachNode{
+ final RegMask _rmask;
+ ParmRISC(ParmNode parm) {
+ super(parm);
+ // Assume int
+ _rmask = riscv.callInMaskInt(_idx);
+ }
+
+ // Register mask allowed on input i. 0 for no register.
+ @Override public RegMask regmap(int i) { return null; }
+ // Register mask allowed as a result. Calling convention register
+ @Override public RegMask outregmap() { return _rmask; }
+
+ // Encoding is appended into the byte array. Returns size
+ @Override public int encoding(ByteArrayOutputStream bytes) { return 0; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java
new file mode 100644
index 00000000..a1312c4c
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ProjRISC.java
@@ -0,0 +1,23 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.ProjNode;
+import com.seaofnodes.simple.node.MachNode;
+import java.io.ByteArrayOutputStream;
+
+public class ProjRISC extends ProjNode implements MachNode{
+ ProjRISC(ProjNode p) {super(p);}
+
+ // Register mask allowed on input i. 0 for no register.
+ @Override public RegMask regmap(int i) { return null; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return null; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java
new file mode 100644
index 00000000..c92e6989
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java
@@ -0,0 +1,48 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.FunNode;
+import com.seaofnodes.simple.node.ReturnNode;
+import com.seaofnodes.simple.node.MachNode;
+
+import java.io.ByteArrayOutputStream;
+
+public class RetRISC extends ReturnNode implements MachNode{
+ RetRISC(ReturnNode ret, FunNode fun) { super(ret, fun); fun.setRet(this); }
+ // Todo: postSelect
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ return switch( i ) {
+ case 0 -> null;
+ case 1 -> null;
+ case 2 -> riscv.RET_MASK;
+ case 3 -> null; // RPC is always on stack
+ default -> throw Utils.TODO();
+ };
+ }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return null; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Human-readable form appended to the SB. Things like the encoding,
+ // indentation, leading address or block labels not printed here.
+ // Just something like "ld4\tR17=[R18+12] // Load array base".
+ // General form: "op\tdst=src+src"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(in(2)));
+ }
+
+ // Correct Nodes outside the normal edges
+ @Override public void postSelect() {
+ FunNode fun = (FunNode)rpc().in(0);
+ _fun = fun;
+ fun.setRet(this);
+ }
+
+ @Override public String op() { return "ret"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java
new file mode 100644
index 00000000..1d8c9de8
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetRISC.java
@@ -0,0 +1,35 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+// corresponds to slt,sltu,slti,sltiu, seqz
+// RISCV doesn't have rflags.
+public class SetRISC extends MachConcreteNode implements MachNode{
+ final String _bop; // One of <,<=,==
+ SetRISC( Node cmp, String bop ) {
+ super(cmp);
+ _inputs.setLen(1); // Pop the cmp inputs
+ // Replace with the matched cmp
+ _inputs.push(cmp);
+ _bop = bop;
+ }
+ @Override public RegMask regmap(int i) { assert i==1; return riscv.FLAGS_MASK; }
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this));
+ String src = code.reg(in(1));
+ if( src!="FLAGS" ) sb.p(" = ").p(src);
+ }
+
+ @Override public String op() { return "set"+_bop; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java
new file mode 100644
index 00000000..8927c086
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java
@@ -0,0 +1,40 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+
+public class SllIRISC extends MachConcreteNode implements MachNode{
+ final TypeInteger _ti;
+ SllIRISC(Node sll, TypeInteger ti) {super(sll); _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 riscv.RMASK; }
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "slli rd, rs1, 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 "slli"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java
new file mode 100644
index 00000000..69538433
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllRISC.java
@@ -0,0 +1,36 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+
+public class SllRISC extends MachConcreteNode implements MachNode{
+ SllRISC(Node sll) {super(sll);}
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ //assert i==1;
+ return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "sll rd, rs1, rs2"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "sll"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java
new file mode 100644
index 00000000..654dd2ae
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+import java.lang.StringBuilder;
+
+
+// Right Shift Arithmetic(immediate)
+public class SraIRISC extends MachConcreteNode implements MachNode{
+ final TypeInteger _ti;
+ SraIRISC(Node sra, TypeInteger ti) {super(sra); _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 riscv.RMASK; }
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "srai rd, rs1, 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 "srai"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java
new file mode 100644
index 00000000..2d50ceaa
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraRISC.java
@@ -0,0 +1,42 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.MachConcreteNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.io.ByteArrayOutputStream;
+
+// Right Shift Arithmetic
+public class SraRISC extends MachConcreteNode implements MachNode {
+
+ SraRISC(Node sra) {super(sra);}
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ // assert i==1;
+ return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "sra rd, rs1, rs2"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "sra"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java
new file mode 100644
index 00000000..f7ad6c25
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+import java.lang.StringBuilder;
+
+
+// Right Shift Logical Immediate
+public class SrlIRISC extends MachConcreteNode implements MachNode {
+ final TypeInteger _ti;
+ SrlIRISC(Node srl, TypeInteger ti) {super(srl); _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 riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "srli 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 "srli"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java
new file mode 100644
index 00000000..25d62688
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlRISC.java
@@ -0,0 +1,38 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+import java.lang.StringBuilder;
+
+// Right Shift Logical
+public class SrlRISC extends MachConcreteNode implements MachNode {
+ SrlRISC(Node srli) {super(srli);}
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ // assert i==1;
+ return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "srl rd, rs1, rs2"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "srl"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java
new file mode 100644
index 00000000..9fbd7c12
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java
@@ -0,0 +1,40 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.MachConcreteNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.StoreNode;
+
+import java.io.ByteArrayOutputStream;
+import java.util.BitSet;
+
+
+// sw rs2,offset(rs1)
+public class StoreRISC extends MemOpRISC {
+ StoreRISC( StoreNode st) {
+ super(st, st);
+ }
+
+ @Override public RegMask regmap(int i) {
+ return riscv.RMASK;
+ }
+
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return null; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) {
+
+ }
+
+ @Override public String op() { return "st"+_sz; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java
new file mode 100644
index 00000000..e6a0b8e4
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java
@@ -0,0 +1,30 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class SubFRISC extends MachConcreteNode implements MachNode{
+ SubFRISC(Node subf) {super(subf);}
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.FMASK; }
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Default on double precision for now(64 bits)
+ // General form: "fsub.d 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)));
+ }
+
+ @Override public String op() { return "subf"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java
new file mode 100644
index 00000000..6fb0e0ef
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubRISC.java
@@ -0,0 +1,29 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+public class SubRISC extends MachConcreteNode implements MachNode {
+ SubRISC( Node sub ) { super(sub); }
+
+ // Register mask allowed on input i.
+ @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form: "sub # 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)));
+ }
+
+ @Override public String op() { return "sub"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java
new file mode 100644
index 00000000..b508541a
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.ConstantNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.TFPX86;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFunPtr;
+
+import java.io.ByteArrayOutputStream;
+
+public class TFPRISC extends ConstantNode implements MachNode{
+ TFPRISC(ConstantNode con) {super(con);}
+ // Register mask allowed on input i. 0 for no register.
+ @Override public RegMask regmap(int i) { return null; }
+ // General int registers
+ @Override public RegMask outregmap() { return x86_64_v2.RMASK; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // Human-readable form appended to the SB. Things like the encoding,
+ // indentation, leading address or block labels not printed here.
+ // Just something like "ld4\tR17=[R18+12] // Load array base".
+ // General form: "op\tdst=src+src"
+ @Override public void asm(CodeGen code, SB sb) {
+ String reg = code.reg(this);
+ if( _con == Type.NIL )
+ sb.p(reg).p(",").p(reg);
+ else
+ _con.print(sb.p(reg).p(" #"));
+ }
+
+ @Override public String op() {
+ if( _con == Type.NIL )
+ return "xor";
+ return "ldx"; // Some fancier encoding
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java
new file mode 100644
index 00000000..3d53ee64
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java
@@ -0,0 +1,45 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.MachConcreteNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.x86_64_v2;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.io.ByteArrayOutputStream;
+
+public class XorIRISC extends MachConcreteNode implements MachNode{
+ final TypeInteger _ti;
+ XorIRISC(Node xor, TypeInteger ti) {super(xor); _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 || i==2;
+
+ return riscv.RMASK; }
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "rd = rs1 ^ 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 "xori"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java
new file mode 100644
index 00000000..2f34529e
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorRISC.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.MachConcreteNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.io.ByteArrayOutputStream;
+
+public class XorRISC extends MachConcreteNode implements MachNode {
+
+ XorRISC(Node or) {
+ super(or);
+ }
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) {
+ assert i==1 || i==2;
+ return riscv.RMASK;
+ }
+
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return riscv.RMASK; }
+
+ // Output is same register as input#1
+ @Override public int twoAddress() { return 0; }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: # # rd = rs1 ^ rs2
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
new file mode 100644
index 00000000..399eebca
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
@@ -0,0 +1,329 @@
+package com.seaofnodes.simple.node.cpus.riscv;
+
+import com.seaofnodes.simple.Machine;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.*;
+import com.seaofnodes.simple.type.*;
+
+public class riscv extends Machine{
+ @Override public String name() {return "riscv";}
+
+ // Using ABI names instead of register names
+ public static int ZERO = 0, RA = 1, SP = 2, GP = 3, TP = 4, T0 = 5, T1 = 6, T2 = 7;
+ public static int S0 = 8, S1 = 9, A0 = 10, A1 = 11, A2 = 12, A3 = 13, A4 = 14, A5 = 15;
+ public static int A6 = 16, A7 = 17, S2 = 18, S3 = 19, S4 = 20, S5 = 21, S6 = 22, S7 = 23;
+ public static int S8 = 24, S9 = 25, S10 = 26, S11 = 27, T3 = 28, T4 = 29, T5 = 30, T6 = 31;
+
+ // FP registers
+ public static int F0 = 32, F1 = 33, F2 = 34, F3 = 35, F4 = 36, F5 = 37, F6 = 38, F7 = 39;
+ public static int FS0 = 40, FS1 = 41, FA0 = 42, FA1 = 43, FA2 = 44, FA3 = 45, FA4 = 46, FA5 = 47;
+ public static int FA6 = 48, FA7 = 49, FS2 = 50, FS3 = 51, FS4 = 52, FS5 = 53, FS6 = 54, FS7 = 55;
+ public static int FS8 = 56, FS9 = 57, FS10 = 58, FS11 = 59, FT8 = 60, FT9 = 61, FT10 = 62, FT11 = 63;
+
+ public static int FLAGS = 64;
+
+ // General purpose register mask: pointers and ints, not floats
+ public static RegMask RMASK = new RegMask(0b11111111111111111111111111111111);
+ // Float mask from(ft0–ft11)
+ public static RegMask FMASK = new RegMask(0b11111111111111111111111111111111);
+
+ // Return single int/ptr register
+ public static RegMask RET_MASK = new RegMask(A0);
+
+ // Arguments masks
+ public static RegMask A0_MASK = new RegMask(1L<<A0);
+ public static RegMask A1_MASK = new RegMask(1L<<A1);
+ public static RegMask A2_MASK = new RegMask(1L<<A2);
+ public static RegMask A3_MASK = new RegMask(1L<<A3);
+ public static RegMask A4_MASK = new RegMask(1L<<A4);
+ public static RegMask A5_MASK = new RegMask(1L<<A5);
+ public static RegMask A6_MASK = new RegMask(1L<<A6);
+ public static RegMask A7_MASK = new RegMask(1L<<A7);
+
+ public static RegMask FLAGS_MASK = new RegMask(1L << FLAGS);
+
+ // Float arguments masks
+ public static RegMask FA0_MASK = new RegMask(1L<<FA0);
+ public static RegMask FA1_MASK = new RegMask(1L<<FA1);
+ public static RegMask FA2_MASK = new RegMask(1L<<FA2);
+ public static RegMask FA3_MASK = new RegMask(1L<<FA3);
+ public static RegMask FA4_MASK = new RegMask(1L<<FA4);
+ public static RegMask FA5_MASK = new RegMask(1L<<FA5);
+ public static RegMask FA6_MASK = new RegMask(1L<<FA6);
+ public static RegMask FA7_MASK = new RegMask(1L<<FA7);
+
+ // Int arguments calling conv
+ static RegMask[] CALLINMASK_RISCV_INT = new RegMask[] {
+ null,
+ null,
+ A0_MASK,
+ A1_MASK,
+ A2_MASK,
+ A3_MASK,
+ A4_MASK,
+ A5_MASK,
+ A6_MASK,
+ A7_MASK
+ };
+
+ static int[] CALLINARG_RISCV_INT = new int[] {
+ 0, // Control, no register
+ 0, // Memory, no register
+ A0,
+ A1,
+ A2,
+ A3,
+ A4,
+ A5,
+ A6,
+ A7
+ };
+
+ static int callInArgInt(int idx) {
+ return CALLINARG_RISCV_INT[idx];
+ }
+
+ static RegMask callInMaskInt(int idx) {
+ return CALLINMASK_RISCV_INT[idx];
+ }
+
+ // Float arguments
+ static RegMask[] CALLINMASK_RISCV_FLOAT = new RegMask[] {
+ null,
+ null,
+ FA0_MASK,
+ FA1_MASK,
+ FA2_MASK,
+ FA3_MASK,
+ FA4_MASK,
+ FA5_MASK,
+ FA6_MASK,
+ FA7_MASK
+ };
+
+
+ static int[] CALLINARG_RISCV_FLOAT = new int[] {
+ 0, // Control, no register
+ 0, // Memory, no register
+ FA0,
+ FA1,
+ FA2,
+ FA3,
+ FA4,
+ FA5,
+ FA6,
+ FA7
+ };
+
+
+ static int callInArgFloat(int idx) {
+ return CALLINARG_RISCV_FLOAT[idx];
+ }
+
+ static RegMask callInMaskFloat(int idx) {
+ return CALLINMASK_RISCV_FLOAT[idx];
+ }
+ // caller saved(riscv)
+ //public static final long RISCV_CALLER_SAVED= TBD
+ // callee saved(riscv)
+ public static final long RISCV_CALLEE_SAVED =
+ (1L << FS0) | (1L << FS1) | (1L << FS2) | (1L << FS3) | (1L << FS4)
+ | (1L << FS5) | (1L << FS6) | (1L << FS7) | (1L << FS8) | (1L << FS9) | (1L << FS10);
+
+
+ // Calling conv metadata
+ public int GPR_COUNT_CONV_RISCV = 7; // A0, A1, A2, A3, A4, A5, A6, A7
+ public int FLOAT_COUNT_CONV_RISCV = 7; // FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7
+
+ public static final String[] REGS = new String[] {
+ "zero", "ra" , "sp" , "gp" , "tp" , "t0" , "t1" , "t2" ,
+ "s0" , "s1" , "a0" , "a1" , "a2" , "a3" , "a4" , "a5" ,
+ "a6" , "a7" , "s2" , "s3" , "s4" , "s5" , "s6" , "s7" ,
+ "s8" , "s9" , "s10" , "s11" , "t3" , "t4" , "t5" , "t6" ,
+ "f0" , "f1" , "f2" , "f3" , "f4" , "f5" , "f6" , "f7" ,
+ "fs0" , "fs1" , "fa0" , "fa1" , "fa2" , "fa3" , "fa4" , "fa5" ,
+ "fa6" , "fa7" , "fs2" , "fs3" , "fs4" , "fs5" , "fs6" , "fs7" ,
+ "fs8" , "fs9" , "fs10", "fs11", "ft8" , "ft9" , "ft10", "ft11",
+ "flags"
+ };
+
+ // General purpose register mask:
+ @Override public String reg( int reg ) { return REGS[reg]; }
+ // Return a MachNode unconditional branch
+ @Override public CFGNode jump() {
+ throw Utils.TODO();
+ }
+
+ // Create a split op; any register to any register, including stack slots
+ @Override public Node split() {
+ throw Utils.TODO();
+ }
+
+ // Break an infinite loop
+ @Override public IfNode never( CFGNode ctrl ) {
+ throw Utils.TODO();
+ }
+
+ @Override public Node instSelect( Node n ) {
+ return switch (n) {
+ case AddFNode addf -> addf(addf);
+ case AddNode add -> add(add);
+ case AndNode and -> and(and);
+ case BoolNode bool -> cmp(bool);
+ case CallEndNode cend -> new CallEndNode((CallNode) cend.in(0));
+ case CallNode call -> call(call);
+ case CProjNode c -> new CProjNode(c);
+ case ConstantNode con -> con(con);
+ case DivFNode divf -> new DivFRISC(divf);
+ case DivNode div -> new DivRISC(div);
+ case FunNode fun -> new FunRISC(fun);
+ case IfNode iff -> jmp(iff);
+ case LoadNode ld -> ld(ld);
+ case MemMergeNode mem -> new MemMergeNode(mem);
+ case MulFNode mulf -> new MulFRISC(mulf);
+ case MulNode mul -> mul(mul);
+ case NewNode nnn -> new NewRISC(nnn);
+ case OrNode or -> or(or);
+ case ParmNode parm -> new ParmRISC(parm);
+ case PhiNode phi -> new PhiNode(phi);
+ case ProjNode prj -> prj(prj);
+ case ReadOnlyNode read -> new ReadOnlyNode(read);
+ case ReturnNode ret -> new RetRISC(ret, ret.fun());
+ case SarNode sar -> sra(sar);
+ case ShlNode shl -> sll(shl);
+ case ShrNode shr -> srl(shr);
+ case StartNode start -> new StartNode(start);
+ case StopNode stop -> new StopNode(stop);
+ case StoreNode st -> st(st);
+ case SubFNode subf -> new SubFRISC(subf);
+ case SubNode sub -> sub(sub);
+ case ToFloatNode tfn -> i2f8(tfn);
+ case XorNode xor -> xor(xor);
+
+ case LoopNode loop -> new LoopNode(loop);
+ case RegionNode region -> new RegionNode(region);
+ default -> throw Utils.TODO();
+ };
+ }
+
+ private Node addf(AddFNode addf) {
+ return new AddFRISC(addf);
+ }
+
+ private Node add(AddNode add) {
+ Node rhs = add.in(2);
+ if( rhs instanceof ConstantNode off && off._con instanceof TypeInteger toff ) {
+ return new AddIRISC(add, toff);
+ }
+ return new AddRISC(add);
+ }
+
+ private Node and(AndNode and) {
+ if( and.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
+ return new AndIRISC(and, ti);
+ return new AndRISC(and);
+ }
+
+ private Node cmp(BoolNode bool) {
+ Node cmp = _cmp(bool);
+ return new SetRISC(cmp, bool.op());
+ }
+
+ private Node call(CallNode call) {
+ if( call.fptr() instanceof ConstantNode con && con._con instanceof TypeFunPtr tfp )
+ return new CallRISC(call, tfp);
+ return new CallRRISC(call);
+ }
+
+ private Node _cmp(BoolNode bool) {
+ Node rhs = bool.in(2);
+
+ return rhs instanceof ConstantNode con && con._con instanceof TypeInteger ti
+ ? new CmpIRISC(bool, ti)
+ : new CmpRISC(bool);
+ }
+
+ private Node con( ConstantNode con ) {
+ return switch( con._con ) {
+ case TypeInteger ti -> new IntRISC(con);
+ case TypeFloat tf -> new IntRISC(con);
+ case TypeFunPtr tfp -> new TFPRISC(con);
+ case TypeMemPtr tmp -> new ConstantNode(con);
+ case TypeNil tn -> throw Utils.TODO();
+ // TOP, BOTTOM, XCtrl, Ctrl, etc. Never any executable code.
+ case Type t -> new ConstantNode(con);
+ };
+ }
+
+ private Node jmp( IfNode iff ) {
+ // If/Bool combos will match to a Cmp/Set which sets flags.
+ // Most general arith ops will also set flags, which the Jmp needs directly.
+ // Loads do not set the flags, and will need an explicit TEST
+ if( !(iff.in(1) instanceof BoolNode) )
+ iff.setDef(1,new BoolNode.EQ(iff.in(1),new ConstantNode(TypeInteger.ZERO)));
+ return new CBranchRISC(iff, ((BoolNode)iff.in(1)).op());
+ }
+
+ private Node or(OrNode or) {
+ if(or.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
+ return new OrIRISC(or, ti);
+
+ return new OrRISC(or);
+ }
+
+ private Node xor(XorNode xor) {
+ if(xor.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
+ return new XorIRISC(xor, ti);
+ return new XorRISC(xor);
+ }
+
+ private Node sra(SarNode sar) {
+ if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
+ return new SraIRISC(sar, ti);
+ return new SraRISC(sar);
+ }
+
+ private Node srl(ShrNode shr) {
+ if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
+ return new SrlIRISC(shr, ti);
+ return new SrlRISC(shr);
+ }
+
+ private Node sll(ShlNode sll) {
+ if( sll.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
+ return new SllIRISC(sll, ti);
+ return new SllRISC(sll);
+ }
+
+ private Node sub(SubNode sub) {
+ return sub.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti
+ ? new AddIRISC(sub, TypeInteger.constant(-ti.value()))
+ : new SubRISC(sub);
+ }
+
+ private Node i2f8(ToFloatNode tfn) {
+ assert tfn.in(1)._type instanceof TypeInteger ti;
+ return new I2F8RISC(tfn);
+ }
+
+ private Node prj(ProjNode prj) {
+ return new ProjRISC(prj);
+ }
+
+ private Node ld(LoadNode ld) {
+ return new LoadRISC(ld);
+ }
+
+ private Node st(StoreNode st) {
+ return new StoreRISC(st);
+ }
+
+ private Node mul(MulNode mul) {
+ return mul.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti
+ ? new MulIRISC(mul, ti)
+ : new MulRISC(mul);
+ }
+}
+
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java
index 4f75edcd..4bb24fa3 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java
@@ -12,7 +12,7 @@ public class AddFMemX86 extends MemOpX86 {
}
@Override public RegMask regmap(int i) {
- if( i==1 ) return RegMask.EMPTY; // Memory
+ if( i==1 ) return null; // Memory
if( i==2 ) return x86_64_v2.RMASK; // base
if( i==3 ) return x86_64_v2.RMASK; // index
if( i==4 ) return x86_64_v2.XMASK; // value
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java
new file mode 100644
index 00000000..45cf2b22
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AndX86.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import java.io.ByteArrayOutputStream;
+
+public class AndX86 extends MachConcreteNode implements MachNode{
+ AndX86(Node and) {
+ super(and);
+ }
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.WMASK; }
+
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "and dst & #imm"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "and"; }
+}
+
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java
new file mode 100644
index 00000000..55ab90c9
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallEndX86.java
@@ -0,0 +1,37 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.RegMask;
+import com.seaofnodes.simple.node.CallEndNode;
+import com.seaofnodes.simple.node.MachNode;
+import com.seaofnodes.simple.type.TypeFloat;
+import com.seaofnodes.simple.type.TypeFunPtr;
+import java.io.ByteArrayOutputStream;
+
+public class CallEndX86 extends CallEndNode implements MachNode {
+ final TypeFunPtr _tfp;
+ CallEndX86( CallEndNode cend ) {
+ super(cend);
+ _tfp = (TypeFunPtr)cend.call().fptr()._type;
+ }
+
+ @Override public String label() { return op(); }
+ @Override public RegMask regmap(int i) { return null; }
+ @Override public RegMask outregmap() { throw Utils.TODO(); }
+ @Override public RegMask outregmap(int idx) {
+ if( idx != 2 ) return null;
+ return _tfp._ret instanceof TypeFloat ? x86_64_v2.RET_FMASK : x86_64_v2.RET_MASK;
+ }
+
+ // Encoding is appended into the byte array; size is returned
+ @Override public int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ @Override public void asm(CodeGen code, SB sb) { }
+
+ @Override public String op() { return "cend"; }
+
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java
index 31d303ed..99260a27 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java
@@ -13,7 +13,7 @@ public class CallRX86 extends CallNode implements MachNode {
@Override public RegMask regmap(int i) {
return i==_inputs._len
? x86_64_v2.WMASK // Function call target
- : x86_64_v2.callInMask(i); // Normal argument
+ : x86_64_v2.callInMask(tfp(),i); // Normal argument
}
@Override public RegMask outregmap() { return x86_64_v2.RET_MASK; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java
index 9c246c24..b3e3bbe8 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java
@@ -20,11 +20,12 @@ public class CallX86 extends CallNode implements MachNode {
@Override public String label() { return op(); }
@Override public RegMask regmap(int i) {
- return x86_64_v2.callInMask(i); // Normal argument
+ return x86_64_v2.callInMask(tfp(),i); // Normal argument
}
@Override public RegMask outregmap() { return x86_64_v2.RET_MASK; }
@Override public String name() { return _name; }
+ @Override public TypeFunPtr tfp() { return _tfp; }
// Encoding is appended into the byte array; size is returned
@Override public int encoding(ByteArrayOutputStream bytes) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java
index 2fa7fbb1..ea526f33 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java
@@ -6,7 +6,7 @@ import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
import java.io.ByteArrayOutputStream;
-// Compare immediate. Sets flags.
+// Compare immediate. Sets flags.(RFLAGS)
public class CmpIX86 extends MachConcreteNode implements MachNode {
final int _imm;
final String _bop;
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java
index 6b502249..d8ebb12d 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java
@@ -5,6 +5,7 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.TypeInteger;
import java.io.ByteArrayOutputStream;
+// Compare. Sets flags.(RFLAGS)
public class CmpX86 extends MachConcreteNode implements MachNode {
CmpX86( Node cmp ) { super(cmp); }
@@ -16,7 +17,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode {
throw Utils.TODO();
}
- // General form: "add dst += src"
+ // General form: "cmp reg1, reg2"
@Override public void asm(CodeGen code, SB sb) {
String dst = code.reg(this);
if( dst!="FLAGS" ) sb.p(dst).p(" = ");
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
index 21529f7b..5e1190da 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java
@@ -13,7 +13,7 @@ public class FltX86 extends ConstantNode implements MachNode {
FltX86(ConstantNode con ) { super(con); }
// Register mask allowed on input i. 0 for no register.
- @Override public RegMask regmap(int i) { return RegMask.EMPTY; }
+ @Override public RegMask regmap(int i) { return null; }
// General int registers
@Override public RegMask outregmap() { return x86_64_v2.XMASK; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java
index f969fae4..8b0f016a 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java
@@ -10,9 +10,9 @@ public class FunX86 extends FunNode implements MachNode {
FunX86( FunNode fun ) { super(fun); }
// Register mask allowed on input i. 0 for no register.
- @Override public RegMask regmap(int i) { return RegMask.EMPTY; }
+ @Override public RegMask regmap(int i) { return null; }
// Register mask allowed as a result. 0 for no register.
- @Override public RegMask outregmap() { return RegMask.EMPTY; }
+ @Override public RegMask outregmap() { return null; }
// Encoding is appended into the byte array; size is returned
@Override public int encoding(ByteArrayOutputStream bytes) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java
index 2cd27c14..566a7293 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java
@@ -16,7 +16,7 @@ public class IntX86 extends ConstantNode implements MachNode {
}
// Register mask allowed on input i. 0 for no register.
- @Override public RegMask regmap(int i) { return RegMask.EMPTY; }
+ @Override public RegMask regmap(int i) { return null; }
// General int registers
@Override public RegMask outregmap() { return x86_64_v2.WMASK; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java
index 7cf4444c..2262e847 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java
@@ -26,7 +26,7 @@ public class JmpX86 extends IfNode implements MachNode {
throw Utils.TODO();
}
@Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.FLAGS_MASK; }
- @Override public RegMask outregmap() { return RegMask.EMPTY; }
+ @Override public RegMask outregmap() { return null; }
// Encoding is appended into the byte array; size is returned
@Override public int encoding(ByteArrayOutputStream bytes) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java
index 418f63f3..a6cdbd05 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java
@@ -11,7 +11,7 @@ public class MemAddX86 extends MemOpX86 {
}
// Register mask allowed as a result. 0 for no register.
- @Override public RegMask outregmap() { return RegMask.EMPTY; }
+ @Override public RegMask outregmap() { return null; }
// General form: "add [base + idx<<2 + 12] += src"
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java
index 1e678a0b..b94ea5ae 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java
@@ -59,7 +59,7 @@ public abstract class MemOpX86 extends MemOpNode implements MachNode {
// Register mask allowed on input i.
@Override public RegMask regmap(int i) {
- if( i==1 ) return RegMask.EMPTY; // Memory
+ if( i==1 ) return null; // Memory
if( i==2 ) return x86_64_v2.RMASK; // base
if( i==3 ) return x86_64_v2.RMASK; // index
if( i==4 ) return x86_64_v2.RMASK; // value
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java
index 7508cf4c..e9eb17fc 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java
@@ -12,7 +12,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode {
// Register mask allowed on input i.
// This is the normal calling convention
@Override public RegMask regmap(int i) {
- // assert i==1;
+ assert i==1;
return x86_64_v2.WMASK; }
// Register mask allowed as a result. 0 for no register.
@Override public RegMask outregmap() { return x86_64_v2.WMASK; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java
index 4396a917..f9778845 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java
@@ -14,7 +14,7 @@ public class NewX86 extends NewNode implements MachNode {
// Size
if( i==1 ) return x86_64_v2.RDI_MASK;
// All the memory alias edges
- return RegMask.EMPTY;
+ return null;
}
@Override public RegMask outregmap() { throw Utils.TODO(); }
@@ -23,7 +23,7 @@ public class NewX86 extends NewNode implements MachNode {
@Override public RegMask outregmap(int i) {
if( i == 1 ) return x86_64_v2.RET_MASK;
// All the memory aliases edges
- return RegMask.EMPTY;
+ return null;
}
// Encoding is appended into the byte array; size is returned
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java
index 513962c2..d3940838 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrIX86.java
@@ -19,7 +19,7 @@ public class OrIX86 extends MachConcreteNode implements MachNode {
// Register mask allowed on input i.
// This is the normal calling convention
@Override public RegMask regmap(int i) {
- //assert i==1;
+ assert i==1;
return x86_64_v2.WMASK; }
// Register mask allowed as a result. 0 for no register.
@Override public RegMask outregmap() { return x86_64_v2.WMASK; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java
new file mode 100644
index 00000000..7c25bdae
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/OrX86.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import java.io.ByteArrayOutputStream;
+
+public class OrX86 extends MachConcreteNode implements MachNode{
+ OrX86(Node or) {
+ super(or);
+ }
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+ @Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.WMASK; }
+
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "and dst & #imm"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "or"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java
index 8a439644..0fcc922d 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ParmX86.java
@@ -1,8 +1,6 @@
package com.seaofnodes.simple.node.cpus.x86_64_v2;
import com.seaofnodes.simple.RegMask;
-import com.seaofnodes.simple.SB;
-import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.node.ParmNode;
import com.seaofnodes.simple.node.MachNode;
import java.io.ByteArrayOutputStream;
@@ -11,11 +9,12 @@ public class ParmX86 extends ParmNode implements MachNode {
final RegMask _rmask;
ParmX86( ParmNode parm ) {
super(parm);
- _rmask = x86_64_v2.callInMask(_idx);
+ // default to int
+ _rmask = x86_64_v2.callInMask(fun().sig(),_idx);
}
// Register mask allowed on input i. 0 for no register.
- @Override public RegMask regmap(int i) { return RegMask.EMPTY; }
+ @Override public RegMask regmap(int i) { return null; }
// Register mask allowed as a result. Calling convention register
@Override public RegMask outregmap() { return _rmask; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java
index 2849b232..77fd7d34 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ProjX86.java
@@ -12,9 +12,11 @@ public class ProjX86 extends ProjNode implements MachNode {
ProjX86( ProjNode p ) { super(p); }
// Register mask allowed on input i. 0 for no register.
- @Override public RegMask regmap(int i) { return RegMask.EMPTY; }
+ @Override public RegMask regmap(int i) { return null; }
// Register mask allowed as a result. 0 for no register.
- @Override public RegMask outregmap() { return RegMask.EMPTY; }
+ @Override public RegMask outregmap() {
+ return ((MachNode)in(0)).outregmap(_idx);
+ }
// Encoding is appended into the byte array; size is returned
@Override public int encoding(ByteArrayOutputStream bytes) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java
index e6219ff4..21db209c 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java
@@ -21,15 +21,15 @@ public class RetX86 extends ReturnNode implements MachNode {
// This is the normal calling convention
@Override public RegMask regmap(int i) {
return switch( i ) {
- case 0 -> RegMask.EMPTY;
- case 1 -> RegMask.EMPTY;
+ case 0 -> null;
+ case 1 -> null;
case 2 -> x86_64_v2.RET_MASK;
- case 3 -> RegMask.EMPTY; // RPC is always on stack
+ case 3 -> null; // RPC is always on stack
default -> throw Utils.TODO();
};
}
// Register mask allowed as a result. 0 for no register.
- @Override public RegMask outregmap() { return RegMask.EMPTY; }
+ @Override public RegMask outregmap() { return null; }
// Encoding is appended into the byte array; size is returned
@Override public int encoding(ByteArrayOutputStream bytes) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java
new file mode 100644
index 00000000..f5337ee8
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java
@@ -0,0 +1,37 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.io.ByteArrayOutputStream;
+
+// Arithmetic Right Shift
+public class SarIX86 extends MachConcreteNode implements MachNode {
+ final TypeInteger _ti;
+ SarIX86(Node sar, TypeInteger ti) {super(sar); _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 x86_64_v2.RMASK; }
+ // Register mask allowed as a result. 0 for no register.
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "sari 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 "sari"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java
index 3d907eef..cb0b18bf 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java
@@ -8,17 +8,19 @@ import java.io.ByteArrayOutputStream;
import java.util.BitSet;
import java.lang.StringBuilder;
-
-public class SarX86 extends MachConcreteNode implements MachNode {
- final TypeInteger _ti;
- SarX86(Node sar, TypeInteger ti) {super(sar); _inputs.pop(); _ti = ti;}
+public class SarX86 extends MachConcreteNode implements MachNode{
+ SarX86(Node sar) {super(sar);}
// Register mask allowed on input i.
// This is the normal calling convention
+
+ // CL register must be used for input(2)
@Override public RegMask regmap(int i) {
- // assert i==1;
- return x86_64_v2.RMASK; }
- // Register mask allowed as a result. 0 for no register.
+ if(i == 1) return x86_64_v2.WMASK;
+ if(i == 2) return x86_64_v2.RCX_MASK;
+ throw Utils.TODO();
+ }
+
@Override public RegMask outregmap() { return x86_64_v2.WMASK; }
// Output is same register as input#1
@@ -30,11 +32,11 @@ public class SarX86 extends MachConcreteNode implements MachNode {
}
// General form
- // General form: "sari dst << #imm"
+ // General form: "sar dst >> src"
@Override public void asm(CodeGen code, SB sb) {
- sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> #");
- _ti.print(sb);
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
}
- @Override public String op() { return "sari"; }
+ @Override public String op() { return "sar"; }
+
}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java
new file mode 100644
index 00000000..b95f9f46
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java
@@ -0,0 +1,39 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import java.io.ByteArrayOutputStream;
+
+public class ShlX86 extends MachConcreteNode implements MachNode {
+ ShlX86(Node shl) {
+ super(shl);
+ };
+
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+
+ // CL register must be used for input(2)
+ @Override public RegMask regmap(int i) {
+ if(i == 1) return x86_64_v2.WMASK;
+ if(i == 2) return x86_64_v2.RCX_MASK;
+ throw Utils.TODO();
+ }
+
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "shl dst << src"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "shl"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java
index 08cae93e..80115ff2 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java
@@ -8,6 +8,7 @@ import java.io.ByteArrayOutputStream;
import java.util.BitSet;
import java.lang.StringBuilder;
+// Logical Right Shift
public class ShrIX86 extends MachConcreteNode implements MachNode{
final TypeInteger _ti;
ShrIX86(Node shr, TypeInteger ti) {super(shr); _inputs.pop(); _ti = ti;}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java
new file mode 100644
index 00000000..43fc730b
--- /dev/null
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java
@@ -0,0 +1,38 @@
+package com.seaofnodes.simple.node.cpus.x86_64_v2;
+
+import com.seaofnodes.simple.*;
+import com.seaofnodes.simple.node.*;
+import java.io.ByteArrayOutputStream;
+
+public class ShrX86 extends MachConcreteNode implements MachNode {
+ ShrX86(Node shr) {
+ super(shr);
+ };
+ // Register mask allowed on input i.
+ // This is the normal calling convention
+
+ // CL register must be used for input(2)
+ @Override public RegMask regmap(int i) {
+ if(i == 1) return x86_64_v2.WMASK;
+ if(i == 2) return x86_64_v2.RCX_MASK;
+ throw Utils.TODO();
+ }
+
+ @Override public RegMask outregmap() { return x86_64_v2.WMASK; }
+
+ // 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 int encoding(ByteArrayOutputStream bytes) {
+ throw Utils.TODO();
+ }
+
+ // General form
+ // General form: "shr dst >>> src"
+ @Override public void asm(CodeGen code, SB sb) {
+ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1)));
+ }
+
+ @Override public String op() { return "shr"; }
+}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
index c9191b87..734f39de 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
@@ -19,7 +19,7 @@ public class StoreX86 extends MemOpX86 {
}
// Register mask allowed as a result. 0 for no register.
- @Override public RegMask outregmap() { return RegMask.EMPTY; }
+ @Override public RegMask outregmap() { return null; }
// General form: "stN [base + idx<<2 + 12],val"
@Override public void asm(CodeGen code, SB sb) {
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
index bd88011f..c7edfcc4 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
@@ -12,7 +12,7 @@ import java.io.ByteArrayOutputStream;
public class TFPX86 extends ConstantNode implements MachNode {
TFPX86( ConstantNode con ) { super(con); }
// Register mask allowed on input i. 0 for no register.
- @Override public RegMask regmap(int i) { return RegMask.EMPTY; }
+ @Override public RegMask regmap(int i) { return null; }
// General int registers
@Override public RegMask outregmap() { return x86_64_v2.WMASK; }
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java
index 795fa814..d71a49dc 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/XorIX86.java
@@ -11,7 +11,7 @@ import com.seaofnodes.simple.type.TypeInteger;
import java.io.ByteArrayOutputStream;
-public class XorIX86 extends MachConcreteNode implements MachNode {
+public class XorIX86 extends MachConcreteNode implements MachNode {
final TypeInteger _ti;
XorIX86(Node xor, TypeInteger ti) {super(xor); _inputs.pop(); _ti = ti;}
diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
index 45ae19dc..ddb2dcd6 100644
--- a/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
+++ b/chapter19/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java
@@ -28,7 +28,8 @@ public class x86_64_v2 extends Machine {
public static RegMask FLAGS_MASK = new RegMask(1L<<FLAGS);
// Return single int/ptr register
- public static RegMask RET_MASK = new RegMask(RAX);
+ public static RegMask RET_MASK = new RegMask(1<<RAX);
+ public static RegMask RET_FMASK = new RegMask(1<<XMM0);
public static RegMask RDI_MASK = new RegMask(1L<<RDI);
public static RegMask RCX_MASK = new RegMask(1L<<RCX);
@@ -37,6 +38,19 @@ public class x86_64_v2 extends Machine {
public static RegMask R09_MASK = new RegMask(1L<<R09);
public static RegMask RSI_MASK = new RegMask(1L<<RSI);
+ public static RegMask XMM0_MASK = new RegMask(1L<<XMM0);
+ public static RegMask XMM1_MASK = new RegMask(1L<<XMM1);
+ public static RegMask XMM2_MASK = new RegMask(1L<<XMM2);
+ public static RegMask XMM3_MASK = new RegMask(1L<<XMM3);
+ public static RegMask XMM4_MASK = new RegMask(1L<<XMM4);
+ public static RegMask XMM5_MASK = new RegMask(1L<<XMM5);
+ public static RegMask XMM6_MASK = new RegMask(1L<<XMM6);
+ public static RegMask XMM7_MASK = new RegMask(1L<<XMM7);
+ public static RegMask[] XMMS = new RegMask[]{
+ XMM0_MASK, XMM1_MASK, XMM2_MASK, XMM3_MASK,
+ XMM4_MASK, XMM5_MASK, XMM6_MASK, XMM7_MASK,
+ };
+
// Calling conv metadata
public int GPR_COUNT_CONV_WIN64 = 4; // RCX, RDX, R9, R9
public int XMM_COUNT_CONV_WIN64 = 4; // XMM0L, XMM1L, XMM2L, XMM3L
@@ -50,41 +64,45 @@ public class x86_64_v2 extends Machine {
"r8" , "r9" , "r10" , "r11" , "r12" , "r13" , "r14" , "r15" ,
"xmm0", "xmm1", "xmm2" , "xmm3" , "xmm4" , "xmm5" , "xmm6" , "xmm7" ,
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
+ "flags",
};
- @Override public String reg( int reg ) { return REGS[reg]; }
+ @Override public String reg( int reg ) {
+ return reg < REGS.length ? REGS[reg] : "[rsp+"+(reg-REGS.length)*4+"]";
+ }
// Calling convention; returns a machine-specific register
// for incoming argument idx.
// index 0 for control, 1 for memory, real args start at index 2
- static int callInArg( int idx ) {
- return switch( CodeGen.CODE._callingConv ) {
- case CodeGen.CallingConv.SystemV -> callInArgSystemV(idx);
- case CodeGen.CallingConv.Win64 -> callInArgWin64 (idx);
+ static int callInArg( TypeFunPtr tfp, int idx ) {
+ int[] cargs = switch( CodeGen.CODE._callingConv ) {
+ case CodeGen.CallingConv.SystemV -> CALLINARG_SYSTEMV_INT;
+ case CodeGen.CallingConv.Win64 -> CALLINARG_WIN64_INT;
};
+ if( idx < 2 ) return -1;
+ if( idx >= cargs.length )
+ throw Utils.TODO(); // Pass on stack slot
+ if( tfp.arg(idx-2) instanceof TypeFloat )
+ return XMM0 + (idx-2);
+ return cargs[idx];
}
// WIN64(param passing)
- static RegMask[] CALLINMASK_WIN64 = new RegMask[] {
- RegMask.EMPTY,
- RegMask.EMPTY,
+ static int[] CALLINARG_WIN64_INT = new int[] {
+ -1, // Control, no register
+ -1, // Memory, no register
+ RCX,
+ RDX,
+ R08,
+ R09,
+ };
+ static RegMask[] CALLINARG_WIN64_MASK = new RegMask[] {
+ null, // Control, no register
+ null, // Memory, no register
RCX_MASK,
RDX_MASK,
R08_MASK,
R09_MASK,
- RegMask.EMPTY,
- RegMask.EMPTY
};
- static int[] CALLINARG_WIN64 = new int[] {
- 0, // Control, no register
- 0, // Memory, no register
- RCX, //
- RDX,
- R08,
- R09,
- 0,
- 0,
- };
- static int callInArgWin64( int idx ) { return CALLINARG_WIN64[idx]; }
// caller saved(win64)
public static final long WIN64_ABI_CALLER_SAVED =
@@ -93,20 +111,9 @@ public class x86_64_v2 extends Machine {
// callee saved(win64)
public static final long WIN64_ABI_CALLEE_SAVED = ~WIN64_ABI_CALLER_SAVED;
- // SystemV(param passing)
- static RegMask[] CALLINMASK_SYSTEMV = new RegMask[] {
- RegMask.EMPTY,
- RegMask.EMPTY,
- RDI_MASK,
- RSI_MASK,
- RDX_MASK,
- RCX_MASK,
- R08_MASK,
- R09_MASK
- };
- static int[] CALLINARG_SYSTEMV = new int[] {
- 0, // Control, no register
- 0, // Memory, no register
+ static int[] CALLINARG_SYSTEMV_INT = new int[] {
+ -1, // Control, no register
+ -1, // Memory, no register
RDI,
RSI,
RDX,
@@ -114,8 +121,16 @@ public class x86_64_v2 extends Machine {
R08,
R09,
};
- static int callInArgSystemV( int idx ) { return CALLINARG_SYSTEMV[idx]; }
-
+ static RegMask[] CALLINARG_SYSTEMV_MASK = new RegMask[] {
+ null, // Control, no register
+ null, // Memory, no register
+ RDI_MASK,
+ RSI_MASK,
+ RDX_MASK,
+ RCX_MASK,
+ R08_MASK,
+ R09_MASK,
+ };
// caller saved(systemv)
// caller saved(win64)
public static final long SYSTEMV_ABI_CALLER_SAVED =
@@ -124,15 +139,22 @@ public class x86_64_v2 extends Machine {
public static final long SYSTEMV_ABI_CALLE_SAVED = ~SYSTEMV_ABI_CALLER_SAVED;
- static RegMask callInMask( int idx ) {
- return switch( CodeGen.CODE._callingConv ) {
- case CodeGen.CallingConv.SystemV -> CALLINMASK_SYSTEMV[idx];
- case CodeGen.CallingConv.Win64 -> CALLINMASK_WIN64 [idx];
+ static RegMask callInMask( TypeFunPtr tfp, int idx ) {
+ RegMask[] cargs = switch( CodeGen.CODE._callingConv ) {
+ case CodeGen.CallingConv.SystemV -> CALLINARG_SYSTEMV_MASK;
+ case CodeGen.CallingConv.Win64 -> CALLINARG_WIN64_MASK;
};
+ if( idx < 2 ) return null;
+ if( idx >= cargs.length )
+ throw Utils.TODO(); // Pass on stack slot
+ if( tfp.arg(idx-2) instanceof TypeFloat )
+ return XMMS[idx-2];
+ return cargs[idx];
}
// Create a split op; any register to any register, including stack slots
- @Override public Node split() {
+ @Override
+ public Node split() {
throw Utils.TODO();
}
@@ -153,7 +175,7 @@ public class x86_64_v2 extends Machine {
case AddNode add -> add(add);
case AndNode and -> and(and);
case BoolNode bool -> cmp(bool);
- case CallEndNode cend -> new CallEndNode((CallNode)cend.in(0));
+ case CallEndNode cend -> new CallEndX86(cend);
case CallNode call -> call(call);
case CProjNode c -> new CProjNode(c);
case ConstantNode con -> con(con);
@@ -247,7 +269,7 @@ public class x86_64_v2 extends Machine {
private Node and(AndNode and) {
if( and.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
return new AndIX86(and, ti);
- throw Utils.TODO();
+ return new AndX86(and);
}
private Node call(CallNode call) {
@@ -315,7 +337,7 @@ public class x86_64_v2 extends Machine {
private Node or(OrNode or) {
if( or.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
return new OrIX86(or, ti);
- throw Utils.TODO();
+ return new OrX86(or);
}
private Node prj( ProjNode prj ) {
@@ -324,20 +346,20 @@ public class x86_64_v2 extends Machine {
private Node sar( SarNode sar ) {
if( sar.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti)
- return new SarX86(sar, ti);
- throw Utils.TODO();
+ return new SarIX86(sar, ti);
+ return new SarX86(sar);
}
private Node shl( ShlNode shl ) {
if( shl.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
return new ShlIX86(shl, ti);
- throw Utils.TODO();
+ return new ShlX86(shl);
}
private Node shr(ShrNode shr) {
if( shr.in(2) instanceof ConstantNode con && con._con instanceof TypeInteger ti )
return new ShrIX86(shr, ti);
- throw Utils.TODO();
+ return new ShrX86(shr);
}
private Node st( StoreNode st ) {