diff options
689 files changed, 3325 insertions, 11321 deletions
diff --git a/.github/workflows/linearize.sh b/.github/workflows/linearize.sh index fb39b380..ef079bb8 100755 --- a/.github/workflows/linearize.sh +++ b/.github/workflows/linearize.sh @@ -47,7 +47,7 @@ while read -r chapter; do done <<< "$all_authors" # Get the first and last dates this chapter was modified. - root_files=(README.md LICENSE pom.xml .gitignore .dir-locals.el transpile-tests graph print build-support) + root_files=(README.md LICENSE pom.xml .gitignore .dir-locals.el transpile-tests graph print isa build-support) author_root_files=() if [[ $chapter = chapter01 ]]; then # Only include the commit date of the root files for chapter01. @@ -71,7 +71,7 @@ while read -r chapter; do git add . # Add the shared files in the root, except for README.md and pom.xml. - root_files=(LICENSE .gitignore .dir-locals.el transpile-tests graph print build-support) + root_files=(LICENSE .gitignore .dir-locals.el transpile-tests graph print isa build-support) cp -R "${root_files[@]/#/"$repo/"}" . git add "${root_files[@]}" @@ -89,11 +89,24 @@ while read -r chapter; do sed -i -e 's,<packaging>pom</packaging>,<packaging>jar</packaging>,' \ -e '/<modules>/,/^$/d' pom.xml fi + # ISA sources enter the standalone Maven build with instruction encoding. + if [[ "$chapter_number" == 21 ]]; then + sed -i '/<source>${simple.print.directory}\/src\/main\/java<\/source>/a\ <source>${project.basedir}/isa/src/main/java</source>' pom.xml + sed -i '/<\/executions>/i\ <execution>\ + <id>shared-isa-test-sources</id>\ + <phase>generate-test-sources</phase>\ + <goals><goal>add-test-source</goal></goals>\ + <configuration><sources>\ + <source>${project.basedir}/isa/src/test-support/java</source>\ + </sources></configuration>\ + </execution>' pom.xml + fi git mv chapter_docs "docs/$chapter" # Restore the link to this chapter. sed -Ei "s,^\* Chapter $chapter_number: ,* [Chapter $chapter_number](docs/$chapter/README.md): ," README.md # Repair links for this chapter. sed -Ei 's,\bdocs/,,' "docs/$chapter/README.md" + sed -Ei 's,\(\.\./isa/,(../../isa/,g' "docs/$chapter/README.md" git add README.md "docs/$chapter/README.md" pom.xml # Create a commit for the chapter, using the metadata. @@ -29,3 +29,5 @@ TAGS !chapter10b/chapter10b.iml !graph/graph.iml !print/print.iml +!isa/isa.iml +!isa/src/test-support/isa-eval.iml @@ -19,3 +19,8 @@ $(CHAPTER_TARGETS): tests: print/tests print/tests: +$(MAKE) --no-print-directory -C print tests + +.PHONY: isa/tests +tests: isa/tests +isa/tests: + +$(MAKE) --no-print-directory -C isa tests @@ -81,6 +81,11 @@ a one-line expression format. A shared `BaseNode` supplies identity and edge access to both printers and the viewer; chapter adapters add semantic details as the IR grows. +The [instruction encoders](isa/README.md) share x86-64, ARM, and RISC-V byte +emission for Chapters 21-25, along with ARM/RISC-V test evaluators. Machine-node +selection, register allocation, and code layout remain in each chapter; the +shared layer takes concrete operands and writes bytes. + The top-level Makefile runs each chapter's `tests`, `tags` (also `tag`), `release`, or `lib` target. Start with `make lib` on a fresh checkout, then `make tests`. diff --git a/chapter21/Makefile b/chapter21/Makefile index f9d7e738..73804a6d 100644 --- a/chapter21/Makefile +++ b/chapter21/Makefile @@ -38,6 +38,7 @@ test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java) main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas)) include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk)) include $(firstword $(wildcard ../print/print.mk print/print.mk)) +include $(firstword $(wildcard ../isa/isa.mk isa/isa.mk)) test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas)) test_cp := $(patsubst $(TST)/$(SIMPLE)/%.java,com.seaofnodes.simple.%,$(wildcard $(TST)/$(SIMPLE)/*Test.java)) com.seaofnodes.simple.codegen.X86EncodingTest classes = $(main_classes) $(test_classes) @@ -55,15 +56,15 @@ endif default: $(default_targets) # Compile just the out-of-date files -$(main_classes): $(CLZDIR)/main/%class: $(SRC)/%java $(graph_javas) $(print_javas) +$(main_classes): $(CLZDIR)/main/%class: $(SRC)/%java $(graph_javas) $(print_javas) $(isa_javas) @echo "compiling " $@ " because " $? @[ -d $(CLZDIR)/main ] || mkdir -p $(CLZDIR)/main @javac $(JAVAC_ARGS) -cp "$(CLZDIR)/main$(SEP)$(jars)" -sourcepath $(SRC) -d $(CLZDIR)/main $(main_javas) -$(test_classes): $(CLZDIR)/test/%class: $(TST)/%java $(main_classes) +$(test_classes): $(CLZDIR)/test/%class: $(TST)/%java $(main_classes) $(isa_test_javas) @echo "compiling " $@ " because " $? @[ -d $(CLZDIR)/test ] || mkdir -p $(CLZDIR)/test - @javac $(JAVAC_ARGS) -cp "$(CLZDIR)/test$(SEP)$(CLZDIR)/main$(SEP)$(jars)" -sourcepath $(TST) -d $(CLZDIR)/test $(test_javas) + @javac $(JAVAC_ARGS) -cp "$(CLZDIR)/test$(SEP)$(CLZDIR)/main$(SEP)$(jars)" -sourcepath $(TST) -d $(CLZDIR)/test $(test_javas) $(isa_test_javas) # Base launch line for JVM tests JVM=nice java -ea -cp "$(CLZDIR)/main${SEP}${jars}${SEP}$(CLZDIR)/test" diff --git a/chapter21/README.md b/chapter21/README.md index 3e082630..c553390a 100644 --- a/chapter21/README.md +++ b/chapter21/README.md @@ -34,7 +34,8 @@ convention; the generated program must preserve the caller's values too. ## Three instruction sets -The targets share this driver, but their machine nodes own the bit details. +The targets share this driver. Machine nodes resolve compiler operands, then +call the shared [ISA encoders](../isa/README.md). | Target | Main encoding concerns | |---|---| @@ -50,8 +51,29 @@ for different machine nodes. The [encoding reference](docs/encoding-reference.md) retains the detailed bit layouts, worked examples, and ISA links. Those details matter when implementing a particular instruction, but do not change the compiler pipeline described here. -The implementations live under -[node/cpus](src/main/java/com/seaofnodes/simple/node/cpus). +The machine-node wiring lives under +[node/cpus](src/main/java/com/seaofnodes/simple/node/cpus). The shared +[X86 encoder](../isa/src/main/java/com/seaofnodes/isa/X86.java) owns x86 byte +emission; [Arm64](../isa/src/main/java/com/seaofnodes/isa/Arm64.java) and +[RiscV](../isa/src/main/java/com/seaofnodes/isa/RiscV.java) pack instruction words. + +For example, `AddX86` chooses opcode `0x03`. Its `RegX86` base reads the two +allocated registers and calls `X86.reg(enc,opcode(),dst,src)`. The shared method +writes REX.W, the opcode, and ModRM directly into `Encoding`'s byte buffer. +For `add r9,r10`, the bytes are `4d 03 ca`. Register constraints and the +two-address requirement remain on the chapter's machine node. This separates +the decision to use ADD from the fixed bit representation of that instruction. + +Loads use the same boundary: the chapter resolves width, sign extension, and +register bank from its types and allocated operands. `X86.load` receives those +facts and the concrete address; it has no dependency on the chapter's graph or +type lattice. Later chapters reuse these encodings as their compiler evolves. + +ARM and RISC-V execution tests also reuse the evaluators in `isa/src/test-support`. +The chapter's test harness prepares and links a memory image; the evaluator +executes its bytes. This keeps instruction semantics in one place while image +construction follows each chapter's compiler. They compile with the tests; +Make's release jar continues to bundle the test harness as well as the compiler. ## Relocation and ELF diff --git a/chapter21/pom.xml b/chapter21/pom.xml index 344f3ce8..264c7e4d 100644 --- a/chapter21/pom.xml +++ b/chapter21/pom.xml @@ -15,4 +15,32 @@ <simple.graph.directory>${project.basedir}/../graph</simple.graph.directory> <simple.print.directory>${project.basedir}/../print</simple.print.directory> </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>shared-isa-sources</id> + <phase>generate-sources</phase> + <goals><goal>add-source</goal></goals> + <configuration> + <sources> + <source>${project.basedir}/../isa/src/main/java</source> + </sources> + </configuration> + </execution> + <execution> + <id>shared-isa-test-sources</id> + <phase>generate-test-sources</phase> + <goals><goal>add-test-source</goal></goals> + <configuration><sources> + <source>${project.basedir}/../isa/src/test-support/java</source> + </sources></configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index c7f8f4bc..81f195b1 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -19,7 +19,7 @@ import java.util.*; * There are also a bunch of generic utilities for managing bits and bytes * common in all encodings. */ -public class Encoding { +public class Encoding implements com.seaofnodes.isa.CodeSink { // Top-level program graph structure public final CodeGen _code; diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index f37738bf..76e7b9b5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // ADD (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_ADD); } // General form: "rd = rs1 + rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index 209f24f4..9c2f64c0 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } //FADD (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);} + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_OP_ADD);} // Default on double precision for now(64 bits) // General form: "addf rd = src1 + src2 diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index a1cd8306..52cf36ea 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class AddIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } //ADD (immediate) @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_ADD,_imm); } // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index ad76ca4c..40812d07 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -13,7 +14,7 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // AND (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_AND); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_AND); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb){ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java index 1f12ef13..82d553aa 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -15,10 +16,10 @@ public class AndIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc,this, in(1), arm.OPI_AND,_imm); + arm.imm_inst_n(enc,this, in(1), Arm64.OPI_AND,_imm); } // General form: "andi rd = rs1 & imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm)); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(Arm64.decodeImm12(_imm)); } }
\ No newline at end of file diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index 342b7519..cce868f9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class AsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sar"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_ASR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_ASR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java index a1775dde..2d50e967 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -22,7 +23,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_ASR,_imm, 0b111111, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_ASR,_imm, 0b111111, rn, rd)); } // General form: "asri rd = rs1 >> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index b36a395b..5a660c90 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -34,10 +35,10 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // by comparison (or sub). No need for regs because it uses flags if( in(1)!=null ) { // B.cond - enc.add4( arm.b_cond(arm.OP_BRANCH, 0, arm.make_condition(_bop)) ); + enc.add4( Arm64.b_cond(Arm64.OP_BRANCH, 0, Arm64.make_condition(_bop)) ); } else { if( _bop=="!=" ) return; // Inverted, no code - enc.add4(arm.b(arm.OP_UJMP, 0)); + enc.add4(Arm64.b(Arm64.OP_UJMP, 0)); } enc.jump(this,cproj(0)); } @@ -54,7 +55,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( opLen==4 ) { - enc.patch4(opStart,arm.b_cond(arm.OP_BRANCH, delta, arm.make_condition(_bop))); + enc.patch4(opStart,Arm64.b_cond(Arm64.OP_BRANCH, delta, Arm64.make_condition(_bop))); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 4fb04f7b..57d7ef7c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -27,7 +28,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); // BL - enc.add4(arm.b(arm.OP_CALL,0)); // Target patched at link time + enc.add4(Arm64.b(Arm64.OP_CALL,0)); // Target patched at link time } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -35,7 +36,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - enc.patch4(opStart,arm.b(arm.OP_CALL,delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_CALL,delta)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index 87dde38c..fa0fbd81 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,7 +20,7 @@ public class CallRRARM extends CallNode implements MachNode { // Needs a register, typically a jump-and-link-register opcode // blr short self = enc.reg(this); - enc.add4(arm.blr(arm.OP_CALLRARM, self)); + enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index dbc86f62..ec5e8ff0 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.FLAGS_MASK; } // SUBS (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,arm.OP_CMP); } + @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,Arm64.OP_CMP); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java index 8a4f242a..dbf9c2e3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -28,7 +29,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public Node copy() { return new CmpIARM(this); } - @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), arm.OPI_CMP,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), Arm64.OPI_CMP,_imm); } // General form: "cmp rs1, 1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index 40bd8387..91bd347f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // SDIV - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_DIV,3); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_DIV,3); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 72b76444..6b86e722 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } // FDIV (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_DIV); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_DIV); } // General form: "VDIF = dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java index 6de65b03..6209397d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -22,7 +23,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - arm.D_OFFSET); double d = ((TypeFloat)_con).value(); long x = Double.doubleToRawLongBits(d); - enc.add4(arm.load_pc(arm.OPF_ARM, 0, dst)); + enc.add4(Arm64.load_pc(Arm64.OPF_ARM, 0, dst)); } // Delta is from opcode start. @@ -31,7 +32,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.patch4(opStart, arm.load_pc(arm.OPF_ARM, delta, dst)); + enc.patch4(opStart, Arm64.load_pc(Arm64.OPF_ARM, delta, dst)); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java index 3ee75608..c49875f4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -16,6 +17,6 @@ public class FunARM extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(arm.imm_inst(arm.OPI_SUB, sz, arm.RSP, arm.RSP)); + enc.add4(Arm64.imm_inst(Arm64.OPI_SUB, sz, arm.RSP, arm.RSP)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index 5ecc98b6..a7fa7a6a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,7 +14,7 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(arm.OP_FLOAT_C, 1, reg1, self); + int body = Arm64.float_cast(Arm64.OP_FLOAT_C, 1, reg1, self); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index 0a07b07a..64d00d57 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -21,39 +22,7 @@ public class IntARM extends ConstantNode implements MachNode { @Override public void encoding( Encoding enc ) { short self = enc.reg(this); long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); - int nb0 = 0; - int nb1 = 0; - // Count number of 0000 and FFFF blocks - for (int i=0; i<64; i+=16) { - int block = (int)(x >> i) & 0xFFFF; - if (block == 0) nb0++; - if (block == 0xFFFF) nb1++; - } - int pattern; - int op; - if(nb0 >= nb1) { - // More 0 blocks then F blocks, use movz - pattern = 0; - op = arm.OP_MOVZ; - } else { - // More F blocks then 0 blocks, use movn - pattern = 0xFFFF; - op = arm.OP_MOVN; - } - int invert = pattern; - for (int i=0; i<4; i++) { - int block = (int)x & 0xFFFF; - x >>= 16; - if (block != pattern) { - enc.add4(arm.mov(op, i, block ^ invert, self)); - op = arm.OP_MOVK; - invert = 0; - } - } - if (op != arm.OP_MOVK) { - // All blocks are the same, special case - enc.add4(arm.mov(op, 0, 0, self)); - } + Arm64.constant(enc,self,x); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 65ca3603..5fa68e19 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; @@ -18,9 +19,9 @@ public class LoadARM extends MemOpARM { @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } - private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; + private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, }; - private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; + private static final int[] OP_LOAD_RS = new int[]{ Arm64.OP_LOAD_R_8 , Arm64.OP_LOAD_R_16 , Arm64.OP_LOAD_R_32 , Arm64.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index 055d6dcc..7624554e 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSL); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSL); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java index 94d3e25b..bf394172 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -24,7 +25,7 @@ public class LslIARM extends MachConcreteNode implements MachNode { assert _imm > 0; // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) // immr must be (-<shift> MOD 64) = 64 - shift - enc.add4(arm.imm_shift(arm.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); } // General form: "lsli rd = rs1 << imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index a691e0fe..2d5fa52c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java index 094cd30f..6a12e4a5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; @@ -20,7 +21,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_LSR,_imm, 0b111111, rn,rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSR,_imm, 0b111111, rn,rd)); } // General form: "lsri rd = rs1 >>> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index afd8723e..5e175b1e 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -65,8 +66,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { val -= arm.D0; } int body = off() == null - ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) - : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? Arm64.load_str_imm(opcode_imm, _off, ptr, val, size) + : Arm64.indr_adr(opcode_reg, off, Arm64.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index 3514db9b..a0955565 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_MUL,31); } // General form: "rd = rs1 * rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 89dba172..33d32bd4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class MulFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_MUL); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_MUL); } // Default on double precision for now(64 bits) // General form: "VMUL.f32 rd = src1 * src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index cb51eea2..0dac086b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,8 +11,8 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { // BL(branch with link) enc.external(this,"calloc"). - add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1 - add4(arm.b(arm.OP_CALL, 0)); + add4(Arm64.mov(Arm64.OP_MOVZ, 0, 1, 0)). // movz x0,#1 + add4(Arm64.b(Arm64.OP_CALL, 0)); } // Patch is for running "new" in a JIT. @@ -23,7 +24,7 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void patch(Encoding enc, int opStart, int opLen, int delta ) { // Negative patches are JIT emulator targets. if( opStart+delta < 0 ) { - enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4)); + enc.patch4(opStart+4, Arm64.b_calloc(Arm64.OP_CALL, delta-4)); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index 5a8d882d..5c388bab 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,9 +19,9 @@ public class NotARM extends MachConcreteNode implements MachNode{ // subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int subs = arm.imm_inst(arm.OP_SUBS, 0, reg1, self); + int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(arm.OP_CSET, 31, arm.COND.EQ, 63, reg1); + int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 63, reg1); enc.add4(cset); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index b5cfa8cf..ba3197c1 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class OrARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "|"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_OR); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" | ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index 2a2d199a..9c7cb8cc 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -15,7 +16,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm); + arm.imm_inst_n(enc, this, in(1), Arm64.OPI_OR, _imm); } // General form: "ori rd = rs1 | imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 4597666b..a7ed5073 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class RetARM extends ReturnNode implements MachNode { @Override public void encoding( Encoding enc ) { int frameAdjust = ((FunARM)fun())._frameAdjust; if( frameAdjust > 0 ) - enc.add4(arm.imm_inst(arm.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); - enc.add4(arm.ret(arm.OP_RET)); + enc.add4(Arm64.imm_inst(Arm64.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); + enc.add4(Arm64.ret(Arm64.OP_RET)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index 246e482a..6809bb1c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -20,7 +21,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop), 0b011111, enc.reg(this)); + int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index 62bb75aa..c0c60ea2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -27,7 +28,7 @@ public class SplitARM extends SplitNode { } int off = enc._fun.computeStackOffset(enc._code,dst); if( srcX ) src -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_STORE_IMM_64, off, arm.RSP, src, 8)); return; } @@ -35,26 +36,26 @@ public class SplitARM extends SplitNode { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); if( dstX ) dst -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); return; } // pick opcode based on regs if(!dstX && !srcX) { // GPR->GPR - enc.add4(arm.mov_reg(arm.OP_MOV, src, dst)); + enc.add4(Arm64.mov_reg(Arm64.OP_MOV, src, dst)); } else if(dstX && srcX) { // FPR->FPR // fmov reg - enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_reg(Arm64.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); } else if(!srcX && dstX) { // GPR->FPR // FMOV(general) 64 bits to DOUBLE-PRECISION - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); } else if( srcX && !dstX) { //FPF->GPR // FMOV(general) DOUBLE-PRECISION to 64 bits - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 0ce6197b..cf858c36 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.StoreNode; @@ -22,9 +23,9 @@ public class StoreARM extends MemOpARM { @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; + private static final int[] OP_STORES = new int[]{ Arm64.OP_STORE_IMM_8, Arm64.OP_STORE_IMM_16, Arm64.OP_STORE_IMM_32, Arm64.OP_STORE_IMM_64, }; - private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; + private static final int[] OP_STORE_RS = new int[]{ Arm64.OP_STORE_R_8, Arm64.OP_STORE_R_16, Arm64.OP_STORE_R_32, Arm64.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[_declaredType.log_size()], val(), size()); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index 552b46df..6024df68 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_SUB); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index 0d8d3c10..dd147544 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class SubFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_SUB); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_SUB); } // Default on double precision for now(64 bits) // General form: "vsub.f32 rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index b882c5a4..e45bfa63 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -19,7 +20,7 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_SUB,_imm); } // General form: "subi rd = rs1 - imm" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 16b56553..1f2b6a37 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -18,10 +19,10 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { enc.relo(this); short self = enc.reg(this); // adrp x0, 0 - int adrp = arm.adrp(1,0, arm.OP_ADRP, 0,self); + int adrp = Arm64.adrp(1,0, Arm64.OP_ADRP, 0,self); // add x0, x0, 0 enc.add4(adrp); - arm.imm_inst(enc,arm.OPI_ADD,0, 0); + arm.imm_inst(enc,Arm64.OPI_ADD,0, 0); } @Override public byte encSize(int delta) { @@ -37,9 +38,9 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { int next = opStart + opLen; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); // low 12 bits via add - enc.patch4(next, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, rpc)); + enc.patch4(next, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, rpc)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java index bf46a7b1..acb32ddb 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; @@ -18,7 +19,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - int body = arm.b(arm.OP_UJMP, 0); + int body = Arm64.b(Arm64.OP_UJMP, 0); enc.add4(body); } @@ -32,7 +33,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,arm.b(arm.OP_UJMP, delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_UJMP, delta)); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index ec86cfa5..5b635303 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class XorARM extends MachConcreteNode implements MachNode{ @Override public String glabel() { return "^"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_XOR); } // General form: "rd = x1 ^ x2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ ").p(code.reg(in(2))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java index e2582d22..017815f3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -20,7 +21,7 @@ public class XorIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // General form: "xori rd = rs1 ^ imm" - @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), Arm64.OPI_XOR,_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index c8dea1f4..af0461a6 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; +import static com.seaofnodes.isa.Arm64.*; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -81,102 +83,6 @@ public class arm extends Machine { static final RegMask D6_MASK = new RegMask(D6); static final RegMask D7_MASK = new RegMask(D7); - // major opcode: OP - public static int OP_ADD = 0b10_001_011; - public static int OPF_ADD = 0b00_011_110; - public static int OPF_OP_ADD = 0b00_101_0; - public static int OPI_ADD = 0b10_010_00100; - - public static int OPI_SUB = 0b11_010_00100; - public static int OP_UJMP = 0b000101; - - public static int OP_ADRP = 0b10000; - - public static int OP_ASR = 0b1010; - public static int OPI_ASR = 0b10_0100_1101; - - public static int OP_LSL = 0b1000; - public static int OPI_LSL =0b1101001101; - - public static int OP_LSR = 0b1001; - public static int OPI_LSR = 0b1101001101; - - public static int OP_BRANCH = 0b01_0101_00; - public static int OP_CALL = 0b10_010_1; - - public static int OP_CALLRARM = 0b1101011000111111000000; - - public static int OP_SUBS = 0b1111000100; - public static int OP_CSET = 0b10011010100; - public static int OP_CMP = 0b11101011; - public static int OPI_CMP = 0b1111000100; - - public static int OP_DIV = 0b10011010110; - public static int OPF_DIV = 0b000110; - - public static int OP_MUL = 0b10011011000; - public static int OPF_MUL = 0b10; - - public static int OPF_ARM = 0b01011100; - - public static int OP_FLOAT_C = 0b10011110; - - public static int OP_XOR = 0b11001010; - public static int OPI_XOR = 0b110100100; - - public static int OP_AND = 0b10_0010_10; - public static int OPI_AND = 0b10_0100_100; - - public static int OP_OR = 0b10101010; - public static int OPI_OR = 0b101100100; - - public static int OP_SUB = 0b11001011; - public static int OPF_SUB = 0b1110; - - public static int OP_MOVK = 0b111100101; - public static int OP_MOVN = 0b100100101; - public static int OP_MOVZ = 0b110100101; - - public static int OP_RET = 0b1101011001011111000000; - // Store/load opcodes - public static int OP_LOAD_R_64 = 0b11111000011; - public static int OP_LOAD_R_32 = 0b10111000011; - public static int OP_LOAD_R_16 = 0b01111000010; - public static int OP_LOAD_R_8 = 0b00111000011; - - public static int OP_LOAD_IMM_64 = 0b1111100101; - public static int OP_LOAD_IMM_32 = 0b1011100101; - public static int OP_LOAD_IMM_16 = 0b0111100101; - public static int OP_LOAD_IMM_8 = 0b0011100101; - - // load - public static int OPF_LOAD_R_64 = 0b11111100011; - public static int OPF_LOAD_R_32 = 0b10111100011; - - public static int OPF_LOAD_IMM_64 = 0b1111110101; - public static int OPF_LOAD_IMM_32 = 0b1011110101; - - public static int OP_STORE_R_64 = 0b11111000001; - public static int OP_STORE_R_32 = 0b10111000001; - public static int OP_STORE_R_16 = 0b01111000001; - public static int OP_STORE_R_8 = 0b00111000001; - - public static int OP_STORE_IMM_64 = 0b1111100100; - public static int OP_STORE_IMM_32 = 0b1011100100; - public static int OP_STORE_IMM_16 = 0b0111100100; - public static int OP_STORE_IMM_8 = 0b0011100100; - - public static int OPF_STORE_R_64 = 0b11111100001; - public static int OPF_STORE_R_32 = 0b10111100001; - - public static int OPF_STORE_IMM_32 = 0b1011110100; - public static int OPF_STORE_IMM_64 = 0b1111110100; - - - public static int OP_FMOV = 0b10011110; - public static int OP_FMOV_REG = 0b00011110; - // https://docsmirror.github.io/A64/2023-06/mov_orr_log_shift.html - public static int OP_MOV = 0b10101010000; // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 @@ -202,54 +108,6 @@ public class arm extends Machine { }; // ARM ENCODING - public enum OPTION { - UXTB, - UXTH, - UXTX, - SXTB, - SXTH, - SXTW, - SXTX, - } - - static public int cset(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 15) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - static public int cset(int opcode, COND cond, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - public enum STORE_LOAD_OPTION { - UXTW, // base+ u32 index [<< logsize] - UXTX, // base+ u64 index [<< logsize] - SXTW, // base+ s32 index [<< logsize] - SXTX, // base+ s64 index [<< logsize] - } - - public enum COND { - EQ, - NE, - CS, - CC, - MI, - PL, - VS, - VC, - HI, - LS, - GE, - LT, - GT, - LE, - AL, - NV - } // True if signed 9-bit immediate private static boolean imm9(TypeInteger ti) { @@ -262,55 +120,10 @@ public class arm extends Machine { return ti.isConstant() && ((ti.value()<<52)>>52) == ti.value(); } - // Can we encode this in ARM's 12-bit LOGICAL immediate form? // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { - if( !ti.isConstant() ) return -1; - if( !ti.isConstant() ) return -1; - long val = ti.value(); - if (val == 0 || val == -1) return -1; // Special cases are not allowed - int immr = 0; - // Rotate until we have 0[...]1 - - // Rotate until: - // The number is negative (MSB is 1) - // Or the LSB is not 1 - while (val < 0 || (val & 1)==0) { - // circular rotation - val = (val >>> 63) | (val << 1); - immr++; - } - // Start by assuming that val might be made of two 32-bit chunks that repeat. - int size = 32; - long pattern = val; - // Is upper half of pattern the same as the lower? - while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { - // Then only take one half - pattern >>= size; - size >>= 1; - } - size <<= 1; - int imms = Long.bitCount(pattern); - // Pattern should now be zeros followed by ones 0000011111 - if (pattern != (1L<<imms)-1) return -1; - imms--; - if (size == 64) return 0x1000 | immr << 6 | imms; - return (32-size)<<1 | immr << 6 | imms; - } - - // sh is encoded in opcode - public static int imm_inst(int opcode, int imm12, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; - } - - public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + return ti.isConstant() ? Arm64.logicalImmediate(ti.value()) : -1; } public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) { @@ -322,64 +135,46 @@ public class arm extends Machine { opcode ^= OPI_ADD ^ OPI_SUB; imm12 = -imm12; } - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); enc.add4(body); } public static void imm_inst_subs(Encoding enc, Node n,Node n2, int opcode, int imm12) { short reg1 = enc.reg(n2); // 31 = 11111 - int body = imm_inst(opcode, imm12&0xFFF, reg1, 31); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, 31); enc.add4(body); } // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static void imm_inst(Encoding enc, int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, self, self); enc.add4(body); } public static void imm_inst_n(Encoding enc, Node n, Node n2, int opcode, int imm13) { short self = enc.reg(n); short reg1 = enc.reg(n2); - int body = imm_inst_n(opcode, imm13, reg1, self); + int body = Arm64.imm_inst_n(opcode, imm13, reg1, self); enc.add4(body); } - // nth bit comes from immediate and not opcode - public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= imm13 && imm13 <= 0x1FFF; - return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; - } - - public static int imm_inst_l(int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); - return body; - } - // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); return body; } // for normal add, reg1, reg2 cases (reg-to-reg) // using shifted-reg form - public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; - } + public static void r_reg(Encoding enc, Node n, int opcode) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); enc.add4(body); } @@ -387,187 +182,43 @@ public class arm extends Machine { short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); // 31 = 11111 - int body = r_reg(opcode, 0, reg2, 0, reg1, 31); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, 31); enc.add4(body); } - public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; - } public static void shift_reg(Encoding enc, Node n, int op2) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(0b10011010110, reg2, op2, reg1, self); + int body = Arm64.shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } // MUL can be considered an alias for MADD with the third operand Ra being set to 0 - public static int madd(int opcode, int rm, int ra, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; - } + public static void madd(Encoding enc, Node n, int opcode, int ra) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = madd(opcode, reg2, ra, reg1, self); + int body = Arm64.madd(opcode, reg2, ra, reg1, self); enc.add4(body); } - // encodes movk, movn, and movz - public static int mov(int opcode, int shift, int imm16, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; - } - - public static int mov_reg(int opcode, int src, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; - } - - public static int ret(int opcode) { - return (opcode << 10) | (X30 << 5); - } - - // FMOV (scalar, immediate) - public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; - } - - public static int f_mov_reg(int opcode, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; - } - public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; - } public static void f_scalar(Encoding enc, Node n, int op ) { short self = (short)(enc.reg(n) -D_OFFSET); short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); + int body = Arm64.f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } - // share same encoding with LDR (literal, SIMD&FP) flavour - public static int load_pc(int opcode, int offset, int rt) { - offset>>=2; - return (opcode << 24) | (offset << 5) | rt; - } - // int l - public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { - assert 0 <= rd && rd < 32; - return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; - } - - // [Rptr+Roff] - public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; - } - // [Rptr+imm9] - public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - - if(size == 8) imm12 = imm12 >> 3; - if(size == 4) imm12 = imm12 >> 2; - if(size == 2) imm12 = imm12 >> 1; - // size == 1 imm12 = imm12 - return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; - } - - // encoding for vcvt, size is encoded in operand - // <Qd>, <Qm> - // F32.S32 - //encoded as op = 0b00, size = 0b10. - // VCVT<c>.<Td>.<Tm> <Dd>, <Dm> - // opcode is broken down into 4 pieces - public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { - return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | - (vd << 12) | (0x01100010 << 4) | vm; - } - public static int float_cast(int opcode, int ftype, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; - } - - - // ftype = 3 - public static int f_cmp(int opcode, int ftype, int rm, int rn) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - // Todo: |8 is not needed - return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); - } public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_cmp(0b00011110, 3, reg1, reg2); + int body = Arm64.f_cmp(0b00011110, 3, reg1, reg2); enc.add4(body); } - public static COND make_condition(String bop) { - return switch (bop) { - case "==" -> COND.EQ; - case "!=" -> COND.NE; - case "<" -> COND.LT; - case "<=" -> COND.LE; - case ">=" -> COND.GE; - case ">" -> COND.GT; - default -> throw Utils.TODO(); - }; - } - - public static int b_cond(int opcode, int delta, COND cond) { - // 24-5 == 19bits offset range - assert -(1<<19) <= delta && delta < (1<<19); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<19)-1; // Zero extend - return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); - } - - public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - // Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4. - public static int blr(int opcode, int rd) { - assert 0 <= rd && rd < 32; - return opcode << 10 | rd << 5; - } - public static int b(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - // no aligned assert(assert (delta&3)==0;) - public static int b_calloc(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; @@ -589,29 +240,6 @@ public class arm extends Machine { throw Utils.TODO(); // Pass on stack slot } - public static long decodeImm12(int imm12) { - int immr = (imm12 >> 6) & 0x3F; - int imms = imm12 & 0x3F; - int size; - if ((imm12 & 0x1000) != 0) { - size = 64; - } else { - size = 31-(imms >> 1); - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size++; - imms &= ~((32-size) << 1); - } - long val = (2L << imms)-1; - while (size < 64) { - val |= val << size; - size <<= 1; - } - val = (val >>> immr) | val << (64-immr); - return val; - } - // Return the max stack slot used by this signature, or 0 @Override public short maxArgSlot( TypeFunPtr tfp ) { int icnt=0, fcnt=0; // Count of ints, floats @@ -791,7 +419,6 @@ public class arm extends Machine { : new LsrARM(lsr); } - private static int off; private static Node idx; private Node st(StoreNode st) { @@ -817,5 +444,4 @@ public class arm extends Machine { return mop; } - } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 37383608..fc96cbe9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -17,7 +18,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); short dst = enc.reg(this); - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -28,7 +29,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { //short rpc = enc.reg(this); //// High half is where the TFP constant used to be, the last input //short auipc = enc.reg(in(_inputs._len-1)); - //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + //enc.patch4(opStart,RiscV.i_type(0x67, rpc, 0, auipc, delta)); throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java index 4d2ac916..b0921fa0 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class AddFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,1); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,1); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java index a85ce5d0..c3aa1276 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; @@ -8,7 +9,7 @@ public class AddIRISC extends ImmRISC { public AddIRISC( Node add, int imm12, boolean pop ) { super(add,imm12,pop); } @Override public String op() { return "addi"; } @Override public String glabel() { return "+"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 0;} @Override public AddIRISC copy() { // Clone the AddI, using the same inputs-only code used during inst select. diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java index ba88bb48..7639ea94 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; @@ -7,6 +8,6 @@ public class AndIRISC extends ImmRISC { public AndIRISC( Node and, int imm) { super(and,imm); } @Override public String op() { return "andi"; } @Override public String glabel() { return "&"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 7;} } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java index f6dc5cf2..b5ad5f59 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -45,12 +46,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { if( in(1)==null && _bop=="!=" ) return; // Inverted never-node, no code enc.jump(this,cproj(0)); if( in(1)==null ) // Never node - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); else { // Todo: relocs (for offset - immf) short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); - enc.add4(riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, 0)); + enc.add4(RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, 0)); } } @@ -66,12 +67,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( in(1)==null ) { // Never node - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); if( opLen==4 ) { - enc.patch4(opStart,riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, delta)); + enc.patch4(opStart,RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, delta)); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index 7a0f3313..2b3232c3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -29,7 +30,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.relo(this); - enc.add4(riscv.j_type(riscv.OP_JAL, riscv.RPC, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, riscv.RPC, 0)); } // Delta is from opcode start @@ -42,7 +43,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, riscv.RPC, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, riscv.RPC, delta)); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index dcc53cbf..55e36ebf 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(riscv.OP_JALR, rpc, 0, src, 0); + int body = RiscV.i_type(RiscV.OP_JALR, rpc, 0, src, 0); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java index c67d7b3d..12a798b5 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class DivFRISC extends MachConcreteNode implements MachNode{ @Override public String op() { return "divf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RUP,13); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RUP,13); } // Default on double precision for now(64 bits) // General form: "fdiv.d rd = src1 / src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index 35de7e04..9f6dec78 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -20,9 +21,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -35,9 +36,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java index 84f0f4c7..4ebdec15 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -17,6 +18,6 @@ public class FunRISC extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java index 5519fe5b..c9b20939 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,7 +15,7 @@ public class I2F8RISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this )-riscv.F_OFFSET); short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.RM.RNE.ordinal(),src1,0,0x69); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.RM.RNE.ordinal(),src1,0,0x69); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index 37cd925f..dd41589c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -41,7 +42,7 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - int body = riscv.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF); + int body = RiscV.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index 70d5c18f..e4dd39dd 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -21,7 +22,7 @@ public class IntRISC extends ConstantNode implements MachNode { int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 75ad6496..596e11cd 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -21,7 +22,7 @@ public class LUI extends ConstantNode implements MachNode { long x = ((TypeInteger)_con).value(); int imm20 = (int)(x>>12) & 0xFFFFF; short dst = enc.reg(this); - int lui = riscv.u_type(riscv.OP_LUI, dst, imm20); + int lui = RiscV.u_type(RiscV.OP_LUI, dst, imm20); enc.add4(lui); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index 7b0e9138..5e1845b8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -17,9 +18,9 @@ public class LoadRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short ptr = enc.reg(ptr()); - int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dst >= riscv.F_OFFSET ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, func3(), ptr, _off)); + enc.add4(RiscV.i_type(op, dst, func3(), ptr, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java index c9917b4f..40609f96 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class MulFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,9); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,9); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java index 77f4a497..58340b32 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,7 +13,7 @@ public class NegRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - riscv.r_type(riscv.OP,dst,0,0,src,0x20); + RiscV.r_type(RiscV.OP,dst,0,0,src,0x20); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = -").p(code.reg(in(1))); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index e395a811..8e3daaba 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,9 +14,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.i_type(riscv.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); - enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); } // Patch is for running "new" in a JIT. @@ -31,8 +32,8 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { int imm20 = delta>>12; if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension int imm12 = delta&0xFFF; - enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); - enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + enc.patch4(opStart+4,RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); } else throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java index 9cbd5025..469221f3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -14,7 +15,7 @@ public class NotRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 2, src, 1)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java index f6a888d9..53abcf0b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class OrIRISC extends ImmRISC { public OrIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 6; } @Override public String glabel() { return "|"; } @Override public String op() { return "ori"; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 8a8186cd..d28311dc 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -14,8 +15,8 @@ public class RetRISC extends ReturnNode implements MachNode { int sz = fun()._frameAdjust; if( sz >= 1L<<12 ) throw Utils.TODO(); if( sz != 0 ) - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); short rpc = enc.reg(rpc()); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.ZERO, 0, rpc, 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR, riscv.ZERO, 0, rpc, 0)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 9ee19e42..fabb9f92 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.BoolNode; @@ -23,7 +24,7 @@ public class SetFRISC extends MachConcreteNode implements MachNode { short dst = enc.reg(this ); short src1 = (short)(enc.reg(in(1))-riscv.F_OFFSET); short src2 = (short)(enc.reg(in(2))-riscv.F_OFFSET); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java index 4edecc04..52b238ec 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class SllIRISC extends ImmRISC { public SllIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 1; } @Override public String glabel() { return "<<"; } @Override public String op() { return "slli"; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 569fa2e0..ca1bf614 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -25,36 +26,36 @@ public class SplitRISC extends SplitNode { throw Utils.TODO(); // Very rare stack-stack move } int off = enc._fun.computeStackOffset(enc._code,dst); - int op = srcX ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = srcX ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( srcX ) src -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, 0b011, riscv.RSP, src, off)); + enc.add4(RiscV.s_type(op, 0b011, riscv.RSP, src, off)); return; } if( src >= riscv.MAX_REG ) { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); - int op = dstX ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dstX ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dstX ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, 0b011, riscv.RSP, off)); + enc.add4(RiscV.i_type(op, dst, 0b011, riscv.RSP, off)); return; } // pick opcode based on regs if( !dstX && !srcX ) { // GPR->GPR - enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + enc.add4(RiscV.r_type(RiscV.OP,dst,0,src,riscv.ZERO,0)); } else if( dstX && srcX ) { // FPR->FPR src -= riscv.F_OFFSET; dst -= riscv.F_OFFSET; - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) } else if(!srcX && dstX) { //GPR->FPR // fmv.d.x - enc.add4(riscv.r_type(riscv.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); } else if(srcX && !dstX) { //FPR->GPR //fmv.x.d - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java index 26404e95..49b1cad9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class SraIRISC extends ImmRISC { public SraIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5;} @Override public String glabel() { return ">>"; } @Override public String op() { return "srai"; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java index ed697678..985abe2c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class SrlIRISC extends ImmRISC { public SrlIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5; } @Override public String glabel() { return ">>>"; } @Override public String op() { return "srli"; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index 55f9d33b..3cb7cc2d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -34,9 +35,9 @@ public class StoreRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short val = enc.reg(val()); short ptr = enc.reg(ptr()); - int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = val >= riscv.F_OFFSET ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); + enc.add4(RiscV.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java index 1e1b43c7..caf751bb 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class SubFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,5); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,5); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index a4355e17..1d3c5920 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -19,9 +20,9 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; // auipc t0,0 - int auipc = riscv.u_type(riscv.OP_AUIPC, dst, 0); + int auipc = RiscV.u_type(RiscV.OP_AUIPC, dst, 0); // addi t1,t0 + #0 - int addi = riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0); + int addi = RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0); enc.add4(auipc); enc.add4(addi); } @@ -33,8 +34,8 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short rpc = enc.reg(this); if( opLen==8 ) { // ADDI sign-extends its low 12 bits, so round the AUIPC high part. - enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, (delta+0x800)>>12)); - enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); + enc.patch4(opStart ,RiscV.u_type(RiscV.OP_AUIPC, rpc, (delta+0x800)>>12)); + enc.patch4(opStart+4,RiscV.i_type(RiscV.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java index 3868990d..cc47b7ed 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -20,7 +21,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.jump(this,uctrl()); - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); } // Delta is from opcode start @@ -33,7 +34,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { throw Utils.TODO(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 61f25be2..df96d10b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } @Override public String op() { return "xori"; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 8e1cccf9..a9a6d84b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; +import static com.seaofnodes.isa.RiscV.*; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -68,7 +70,6 @@ public class riscv extends Machine { static final RegMask SPLIT_MASK = new RegMask( WR_BITS | FP_BITS, -1L ); - // Arguments masks public static RegMask A0_MASK = new RegMask(A0); public static RegMask A1_MASK = new RegMask(A1); @@ -114,40 +115,13 @@ public class riscv extends Machine { FA7_MASK }; - // major opcode: OP - public static int OP_LOAD = 0b00_000_11; - public static int OP_LOADFP = 0b00_001_11; - public static int OP_CUSTOM0 = 0b00_010_11; - public static int OP_IMM = 0b00_100_11; - public static int OP_AUIPC = 0b00_101_11; - - public static int OP_STORE = 0b01_000_11; - public static int OP_STOREFP = 0b01_001_11; - public static int OP_CUSTOM1 = 0b01_010_11; - public static int OP = 0b01_100_11; - public static int OP_LUI = 0b01_101_11; - - public static int OP_CUSTOM2 = 0b10_010_11; - public static int OP_FP = 0b10_100_11; - - public static int OP_BRANCH = 0b11_000_11; - public static int OP_JALR = 0b11_001_11; - public static int OP_RESERVED= 0b11_010_11; - public static int OP_JAL = 0b11_011_11; - - // Since riscv instructions are fixed we can just or them together - public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= rd && rd < 32; - return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } + public static void r_type(Encoding enc, Node n, int func3, int func7) { short dst = enc.reg(n); short src1 = enc.reg(n.in(1)); short src2 = enc.reg(n.in(2)); - int body = r_type(OP,dst,func3,src1,src2,func7); + int body = RiscV.r_type(OP,dst,func3,src1,src2,func7); enc.add4(body); } @@ -155,104 +129,10 @@ public class riscv extends Machine { short dst = (short)(enc.reg(n )-F_OFFSET); short src1 = (short)(enc.reg(n.in(1))-F_OFFSET); short src2 = (short)(enc.reg(n.in(2))-F_OFFSET); - int body = r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); + int body = RiscV.r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); enc.add4(body); } - - public static int u_type(int opcode, int rd, int imm20) { - assert 0 <= rd && rd < 32; - return (imm20 << 12) | (rd << 7) | opcode; - } - - public static int j_type(int opcode, int rd, int delta) { - assert -(1L<<20) <= delta && delta < (1L<<20); - assert 0 <= rd && rd < 32; - // Messy branch offset encoding - // 31 30-21 20 19-12 11-7 6-0 - // 20 10- 1 11 19-12 rpc JAL - assert (delta&1)==0; // Low bit is always zero, not encoded - int imm10_01 = (delta>> 1) & 0x3FF; - int imm11 = (delta>>11) & 1; - int imm12_19 = (delta>>12) & 0xFF; - int imm20 = (delta>>19) & 1; - int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; - return bits << 12 | rd << 7 | opcode; - } - - - public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { - assert 0 <= rd && rd < 32; - assert 0 <= rs1 && rs1 < 32; - assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller - return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } - - - // S-type instructions(store) - public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= func3; - - assert imm12 >= 0; // Masked to high zero bits by caller - int imm_lo = imm12 & 0x1F; - int imm_hi = imm12 >> 5; - return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; - } - - // BRANCH - public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert -4*1024 <= delta && delta < 4*1024; - assert (delta&1)==0; // Low bit is always zero, not encoded - // Messy branch offset encoding - // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 - // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP - int imm4_1 = (delta>> 1) & 0xF; - int imm10_5= (delta>> 5) &0x3F; - int imm11 = (delta>>11) & 1; - int imm12 = (delta>>12) & 1; - int imm5 = imm4_1<<1 | imm11; - int imm7 = imm12<<6 | imm10_5; - return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; - } - - public enum RM { - RNE, // Round to Nearest, ties to Even - RTZ, // Round towards Zero - RDN, // Round Down - RUP, // Round Up - DIRECT, // Round to Nearest, ties to Max Magnitude - RESERVED1, // Reserved for futue use - RESERVED2, // Reserved for future use - DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved - } - - // Since opcode is the same just return back func3 - static public int jumpop(String op) { - return switch(op) { - case "==" -> 0x0; - case "!=" -> 0x1; - case "<" -> 0x4; - case ">=" -> 0x5; - case "u<" -> 0x6; - case "u<=" -> 0x7; - default -> throw Utils.TODO(); - }; - } - - // Since opcode is the same just return back func3 - static public int fsetop(String op) { - return switch(op) { - case "<" -> 1; - case "<=" -> 0; - case "==" -> 2; - default -> throw Utils.TODO(); - }; - } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; @@ -301,7 +181,6 @@ public class riscv extends Machine { } @Override public int rpc() { return RPC; } - // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index d54c7c31..76a2d3f7 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -20,19 +21,7 @@ public class AddFMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // addsd xmm0, DWORD PTR [rdi+0xc] - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - // F opcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, ptr, idx, false, enc); - - // FP ADD - enc.add1(0x0F).add1(0x58); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst = src + [base + idx<<2 + 12]" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index a4166bc7..b3266cb0 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,17 +14,7 @@ public class AddFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 58 /r ADDSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x58); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "addf dst += src" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java index f97a7cb8..d2111d07 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,18 +13,7 @@ public class AddMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // add something to register from memory - // add eax,DWORD PTR [rdi+0xc] - // REX.W + 03 /r ADD r64, r/m64 - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - // opcode - enc.add1(0x03); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0,0x03,true,enc.reg(this),enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst += [base + idx<<2 + 12]" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 1a74f817..15b83bfc 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; @@ -16,11 +17,7 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // FF /2 CALL r/m64 - // calls the function in the register - short src = enc.reg(fptr()); - enc.add1(0xFF); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT,2,src)); + X86.callRegister(enc,enc.reg(fptr())); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java index 35b92170..5a0c7a37 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,16 +12,7 @@ public class CmpFX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // UCOMISD - short src1 = (short)(enc.reg(in(1)) - x86_64_v2.XMM_OFFSET); - short src2 = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // float opcode - enc.add1(0x66); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(src1, src2, 0, false, enc); - - enc.add1(0x0F).add1(0x2E); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src1, src2)); + X86.sse(enc,0x66,0x0F2E,false,enc.reg(in(1))-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "cmp src1,src2" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 91b6d43c..2811a640 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -26,14 +27,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode { @Override public Node copy() { return new CmpIX86(this); } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,0x81,7,enc.reg(in(1)),_imm); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index 9f2cd5f9..bf8f1631 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -16,51 +17,16 @@ public class CmpMemX86 extends MemOpX86 { @Override public String op() { return ((val()==null && _imm==0) ? "test" : "cmp") + _sz; } @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64 - // CMP [mem], imm32 - - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if(src == -1) { + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) { assert !_swap; - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch(log) { - case 0: enc.add1(0x80); break; - case 1: enc.add1(0x66).add1(0x81); break; - case 2: enc.add1(0x81); break; - case 3: enc.add1(0x81); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc); - switch(log) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; - } - } else { - encVal(enc, _declaredType, ptr, idx, src, _off, _scale, _swap); - } + X86.cmpImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + } else encVal(enc,_declaredType,ptr,idx,src,_off,_scale,_swap); } static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale, boolean _swap) { - if(decl instanceof TypeFloat) { - src -= (short)x86_64_v2.XMM_OFFSET; - enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2); - } else { - int log = decl.log_size(); - x86_64_v2.rexF(src, ptr, idx, log == 3, enc); - int swap = _swap ? 2 : 0; - switch(log) { - case 0: enc.add1(0x38+swap); break; - case 1: enc.add1(0x66).add1(0x39+swap); break; - case 2: enc.add1(0x39+swap); break; - case 3: enc.add1(0x39+swap); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + assert !(decl instanceof TypeFloat); // Selected separately as CmpFX86. + X86.cmpMem(enc,decl.log_size(),src,ptr,idx,off,scale,_swap); } // General form: "cmp dst = src, [base + idx<<2 + 12]" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index 06a36d99..e3cbe75f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,12 +12,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); - short src = enc.reg(in(2)); - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x3B); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x3B,enc.reg(in(1)),enc.reg(in(2))); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index 9509a1f5..962ec44e 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,18 +13,7 @@ public class DivFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5E /r DIVSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5E); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5E,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java index 87b8b0c3..e61f576c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,16 +15,7 @@ public class DivX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.RDX_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + F7 /7 IDIV r/m64 - short src = enc.reg(in(2)); - // sign extend rax before 128/64 bits division - // sign extend rax to rdx:rax - enc.add1(x86_64_v2.REX_W); - enc.add1(0x99); - enc.add1(x86_64_v2.rex(0, src, 0)); - // divide - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x07, src)); + X86.divide(enc,enc.reg(in(2))); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index e3b20003..b17ea305 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,20 +15,8 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public Node copy() { return new FltX86(this); } @Override public void encoding( Encoding enc ) { - // Load the constant into a FPR - // movsd xmm, [rip + 0] - // F2 0F 10 /r MOVSD xmm1, m64 - _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - _encSize += x86_64_v2.rexF(dst, 0, 0, false, enc); - enc.add1(0x0F).add1(0x10); - // hard-code rip here - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); - enc.add4(0); - enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); + _encSize=X86.rip(enc,0xF2,0x0F10,false,enc.reg(this)-x86_64_v2.XMM_OFFSET); + enc.largeConstant(this,_con,_encSize-4,2/*ELF PC32*/); } // Delta is from opcode start diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index 07418eb0..24c2a78b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -24,11 +25,7 @@ public class FunX86 extends FunNode implements MachNode { @Override public void encoding( Encoding enc ) { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust - // opcode: 0x83, addi rsp with immediate 8 - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b101, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); + X86.imm(enc,0x81,5,x86_64_v2.RSP,sz); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java index d3213ae4..4a17b92b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,18 +12,7 @@ public class I2f8X86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public void encoding( Encoding enc ) { - // F2 0F 2A /r CVTSI2SD xmm1, r32/m32 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = enc.reg(in(1)); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, true, enc); - - enc.add1(0x0F).add1(0x2A); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F2A,true,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java index 760d6805..b87e7f47 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -20,14 +21,7 @@ public abstract class ImmX86 extends MachConcreteNode implements MachNode { abstract int mod(); @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( opcode() + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,opcode(),mod(),enc.reg(this),_imm); } // General form: "addi dst += #imm" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 6d9110f2..29513d98 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -22,44 +23,7 @@ public class IntX86 extends ConstantNode implements MachNode { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL || _con==TypeInteger.ZERO ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // Simply move the constant into a GPR - // Conditional encoding based on 64 or 32 bits - //REX.W + C7 /0 id MOV r/m64, imm32 - - long imm = ((TypeInteger)_con).value(); - if (Integer.MIN_VALUE <= imm && imm < 0) { - // We need sign extension, so use imm32 into 64 bit register - // REX.W + C7 /0 id MOV r/m64, imm32 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xC7); // 32 bits encoding - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x00, dst)); - enc.add4((int)imm); - } else if (0 <= imm && imm <= 0xFFFFFFFFL) { - // We want zero extension into 64 bit register - // so move 32 bit into 32 bit register which zeros - // the upper bits in the 64 bit register. - // B8+ rd id MOV r32, imm32 - if (dst >= 8) enc.add1(0x41); - enc.add1(0xB8 + (dst & 0x07)); - enc.add4((int)imm); - } else { - // Just write the full 64 bit constant - // REX.W + B8+ rd io MOV r64, imm64 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xB8 + (dst & 0x07)); - enc.add8(imm); // 64 bits encoding - } + X86.constant(enc,enc.reg(this),_con==Type.NIL ? 0 : ((TypeInteger)_con).value()); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index d7acf8b8..92156c58 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -29,38 +30,21 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { @Override public void negate() { _bop = negate(_bop); } @Override public void encoding( Encoding enc ) { - if( in(1)!=null ) { - int op = x86_64_v2.jumpop(_bop); - enc.add1(op-16).add1(0); // Short form jump - } else { - if( _bop=="!=" ) return; // Inverted, no code - enc.add1(0xEB).add1(0); // Never-node - } + if( in(1)==null && _bop=="!=" ) return; + X86.branch(enc,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); enc.jump(this,cproj(0)); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding @Override public byte encSize(int delta) { - if( in(1)==null && _bop=="!=" ) return 0; // Inverted never-node, no code - return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 6); + if( in(1)==null && _bop=="!=" ) return 0; + return X86.branchSize(delta,in(1)!=null); } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 6; // Offset from opcode END - bits[opStart] = 0x0F; - bits[opStart+1] = (byte)(in(1)==null ? 0xE9 : x86_64_v2.jumpop(_bop)); - enc.patch4(opStart+2,delta); - } + assert !(in(1)==null && _bop=="!="); + X86.patchBranch(enc.bits(),opStart,opLen,delta,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java index dce8a49a..e20fd1ec 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -23,25 +24,7 @@ public class LeaX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 8D /r LEA r64,m - short dst = enc.reg(this); - short ptr = enc.reg(in(1)); - short idx = enc.reg(in(2)); - // ptr is null - // just do: [(index * s) + disp32] - if( ptr == -1 ) { - enc.add1(x86_64_v2.rex(dst, 0, idx)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x04)); - enc.add1(x86_64_v2.sib(_scale, idx, x86_64_v2.RBP)); - enc.add4(_offset); - return; - } - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - enc.add1(0x8D); // opcode - // rsp is hard-coded here(0x04) - x86_64_v2.indirectAdr(_scale, idx, ptr, _offset, dst, enc); + X86.lea(enc,enc.reg(this),enc.reg(in(1)),enc.reg(in(2)),_offset,_scale); } // General form: "lea dst = base + 4*idx + 12" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java index c712eb7d..c5329e1d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -27,33 +28,14 @@ public class LoadX86 extends MemOpX86 { } static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) { - // Allocation may put a full-width integer in an XMM register (or a - // floating value in a GPR). Move its bits using the selected register bank. - if( dst>=x86_64_v2.XMM_OFFSET && decl.log_size()==3 ) decl=TypeFloat.F64; - else if( dst<x86_64_v2.XMM_OFFSET && decl instanceof TypeFloat ) - decl = decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; - if( decl == TypeFloat.F32) enc.add1(0xF3); - if( decl == TypeFloat.F64) enc.add1(0xF2); - - if( decl.isa(TypeFloat.F64) ) - dst -= (short)x86_64_v2.XMM_OFFSET; - - x86_64_v2.rexF(dst, ptr, idx, decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64, enc); - - if( false ) ; - else if( decl == TypeFloat.F32 ) enc.add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32 - else if( decl == TypeFloat.F64 ) enc.add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64 - else if( decl.isa(TypeInteger.I8)) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8 - else if( decl == TypeInteger.I16 ) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16 - else if( decl == TypeInteger.I32 ) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32 - else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8 - else if( decl == TypeInteger.U16 ) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16 - // Covers U32, I64/BOT, TMP - else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32 - else throw Utils.TODO(); - - // includes modrm internally - x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc); + // The chapter chooses the register bank and extension from its own type facts. + boolean xmm=dst>=x86_64_v2.XMM_OFFSET; + if( xmm && decl.log_size()==3 ) decl=TypeFloat.F64; + else if( !xmm && decl instanceof TypeFloat ) + decl=decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; + boolean signed=decl.isa(TypeInteger.I8) || decl==TypeInteger.I16 || decl==TypeInteger.I32; + X86.load(enc,decl.log_size(),signed,xmm, + xmm ? dst-x86_64_v2.XMM_OFFSET : dst,ptr,idx,off,scale); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index a97f3d9f..6c7ecbbc 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,20 +15,7 @@ public class MemAddX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // add something to memory - // REX.W + 01 /r | REX.W + 81 /0 id - // ADD [mem], imm32/reg - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - enc.add1(x86_64_v2.rex(src, ptr, idx)); - // opcode - enc.add1( src == -1 ? 0x81: 0x01); - - // includes modrm - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc); - if( src == -1 ) enc.add4(_imm); + X86.addMem(enc,enc.reg(val()),_imm,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add [base + idx<<2 + 12] += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index c1edb082..3371a8ba 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,16 +14,7 @@ public class MulFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 59 /r MULSD xmm1,xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x59).add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F59,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "mulf dst *= src" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 3c00b2e8..2c1ce261 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.codegen.*; @@ -20,15 +21,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { // IMUL encodes a destination register, unlike ImmX86's opcode extension. @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // Also src1 in this chapter - short src = enc.reg(in(1)); - enc.add1(x86_64_v2.rex(dst, src, 0)); - // opcode; 0x69 or 0x6B - enc.add1( 0x69 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imul(enc,enc.reg(this),enc.reg(in(1)),_imm); } // General form: "muli dst = src * #imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java index 3cd1f795..cdc67ea8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,13 +14,7 @@ public class MulX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // REX.W + 0F AF /r IMUL r64, r/m64 - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xAF); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x0FAF,enc.reg(this),enc.reg(in(2))); } // General form: "mul dst *= src" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java index b8b83cb0..3d3798cd 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,10 +13,7 @@ public class NegX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 3, dst)); + X86.unary(enc,0xF7,3,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index 0439adfd..877ec224 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,11 +11,8 @@ public class NewX86 extends NewNode implements MachNode { NewX86( NewNode nnn ) { super(nnn); } @Override public void encoding( Encoding enc ) { enc.external(this,"calloc"); - // ldi rcx,#1 // number of elements to calloc - enc.add1(0xB8 + _arg2Reg).add4(1); - // E8 cd CALL rel32; - enc.add1(0xE8); - enc.add4(0); // offset + X86.constant(enc,_arg2Reg,1); + X86.call(enc); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java index 2d611931..46227dd4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,25 +13,9 @@ public class NotX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - assert !(in(1) instanceof NotNode); // Cleared out by peeps - assert !(in(1) instanceof BoolNode); // Cleared out by peeps - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - - // test rdi,rdi - enc.add1(x86_64_v2.rex(src, src, 0)); - enc.add1(0x85); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src, src)); - - // setz dstb; then zero-extend the low byte into the full register. - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0x94); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0xB6); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + assert !(in(1) instanceof NotNode); // Cleared out by peeps + assert !(in(1) instanceof BoolNode); + X86.not(enc,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java index 0997644d..8dc749ee 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,13 +12,7 @@ public abstract class RegX86 extends MachConcreteNode { @Override public int twoAddress() { return 1; } abstract int opcode(); @Override public void encoding( Encoding enc ) { - // REX.W + 01 /r - short dst = enc.reg(in(1)); // src1 - short src = enc.reg(in(2)); // src2 - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); } // General form: "add dst += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index a35d43a2..e4467bb4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -8,12 +9,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public void encoding( Encoding enc ) { int sz = fun()._frameAdjust; - if( sz != 0 ) { - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b000, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); - } - enc.add1(0xC3); + if( sz!=0 ) X86.imm(enc,0x81,0,x86_64_v2.RSP,sz); + X86.ret(enc); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index 07256604..43ad6bbd 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -23,15 +24,7 @@ public class SarIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index b1be643c..50693034 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; @@ -15,10 +16,6 @@ public class SarX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst)); + X86.unary(enc,opcode(),7,enc.reg(this)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index b2902086..591bf8da 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -23,26 +24,14 @@ public class SetX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX + 0F 94 - short dst = enc.reg(this ); - - // Optional rex, for dst - if( dst >= 8 ) enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0x0F); // opcode - enc.add1(switch (_bop) { + int op=switch (_bop) { case "==" -> 0x94; // SETE case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE default -> throw Utils.TODO(); - }); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - - // low 8 bites are set, now zero extend for next instruction - if( dst >= 8 ) enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xB6); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + }; + X86.set(enc,op&15,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index 0b75b456..f31832e6 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.*; @@ -24,15 +25,7 @@ public class ShlIX86 extends MachConcreteNode implements MachNode { @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java index 9f358575..08c4db25 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; @@ -15,10 +16,6 @@ public class ShlX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 4, dst)); + X86.unary(enc,opcode(),4,enc.reg(this)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 893eb23d..218542f3 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.*; @@ -19,15 +20,7 @@ public class ShrIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java index d869260f..c72f21e2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; @@ -15,10 +16,6 @@ public class ShrX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 5, dst)); + X86.unary(enc,opcode(),5,enc.reg(this)); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index 960ea6f8..5cf668d1 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -19,44 +20,17 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. @Override public void encoding( Encoding enc ) { - // REX.W + 8B /r MOV r64, r/m64 - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - if( dst == x86_64_v2.FLAGS ) { - // mov reg, flags - // push rcx - // popf (Pop the top of the stack into the FLAGS register) - // 50+rd PUSH r64 - x86_64_v2.rexF(0,src,0,false,enc); - enc.add1(0x50 + src); - // popf - enc.add1(0x9D); - return; - } - if( src == x86_64_v2.FLAGS ) { - // mov flags, reg - // pushf; pop reg - enc.add1(0x9C); - // 58+ rd POP r64 - x86_64_v2.rexF(0,dst,0,false, enc); - enc.add1(0x58 + dst); - return; - } - - // Flag for being either XMM or stack - boolean dstX = dst >= x86_64_v2.XMM_OFFSET; - boolean srcX = src >= x86_64_v2.XMM_OFFSET; - + short dst=enc.reg(this), src=enc.reg(in(1)); + if( dst==x86_64_v2.FLAGS ) { X86.flags(enc,src,true); return; } + if( src==x86_64_v2.FLAGS ) { X86.flags(enc,dst,false); return; } + boolean dstX=dst>=x86_64_v2.XMM_OFFSET, srcX=src>=x86_64_v2.XMM_OFFSET; // Stack spills if( dst >= x86_64_v2.MAX_REG ) { int off = enc._fun.computeStackOffset(enc._code,dst); if( src >= x86_64_v2.MAX_REG ) { // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] int soff = enc._fun.computeStackOffset(enc._code,src); - enc.add1(0xFF); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); - enc.add1(0x8F); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + X86.stackCopy(enc,soff,off); return; } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); @@ -68,35 +42,8 @@ public class SplitX86 extends SplitNode { return; } - // reg-reg move. Adjust numbering for GPR vs FPR reg set - if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; - if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; - - // 0x66 if moving between register classes - if( dstX ^ srcX ) enc.add1(0x66); - if( !dstX && srcX ) - { short tmp=src; src=dst; dst=tmp; } - enc.add1(x86_64_v2.rex(dst, src, 0)); - - // pick opcode based on regs - if( !dstX && !srcX ) { - // reg->reg (MOV r64, r/m64) - enc.add1(0x8B); - } else if( dstX && srcX ) { - // xmm->xmm (NP 0F 28 /r MOVAPS xmm1, xmm2/m128) - enc.add1(0x0F); - enc.add1(0x28); - } else if( dstX && !srcX ) { - // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) - enc.add1(0x0F); - enc.add1(0x6E); - } else if( !dstX && srcX ) { - // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) - enc.add1(0x0F); - enc.add1(0x7E); - } - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.move(enc,dstX,srcX,dstX ? dst-x86_64_v2.XMM_OFFSET : dst, + srcX ? src-x86_64_v2.XMM_OFFSET : src); } // General form: "mov dst = src" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index 22a0bd79..4796c0fe 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.SB; @@ -25,55 +26,16 @@ public class StoreX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // REX.W + C7 /0 id MOV r/m64, imm32 | - // REX.W + 89 /r MOV r/m64, r64 - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if( src == -1 ) { - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch( log ) { - case 0: enc .add1(0xC6); break; - case 1: enc.add1(0x66).add1(0xC7); break; - case 2: enc .add1(0xC7); break; - case 3: enc .add1(0xC7); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc); - switch( log ) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate - } - } else { - encVal(enc,_declaredType,ptr,idx,src,_off,_scale); - } + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) X86.storeImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + else encVal(enc,_declaredType,ptr,idx,src,_off,_scale); } // Non-immediate encoding static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) { - int log = decl.log_size(); - // Float reg being stored - if( src >= x86_64_v2.XMM_OFFSET ) { - src -= (short)x86_64_v2.XMM_OFFSET; - assert log == 2 || log == 3; - enc.add1( log==2 ? 0xF3 : 0xF2 ); - x86_64_v2.rexF(src,ptr,idx,false,enc); - enc.add1(0x0F).add1(0x11); - } else { - // byte stores from sil, dil, bpl, spl need a rex - if( log == 0 && src >= x86_64_v2.RSP ) enc.add1(x86_64_v2.rex(src,ptr,idx,false)); - else x86_64_v2.rexF(src,ptr,idx,log==3,enc); - switch( log ) { - case 0: enc .add1(0x88); break; - case 1: enc.add1(0x66).add1(0x89); break; - case 2: enc .add1(0x89); break; - case 3: enc .add1(0x89); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + boolean xmm=src>=x86_64_v2.XMM_OFFSET; + X86.store(enc,decl.log_size(),xmm, + xmm ? src-x86_64_v2.XMM_OFFSET : src,ptr,idx,off,scale); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index 0a169a22..6a008551 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,16 +13,7 @@ public class SubFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5C /r SUBSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5C); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5C,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "subf dst -= src" diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index be4d1a83..d0c6157c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -23,24 +24,9 @@ public class TFPX86 extends ConstantNode implements MachNode, RIPRelSize { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // lea to load function pointer address - // lea rax, [rip+disp32] + if( _con==Type.NIL ) { X86.constant(enc,enc.reg(this),0); return; } enc.relo(this); - enc.add1(x86_64_v2.rex(dst, 0, 0)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); - enc.add4(0); + X86.rip(enc,0,0x8D,true,enc.reg(this)); } @Override public byte encSize(int delta) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java index 5db9e75e..d991e40a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; @@ -18,29 +19,17 @@ public class UJmpX86 extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - // Short-form jump - enc.add1(0xEB).add1(0); - //// E9 cd JMP rel32 - //enc.add1(0xE9).add4(0); + X86.branch(enc,-1); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding - @Override public byte encSize(int delta) { return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 5); } + @Override public byte encSize(int delta) { + return X86.branchSize(delta,false); + } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert bits[opStart] == (byte)0xEB; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert bits[opStart] == (byte)0xEB; - bits[opStart] = (byte)0xE9; // Long form - delta -= 5; // Offset from opcode END - enc.patch4(opStart+1,delta); - } + X86.patchBranch(enc.bits(),opStart,opLen,delta,-1); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 4e3cda14..959ea440 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -67,13 +67,6 @@ public class x86_64_v2 extends Machine { public static int REX_WRB= 0x4D; public static int REX_WB = 0x49; - public enum MOD { - INDIRECT, // [mem] - INDIRECT_disp8, // [mem + 0x12] - INDIRECT_disp32, // [mem + 0x12345678] - DIRECT, // mem - }; - // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -93,90 +86,6 @@ public class x86_64_v2 extends Machine { }; } - public static int modrm(MOD mod, int reg, int m_r) { - if( reg == -1 ) reg=0; // Missing reg in this flavor - // combine all the bits - assert 0 <= reg && reg < 16; - assert 0 <= m_r && m_r < 16; - return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07; - } - - // 00 000 000 - // same bit-layout as modrm - public static int sib(int scale, int index, int base) { - assert 0 <= base && base < 16; - assert 0 <= index && index < 16; - return (scale << 6) | ((index & 0x07) << 3) | base & 0x07; - } - - // reg1 is reg(R) - // reg2 is r/mem(B) - // reg3 is X(index) - // reg4 is X(base) - - // 0 denotes no direct register - public static int rex(int reg, int ptr, int idx, boolean wide) { - // assuming 64 bit by default so: 0100 1000 - assert -1 <= reg && reg < 16; - assert -1 <= ptr && ptr < 16; - assert -1 <= idx && idx < 16; - - int rex = wide ? REX_W : REX; - if( 8 <= reg ) rex |= 0b00000100; // REX.R - if( 8 <= ptr ) rex |= 0b00000001; // REX.B - if( 8 <= idx ) rex |= 0b00000010; // REX.X - return rex; - } - - public static int rex(int reg, int ptr, int idx) { - return rex(reg, ptr, idx, true); - } - - // rex for floats. Return size (0 or 1) - // don't need to use REX if 0x40. - public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { - int rex = rex(reg, ptr, idx, wide); - if (rex == REX) return 0; - enc.add1(rex); - return 1; - } - // Function used for encoding indirect memory addresses - // Does not always generate SIB byte e.g index == -1. - // -1 denotes empty value, not set - note 0 is different from -1 as it can represent rax. - // Looks for best mod locally - public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { - // Assume indirect - assert 0 <= base && base < 16; - assert -1 <= index && index < 16 && index != RSP; - - MOD mod = MOD.INDIRECT; - // is 1 byte enough or need more? - if( offset != 0 ) - mod = imm8(offset) - ? MOD.INDIRECT_disp8 - : MOD.INDIRECT_disp32; - - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { - mod = MOD.INDIRECT_disp8; - } else if( index == -1 && (base == RSP || base == R12) ) { - index = RSP; - } - - if( index == -1 ) { - enc.add1(modrm(mod, reg, base)); - } else { - enc.add1(modrm(mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, index, base)); - } - - if( mod == MOD.INDIRECT_disp8 ) { - enc.add1(offset); - } else if( mod == MOD.INDIRECT_disp32 ) { - enc.add4(offset); - } - } - - // Limit of float args passed in registers static RegMask[] XMMS8 = new RegMask[]{ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3), diff --git a/chapter21/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter21/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index 610969e7..97d33b70 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; import com.seaofnodes.simple.node.cpus.riscv.riscv; diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java index a8712a2e..94170fcb 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; import com.seaofnodes.simple.node.cpus.riscv.riscv; diff --git a/chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java deleted file mode 100644 index f8996b00..00000000 --- a/chapter21/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ /dev/null @@ -1,752 +0,0 @@ -package com.seaofnodes.simple; - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.arm.arm; - -public class EvalArm64 { - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - - int _pc; - int SENTINEL_CALLOC = -4; - // Start of free memory for allocation - int _heap; - // Cycle counters - int _cycle; - - // flags - boolean N = false; - boolean Z = false; - boolean C = false; - boolean V = false; - - EvalArm64(byte[] buf, int stackSize) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[arm.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { - return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - public int step(int maxops) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for(int icount = 0; icount < maxops; icount++) { - int ir = 0; - rval = 0; - frval = 0; - cycle++; - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - - // Load instruction from image buffer at PC - ir = ld4s( pc ); - - int rdid = ir & 0x1f; - // [31:24] - int opcode1 = (ir >> 24) & 0xFF; - // [31:26] - int opcode2 = (ir >> 26) & 0x3F; - - switch(opcode2) { - case 5: { - //b - int imm26 = ir << 6 >> 6; - - pc = pc + (imm26 * 4) - 4; - // won't hit pc += 4 at the bottom because continue - // do it manually - pc += 4; - rdid = -1; - continue ; - } - case 0x25: { - // BL, including ordinary calls - rval = pc + 4; - regs[arm.X30] = rval; - int imm26 = (ir & 0x03FFFFFF); - int imm = (imm26 << 6) >> 6; - pc = pc + (imm << 2) ; - if (pc == SENTINEL_CALLOC) { - long size = regs[arm.X0]*regs[arm.X1]; - size = (size+7) & -8; - regs[arm.X0] = _heap; - _heap += (int)size; - // unwind pc - pc = (int)rval; - } - continue; - } - } - // for the opcode we just match for bits[31:24]; - switch(opcode1) { - case 0xD2: // MOVZ - case 0xF2: { // MOVK preserves the other halfwords - int shift = ((ir >> 21) & 3)*16; - rval = ((ir >> 5) & 0xFFFFL) << shift; - if( opcode1==0xF2 ) rval |= regs[rdid] & ~(0xFFFFL << shift); - break; - } - case 0x38: { - // STRB/LDRB(register) - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - // store - if(opcode1 == arm.OP_STORE_R_8) { - st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_8) { - rval = ld1s((int)regs[rn] + (int)regs[rm]); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - break; - } - case 0x39: { - // STRB/LDRB(immediate) - // str/ldr(immediate) - // rn - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_8) { - st1((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_8) { - rval = ld1s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - case 0x78: { - // STRH/LDRH(register) - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - // store - if(opcode1 == arm.OP_STORE_R_16) { - st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_16) { - rval = ld1s((int)regs[rn] + (int)regs[rm]); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - break; - } - - case 0x79: { - // STRH/LDRH(immediate) - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 2; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_16) { - st2((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_16) { - rval = ld2s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - - - case 0x5c: { - // ldr - is_f = true; - // address = delta - int address = ir << 8 >> 13; - address *= 4; - if(address >= _buf.length-3) trap = (5 + 1); - frval = ld8f(pc + address); - break; - } - case 0xB9: { - // str/ldr(immediate) 32 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 4; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_32) { - rval = ld4s((int) rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - case 0xF9: { - // str/ldr(immediate) 64 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_64) { - st8((int)rval, regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_64) { - rval = ld8((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - case 0xf8: { - // LDR/STR (register + index) 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_64) { - rval = ld8((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xB8: { - // LDR/STR (register + index) 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if( opcode1 == arm.OP_LOAD_R_32) { - rval = ld4s((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xFC: { - // LDR/STR (register + index) float 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_64) { - frval = ld8f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xBC: { - // LDR/STR (register + index) float 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_32) { - frval = ld4f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xBD: { - // LDR/STR(immediate) 32 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 4; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - case 0xFD: { - // LDR/STR(immediate) 64 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - case 0x9b: { - // mul - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] * regs[rm]; - break; - } - case 0x54: { - // b.cond - int imm19 = ir << 8 >> 13; - imm19 = pc + (imm19 * 4) - 4; - rdid = -1; - - switch(ir & 0xF) { - case 0x0: if(Z) pc = imm19; break; // eq - case 0x1: if(!Z) pc = imm19; break; // ne - case 0x2: if(C) pc = imm19; break; // cs - case 0x3: if(!C) pc = imm19; break; - case 0x4: if(N) pc = imm19; break; // mi - case 0x5: if(!N) pc = imm19; break; // pl - case 0x6: if(V) pc = imm19; break; // vs - case 0x7: if(!V) pc = imm19; break; // vc - case 0x8: if(C && !Z) pc = imm19; break; // hi - case 0x9: if(!C || Z) pc = imm19; break; // ls - case 0xA: if(N == V) pc = imm19; break; // ge - case 0xB: if(N != V) pc = imm19; break; // lt - case 0xC: if(!Z && N == V) pc = imm19; break; // gt - case 0xD: if(Z || N != V) pc = imm19; break; // le - case 0xE: pc = imm19; break; // always executed(al) - default: trap = (2+1); - } - break; - } - case 0x9a: { - // conditional select(csel) - int rm = (ir >> 16) & 0x1F; - switch((ir >> 12) & 0xF) { - case 0x0: if(Z) rval = regs[rm]; break; // eq - case 0x1: if(!Z) rval = regs[rm]; break; // ne - case 0x2: if(C) rval = regs[rm]; break; // cs - case 0x3: if(!C) rval = regs[rm]; break; - case 0x4: if(N) rval = regs[rm]; break; // mi - case 0x5: if(!N) rval = regs[rm]; break; // pl - case 0x6: if(V) rval = regs[rm]; break; // vs - case 0x7: if(!V) rval = regs[rm]; break; // vc - case 0x8: if(C && !Z) rval = regs[rm]; break; // hi - case 0x9: if(!C || Z) rval = regs[rm]; break; // ls - case 0xA: if(N == V) rval = regs[rm]; break; // ge - case 0xB: if(N != V) rval = regs[rm]; break; // lt - case 0xC: if(!Z && N == V) rval = regs[rm]; break; // gt - case 0xD: if(Z || N != V) rval = regs[rm]; break; // le - case 0xE: rval = regs[rm]; break; // always executed(al) - default: { - rval = regs[(ir >> 5) & 0x1F]; - } - } - break; - } - case 0xeb: { - // subs(shifted register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = lhs - rhs; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= rhs; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (rhs >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - case 0xF1: { - // subs(immediate) - int rn = (ir >> 5) & 0x1F; - int immediate = ir << 10 >> 20; - long lhs = regs[rn]; - - rval = lhs - immediate; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= immediate; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (immediate >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - case 0x8B, 0xCB: { - // add/sub(register), unshifted form emitted by Simple - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = opcode1==0x8B ? lhs + rhs : lhs - rhs; - break; - } - case 0x91, 0xD1: { // ADD/SUB (immediate), unsigned imm12, optional LSL #12 - int rn = (ir >> 5) & 0x1F; - long immediate = (ir >>> 10) & 0xFFF; - if( (ir & (1<<22))!=0 ) immediate <<= 12; - rval = opcode1==0x91 ? regs[rn] + immediate : regs[rn] - immediate; - break; - } - case 0x93, 0xD3: { // SBFM/UBFM: shifts and signed/unsigned extracts - int immr = (ir >>> 16) & 63; - int imms = (ir >>> 10) & 63; - int rn = (ir >>> 5) & 31; - boolean signed = (ir & 0x40000000)==0; - long value = regs[rn] << (63-imms); - value = signed ? value >> (63-imms) : value >>> (63-imms); - rval = immr > imms ? value << (64-immr) - : signed ? value >> immr : value >>> immr; - break; - } - - case 0x92: { - // and(immediate) - int imm12 = (ir >> 10) & 0x1FFF; - long immediate = arm.decodeImm12(imm12); - int rn = (ir >> 5) & 0x1F; - rval = regs[rn] & immediate; - break; - } - case 0xAA: { - // MOV(register) - int rm = (ir >> 16) & 0x1F; - rval = regs[rm]; - break; - } - case 0xD6: { - int op = ir & 0xFFFFFC1F; - int rn = (ir >>> 5) & 31; - int target = (int)regs[rn]; // Read before BLR overwrites X30. - rdid = -1; - if( op==0xD63F0000 ) regs[arm.X30] = pc+4; // BLR - else if( op!=0xD65F0000 ) { trap = 3; break; } // RET - pc = target; - if( op==0xD65F0000 && pc==0 ) break outer; - pc -= 4; - break; - } - // bitwise - case 0x8A: { - // AND - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] & regs[rm]; - break; - } - // floats - case 0x1E: { - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - int rs2 = (ir >> 16) & 0x1F; - - int op = (ir >> 10) & 0x3F; - switch(op) { - case 16: frval = fregs[rs1]; break; // fmov - case 10:frval = fregs[rs1] + fregs[rs2]; break; // fadd - - case 6: if (fregs[rs2] == 0) frval = 0; else frval = fregs[rs1] / fregs[rs2]; break; // fdiv - case 8: { - // fcmp - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - - Z = (lhs == rhs); - N = (lhs < rhs); - C = lhs >= rhs; - V = Double.isNaN(lhs) || Double.isNaN(rhs); - rdid = -1; - - break; - } - case 2: frval = fregs[rs1] * fregs[rs2]; break; // fmul - case 14: frval = fregs[rs1] - fregs[rs2]; break; // fsub - default: trap = (2+1); - } - break; - } - case 0x9e: { - // scvtf - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - frval = (double)regs[rs1]; - break; - } - default: trap = (2+1); - } - if(trap != 0) { - _pc = pc; - break; - } - if(rdid != -1) { - if(is_f) {fregs[rdid] = frval; is_f = false;} - else regs[rdid] = rval; - } - - pc += 4; - } - // Handle traps and interrupts. - if(trap != 0) { - return trap; - } - _cycle = cycle; - _pc = pc; - return 0; - } - - -} diff --git a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java deleted file mode 100644 index aa9702f1..00000000 --- a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ /dev/null @@ -1,353 +0,0 @@ - package com.seaofnodes.simple; - -/** Simple RISC5 CPU Emulator - * - * Original works credit Charles Lohr. - * This is a complete rewrite in Java. - * - * Load code into memory and go! - */ - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.riscv.riscv; - -import java.util.Arrays; - - public class EvalRisc5 { - - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - // PC - int _pc; - - // Start of free memory for allocation - int _heap; - - // Cycle counters - int _cycle; - - EvalRisc5( byte[] buf, int stackSize ) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[riscv.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) {st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - // Note: only a few bits are used. (Machine = 3, User = 0) - // Bits 0..1 = privilege. - // Bit 2 = WFI (Wait for interrupt) - // Bit 3+ = Load/Store reservation LSBs. - int _extraflags; - - public int step( int maxops ) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for( int icount = 0; icount < maxops; icount++ ) { - int ir = 0; - rval = 0; - cycle++; - - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - // Load instruction from image buffer at PC - ir = ld4s( pc ); - int rdid = (ir >> 7) & 0x1f; - - switch( ir & 0x7f ) { - case 0x37: // LUI (0b0110111) - rval = ( ir & 0xfffff000 ); - break; - case 0x17: // AUIPC (0b0010111) - rval = pc + ( ir & 0xfffff000 ); - break; - case 0x6F: { // JAL (0b1101111) - int reladdy = ((ir & 0x80000000)>>11) | ((ir & 0x7fe00000)>>20) | ((ir & 0x00100000)>>9) | ((ir&0x000ff000)); - if( (reladdy & 0x00100000)!=0 ) reladdy |= 0xffe00000; // Sign extension. - rval = pc + 4; - pc = pc + reladdy - 4; - break; - } - case 0x67: { // JALR (0b1100111) - int imm_se = ir >> 20; // Sign extend 12 bits - rval = pc + 4; - pc = ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1; - // Return from top-level ; exit sim - if( pc==0 ) { - if( rdid!=0 ) regs[rdid] = rval; // Write PC into register before exit - break outer; - } - // Inline CALLOC effect - if( pc == Encoding.SENTINAL_CALLOC ) { - int size = (int)(regs[10]*regs[11]); - regs[10] = _heap; // Return next free address - // Pre-zeroed; epsilon (null) collector, never recycles memory so always zero - // Arrays.fill(_buf,_heap,_heap+size, (byte) 0 ); - _heap += size; - pc = (int)(rval - 4); // Unwind PC, as-if returned from calloc - } else - pc -= 4; - break; - } - case 0x63: { // Branch (0b1100011) - int immm4 = ((ir & 0xf00)>>7) | ((ir & 0x7e000000)>>20) | ((ir & 0x80) << 4) | ((ir >> 31)<<12); - if( (immm4 & 0x1000)!=0 ) immm4 |= 0xffffe000; - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - immm4 = pc + immm4 - 4; - rdid = 0; - if( switch( (ir >> 12) & 0x7 ) { - case 0 -> rs1 == rs2; - case 1 -> rs1 != rs2; - case 4 -> rs1 < rs2; - case 5 -> rs1 >= rs2; - case 6 -> Long.compareUnsigned(rs1,rs2) < 0; //BLTU - case 7 -> Long.compareUnsigned(rs1,rs2) >= 0; //BGEU - default -> { trap = (2+1); yield false; } - } ) pc = immm4; - break; - } - case 0x03: { // Load (0b0000011) - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - //LB, LH, LW, LBU, LHU - case 0: rval = ld1s( rsval ); break; - case 1: rval = ld2s( rsval ); break; - case 2: rval = ld4s( rsval ); break; - case 3: rval = ld8 ( rsval ); break; - case 4: rval = ld1z( rsval ); break; - case 5: rval = ld2z( rsval ); break; - case 6: rval = ld4s( rsval ); break; - default: trap = (2+1); - } - } - break; - } - // floats - case 0x7: { - is_f = true; - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - case 2: frval = ld4f( rsval ); break; - case 3: frval = ld8f( rsval ); break; - default: trap = (2+1); - } - } - break; - } - - case 0x23: { // Store 0b0100011 - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - long rs2 = regs[(ir >> 20) & 0x1f]; - int addy = ( ( ir >> 7 ) & 0x1f ) | ( ( ir & 0xfe000000 ) >> 20 ); - if( (addy & 0x800)!=0 ) addy |= 0xfffff000; - addy += rs1; - rdid = 0; - if( addy >= _buf.length-3 ) { - trap = (7+1); // Store access fault. - rval = addy; - } else { - switch( ( ir >> 12 ) & 0x7 ) { //SB, SH, SW - case 0: st1( addy, (int)rs2 ); break; - case 1: st2( addy, (int)rs2 ); break; - case 2: st4( addy, (int)rs2 ); break; - case 3: st8( addy, rs2 ); break; - default: trap = (2+1); - } - } - break; - } - case 0x13: // Op-immediate 0b0010011 - case 0x33: { // Op 0b0110011 - int imm = ir >> 20; - imm = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); - long rs1 = regs[(ir >> 15) & 0x1f]; - boolean is_reg = (ir & 0x20)!=0; - long rs2 = is_reg ? regs[imm & 0x1f] : imm; - - // Insert the detection here - int rs1id = (ir >> 15) & 0x1f; - int funct3 = (ir >> 12) & 0x7; - - if( is_reg && ( ir & 0x02000000 )!=0 ) { - switch( (ir>>12)&7 ) { //0x02000000 = RV32M - case 0: rval = rs1 * rs2; break; // MUL - case 1: rval = (int)((long)((int)rs1) * (long)((int)rs2)) >> 32; break; // MULH - case 2: rval = (int)((long)((int)rs1) * (long)rs2) >> 32; break; // MULHSU - case 3: rval = (int)((long)rs1 * (long)rs2) >> 32; break; // MULHU - case 4: if( rs2 == 0 ) rval = -1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? rs1 : ((int)rs1 / (int)rs2); break; // DIV - case 5: if( rs2 == 0 ) rval = 0xffffffff; else rval = rs1 / rs2; break; // DIVU - case 6: if( rs2 == 0 ) rval = rs1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? 0 : ((int)((int)rs1 % (int)rs2)); break; // REM - case 7: if( rs2 == 0 ) rval = rs1; else rval = rs1 % rs2; break; // REMU - } - } else { - rval = switch( (ir >> 12) & 7 ) { // These could be either op-immediate or op commands. Be careful. - case 0 -> (is_reg && (ir & 0x40000000) != 0) ? (rs1 - rs2) : (rs1 + rs2); - case 1 -> rs1 << (rs2 & 0x1F); - case 2 -> (rs1 < rs2) ? 1 : 0; - case 3 -> (rs1 < rs2) ? 1 : 0; - case 4 -> rs1 ^ rs2; - case 5 -> (ir & 0x40000000) != 0 ? (((int) rs1) >> (rs2 & 0x1F)) : (rs1 >> (rs2 & 0x1F)); - case 6 -> rs1 | rs2; - case 7 -> rs1 & rs2; - default -> rval; - }; - } - break; - } - case 0x0f: // 0b0001111 - rdid = 0; // fencetype = (ir >> 12) & 0b111; We ignore fences in this impl. - break; - case 0x73: // Zifencei+Zicsr (0b1110011) - trap = (2+1); // Note micrrop 0b100 == undefined. - break; - - case 0x2f: { // RV32A (0b00101111) - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - int irmid = ( ir>>27 ) & 0x1f; - - // We don't implement load/store from UART or CLNT with RV32A here. - if( rs1 >= _buf.length-3 ) { - trap = (7+1); //Store/AMO access fault - rval = rs1; - } else { - rval = ld4s( (int)rs1 ); - - // Referenced a little bit of https://github.com/franzflasch/riscv_em/blob/master/src/core/core.c - boolean dowrite = true; - switch( irmid ) { - case 2: //LR.W (0b00010) - dowrite = false; - _extraflags = (_extraflags & 0x07) | (int)(rs1<<3); - break; - case 3: { //SC.W (0b00011) (Make sure we have a slot, and, it's valid) - boolean xflag = _extraflags >> 3 != ( rs1 & 0x1fffffff ); - rval = xflag ? 1 : 0; // Validate that our reservation slot is OK. - dowrite = !xflag; // Only write if slot is valid. - break; - } - case 0: rs2 += rval; break; // AMOADD.W (0b00000) - case 1: break; // AMOSWAP.W (0b00001) - case 4: rs2 ^= rval; break; // AMOXOR.W (0b00100) - case 8: rs2 |= rval; break; // AMOOR.W (0b01000) - case 12: rs2 &= rval; break; // AMOAND.W (0b01100) - case 16: rs2 = Math.min( rs2, rval ); break; //AMOMIN.W (0b10000) - case 20: rs2 = Math.max( rs2, rval ); break; //AMOMAX.W (0b10100) - case 24: rs2 = Math.min( rs2, rval ); break; //AMOMINU.W (0b11000) - case 28: rs2 = Math.max( rs2, rval ); break; //AMOMAXU.W (0b11100) - default: trap = (2+1); dowrite = false; break; //Not supported. - } - if( dowrite ) st4( (int)rs1, (int)rs2 ); - } - break; - } - - case 0x53: { - is_f = true; - int rs1 = (ir >> 15) & 0x1F; - int rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - int func5 = (ir >> 27) & 0x1F; - int func2 = (ir >> 25) & 0x3; - if( func2 != 1 ) throw Utils.TODO(); // 1==double - switch( func5 ) { - case 0: frval = lhs + rhs; break; // fadd.d - case 1: frval = lhs - rhs; break; // fsub.d - case 2: frval = lhs * rhs; break; // fmul.d - case 3: frval = lhs / rhs; break; // fdiv.d - case 5: frval = Math.min(lhs,rhs); break; // fmin.d, also used for move - case 20: - is_f = false; // Output into a GPR - rval = switch( (ir >> 12) & 7 ) { - case 0 -> lhs <= rhs ? 1 : 0; - case 1 -> lhs == rhs ? 1 : 0; - case 2 -> lhs < rhs ? 1 : 0; - default -> throw Utils.TODO(); - }; - break; - case 26: frval = (double)regs[rs1]; break; // fcvt.w.d - default: - trap = (2+1); // Fault: Invalid opcode. - throw Utils.TODO(); - } - break; - } - - default: trap = (2+1); // Fault: Invalid opcode. - } - - // If there was a trap, do NOT allow register writeback. - if( trap!=0 ) { - _pc = pc; - break; - } - - if( rdid!=0 || is_f) { - if(is_f) {fregs[rdid] = frval; is_f = false;} // Write back register. - else regs[rdid] = rval; // Write back register. - } - - pc += 4; - } - - // Handle traps and interrupts. - if( trap!=0 ) - return trap; - - _cycle = cycle; - _pc = pc; - return 0; - } -} diff --git a/chapter21/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java b/chapter21/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java index 0de4e960..98e0311d 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.RegAllocTestSupport; import com.seaofnodes.simple.node.*; diff --git a/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java index 82b1e58e..788bd9c2 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.riscv.riscv; import java.io.IOException; diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java index 39676d3a..e4bc38a0 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java index 36c5fb50..1289575d 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; diff --git a/chapter22/Makefile b/chapter22/Makefile index 9725bc7d..8fa5a13a 100644 --- a/chapter22/Makefile +++ b/chapter22/Makefile @@ -66,6 +66,7 @@ test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java) main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas)) include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk)) include $(firstword $(wildcard ../print/print.mk print/print.mk)) +include $(firstword $(wildcard ../isa/isa.mk isa/isa.mk)) test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas)) test_cp := $(patsubst $(TST)/$(SIMPLE)/%.java,com.seaofnodes.simple.%,$(wildcard $(TST)/$(SIMPLE)/*Test.java)) com.seaofnodes.simple.codegen.X86EncodingTest classes = $(main_classes) $(test_classes) @@ -108,8 +109,8 @@ $(main_classes): $(CLZDIR)/main/.mtag ####################################################### -OODT := -$(CLZDIR)/test/.ttag: $(test_classes) $(test_javas) $(CLZDIR)/main/.mtag +OODT := $(isa_test_javas) +$(CLZDIR)/test/.ttag: $(test_classes) $(test_javas) $(isa_test_javas) $(CLZDIR)/main/.mtag @[ -d $(CLZDIR)/test ] || mkdir -p $(CLZDIR)/test $(file >.argsT.txt,$(OODT)) @if [ ! -z "$(OODT)" ] ; then \ diff --git a/chapter22/pom.xml b/chapter22/pom.xml index d54196f7..fd5a680f 100644 --- a/chapter22/pom.xml +++ b/chapter22/pom.xml @@ -15,4 +15,32 @@ <simple.graph.directory>${project.basedir}/../graph</simple.graph.directory> <simple.print.directory>${project.basedir}/../print</simple.print.directory> </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>shared-isa-sources</id> + <phase>generate-sources</phase> + <goals><goal>add-source</goal></goals> + <configuration> + <sources> + <source>${project.basedir}/../isa/src/main/java</source> + </sources> + </configuration> + </execution> + <execution> + <id>shared-isa-test-sources</id> + <phase>generate-test-sources</phase> + <goals><goal>add-test-source</goal></goals> + <configuration><sources> + <source>${project.basedir}/../isa/src/test-support/java</source> + </sources></configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 162263d9..aad19090 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -19,7 +19,7 @@ import java.util.*; * There are also a bunch of generic utilities for managing bits and bytes * common in all encodings. */ -public class Encoding { +public class Encoding implements com.seaofnodes.isa.CodeSink { // Top-level program graph structure public final CodeGen _code; diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index f37738bf..76e7b9b5 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // ADD (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_ADD); } // General form: "rd = rs1 + rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index 209f24f4..9c2f64c0 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } //FADD (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);} + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_OP_ADD);} // Default on double precision for now(64 bits) // General form: "addf rd = src1 + src2 diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index a1cd8306..52cf36ea 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class AddIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } //ADD (immediate) @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_ADD,_imm); } // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index ad76ca4c..40812d07 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -13,7 +14,7 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // AND (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_AND); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_AND); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb){ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java index 1f12ef13..82d553aa 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -15,10 +16,10 @@ public class AndIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc,this, in(1), arm.OPI_AND,_imm); + arm.imm_inst_n(enc,this, in(1), Arm64.OPI_AND,_imm); } // General form: "andi rd = rs1 & imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm)); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(Arm64.decodeImm12(_imm)); } }
\ No newline at end of file diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index 342b7519..cce868f9 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class AsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sar"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_ASR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_ASR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> ").p(code.reg(in(2))); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java index a1775dde..2d50e967 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -22,7 +23,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_ASR,_imm, 0b111111, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_ASR,_imm, 0b111111, rn, rd)); } // General form: "asri rd = rs1 >> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index b36a395b..5a660c90 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -34,10 +35,10 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // by comparison (or sub). No need for regs because it uses flags if( in(1)!=null ) { // B.cond - enc.add4( arm.b_cond(arm.OP_BRANCH, 0, arm.make_condition(_bop)) ); + enc.add4( Arm64.b_cond(Arm64.OP_BRANCH, 0, Arm64.make_condition(_bop)) ); } else { if( _bop=="!=" ) return; // Inverted, no code - enc.add4(arm.b(arm.OP_UJMP, 0)); + enc.add4(Arm64.b(Arm64.OP_UJMP, 0)); } enc.jump(this,cproj(0)); } @@ -54,7 +55,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( opLen==4 ) { - enc.patch4(opStart,arm.b_cond(arm.OP_BRANCH, delta, arm.make_condition(_bop))); + enc.patch4(opStart,Arm64.b_cond(Arm64.OP_BRANCH, delta, Arm64.make_condition(_bop))); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 989bd366..dd2d9e2c 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -30,7 +31,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); // BL - enc.add4(arm.b(arm.OP_CALL,0)); // Target patched at link time + enc.add4(Arm64.b(Arm64.OP_CALL,0)); // Target patched at link time } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -38,7 +39,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - enc.patch4(opStart,arm.b(arm.OP_CALL,delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_CALL,delta)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index 87dde38c..fa0fbd81 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,7 +20,7 @@ public class CallRRARM extends CallNode implements MachNode { // Needs a register, typically a jump-and-link-register opcode // blr short self = enc.reg(this); - enc.add4(arm.blr(arm.OP_CALLRARM, self)); + enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index dbc86f62..ec5e8ff0 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.FLAGS_MASK; } // SUBS (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,arm.OP_CMP); } + @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,Arm64.OP_CMP); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java index 8a4f242a..dbf9c2e3 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -28,7 +29,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public Node copy() { return new CmpIARM(this); } - @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), arm.OPI_CMP,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), Arm64.OPI_CMP,_imm); } // General form: "cmp rs1, 1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index 40bd8387..91bd347f 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // SDIV - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_DIV,3); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_DIV,3); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 72b76444..6b86e722 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } // FDIV (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_DIV); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_DIV); } // General form: "VDIF = dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java index 84075edb..6fec7a77 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,7 +23,7 @@ public class ExtendARM extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); // SBFM/UBFM aliases: sign/zero extend the low byte, short or int. - enc.add4(arm.imm_shift(_signed ? arm.OPI_ASR : arm.OPI_LSR,0,_bits-1,src,dst)); + enc.add4(Arm64.imm_shift(_signed ? Arm64.OPI_ASR : Arm64.OPI_LSR,0,_bits-1,src,dst)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java index 63c57770..6bc2fe08 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -20,7 +21,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/); short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.add4(arm.load_pc(arm.OPF_ARM, 0, dst)); + enc.add4(Arm64.load_pc(Arm64.OPF_ARM, 0, dst)); } // Delta is from opcode start. @@ -29,7 +30,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.patch4(opStart, arm.load_pc(arm.OPF_ARM, delta, dst)); + enc.patch4(opStart, Arm64.load_pc(Arm64.OPF_ARM, delta, dst)); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java index 3ee75608..c49875f4 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -16,6 +17,6 @@ public class FunARM extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(arm.imm_inst(arm.OPI_SUB, sz, arm.RSP, arm.RSP)); + enc.add4(Arm64.imm_inst(Arm64.OPI_SUB, sz, arm.RSP, arm.RSP)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index 5ecc98b6..a7fa7a6a 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,7 +14,7 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(arm.OP_FLOAT_C, 1, reg1, self); + int body = Arm64.float_cast(Arm64.OP_FLOAT_C, 1, reg1, self); enc.add4(body); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index 0a07b07a..64d00d57 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -21,39 +22,7 @@ public class IntARM extends ConstantNode implements MachNode { @Override public void encoding( Encoding enc ) { short self = enc.reg(this); long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); - int nb0 = 0; - int nb1 = 0; - // Count number of 0000 and FFFF blocks - for (int i=0; i<64; i+=16) { - int block = (int)(x >> i) & 0xFFFF; - if (block == 0) nb0++; - if (block == 0xFFFF) nb1++; - } - int pattern; - int op; - if(nb0 >= nb1) { - // More 0 blocks then F blocks, use movz - pattern = 0; - op = arm.OP_MOVZ; - } else { - // More F blocks then 0 blocks, use movn - pattern = 0xFFFF; - op = arm.OP_MOVN; - } - int invert = pattern; - for (int i=0; i<4; i++) { - int block = (int)x & 0xFFFF; - x >>= 16; - if (block != pattern) { - enc.add4(arm.mov(op, i, block ^ invert, self)); - op = arm.OP_MOVK; - invert = 0; - } - } - if (op != arm.OP_MOVK) { - // All blocks are the same, special case - enc.add4(arm.mov(op, 0, 0, self)); - } + Arm64.constant(enc,self,x); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 65ca3603..5fa68e19 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; @@ -18,9 +19,9 @@ public class LoadARM extends MemOpARM { @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } - private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; + private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, }; - private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; + private static final int[] OP_LOAD_RS = new int[]{ Arm64.OP_LOAD_R_8 , Arm64.OP_LOAD_R_16 , Arm64.OP_LOAD_R_32 , Arm64.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index 055d6dcc..7624554e 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSL); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSL); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << ").p(code.reg(in(2))); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java index 94d3e25b..bf394172 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -24,7 +25,7 @@ public class LslIARM extends MachConcreteNode implements MachNode { assert _imm > 0; // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) // immr must be (-<shift> MOD 64) = 64 - shift - enc.add4(arm.imm_shift(arm.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); } // General form: "lsli rd = rs1 << imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index a691e0fe..2d5fa52c 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> ").p(code.reg(in(2))); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java index 094cd30f..6a12e4a5 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; @@ -20,7 +21,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_LSR,_imm, 0b111111, rn,rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSR,_imm, 0b111111, rn,rd)); } // General form: "lsri rd = rs1 >>> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index afd8723e..5e175b1e 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -65,8 +66,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { val -= arm.D0; } int body = off() == null - ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) - : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? Arm64.load_str_imm(opcode_imm, _off, ptr, val, size) + : Arm64.indr_adr(opcode_reg, off, Arm64.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index 3514db9b..a0955565 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_MUL,31); } // General form: "rd = rs1 * rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 89dba172..33d32bd4 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class MulFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_MUL); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_MUL); } // Default on double precision for now(64 bits) // General form: "VMUL.f32 rd = src1 * src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index cb51eea2..0dac086b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,8 +11,8 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { // BL(branch with link) enc.external(this,"calloc"). - add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1 - add4(arm.b(arm.OP_CALL, 0)); + add4(Arm64.mov(Arm64.OP_MOVZ, 0, 1, 0)). // movz x0,#1 + add4(Arm64.b(Arm64.OP_CALL, 0)); } // Patch is for running "new" in a JIT. @@ -23,7 +24,7 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void patch(Encoding enc, int opStart, int opLen, int delta ) { // Negative patches are JIT emulator targets. if( opStart+delta < 0 ) { - enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4)); + enc.patch4(opStart+4, Arm64.b_calloc(Arm64.OP_CALL, delta-4)); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index 5a8d882d..5c388bab 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,9 +19,9 @@ public class NotARM extends MachConcreteNode implements MachNode{ // subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int subs = arm.imm_inst(arm.OP_SUBS, 0, reg1, self); + int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(arm.OP_CSET, 31, arm.COND.EQ, 63, reg1); + int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 63, reg1); enc.add4(cset); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index b5cfa8cf..ba3197c1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,7 +12,7 @@ public class OrARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "|"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_OR); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" | ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index 2a2d199a..9c7cb8cc 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -15,7 +16,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm); + arm.imm_inst_n(enc, this, in(1), Arm64.OPI_OR, _imm); } // General form: "ori rd = rs1 | imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 4597666b..a7ed5073 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class RetARM extends ReturnNode implements MachNode { @Override public void encoding( Encoding enc ) { int frameAdjust = ((FunARM)fun())._frameAdjust; if( frameAdjust > 0 ) - enc.add4(arm.imm_inst(arm.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); - enc.add4(arm.ret(arm.OP_RET)); + enc.add4(Arm64.imm_inst(Arm64.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); + enc.add4(Arm64.ret(Arm64.OP_RET)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index 246e482a..6809bb1c 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -20,7 +21,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop), 0b011111, enc.reg(this)); + int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index 62bb75aa..c0c60ea2 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -27,7 +28,7 @@ public class SplitARM extends SplitNode { } int off = enc._fun.computeStackOffset(enc._code,dst); if( srcX ) src -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_STORE_IMM_64, off, arm.RSP, src, 8)); return; } @@ -35,26 +36,26 @@ public class SplitARM extends SplitNode { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); if( dstX ) dst -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); return; } // pick opcode based on regs if(!dstX && !srcX) { // GPR->GPR - enc.add4(arm.mov_reg(arm.OP_MOV, src, dst)); + enc.add4(Arm64.mov_reg(Arm64.OP_MOV, src, dst)); } else if(dstX && srcX) { // FPR->FPR // fmov reg - enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_reg(Arm64.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); } else if(!srcX && dstX) { // GPR->FPR // FMOV(general) 64 bits to DOUBLE-PRECISION - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); } else if( srcX && !dstX) { //FPF->GPR // FMOV(general) DOUBLE-PRECISION to 64 bits - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 0ce6197b..cf858c36 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.StoreNode; @@ -22,9 +23,9 @@ public class StoreARM extends MemOpARM { @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; + private static final int[] OP_STORES = new int[]{ Arm64.OP_STORE_IMM_8, Arm64.OP_STORE_IMM_16, Arm64.OP_STORE_IMM_32, Arm64.OP_STORE_IMM_64, }; - private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; + private static final int[] OP_STORE_RS = new int[]{ Arm64.OP_STORE_R_8, Arm64.OP_STORE_R_16, Arm64.OP_STORE_R_32, Arm64.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[_declaredType.log_size()], val(), size()); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index 552b46df..6024df68 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_SUB); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index 0d8d3c10..dd147544 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class SubFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_SUB); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_SUB); } // Default on double precision for now(64 bits) // General form: "vsub.f32 rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index b882c5a4..e45bfa63 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -19,7 +20,7 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_SUB,_imm); } // General form: "subi rd = rs1 - imm" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 606b03f0..720a14c1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -18,10 +19,10 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { enc.relo(this); short self = enc.reg(this); // adrp x0, 0 - int adrp = arm.adrp(1,0, arm.OP_ADRP, 0,self); + int adrp = Arm64.adrp(1,0, Arm64.OP_ADRP, 0,self); // add x0, x0, 0 enc.add4(adrp); - arm.imm_inst(enc,arm.OPI_ADD,0, 0); + arm.imm_inst(enc,Arm64.OPI_ADD,0, 0); } @Override public byte encSize(int delta) { @@ -38,9 +39,9 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { delta = target-base; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); // low 12 bits via add - enc.patch4(opStart+4, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, rpc)); + enc.patch4(opStart+4, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, rpc)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java index 68e32c78..adbaa8c2 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -18,9 +19,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { @@ -37,9 +38,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { delta = target-base; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, dst)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, dst)); // low 12 bits via add - enc.patch4(opStart+4, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, dst)); + enc.patch4(opStart+4, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, dst)); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java index bf46a7b1..acb32ddb 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; @@ -18,7 +19,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - int body = arm.b(arm.OP_UJMP, 0); + int body = Arm64.b(Arm64.OP_UJMP, 0); enc.add4(body); } @@ -32,7 +33,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,arm.b(arm.OP_UJMP, delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_UJMP, delta)); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index ec86cfa5..5b635303 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class XorARM extends MachConcreteNode implements MachNode{ @Override public String glabel() { return "^"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_XOR); } // General form: "rd = x1 ^ x2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ ").p(code.reg(in(2))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java index e2582d22..017815f3 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -20,7 +21,7 @@ public class XorIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // General form: "xori rd = rs1 ^ imm" - @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), Arm64.OPI_XOR,_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 7f175f52..15e2f0fe 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; +import static com.seaofnodes.isa.Arm64.*; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -81,102 +83,6 @@ public class arm extends Machine { static final RegMask D6_MASK = new RegMask(D6); static final RegMask D7_MASK = new RegMask(D7); - // major opcode: OP - public static int OP_ADD = 0b10_001_011; - public static int OPF_ADD = 0b00_011_110; - public static int OPF_OP_ADD = 0b00_101_0; - public static int OPI_ADD = 0b10_010_00100; - - public static int OPI_SUB = 0b11_010_00100; - public static int OP_UJMP = 0b000101; - - public static int OP_ADRP = 0b10000; - - public static int OP_ASR = 0b1010; - public static int OPI_ASR = 0b10_0100_1101; - - public static int OP_LSL = 0b1000; - public static int OPI_LSL =0b1101001101; - - public static int OP_LSR = 0b1001; - public static int OPI_LSR = 0b1101001101; - - public static int OP_BRANCH = 0b01_0101_00; - public static int OP_CALL = 0b10_010_1; - - public static int OP_CALLRARM = 0b1101011000111111000000; - - public static int OP_SUBS = 0b1111000100; - public static int OP_CSET = 0b10011010100; - public static int OP_CMP = 0b11101011; - public static int OPI_CMP = 0b1111000100; - - public static int OP_DIV = 0b10011010110; - public static int OPF_DIV = 0b000110; - - public static int OP_MUL = 0b10011011000; - public static int OPF_MUL = 0b10; - - public static int OPF_ARM = 0b01011100; - - public static int OP_FLOAT_C = 0b10011110; - - public static int OP_XOR = 0b11001010; - public static int OPI_XOR = 0b110100100; - - public static int OP_AND = 0b10_0010_10; - public static int OPI_AND = 0b10_0100_100; - - public static int OP_OR = 0b10101010; - public static int OPI_OR = 0b101100100; - - public static int OP_SUB = 0b11001011; - public static int OPF_SUB = 0b1110; - - public static int OP_MOVK = 0b111100101; - public static int OP_MOVN = 0b100100101; - public static int OP_MOVZ = 0b110100101; - - public static int OP_RET = 0b1101011001011111000000; - // Store/load opcodes - public static int OP_LOAD_R_64 = 0b11111000011; - public static int OP_LOAD_R_32 = 0b10111000011; - public static int OP_LOAD_R_16 = 0b01111000010; - public static int OP_LOAD_R_8 = 0b00111000011; - - public static int OP_LOAD_IMM_64 = 0b1111100101; - public static int OP_LOAD_IMM_32 = 0b1011100101; - public static int OP_LOAD_IMM_16 = 0b0111100101; - public static int OP_LOAD_IMM_8 = 0b0011100101; - - // load - public static int OPF_LOAD_R_64 = 0b11111100011; - public static int OPF_LOAD_R_32 = 0b10111100011; - - public static int OPF_LOAD_IMM_64 = 0b1111110101; - public static int OPF_LOAD_IMM_32 = 0b1011110101; - - public static int OP_STORE_R_64 = 0b11111000001; - public static int OP_STORE_R_32 = 0b10111000001; - public static int OP_STORE_R_16 = 0b01111000001; - public static int OP_STORE_R_8 = 0b00111000001; - - public static int OP_STORE_IMM_64 = 0b1111100100; - public static int OP_STORE_IMM_32 = 0b1011100100; - public static int OP_STORE_IMM_16 = 0b0111100100; - public static int OP_STORE_IMM_8 = 0b0011100100; - - public static int OPF_STORE_R_64 = 0b11111100001; - public static int OPF_STORE_R_32 = 0b10111100001; - - public static int OPF_STORE_IMM_32 = 0b1011110100; - public static int OPF_STORE_IMM_64 = 0b1111110100; - - - public static int OP_FMOV = 0b10011110; - public static int OP_FMOV_REG = 0b00011110; - // https://docsmirror.github.io/A64/2023-06/mov_orr_log_shift.html - public static int OP_MOV = 0b10101010000; // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 @@ -202,54 +108,6 @@ public class arm extends Machine { }; // ARM ENCODING - public enum OPTION { - UXTB, - UXTH, - UXTX, - SXTB, - SXTH, - SXTW, - SXTX, - } - - static public int cset(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 15) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - static public int cset(int opcode, COND cond, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - public enum STORE_LOAD_OPTION { - UXTW, // base+ u32 index [<< logsize] - UXTX, // base+ u64 index [<< logsize] - SXTW, // base+ s32 index [<< logsize] - SXTX, // base+ s64 index [<< logsize] - } - - public enum COND { - EQ, - NE, - CS, - CC, - MI, - PL, - VS, - VC, - HI, - LS, - GE, - LT, - GT, - LE, - AL, - NV - } // True if signed 9-bit immediate private static boolean imm9(TypeInteger ti) { @@ -262,55 +120,10 @@ public class arm extends Machine { return ti.isConstant() && ((ti.value()<<52)>>52) == ti.value(); } - // Can we encode this in ARM's 12-bit LOGICAL immediate form? // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { - if( !ti.isConstant() ) return -1; - if( !ti.isConstant() ) return -1; - long val = ti.value(); - if (val == 0 || val == -1) return -1; // Special cases are not allowed - int immr = 0; - // Rotate until we have 0[...]1 - - // Rotate until: - // The number is negative (MSB is 1) - // Or the LSB is not 1 - while (val < 0 || (val & 1)==0) { - // circular rotation - val = (val >>> 63) | (val << 1); - immr++; - } - // Start by assuming that val might be made of two 32-bit chunks that repeat. - int size = 32; - long pattern = val; - // Is upper half of pattern the same as the lower? - while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { - // Then only take one half - pattern >>= size; - size >>= 1; - } - size <<= 1; - int imms = Long.bitCount(pattern); - // Pattern should now be zeros followed by ones 0000011111 - if (pattern != (1L<<imms)-1) return -1; - imms--; - if (size == 64) return 0x1000 | immr << 6 | imms; - return (32-size)<<1 | immr << 6 | imms; - } - - // sh is encoded in opcode - public static int imm_inst(int opcode, int imm12, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; - } - - public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + return ti.isConstant() ? Arm64.logicalImmediate(ti.value()) : -1; } public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) { @@ -322,64 +135,46 @@ public class arm extends Machine { opcode ^= OPI_ADD ^ OPI_SUB; imm12 = -imm12; } - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); enc.add4(body); } public static void imm_inst_subs(Encoding enc, Node n,Node n2, int opcode, int imm12) { short reg1 = enc.reg(n2); // 31 = 11111 - int body = imm_inst(opcode, imm12&0xFFF, reg1, 31); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, 31); enc.add4(body); } // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static void imm_inst(Encoding enc, int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, self, self); enc.add4(body); } public static void imm_inst_n(Encoding enc, Node n, Node n2, int opcode, int imm13) { short self = enc.reg(n); short reg1 = enc.reg(n2); - int body = imm_inst_n(opcode, imm13, reg1, self); + int body = Arm64.imm_inst_n(opcode, imm13, reg1, self); enc.add4(body); } - // nth bit comes from immediate and not opcode - public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= imm13 && imm13 <= 0x1FFF; - return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; - } - - public static int imm_inst_l(int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); - return body; - } - // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); return body; } // for normal add, reg1, reg2 cases (reg-to-reg) // using shifted-reg form - public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; - } + public static void r_reg(Encoding enc, Node n, int opcode) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); enc.add4(body); } @@ -387,187 +182,43 @@ public class arm extends Machine { short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); // 31 = 11111 - int body = r_reg(opcode, 0, reg2, 0, reg1, 31); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, 31); enc.add4(body); } - public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; - } public static void shift_reg(Encoding enc, Node n, int op2) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(0b10011010110, reg2, op2, reg1, self); + int body = Arm64.shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } // MUL can be considered an alias for MADD with the third operand Ra being set to 0 - public static int madd(int opcode, int rm, int ra, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; - } + public static void madd(Encoding enc, Node n, int opcode, int ra) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = madd(opcode, reg2, ra, reg1, self); + int body = Arm64.madd(opcode, reg2, ra, reg1, self); enc.add4(body); } - // encodes movk, movn, and movz - public static int mov(int opcode, int shift, int imm16, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; - } - - public static int mov_reg(int opcode, int src, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; - } - - public static int ret(int opcode) { - return (opcode << 10) | (X30 << 5); - } - - // FMOV (scalar, immediate) - public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; - } - - public static int f_mov_reg(int opcode, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; - } - public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; - } public static void f_scalar(Encoding enc, Node n, int op ) { short self = (short)(enc.reg(n) -D_OFFSET); short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); + int body = Arm64.f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } - // share same encoding with LDR (literal, SIMD&FP) flavour - public static int load_pc(int opcode, int offset, int rt) { - offset>>=2; - return (opcode << 24) | (offset << 5) | rt; - } - // int l - public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { - assert 0 <= rd && rd < 32; - return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; - } - - // [Rptr+Roff] - public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; - } - // [Rptr+imm9] - public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - - if(size == 8) imm12 = imm12 >> 3; - if(size == 4) imm12 = imm12 >> 2; - if(size == 2) imm12 = imm12 >> 1; - // size == 1 imm12 = imm12 - return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; - } - - // encoding for vcvt, size is encoded in operand - // <Qd>, <Qm> - // F32.S32 - //encoded as op = 0b00, size = 0b10. - // VCVT<c>.<Td>.<Tm> <Dd>, <Dm> - // opcode is broken down into 4 pieces - public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { - return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | - (vd << 12) | (0x01100010 << 4) | vm; - } - public static int float_cast(int opcode, int ftype, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; - } - - - // ftype = 3 - public static int f_cmp(int opcode, int ftype, int rm, int rn) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - // Todo: |8 is not needed - return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); - } public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_cmp(0b00011110, 3, reg1, reg2); + int body = Arm64.f_cmp(0b00011110, 3, reg1, reg2); enc.add4(body); } - public static COND make_condition(String bop) { - return switch (bop) { - case "==" -> COND.EQ; - case "!=" -> COND.NE; - case "<" -> COND.LT; - case "<=" -> COND.LE; - case ">=" -> COND.GE; - case ">" -> COND.GT; - default -> throw Utils.TODO(); - }; - } - - public static int b_cond(int opcode, int delta, COND cond) { - // 24-5 == 19bits offset range - assert -(1<<19) <= delta && delta < (1<<19); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<19)-1; // Zero extend - return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); - } - - public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - // Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4. - public static int blr(int opcode, int rd) { - assert 0 <= rd && rd < 32; - return opcode << 10 | rd << 5; - } - public static int b(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - // no aligned assert(assert (delta&3)==0;) - public static int b_calloc(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; @@ -591,29 +242,6 @@ public class arm extends Machine { throw Utils.TODO(); // Pass on stack slot } - public static long decodeImm12(int imm12) { - int immr = (imm12 >> 6) & 0x3F; - int imms = imm12 & 0x3F; - int size; - if ((imm12 & 0x1000) != 0) { - size = 64; - } else { - size = 31-(imms >> 1); - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size++; - imms &= ~((32-size) << 1); - } - long val = (2L << imms)-1; - while (size < 64) { - val |= val << size; - size <<= 1; - } - val = (val >>> immr) | val << (64-immr); - return val; - } - // Return the max stack slot used by this signature, or 0 @Override public short maxArgSlot( TypeFunPtr tfp ) { int icnt=0, fcnt=0; // Count of ints, floats @@ -793,7 +421,6 @@ public class arm extends Machine { : new LsrARM(lsr); } - private static int off; private static Node idx; private Node st(StoreNode st) { @@ -819,7 +446,6 @@ public class arm extends Machine { return mop; } - private Node prj(ProjNode prj) { TypeInteger ret = cReturn(prj); return ret==null ? new ProjARM(prj) : new ExtendARM(prj,ret); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 37383608..fc96cbe9 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -17,7 +18,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); short dst = enc.reg(this); - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -28,7 +29,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { //short rpc = enc.reg(this); //// High half is where the TFP constant used to be, the last input //short auipc = enc.reg(in(_inputs._len-1)); - //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + //enc.patch4(opStart,RiscV.i_type(0x67, rpc, 0, auipc, delta)); throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java index 4d2ac916..b0921fa0 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class AddFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,1); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,1); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java index a85ce5d0..c3aa1276 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; @@ -8,7 +9,7 @@ public class AddIRISC extends ImmRISC { public AddIRISC( Node add, int imm12, boolean pop ) { super(add,imm12,pop); } @Override public String op() { return "addi"; } @Override public String glabel() { return "+"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 0;} @Override public AddIRISC copy() { // Clone the AddI, using the same inputs-only code used during inst select. diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java index ba88bb48..7639ea94 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; @@ -7,6 +8,6 @@ public class AndIRISC extends ImmRISC { public AndIRISC( Node and, int imm) { super(and,imm); } @Override public String op() { return "andi"; } @Override public String glabel() { return "&"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 7;} } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java index f6dc5cf2..b5ad5f59 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -45,12 +46,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { if( in(1)==null && _bop=="!=" ) return; // Inverted never-node, no code enc.jump(this,cproj(0)); if( in(1)==null ) // Never node - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); else { // Todo: relocs (for offset - immf) short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); - enc.add4(riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, 0)); + enc.add4(RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, 0)); } } @@ -66,12 +67,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( in(1)==null ) { // Never node - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); if( opLen==4 ) { - enc.patch4(opStart,riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, delta)); + enc.patch4(opStart,RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, delta)); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index 89b2c865..ff50a67f 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -32,7 +33,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); short rpc = enc.reg(this); - enc.add4(riscv.j_type(riscv.OP_JAL, rpc, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, rpc, 0)); } // Delta is from opcode start @@ -46,7 +47,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short rpc = enc.reg(this); if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, rpc, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, rpc, delta)); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index dcc53cbf..55e36ebf 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(riscv.OP_JALR, rpc, 0, src, 0); + int body = RiscV.i_type(RiscV.OP_JALR, rpc, 0, src, 0); enc.add4(body); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java index c67d7b3d..12a798b5 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class DivFRISC extends MachConcreteNode implements MachNode{ @Override public String op() { return "divf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RUP,13); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RUP,13); } // Default on double precision for now(64 bits) // General form: "fdiv.d rd = src1 / src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java index 4d487942..c2e93159 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,8 +23,8 @@ public class ExtendRISC extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); int shift = 64-_bits; - enc.add4(riscv.i_type(riscv.OP_IMM,dst,1,src,shift)); - enc.add4(riscv.i_type(riscv.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,1,src,shift)); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index be699280..3dbb40d1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -20,9 +21,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -34,9 +35,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java index 84f0f4c7..4ebdec15 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -17,6 +18,6 @@ public class FunRISC extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java index 5519fe5b..c9b20939 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,7 +15,7 @@ public class I2F8RISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this )-riscv.F_OFFSET); short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.RM.RNE.ordinal(),src1,0,0x69); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.RM.RNE.ordinal(),src1,0,0x69); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index 8847d2b7..ceea98e3 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -41,7 +42,7 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); + enc.add4(RiscV.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); } // General form: "addi rd = rs1 + imm" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java index f9b7daee..fabb3b9d 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.*; @@ -24,9 +25,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short tmp = (short)riscv.T6; enc.largeConstant(this,_con, 0, -1); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -35,9 +36,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index 70d5c18f..e4dd39dd 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -21,7 +22,7 @@ public class IntRISC extends ConstantNode implements MachNode { int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index b65afc79..deaa3b59 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -21,7 +22,7 @@ public class LUI extends ConstantNode implements MachNode { long x = ((TypeInteger)_con).value(); int imm20 = (int)(x>>12) & 0xFFFFF; short dst = enc.reg(this); - int lui = riscv.u_type(riscv.OP_LUI, dst, imm20); + int lui = RiscV.u_type(RiscV.OP_LUI, dst, imm20); enc.add4(lui); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index 7b0e9138..5e1845b8 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -17,9 +18,9 @@ public class LoadRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short ptr = enc.reg(ptr()); - int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dst >= riscv.F_OFFSET ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, func3(), ptr, _off)); + enc.add4(RiscV.i_type(op, dst, func3(), ptr, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java index c9917b4f..40609f96 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class MulFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,9); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,9); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java index 77f4a497..58340b32 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,7 +13,7 @@ public class NegRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - riscv.r_type(riscv.OP,dst,0,0,src,0x20); + RiscV.r_type(RiscV.OP,dst,0,0,src,0x20); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = -").p(code.reg(in(1))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index e395a811..8e3daaba 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,9 +14,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.i_type(riscv.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); - enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); } // Patch is for running "new" in a JIT. @@ -31,8 +32,8 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { int imm20 = delta>>12; if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension int imm12 = delta&0xFFF; - enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); - enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + enc.patch4(opStart+4,RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); } else throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java index 9cbd5025..469221f3 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -14,7 +15,7 @@ public class NotRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 2, src, 1)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java index f6a888d9..53abcf0b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class OrIRISC extends ImmRISC { public OrIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 6; } @Override public String glabel() { return "|"; } @Override public String op() { return "ori"; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 8a8186cd..d28311dc 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -14,8 +15,8 @@ public class RetRISC extends ReturnNode implements MachNode { int sz = fun()._frameAdjust; if( sz >= 1L<<12 ) throw Utils.TODO(); if( sz != 0 ) - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); short rpc = enc.reg(rpc()); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.ZERO, 0, rpc, 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR, riscv.ZERO, 0, rpc, 0)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 9ee19e42..fabb9f92 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.BoolNode; @@ -23,7 +24,7 @@ public class SetFRISC extends MachConcreteNode implements MachNode { short dst = enc.reg(this ); short src1 = (short)(enc.reg(in(1))-riscv.F_OFFSET); short src2 = (short)(enc.reg(in(2))-riscv.F_OFFSET); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java index 4edecc04..52b238ec 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class SllIRISC extends ImmRISC { public SllIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 1; } @Override public String glabel() { return "<<"; } @Override public String op() { return "slli"; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 569fa2e0..ca1bf614 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -25,36 +26,36 @@ public class SplitRISC extends SplitNode { throw Utils.TODO(); // Very rare stack-stack move } int off = enc._fun.computeStackOffset(enc._code,dst); - int op = srcX ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = srcX ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( srcX ) src -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, 0b011, riscv.RSP, src, off)); + enc.add4(RiscV.s_type(op, 0b011, riscv.RSP, src, off)); return; } if( src >= riscv.MAX_REG ) { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); - int op = dstX ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dstX ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dstX ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, 0b011, riscv.RSP, off)); + enc.add4(RiscV.i_type(op, dst, 0b011, riscv.RSP, off)); return; } // pick opcode based on regs if( !dstX && !srcX ) { // GPR->GPR - enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + enc.add4(RiscV.r_type(RiscV.OP,dst,0,src,riscv.ZERO,0)); } else if( dstX && srcX ) { // FPR->FPR src -= riscv.F_OFFSET; dst -= riscv.F_OFFSET; - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) } else if(!srcX && dstX) { //GPR->FPR // fmv.d.x - enc.add4(riscv.r_type(riscv.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); } else if(srcX && !dstX) { //FPR->GPR //fmv.x.d - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java index 1533003c..48171483 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; @@ -7,7 +8,7 @@ public class SraIRISC extends ImmRISC { public SraIRISC( Node and, int imm) { super(and,imm | (0x20 << 5)); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5;} @Override public String glabel() { return ">>"; } @Override public String op() { return "srai"; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java index ed697678..985abe2c 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class SrlIRISC extends ImmRISC { public SrlIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5; } @Override public String glabel() { return ">>>"; } @Override public String op() { return "srli"; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index f07389eb..03e06f83 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -36,9 +37,9 @@ public class StoreRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short val = enc.reg(val()); short ptr = enc.reg(ptr()); - int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = val >= riscv.F_OFFSET ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); + enc.add4(RiscV.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java index 1e1b43c7..caf751bb 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,7 +11,7 @@ public class SubFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,5); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,5); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index 1d1f30e9..d7da5ba1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -20,9 +21,9 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; // auipc t0,0 - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi t1,t0 + #0 - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -32,8 +33,8 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short rpc = enc.reg(this); if( opLen==8 ) { // ADDI sign-extends its low 12 bits, so round the AUIPC high part. - enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, (delta+0x800)>>12)); - enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); + enc.patch4(opStart ,RiscV.u_type(RiscV.OP_AUIPC, rpc, (delta+0x800)>>12)); + enc.patch4(opStart+4,RiscV.i_type(RiscV.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java index 2f7ffe0d..46b8aace 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; @@ -18,9 +19,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -29,9 +30,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = enc.reg(this); // Round the high part because ADDI's low 12 bits are signed. - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, (delta+0x800)>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, dst, (delta+0x800)>>12)); // ADDI dst,dst,#low12_constant_pool - enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, dst, 0, dst, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java index 3868990d..cc47b7ed 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.*; @@ -20,7 +21,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.jump(this,uctrl()); - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); } // Delta is from opcode start @@ -33,7 +34,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 27098033..ebdf9fa8 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -1,12 +1,13 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.Node; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } public XorIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } @Override public String op() { return "xori"; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 1618334f..a9327c50 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; +import static com.seaofnodes.isa.RiscV.*; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -68,7 +70,6 @@ public class riscv extends Machine { static final RegMask SPLIT_MASK = new RegMask( WR_BITS | FP_BITS, -1L ); - // Arguments masks public static RegMask A0_MASK = new RegMask(A0); public static RegMask A1_MASK = new RegMask(A1); @@ -114,40 +115,13 @@ public class riscv extends Machine { FA7_MASK }; - // major opcode: OP - public static int OP_LOAD = 0b00_000_11; - public static int OP_LOADFP = 0b00_001_11; - public static int OP_CUSTOM0 = 0b00_010_11; - public static int OP_IMM = 0b00_100_11; - public static int OP_AUIPC = 0b00_101_11; - - public static int OP_STORE = 0b01_000_11; - public static int OP_STOREFP = 0b01_001_11; - public static int OP_CUSTOM1 = 0b01_010_11; - public static int OP = 0b01_100_11; - public static int OP_LUI = 0b01_101_11; - - public static int OP_CUSTOM2 = 0b10_010_11; - public static int OP_FP = 0b10_100_11; - - public static int OP_BRANCH = 0b11_000_11; - public static int OP_JALR = 0b11_001_11; - public static int OP_RESERVED= 0b11_010_11; - public static int OP_JAL = 0b11_011_11; - - // Since riscv instructions are fixed we can just or them together - public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= rd && rd < 32; - return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } + public static void r_type(Encoding enc, Node n, int func3, int func7) { short dst = enc.reg(n); short src1 = enc.reg(n.in(1)); short src2 = enc.reg(n.in(2)); - int body = r_type(OP,dst,func3,src1,src2,func7); + int body = RiscV.r_type(OP,dst,func3,src1,src2,func7); enc.add4(body); } @@ -155,103 +129,10 @@ public class riscv extends Machine { short dst = (short)(enc.reg(n )-F_OFFSET); short src1 = (short)(enc.reg(n.in(1))-F_OFFSET); short src2 = (short)(enc.reg(n.in(2))-F_OFFSET); - int body = r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); + int body = RiscV.r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); enc.add4(body); } - - public static int u_type(int opcode, int rd, int imm20) { - assert 0 <= rd && rd < 32; - return (imm20 << 12) | (rd << 7) | opcode; - } - - public static int j_type(int opcode, int rd, int delta) { - assert -(1L<<20) <= delta && delta < (1L<<20); - assert 0 <= rd && rd < 32; - // Messy branch offset encoding - // 31 30-21 20 19-12 11-7 6-0 - // 20 10- 1 11 19-12 rpc JAL - assert (delta&1)==0; // Low bit is always zero, not encoded - int imm10_01 = (delta>> 1) & 0x3FF; - int imm11 = (delta>>11) & 1; - int imm12_19 = (delta>>12) & 0xFF; - int imm20 = (delta>>19) & 1; - int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; - return bits << 12 | rd << 7 | opcode; - } - - - public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { - assert 0 <= rd && rd < 32; - assert 0 <= rs1 && rs1 < 32; - assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller - return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } - - // S-type instructions(store) - public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= func3; - - assert imm12 >= 0; // Masked to high zero bits by caller - int imm_lo = imm12 & 0x1F; - int imm_hi = imm12 >> 5; - return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; - } - - // BRANCH - public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert -4*1024 <= delta && delta < 4*1024; - assert (delta&1)==0; // Low bit is always zero, not encoded - // Messy branch offset encoding - // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 - // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP - int imm4_1 = (delta>> 1) & 0xF; - int imm10_5= (delta>> 5) &0x3F; - int imm11 = (delta>>11) & 1; - int imm12 = (delta>>12) & 1; - int imm5 = imm4_1<<1 | imm11; - int imm7 = imm12<<6 | imm10_5; - return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; - } - - public enum RM { - RNE, // Round to Nearest, ties to Even - RTZ, // Round towards Zero - RDN, // Round Down - RUP, // Round Up - DIRECT, // Round to Nearest, ties to Max Magnitude - RESERVED1, // Reserved for futue use - RESERVED2, // Reserved for future use - DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved - } - - // Since opcode is the same just return back func3 - static public int jumpop(String op) { - return switch(op) { - case "==" -> 0x0; - case "!=" -> 0x1; - case "<" -> 0x4; - case ">=" -> 0x5; - case "u<" -> 0x6; - case "u<=" -> 0x7; - default -> throw Utils.TODO(); - }; - } - - // Since opcode is the same just return back func3 - static public int fsetop(String op) { - return switch(op) { - case "<" -> 1; - case "<=" -> 0; - case "==" -> 2; - default -> throw Utils.TODO(); - }; - } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; @@ -301,7 +182,6 @@ public class riscv extends Machine { } @Override public int rpc() { return RPC; } - // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index d54c7c31..76a2d3f7 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -20,19 +21,7 @@ public class AddFMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // addsd xmm0, DWORD PTR [rdi+0xc] - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - // F opcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, ptr, idx, false, enc); - - // FP ADD - enc.add1(0x0F).add1(0x58); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst = src + [base + idx<<2 + 12]" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index a4166bc7..b3266cb0 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,17 +14,7 @@ public class AddFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 58 /r ADDSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x58); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "addf dst += src" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java index 050451f1..c55f975c 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.Encoding; @@ -16,9 +17,7 @@ public class AddIX86 extends ImmX86 { @Override public final void encoding( Encoding enc ) { if( _imm== 1 || _imm== -1 ) { short dst = enc.reg(this); // Also src1 - enc.add1( x86_64_v2.rex(0,dst,0)); - enc.add1(0xFF); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, _imm==1 ? 0 : 1, dst) ); + X86.unary(enc,0xFF,_imm==1 ? 0 : 1,dst); } else super.encoding(enc); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java index f97a7cb8..d2111d07 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,18 +13,7 @@ public class AddMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // add something to register from memory - // add eax,DWORD PTR [rdi+0xc] - // REX.W + 03 /r ADD r64, r/m64 - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - // opcode - enc.add1(0x03); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0,0x03,true,enc.reg(this),enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst += [base + idx<<2 + 12]" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 1a74f817..15b83bfc 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; @@ -16,11 +17,7 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // FF /2 CALL r/m64 - // calls the function in the register - short src = enc.reg(fptr()); - enc.add1(0xFF); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT,2,src)); + X86.callRegister(enc,enc.reg(fptr())); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index 4696c859..3d450040 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -28,7 +29,7 @@ public class CallX86 extends CallNode implements MachNode, RIPRelSize { FunNode fun = CodeGen.CODE.link(_tfp); if( fun==null ) enc.external(this,_name); else enc.relo(this); - enc.add1(0xe8).add4(0); + X86.call(enc); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java index 35b92170..5a0c7a37 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,16 +12,7 @@ public class CmpFX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // UCOMISD - short src1 = (short)(enc.reg(in(1)) - x86_64_v2.XMM_OFFSET); - short src2 = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // float opcode - enc.add1(0x66); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(src1, src2, 0, false, enc); - - enc.add1(0x0F).add1(0x2E); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src1, src2)); + X86.sse(enc,0x66,0x0F2E,false,enc.reg(in(1))-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "cmp src1,src2" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 91b6d43c..2811a640 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -26,14 +27,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode { @Override public Node copy() { return new CmpIX86(this); } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,0x81,7,enc.reg(in(1)),_imm); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index 8c558ff2..942400f4 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -16,51 +17,16 @@ public class CmpMemX86 extends MemOpX86 { @Override public String op() { return ((val()==null && _imm==0) ? "test" : "cmp") + _sz; } @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64 - // CMP [mem], imm32 - - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if(src == -1) { + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) { assert !_swap; - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch(log) { - case 0: enc.add1(0x80); break; - case 1: enc.add1(0x66).add1(0x81); break; - case 2: enc.add1(0x81); break; - case 3: enc.add1(0x81); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc); - switch(log) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; - } - } else { - encVal(enc, _declaredType, ptr, idx, src, _off, _scale, _swap); - } + X86.cmpImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + } else encVal(enc,_declaredType,ptr,idx,src,_off,_scale,_swap); } static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale, boolean _swap) { - if(decl instanceof TypeFloat) { - src -= (short)x86_64_v2.XMM_OFFSET; - enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2); - } else { - int log = decl.log_size(); - x86_64_v2.rexF(src, ptr, idx, log == 3, enc); - int swap = _swap ? 2 : 0; - switch(log) { - case 0: enc.add1(0x38+swap); break; - case 1: enc.add1(0x66).add1(0x39+swap); break; - case 2: enc.add1(0x39+swap); break; - case 3: enc.add1(0x39+swap); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + assert !(decl instanceof TypeFloat); // Selected separately as CmpFX86. + X86.cmpMem(enc,decl.log_size(),src,ptr,idx,off,scale,_swap); } // General form: "cmp dst = src, [base + idx<<2 + 12]" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index 3e4200c0..27246db5 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -17,12 +18,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); - short src = enc.reg(in(2)); - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x3B); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x3B,enc.reg(in(1)),enc.reg(in(2))); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index 9509a1f5..962ec44e 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,18 +13,7 @@ public class DivFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5E /r DIVSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5E); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5E,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java index 06f001b0..5d061ae1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,16 +15,7 @@ public class DivX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.RDX_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + F7 /7 IDIV r/m64 - short src = enc.reg(in(2)); - // sign extend rax before 128/64 bits division - // sign extend rax to rdx:rax - enc.add1(x86_64_v2.REX_W); - enc.add1(0x99); - enc.add1(x86_64_v2.rex(0, src, 0)); - // divide - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x07, src)); + X86.divide(enc,enc.reg(in(2))); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java index 3997d768..bd40bae7 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -20,12 +21,7 @@ public class ExtendX86 extends MachConcreteNode { @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this), src = enc.reg(in(1)); - // MOVSX/MOVZX for bytes and shorts; MOVSXD/MOV r32 for ints. - enc.add1(x86_64_v2.rex(dst,src,0,_signed || _bits<32)); - if( _bits==32 ) enc.add1(_signed ? 0x63 : 0x8b); - else enc.add1(0x0f).add1((_signed ? 0xbe : 0xb6) + (_bits==16 ? 1 : 0)); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,dst,src)); + X86.extend(enc,_bits,_signed,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index e3b20003..b17ea305 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -14,20 +15,8 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public Node copy() { return new FltX86(this); } @Override public void encoding( Encoding enc ) { - // Load the constant into a FPR - // movsd xmm, [rip + 0] - // F2 0F 10 /r MOVSD xmm1, m64 - _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - _encSize += x86_64_v2.rexF(dst, 0, 0, false, enc); - enc.add1(0x0F).add1(0x10); - // hard-code rip here - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); - enc.add4(0); - enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); + _encSize=X86.rip(enc,0xF2,0x0F10,false,enc.reg(this)-x86_64_v2.XMM_OFFSET); + enc.largeConstant(this,_con,_encSize-4,2/*ELF PC32*/); } // Delta is from opcode start diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index 07418eb0..24c2a78b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -24,11 +25,7 @@ public class FunX86 extends FunNode implements MachNode { @Override public void encoding( Encoding enc ) { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust - // opcode: 0x83, addi rsp with immediate 8 - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b101, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); + X86.imm(enc,0x81,5,x86_64_v2.RSP,sz); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java index d3213ae4..4a17b92b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -11,18 +12,7 @@ public class I2f8X86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public void encoding( Encoding enc ) { - // F2 0F 2A /r CVTSI2SD xmm1, r32/m32 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = enc.reg(in(1)); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, true, enc); - - enc.add1(0x0F).add1(0x2A); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F2A,true,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java index 95f617e7..08c9b4c9 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -21,14 +22,7 @@ public abstract class ImmX86 extends MachConcreteNode implements MachNode { abstract int mod(); @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( opcode() + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,opcode(),mod(),enc.reg(this),_imm); } // General form: "addi dst += #imm" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 6d9110f2..29513d98 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -22,44 +23,7 @@ public class IntX86 extends ConstantNode implements MachNode { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL || _con==TypeInteger.ZERO ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // Simply move the constant into a GPR - // Conditional encoding based on 64 or 32 bits - //REX.W + C7 /0 id MOV r/m64, imm32 - - long imm = ((TypeInteger)_con).value(); - if (Integer.MIN_VALUE <= imm && imm < 0) { - // We need sign extension, so use imm32 into 64 bit register - // REX.W + C7 /0 id MOV r/m64, imm32 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xC7); // 32 bits encoding - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x00, dst)); - enc.add4((int)imm); - } else if (0 <= imm && imm <= 0xFFFFFFFFL) { - // We want zero extension into 64 bit register - // so move 32 bit into 32 bit register which zeros - // the upper bits in the 64 bit register. - // B8+ rd id MOV r32, imm32 - if (dst >= 8) enc.add1(0x41); - enc.add1(0xB8 + (dst & 0x07)); - enc.add4((int)imm); - } else { - // Just write the full 64 bit constant - // REX.W + B8+ rd io MOV r64, imm64 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xB8 + (dst & 0x07)); - enc.add8(imm); // 64 bits encoding - } + X86.constant(enc,enc.reg(this),_con==Type.NIL ? 0 : ((TypeInteger)_con).value()); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index d7acf8b8..92156c58 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -29,38 +30,21 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { @Override public void negate() { _bop = negate(_bop); } @Override public void encoding( Encoding enc ) { - if( in(1)!=null ) { - int op = x86_64_v2.jumpop(_bop); - enc.add1(op-16).add1(0); // Short form jump - } else { - if( _bop=="!=" ) return; // Inverted, no code - enc.add1(0xEB).add1(0); // Never-node - } + if( in(1)==null && _bop=="!=" ) return; + X86.branch(enc,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); enc.jump(this,cproj(0)); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding @Override public byte encSize(int delta) { - if( in(1)==null && _bop=="!=" ) return 0; // Inverted never-node, no code - return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 6); + if( in(1)==null && _bop=="!=" ) return 0; + return X86.branchSize(delta,in(1)!=null); } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 6; // Offset from opcode END - bits[opStart] = 0x0F; - bits[opStart+1] = (byte)(in(1)==null ? 0xE9 : x86_64_v2.jumpop(_bop)); - enc.patch4(opStart+2,delta); - } + assert !(in(1)==null && _bop=="!="); + X86.patchBranch(enc.bits(),opStart,opLen,delta,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java index dce8a49a..e20fd1ec 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -23,25 +24,7 @@ public class LeaX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 8D /r LEA r64,m - short dst = enc.reg(this); - short ptr = enc.reg(in(1)); - short idx = enc.reg(in(2)); - // ptr is null - // just do: [(index * s) + disp32] - if( ptr == -1 ) { - enc.add1(x86_64_v2.rex(dst, 0, idx)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x04)); - enc.add1(x86_64_v2.sib(_scale, idx, x86_64_v2.RBP)); - enc.add4(_offset); - return; - } - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - enc.add1(0x8D); // opcode - // rsp is hard-coded here(0x04) - x86_64_v2.indirectAdr(_scale, idx, ptr, _offset, dst, enc); + X86.lea(enc,enc.reg(this),enc.reg(in(1)),enc.reg(in(2)),_offset,_scale); } // General form: "lea dst = base + 4*idx + 12" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java index c712eb7d..c5329e1d 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -27,33 +28,14 @@ public class LoadX86 extends MemOpX86 { } static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) { - // Allocation may put a full-width integer in an XMM register (or a - // floating value in a GPR). Move its bits using the selected register bank. - if( dst>=x86_64_v2.XMM_OFFSET && decl.log_size()==3 ) decl=TypeFloat.F64; - else if( dst<x86_64_v2.XMM_OFFSET && decl instanceof TypeFloat ) - decl = decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; - if( decl == TypeFloat.F32) enc.add1(0xF3); - if( decl == TypeFloat.F64) enc.add1(0xF2); - - if( decl.isa(TypeFloat.F64) ) - dst -= (short)x86_64_v2.XMM_OFFSET; - - x86_64_v2.rexF(dst, ptr, idx, decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64, enc); - - if( false ) ; - else if( decl == TypeFloat.F32 ) enc.add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32 - else if( decl == TypeFloat.F64 ) enc.add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64 - else if( decl.isa(TypeInteger.I8)) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8 - else if( decl == TypeInteger.I16 ) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16 - else if( decl == TypeInteger.I32 ) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32 - else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8 - else if( decl == TypeInteger.U16 ) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16 - // Covers U32, I64/BOT, TMP - else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32 - else throw Utils.TODO(); - - // includes modrm internally - x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc); + // The chapter chooses the register bank and extension from its own type facts. + boolean xmm=dst>=x86_64_v2.XMM_OFFSET; + if( xmm && decl.log_size()==3 ) decl=TypeFloat.F64; + else if( !xmm && decl instanceof TypeFloat ) + decl=decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; + boolean signed=decl.isa(TypeInteger.I8) || decl==TypeInteger.I16 || decl==TypeInteger.I32; + X86.load(enc,decl.log_size(),signed,xmm, + xmm ? dst-x86_64_v2.XMM_OFFSET : dst,ptr,idx,off,scale); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index f0d01b3d..22a1a7ae 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -15,20 +16,7 @@ public class MemAddX86 extends MemOpX86 { @Override public RegMask outregmap() { return null; } @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // add something to memory - // REX.W + 01 /r | REX.W + 81 /0 id - // ADD [mem], imm32/reg - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - enc.add1(x86_64_v2.rex(src, ptr, idx)); - // opcode - enc.add1( src == -1 ? (_imm==1 ? 0xFF : 0x81): 0x01); - - // includes modrm - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc); - if( src == -1 && _imm!=1 ) enc.add4(_imm); + X86.addMem(enc,enc.reg(val()),_imm,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add [base + idx<<2 + 12] += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index c1edb082..3371a8ba 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,16 +14,7 @@ public class MulFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 59 /r MULSD xmm1,xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x59).add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F59,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "mulf dst *= src" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 17006558..4a7e24d0 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.codegen.*; @@ -17,15 +18,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } // Rare 3-address form @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // Also src1 - short src = enc.reg(in(1)); - enc.add1(x86_64_v2.rex(dst, src, 0)); - // opcode; 0x69 or 0x6B - enc.add1( 0x69 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imul(enc,enc.reg(this),enc.reg(in(1)),_imm); } // General form: "addi dst += #imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java index 3cd1f795..cdc67ea8 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -13,13 +14,7 @@ public class MulX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // REX.W + 0F AF /r IMUL r64, r/m64 - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xAF); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x0FAF,enc.reg(this),enc.reg(in(2))); } // General form: "mul dst *= src" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java index b8b83cb0..3d3798cd 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,10 +13,7 @@ public class NegX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 3, dst)); + X86.unary(enc,0xF7,3,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index 0439adfd..877ec224 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -10,11 +11,8 @@ public class NewX86 extends NewNode implements MachNode { NewX86( NewNode nnn ) { super(nnn); } @Override public void encoding( Encoding enc ) { enc.external(this,"calloc"); - // ldi rcx,#1 // number of elements to calloc - enc.add1(0xB8 + _arg2Reg).add4(1); - // E8 cd CALL rel32; - enc.add1(0xE8); - enc.add4(0); // offset + X86.constant(enc,_arg2Reg,1); + X86.call(enc); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java index 2d611931..46227dd4 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,25 +13,9 @@ public class NotX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - assert !(in(1) instanceof NotNode); // Cleared out by peeps - assert !(in(1) instanceof BoolNode); // Cleared out by peeps - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - - // test rdi,rdi - enc.add1(x86_64_v2.rex(src, src, 0)); - enc.add1(0x85); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src, src)); - - // setz dstb; then zero-extend the low byte into the full register. - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0x94); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0xB6); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + assert !(in(1) instanceof NotNode); // Cleared out by peeps + assert !(in(1) instanceof BoolNode); + X86.not(enc,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java index a4a6a814..50c8e974 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,13 +13,7 @@ public abstract class RegX86 extends MachConcreteNode { @Override public int twoAddress() { return 1; } abstract int opcode(); @Override public void encoding( Encoding enc ) { - // REX.W + 01 /r - short dst = enc.reg(in(1)); // src1 - short src = enc.reg(in(2)); // src2 - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); } // General form: "add dst += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index a35d43a2..e4467bb4 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -8,12 +9,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public void encoding( Encoding enc ) { int sz = fun()._frameAdjust; - if( sz != 0 ) { - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b000, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); - } - enc.add1(0xC3); + if( sz!=0 ) X86.imm(enc,0x81,0,x86_64_v2.RSP,sz); + X86.ret(enc); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index 07256604..43ad6bbd 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; @@ -23,15 +24,7 @@ public class SarIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index b1be643c..50693034 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; @@ -15,10 +16,6 @@ public class SarX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst)); + X86.unary(enc,opcode(),7,enc.reg(this)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 775ea8eb..591bf8da 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -23,26 +24,14 @@ public class SetX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX + 0F 94 - short dst = enc.reg(this ); - - // Optional rex, for dst - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(switch (_bop) { + int op=switch (_bop) { case "==" -> 0x94; // SETE case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE default -> throw Utils.TODO(); - }); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - - // low 8 bites are set, now zero extend for next instruction - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(0xB6); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + }; + X86.set(enc,op&15,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index 0b75b456..f31832e6 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.*; @@ -24,15 +25,7 @@ public class ShlIX86 extends MachConcreteNode implements MachNode { @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java index 9f358575..08c4db25 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; @@ -15,10 +16,6 @@ public class ShlX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 4, dst)); + X86.unary(enc,opcode(),4,enc.reg(this)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 893eb23d..218542f3 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.*; @@ -19,15 +20,7 @@ public class ShrIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java index d869260f..c72f21e2 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; @@ -15,10 +16,6 @@ public class ShrX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 5, dst)); + X86.unary(enc,opcode(),5,enc.reg(this)); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index 960ea6f8..5cf668d1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.*; @@ -19,44 +20,17 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. @Override public void encoding( Encoding enc ) { - // REX.W + 8B /r MOV r64, r/m64 - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - if( dst == x86_64_v2.FLAGS ) { - // mov reg, flags - // push rcx - // popf (Pop the top of the stack into the FLAGS register) - // 50+rd PUSH r64 - x86_64_v2.rexF(0,src,0,false,enc); - enc.add1(0x50 + src); - // popf - enc.add1(0x9D); - return; - } - if( src == x86_64_v2.FLAGS ) { - // mov flags, reg - // pushf; pop reg - enc.add1(0x9C); - // 58+ rd POP r64 - x86_64_v2.rexF(0,dst,0,false, enc); - enc.add1(0x58 + dst); - return; - } - - // Flag for being either XMM or stack - boolean dstX = dst >= x86_64_v2.XMM_OFFSET; - boolean srcX = src >= x86_64_v2.XMM_OFFSET; - + short dst=enc.reg(this), src=enc.reg(in(1)); + if( dst==x86_64_v2.FLAGS ) { X86.flags(enc,src,true); return; } + if( src==x86_64_v2.FLAGS ) { X86.flags(enc,dst,false); return; } + boolean dstX=dst>=x86_64_v2.XMM_OFFSET, srcX=src>=x86_64_v2.XMM_OFFSET; // Stack spills if( dst >= x86_64_v2.MAX_REG ) { int off = enc._fun.computeStackOffset(enc._code,dst); if( src >= x86_64_v2.MAX_REG ) { // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] int soff = enc._fun.computeStackOffset(enc._code,src); - enc.add1(0xFF); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); - enc.add1(0x8F); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + X86.stackCopy(enc,soff,off); return; } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); @@ -68,35 +42,8 @@ public class SplitX86 extends SplitNode { return; } - // reg-reg move. Adjust numbering for GPR vs FPR reg set - if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; - if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; - - // 0x66 if moving between register classes - if( dstX ^ srcX ) enc.add1(0x66); - if( !dstX && srcX ) - { short tmp=src; src=dst; dst=tmp; } - enc.add1(x86_64_v2.rex(dst, src, 0)); - - // pick opcode based on regs - if( !dstX && !srcX ) { - // reg->reg (MOV r64, r/m64) - enc.add1(0x8B); - } else if( dstX && srcX ) { - // xmm->xmm (NP 0F 28 /r MOVAPS xmm1, xmm2/m128) - enc.add1(0x0F); - enc.add1(0x28); - } else if( dstX && !srcX ) { - // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) - enc.add1(0x0F); - enc.add1(0x6E); - } else if( !dstX && srcX ) { - // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) - enc.add1(0x0F); - enc.add1(0x7E); - } - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.move(enc,dstX,srcX,dstX ? dst-x86_64_v2.XMM_OFFSET : dst, + srcX ? src-x86_64_v2.XMM_OFFSET : src); } // General form: "mov dst = src" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index 22a0bd79..4796c0fe 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.SB; @@ -25,55 +26,16 @@ public class StoreX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // REX.W + C7 /0 id MOV r/m64, imm32 | - // REX.W + 89 /r MOV r/m64, r64 - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if( src == -1 ) { - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch( log ) { - case 0: enc .add1(0xC6); break; - case 1: enc.add1(0x66).add1(0xC7); break; - case 2: enc .add1(0xC7); break; - case 3: enc .add1(0xC7); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc); - switch( log ) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate - } - } else { - encVal(enc,_declaredType,ptr,idx,src,_off,_scale); - } + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) X86.storeImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + else encVal(enc,_declaredType,ptr,idx,src,_off,_scale); } // Non-immediate encoding static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) { - int log = decl.log_size(); - // Float reg being stored - if( src >= x86_64_v2.XMM_OFFSET ) { - src -= (short)x86_64_v2.XMM_OFFSET; - assert log == 2 || log == 3; - enc.add1( log==2 ? 0xF3 : 0xF2 ); - x86_64_v2.rexF(src,ptr,idx,false,enc); - enc.add1(0x0F).add1(0x11); - } else { - // byte stores from sil, dil, bpl, spl need a rex - if( log == 0 && src >= x86_64_v2.RSP ) enc.add1(x86_64_v2.rex(src,ptr,idx,false)); - else x86_64_v2.rexF(src,ptr,idx,log==3,enc); - switch( log ) { - case 0: enc .add1(0x88); break; - case 1: enc.add1(0x66).add1(0x89); break; - case 2: enc .add1(0x89); break; - case 3: enc .add1(0x89); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + boolean xmm=src>=x86_64_v2.XMM_OFFSET; + X86.store(enc,decl.log_size(),xmm, + xmm ? src-x86_64_v2.XMM_OFFSET : src,ptr,idx,off,scale); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index 0a169a22..6a008551 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -12,16 +13,7 @@ public class SubFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5C /r SUBSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5C); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5C,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "subf dst -= src" diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index d7566f9e..8723af91 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -23,24 +24,9 @@ public class TFPX86 extends ConstantNode implements MachNode, RIPRelSize { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // lea to load function pointer address - // lea rax, [rip+disp32] + if( _con==Type.NIL ) { X86.constant(enc,enc.reg(this),0); return; } enc.relo(this); - enc.add1(x86_64_v2.rex(dst, 0, 0)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); - enc.add4(0); + X86.rip(enc,0,0x8D,true,enc.reg(this)); } @Override public byte encSize(int delta) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java index c44cf2f9..027b2e01 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -15,8 +16,8 @@ public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { short dst = enc.reg(this); - x86_64_v2.rexF(dst, 0, 0, true, enc); - enc.add1(0x8D).add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)).add4(0); + X86.rexF(dst, 0, 0, true, enc); + enc.add1(0x8D).add1(X86.modrm(X86.MOD.INDIRECT, dst, 0b101)).add4(0); enc.largeConstant(this,((TypeMemPtr)_con)._obj,7-4,2/*ELF encoding PC32*/); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java index 5db9e75e..d991e40a 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; @@ -18,29 +19,17 @@ public class UJmpX86 extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - // Short-form jump - enc.add1(0xEB).add1(0); - //// E9 cd JMP rel32 - //enc.add1(0xE9).add4(0); + X86.branch(enc,-1); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding - @Override public byte encSize(int delta) { return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 5); } + @Override public byte encSize(int delta) { + return X86.branchSize(delta,false); + } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert bits[opStart] == (byte)0xEB; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert bits[opStart] == (byte)0xEB; - bits[opStart] = (byte)0xE9; // Long form - delta -= 5; // Offset from opcode END - enc.patch4(opStart+1,delta); - } + X86.patchBranch(enc.bits(),opStart,opLen,delta,-1); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index f9dfe8f4..5c0d4599 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -69,13 +69,6 @@ public class x86_64_v2 extends Machine { public static int REX_WRB= 0x4D; public static int REX_WB = 0x49; - public enum MOD { - INDIRECT, // [mem] - INDIRECT_disp8, // [mem + 0x12] - INDIRECT_disp32, // [mem + 0x12345678] - DIRECT, // mem - }; - // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -95,90 +88,6 @@ public class x86_64_v2 extends Machine { }; } - public static int modrm(MOD mod, int reg, int m_r) { - if( reg == -1 ) reg=0; // Missing reg in this flavor - // combine all the bits - assert 0 <= reg && reg < 16; - assert 0 <= m_r && m_r < 16; - return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07; - } - - // 00 000 000 - // same bit-layout as modrm - public static int sib(int scale, int index, int base) { - assert 0 <= base && base < 16; - assert 0 <= index && index < 16; - return (scale << 6) | ((index & 0x07) << 3) | base & 0x07; - } - - // reg1 is reg(R) - // reg2 is r/mem(B) - // reg3 is X(index) - // reg4 is X(base) - - // 0 denotes no direct register - public static int rex(int reg, int ptr, int idx, boolean wide) { - // assuming 64 bit by default so: 0100 1000 - assert -1 <= reg && reg < 16; - assert -1 <= ptr && ptr < 16; - assert -1 <= idx && idx < 16; - - int rex = wide ? REX_W : REX; - if( 8 <= reg ) rex |= 0b00000100; // REX.R - if( 8 <= ptr ) rex |= 0b00000001; // REX.B - if( 8 <= idx ) rex |= 0b00000010; // REX.X - return rex; - } - - public static int rex(int reg, int ptr, int idx) { - return rex(reg, ptr, idx, true); - } - - // rex for floats. Return size (0 or 1) - // don't need to use REX if 0x40. - public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { - int rex = rex(reg, ptr, idx, wide); - if (rex == REX) return 0; - enc.add1(rex); - return 1; - } - // Function used for encoding indirect memory addresses - // Does not always generate SIB byte e.g index == -1. - // -1 denotes empty value, not set - note 0 is different from -1 as it can represent rax. - // Looks for best mod locally - public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { - // Assume indirect - assert 0 <= base && base < 16; - assert -1 <= index && index < 16 && index != RSP; - - MOD mod = MOD.INDIRECT; - // is 1 byte enough or need more? - if( offset != 0 ) - mod = imm8(offset) - ? MOD.INDIRECT_disp8 - : MOD.INDIRECT_disp32; - - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { - mod = MOD.INDIRECT_disp8; - } else if( index == -1 && (base == RSP || base == R12) ) { - index = RSP; - } - - if( index == -1 ) { - enc.add1(modrm(mod, reg, base)); - } else { - enc.add1(modrm(mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, index, base)); - } - - if( mod == MOD.INDIRECT_disp8 ) { - enc.add1(offset); - } else if( mod == MOD.INDIRECT_disp32 ) { - enc.add4(offset); - } - } - - // Limit of float args passed in registers static RegMask[] XMMS8 = new RegMask[]{ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3), diff --git a/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index bf809d2a..9f626805 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; import com.seaofnodes.simple.node.cpus.riscv.riscv; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java index df58f32a..926acf93 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java index 5c6dc601..2494ed2c 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import java.io.IOException; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java deleted file mode 100644 index 0a3e9196..00000000 --- a/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ /dev/null @@ -1,765 +0,0 @@ -package com.seaofnodes.simple; - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.arm.arm; -import java.io.ByteArrayOutputStream; - -public class EvalArm64 { - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - // flags - boolean N = false; - boolean Z = false; - boolean C = false; - boolean V = false; - - EvalArm64(byte[] buf, int stackSize) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[arm.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - public int step(int maxops) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for(int icount = 0; icount < maxops; icount++) { - int ir = 0; - rval = 0; - frval = 0; - cycle++; - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - - // Load instruction from image buffer at PC - ir = ld4s( pc ); - - int rdid = ir & 0x1f; - // [31:24] - int opcode1 = (ir >> 24) & 0xFF; - - // for the opcode we just match for bits[31:24]; - switch( opcode1 ) { - case 0x14, 0x15, 0x16, 0x17: { //b - int imm26 = ir << 6 >> 6; - pc = pc + (imm26 * 4) - 4; - rdid = -1; - break; - } - case 0x1E: { // floats - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - int rs2 = (ir >> 16) & 0x1F; - - int op = (ir >> 10) & 0x3F; - switch(op) { - case 16: frval = fregs[rs1]; break; // fmov - case 10:frval = fregs[rs1] + fregs[rs2]; break; // fadd - - case 6: if (fregs[rs2] == 0) frval = 0; else frval = fregs[rs1] / fregs[rs2]; break; // fdiv - case 8: { - // fcmp - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - - Z = (lhs == rhs); - N = (lhs < rhs); - C = lhs >= rhs; - V = Double.isNaN(lhs) || Double.isNaN(rhs); - rdid = -1; - - break; - } - case 2: frval = fregs[rs1] * fregs[rs2]; break; // fmul - case 14: frval = fregs[rs1] - fregs[rs2]; break; // fsub - default: trap = (2+1); - } - break; - } - - case 0x38: { - // STRB/LDRB(register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch( ir >> 21 & 0x7 ) { - case 0x1 -> { // store - if( opcode1 == arm.OP_STORE_R_8 ) st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - else trap = (2+1); - rdid = -1; - } - case 0x3 -> { // load - if( opcode1 == arm.OP_LOAD_R_8 ) rval = ld1s((int)regs[rn] + (int)regs[rm]); - else trap = (2+1); - } - default -> trap = (2+1); - } - break; - } - case 0x39: { - // STRB/LDRB(immediate) - // str/ldr(immediate) - // rn - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_8) { - st1((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_8) { - rval = ld1s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - case 0x54: { - // b.cond - int imm19 = ir << 8 >> 13; - imm19 = pc + (imm19 * 4) - 4; - rdid = -1; - - switch(ir & 0xF) { - case 0x0: if(Z) pc = imm19; break; // eq - case 0x1: if(!Z) pc = imm19; break; // ne - case 0x2: if(C) pc = imm19; break; // cs - case 0x3: if(!C) pc = imm19; break; - case 0x4: if(N) pc = imm19; break; // mi - case 0x5: if(!N) pc = imm19; break; // pl - case 0x6: if(V) pc = imm19; break; // vs - case 0x7: if(!V) pc = imm19; break; // vc - case 0x8: if(C && !Z) pc = imm19; break; // hi - case 0x9: if(!C || Z) pc = imm19; break; // ls - case 0xA: if(N == V) pc = imm19; break; // ge - case 0xB: if(N != V) pc = imm19; break; // lt - case 0xC: if(!Z && N == V) pc = imm19; break; // gt - case 0xD: if(Z || N != V) pc = imm19; break; // le - case 0xE: pc = imm19; break; // always executed(al) - default: trap = (2+1); - } - break; - } - - case 0x5c: { - // ldr - is_f = true; - // address = delta - int address = ir << 8 >> 13; - address *= 4; - if(address >= _buf.length-3) trap = (5 + 1); - frval = ld8f(pc + address); - break; - } - - case 0x78: { - // STRH/LDRH(register) - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - // store - if(opcode1 == arm.OP_STORE_R_16) { - st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_16) { - rval = ld1s((int)regs[rn] + (int)regs[rm]); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - break; - } - - case 0x79: { - // STRH/LDRH(immediate) - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 2; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_16) { - st2((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_16) { - rval = ld2s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - - case 0x8A: { // AND - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] & regs[rm]; - break; - } - - case 0x8B, 0xCB: { - // add/sub(register), unshifted form emitted by Simple - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = opcode1==0x8B ? lhs + rhs : lhs - rhs; - break; - } - - case 0x90: { // adrp - int immhi = ( (ir& ~0x1F) << 8 ) >> 8; - int immlo = (ir>>29)& 3; - int imm = ((immhi<<2) | immlo) << 12; - rval = (pc & ~0xFFF) + imm; - break; - } - - case 0x91, 0xD1: { // ADD/SUB (immediate), unsigned imm12, optional LSL #12 - int rn = (ir >> 5) & 0x1F; - long immediate = (ir >>> 10) & 0xFFF; - if( (ir & (1<<22))!=0 ) immediate <<= 12; - rval = opcode1==0x91 ? regs[rn] + immediate : regs[rn] - immediate; - break; - } - case 0x92: { // and(immediate) - int imm12 = (ir >> 10) & 0x1FFF; - long immediate = arm.decodeImm12(imm12); - int rn = (ir >> 5) & 0x1F; - rval = regs[rn] & immediate; - break; - } - case 0x93, 0xD3: { // SBFM/UBFM: shifts and signed/unsigned extracts - int immr = (ir >>> 16) & 63; - int imms = (ir >>> 10) & 63; - int rn = (ir >>> 5) & 31; - boolean signed = (ir & 0x40000000)==0; - long value = regs[rn] << (63-imms); - value = signed ? value >> (63-imms) : value >>> (63-imms); - rval = immr > imms ? value << (64-immr) - : signed ? value >> immr : value >>> immr; - break; - } - - case 0x94, 0x95, 0x96, 0x97: { // bl - rdid = -1; // BL writes only X30, not a displacement-selected register. - rval = pc + 4; - regs[arm.X30] = rval; - int imm26 = (ir & 0x03FFFFFF); - int imm = (imm26 << 6) >> 6; - pc = pc + (imm << 2) ; - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - long size = regs[arm.X0]*regs[arm.X1]; - size = (size+7) & -8; // 8-byte aligned - regs[arm.X0] = _heap; - _heap += (int)size; - pc = (int)rval; - rdid = -1; - } - if( pc == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[0]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[1],(int)regs[2]); - regs[0] = regs[2]; - pc = (int)rval; - rdid = -1; - } - pc -= 4; - break; - } - - case 0x9A: { - // conditional select(csel) - int rm = (ir >> 16) & 0x1F; - switch((ir >> 12) & 0xF) { - case 0x0: if(Z) rval = regs[rm]; break; // eq - case 0x1: if(!Z) rval = regs[rm]; break; // ne - case 0x2: if(C) rval = regs[rm]; break; // cs - case 0x3: if(!C) rval = regs[rm]; break; - case 0x4: if(N) rval = regs[rm]; break; // mi - case 0x5: if(!N) rval = regs[rm]; break; // pl - case 0x6: if(V) rval = regs[rm]; break; // vs - case 0x7: if(!V) rval = regs[rm]; break; // vc - case 0x8: if(C && !Z) rval = regs[rm]; break; // hi - case 0x9: if(!C || Z) rval = regs[rm]; break; // ls - case 0xA: if(N == V) rval = regs[rm]; break; // ge - case 0xB: if(N != V) rval = regs[rm]; break; // lt - case 0xC: if(!Z && N == V) rval = regs[rm]; break; // gt - case 0xD: if(Z || N != V) rval = regs[rm]; break; // le - case 0xE: rval = regs[rm]; break; // always executed(al) - default: rval = regs[(ir >> 5) & 0x1F]; - } - break; - } - case 0x9B: { // mul - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] * regs[rm]; - break; - } - case 0x9E: { - // scvtf - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - frval = (double)regs[rs1]; - break; - } - - case 0xAA: { - // MOV(register) - int rm = (ir >> 16) & 0x1F; - rval = regs[rm]; - break; - } - - case 0xB8: { - // LDR/STR (register + index) 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if( opcode1 == arm.OP_LOAD_R_32) { - rval = ld4s((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xB9: { - // str/ldr(immediate) 32 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 4; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_32) { - rval = ld4s((int) rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xBC: { - // LDR/STR (register + index) float 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_32) { - frval = ld4f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xBD: { - // LDR/STR(immediate) 32 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 4; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xD2: // MOVZ - case 0xF2: { // MOVK preserves the other halfwords - // movz - // get immediate - int shift = ((ir >> 21) & 3)*16; - rval = ((ir >> 5) & 0xFFFFL) << shift; - if( opcode1==0xF2 ) rval |= regs[rdid] & ~(0xFFFFL << shift); - break; - } - - case 0xEB: { - // subs(shifted register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = lhs - rhs; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= rhs; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (rhs >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - - case 0xD6: { - int op = ir & 0xFFFFFC1F; - int rn = (ir >>> 5) & 31; - int target = (int)regs[rn]; // Read before BLR overwrites X30. - rdid = -1; - if( op==0xD63F0000 ) regs[arm.X30] = pc+4; // BLR - else if( op!=0xD65F0000 ) { trap = 3; break; } // RET - pc = target; - if( op==0xD65F0000 && pc==0 ) break outer; - pc -= 4; - break; - } - - case 0xF1: { - // subs(immediate) - int rn = (ir >> 5) & 0x1F; - int immediate = ir << 10 >> 20; - long lhs = regs[rn]; - - rval = lhs - immediate; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= immediate; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (immediate >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - case 0xF8: { - // LDR/STR (register + index) 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_64) { - rval = ld8((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xF9: { - // str/ldr(immediate) 64 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_64) { - st8((int)rval, regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_64) { - rval = ld8((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xFC: { - // LDR/STR (register + index) float 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_64) { - frval = ld8f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xFD: { - // LDR/STR(immediate) 64 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - default: trap = (2+1); - } - - if(trap != 0) { - _pc = pc; - break; - } - if(rdid != -1) { - if(is_f) {fregs[rdid] = frval; is_f = false;} - else regs[rdid] = rval; - } - - pc += 4; - } - // Handle traps and interrupts. - if(trap != 0) { - return trap; - } - _cycle = cycle; - _pc = pc; - return 0; - } - - -} diff --git a/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java deleted file mode 100644 index 00711f4e..00000000 --- a/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ /dev/null @@ -1,367 +0,0 @@ - package com.seaofnodes.simple; - -/** Simple RISC5 CPU Emulator - * - * Original works credit Charles Lohr. - * This is a complete rewrite in Java. - * - * Load code into memory and go! - */ - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.riscv.riscv; -import java.io.ByteArrayOutputStream; -import java.util.Arrays; - -public class EvalRisc5 { - - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - // PC - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - EvalRisc5( byte[] buf, int stackSize ) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[riscv.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) {st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - // Note: only a few bits are used. (Machine = 3, User = 0) - // Bits 0..1 = privilege. - // Bit 2 = WFI (Wait for interrupt) - // Bit 3+ = Load/Store reservation LSBs. - int _extraflags; - - public int step( int maxops ) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for( int icount = 0; icount < maxops; icount++ ) { - int ir = 0; - rval = 0; - cycle++; - - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - // Load instruction from image buffer at PC - ir = ld4s( pc ); - int rdid = (ir >> 7) & 0x1f; - - switch( ir & 0x7f ) { - case 0x37: // LUI (0b0110111) - rval = ( ir & 0xfffff000 ); - break; - case 0x17: // AUIPC (0b0010111) - rval = pc + ( ir & 0xfffff000 ); - break; - case 0x6F: { // JAL (0b1101111) - int reladdy = ((ir & 0x80000000)>>11) | ((ir & 0x7fe00000)>>20) | ((ir & 0x00100000)>>9) | ((ir&0x000ff000)); - if( (reladdy & 0x00100000)!=0 ) reladdy |= 0xffe00000; // Sign extension. - rval = pc + 4; - pc = pc + reladdy - 4; - if( pc+4 == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[10]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[11],(int)regs[12]); - regs[10] = regs[12]; - rdid = 0; - pc = (int)(rval - 4); // Unwind PC, as-if returned from write - } - break; - } - case 0x67: { // JALR (0b1100111) - int imm_se = ir >> 20; // Sign extend 12 bits - rval = pc + 4; - pc = ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1; - // Return from top-level ; exit sim - if( pc==0 ) { - if( rdid!=0 ) regs[rdid] = rval; // Write PC into register before exit - break outer; - } - // Inline CALLOC effect - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - int size = (int)(regs[10]*regs[11]); - size = (size+7) & -8; // 8-byte aligned - regs[10] = _heap; // Return next free address - _heap += size; - pc = (int)(rval - 4); // Unwind PC, as-if returned from calloc - } else - pc -= 4; - break; - } - case 0x63: { // Branch (0b1100011) - int immm4 = ((ir & 0xf00)>>7) | ((ir & 0x7e000000)>>20) | ((ir & 0x80) << 4) | ((ir >> 31)<<12); - if( (immm4 & 0x1000)!=0 ) immm4 |= 0xffffe000; - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - immm4 = pc + immm4 - 4; - rdid = 0; - if( switch( (ir >> 12) & 0x7 ) { - case 0 -> rs1 == rs2; - case 1 -> rs1 != rs2; - case 4 -> rs1 < rs2; - case 5 -> rs1 >= rs2; - case 6 -> Long.compareUnsigned(rs1,rs2) < 0; //BLTU - case 7 -> Long.compareUnsigned(rs1,rs2) >= 0; //BGEU - default -> { trap = (2+1); yield false; } - } ) pc = immm4; - break; - } - case 0x03: { // Load (0b0000011) - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - //LB, LH, LW, LBU, LHU - case 0: rval = ld1s( rsval ); break; - case 1: rval = ld2s( rsval ); break; - case 2: rval = ld4s( rsval ); break; - case 3: rval = ld8 ( rsval ); break; - case 4: rval = ld1z( rsval ); break; - case 5: rval = ld2z( rsval ); break; - case 6: rval = ld4s( rsval ); break; - default: trap = (2+1); - } - } - break; - } - // floats - case 0x7: { - is_f = true; - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - case 2: frval = ld4f( rsval ); break; - case 3: frval = ld8f( rsval ); break; - default: trap = (2+1); - } - } - break; - } - - case 0x23: { // Store 0b0100011 - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - long rs2 = regs[(ir >> 20) & 0x1f]; - int addy = ( ( ir >> 7 ) & 0x1f ) | ( ( ir & 0xfe000000 ) >> 20 ); - if( (addy & 0x800)!=0 ) addy |= 0xfffff000; - addy += rs1; - rdid = 0; - if( addy >= _buf.length-3 ) { - trap = (7+1); // Store access fault. - rval = addy; - } else { - switch( ( ir >> 12 ) & 0x7 ) { //SB, SH, SW - case 0: st1( addy, (int)rs2 ); break; - case 1: st2( addy, (int)rs2 ); break; - case 2: st4( addy, (int)rs2 ); break; - case 3: st8( addy, rs2 ); break; - default: trap = (2+1); - } - } - break; - } - case 0x13: // Op-immediate 0b0010011 - case 0x33: { // Op 0b0110011 - int imm = ir >> 20; - imm = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); - long rs1 = regs[(ir >> 15) & 0x1f]; - boolean is_reg = (ir & 0x20)!=0; - long rs2 = is_reg ? regs[imm & 0x1f] : imm; - - // Insert the detection here - int rs1id = (ir >> 15) & 0x1f; - int funct3 = (ir >> 12) & 0x7; - - if( is_reg && ( ir & 0x02000000 )!=0 ) { - switch( (ir>>12)&7 ) { //0x02000000 = RV32M - case 0: rval = rs1 * rs2; break; // MUL - case 1: rval = (int)((long)((int)rs1) * (long)((int)rs2)) >> 32; break; // MULH - case 2: rval = (int)((long)((int)rs1) * (long)rs2) >> 32; break; // MULHSU - case 3: rval = (int)((long)rs1 * (long)rs2) >> 32; break; // MULHU - case 4: if( rs2 == 0 ) rval = -1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? rs1 : ((int)rs1 / (int)rs2); break; // DIV - case 5: if( rs2 == 0 ) rval = 0xffffffff; else rval = rs1 / rs2; break; // DIVU - case 6: if( rs2 == 0 ) rval = rs1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? 0 : ((int)((int)rs1 % (int)rs2)); break; // REM - case 7: if( rs2 == 0 ) rval = rs1; else rval = rs1 % rs2; break; // REMU - } - } else { - rval = switch( (ir >> 12) & 7 ) { // These could be either op-immediate or op commands. Be careful. - case 0 -> (is_reg && (ir & 0x40000000) != 0) ? (rs1 - rs2) : (rs1 + rs2); - case 1 -> rs1 << (rs2 & 0x3F); - case 2 -> (rs1 < rs2) ? 1 : 0; - case 3 -> (rs1 < rs2) ? 1 : 0; - case 4 -> rs1 ^ rs2; - case 5 -> (ir & 0x40000000) != 0 ? (rs1 >> (rs2 & 0x3F)) : (rs1 >>> (rs2 & 0x3F)); - case 6 -> rs1 | rs2; - case 7 -> rs1 & rs2; - default -> rval; - }; - } - break; - } - case 0x0f: // 0b0001111 - rdid = 0; // fencetype = (ir >> 12) & 0b111; We ignore fences in this impl. - break; - case 0x73: // Zifencei+Zicsr (0b1110011) - trap = (2+1); // Note micrrop 0b100 == undefined. - break; - - case 0x2f: { // RV32A (0b00101111) - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - int irmid = ( ir>>27 ) & 0x1f; - - // We don't implement load/store from UART or CLNT with RV32A here. - if( rs1 >= _buf.length-3 ) { - trap = (7+1); //Store/AMO access fault - rval = rs1; - } else { - rval = ld4s( (int)rs1 ); - - // Referenced a little bit of https://github.com/franzflasch/riscv_em/blob/master/src/core/core.c - boolean dowrite = true; - switch( irmid ) { - case 2: //LR.W (0b00010) - dowrite = false; - _extraflags = (_extraflags & 0x07) | (int)(rs1<<3); - break; - case 3: { //SC.W (0b00011) (Make sure we have a slot, and, it's valid) - boolean xflag = _extraflags >> 3 != ( rs1 & 0x1fffffff ); - rval = xflag ? 1 : 0; // Validate that our reservation slot is OK. - dowrite = !xflag; // Only write if slot is valid. - break; - } - case 0: rs2 += rval; break; // AMOADD.W (0b00000) - case 1: break; // AMOSWAP.W (0b00001) - case 4: rs2 ^= rval; break; // AMOXOR.W (0b00100) - case 8: rs2 |= rval; break; // AMOOR.W (0b01000) - case 12: rs2 &= rval; break; // AMOAND.W (0b01100) - case 16: rs2 = Math.min( rs2, rval ); break; //AMOMIN.W (0b10000) - case 20: rs2 = Math.max( rs2, rval ); break; //AMOMAX.W (0b10100) - case 24: rs2 = Math.min( rs2, rval ); break; //AMOMINU.W (0b11000) - case 28: rs2 = Math.max( rs2, rval ); break; //AMOMAXU.W (0b11100) - default: trap = (2+1); dowrite = false; break; //Not supported. - } - if( dowrite ) st4( (int)rs1, (int)rs2 ); - } - break; - } - - case 0x53: { - is_f = true; - int rs1 = (ir >> 15) & 0x1F; - int rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - int func5 = (ir >> 27) & 0x1F; - int func2 = (ir >> 25) & 0x3; - if( func2 != 1 ) throw Utils.TODO(); // 1==double - switch( func5 ) { - case 0: frval = lhs + rhs; break; // fadd.d - case 1: frval = lhs - rhs; break; // fsub.d - case 2: frval = lhs * rhs; break; // fmul.d - case 3: frval = lhs / rhs; break; // fdiv.d - case 5: frval = Math.min(lhs,rhs); break; // fmin.d, also used for move - case 20: - is_f = false; // Output into a GPR - rval = switch( (ir >> 12) & 7 ) { - case 0 -> lhs <= rhs ? 1 : 0; - case 1 -> lhs == rhs ? 1 : 0; - case 2 -> lhs < rhs ? 1 : 0; - default -> throw Utils.TODO(); - }; - break; - case 26: frval = (double)regs[rs1]; break; // fcvt.w.d - default: - trap = (2+1); // Fault: Invalid opcode. - throw Utils.TODO(); - } - break; - } - - default: trap = (2+1); // Fault: Invalid opcode. - } - - // If there was a trap, do NOT allow register writeback. - if( trap!=0 ) { - _pc = pc; - break; - } - - if( rdid!=0 || is_f) { - if(is_f) {fregs[rdid] = frval; is_f = false;} // Write back register. - else regs[rdid] = rval; // Write back register. - } - - pc += 4; - } - - // Handle traps and interrupts. - if( trap!=0 ) - return trap; - - _cycle = cycle; - _pc = pc; - return 0; - } -} diff --git a/chapter22/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java b/chapter22/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java index 1717fbcd..f20fe6f5 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.RegAllocTestSupport; import com.seaofnodes.simple.node.*; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter22/src/test/java/com/seaofnodes/simple/MergeSortTest.java index 82b1e58e..788bd9c2 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.riscv.riscv; import java.io.IOException; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java index edce92f3..a22063eb 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java index adb256eb..ace2a7ea 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.FunNode; diff --git a/chapter23/Makefile b/chapter23/Makefile index 9725bc7d..8fa5a13a 100644 --- a/chapter23/Makefile +++ b/chapter23/Makefile @@ -66,6 +66,7 @@ test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java) main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas)) include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk)) include $(firstword $(wildcard ../print/print.mk print/print.mk)) +include $(firstword $(wildcard ../isa/isa.mk isa/isa.mk)) test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas)) test_cp := $(patsubst $(TST)/$(SIMPLE)/%.java,com.seaofnodes.simple.%,$(wildcard $(TST)/$(SIMPLE)/*Test.java)) com.seaofnodes.simple.codegen.X86EncodingTest classes = $(main_classes) $(test_classes) @@ -108,8 +109,8 @@ $(main_classes): $(CLZDIR)/main/.mtag ####################################################### -OODT := -$(CLZDIR)/test/.ttag: $(test_classes) $(test_javas) $(CLZDIR)/main/.mtag +OODT := $(isa_test_javas) +$(CLZDIR)/test/.ttag: $(test_classes) $(test_javas) $(isa_test_javas) $(CLZDIR)/main/.mtag @[ -d $(CLZDIR)/test ] || mkdir -p $(CLZDIR)/test $(file >.argsT.txt,$(OODT)) @if [ ! -z "$(OODT)" ] ; then \ diff --git a/chapter23/pom.xml b/chapter23/pom.xml index e3547147..7347f9e2 100644 --- a/chapter23/pom.xml +++ b/chapter23/pom.xml @@ -15,4 +15,32 @@ <simple.graph.directory>${project.basedir}/../graph</simple.graph.directory> <simple.print.directory>${project.basedir}/../print</simple.print.directory> </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>shared-isa-sources</id> + <phase>generate-sources</phase> + <goals><goal>add-source</goal></goals> + <configuration> + <sources> + <source>${project.basedir}/../isa/src/main/java</source> + </sources> + </configuration> + </execution> + <execution> + <id>shared-isa-test-sources</id> + <phase>generate-test-sources</phase> + <goals><goal>add-test-source</goal></goals> + <configuration><sources> + <source>${project.basedir}/../isa/src/test-support/java</source> + </sources></configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/chapter23/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter23/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 6a16d56b..5099c02a 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -19,7 +19,7 @@ import java.util.*; * There are also a bunch of generic utilities for managing bits and bytes * common in all encodings. */ -public class Encoding { +public class Encoding implements com.seaofnodes.isa.CodeSink { // Top-level program graph structure public final CodeGen _code; diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index 1c865254..76e47ca2 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // ADD (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_ADD); } // General form: "rd = rs1 + rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index eb75c1a0..67a10b48 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } //FADD (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);} + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_OP_ADD);} // Default on double precision for now(64 bits) // General form: "addf rd = src1 + src2 diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index 93c9e8c3..4c635d07 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class AddIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } //ADD (immediate) @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_ADD,_imm); } // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index 77115d54..1a0365ad 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -13,7 +14,7 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // AND (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_AND); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_AND); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb){ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java index 5b739cd3..6292e98e 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,10 +16,10 @@ public class AndIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc,this, in(1), arm.OPI_AND,_imm); + arm.imm_inst_n(enc,this, in(1), Arm64.OPI_AND,_imm); } // General form: "andi rd = rs1 & imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm)); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(Arm64.decodeImm12(_imm)); } }
\ No newline at end of file diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index b83fb3cb..77f14d4c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sar"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_ASR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_ASR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> ").p(code.reg(in(2))); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java index 38373e67..7cb42eec 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,7 +23,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_ASR,_imm, 0b111111, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_ASR,_imm, 0b111111, rn, rd)); } // General form: "asri rd = rs1 >> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index b9ede544..127f17ff 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -35,10 +36,10 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // by comparison (or sub). No need for regs because it uses flags if( in(1)!=null ) { // B.cond - enc.add4( arm.b_cond(arm.OP_BRANCH, 0, arm.make_condition(_bop)) ); + enc.add4( Arm64.b_cond(Arm64.OP_BRANCH, 0, Arm64.make_condition(_bop)) ); } else { if( _bop=="!=" ) return; // Inverted, no code - enc.add4(arm.b(arm.OP_UJMP, 0)); + enc.add4(Arm64.b(Arm64.OP_UJMP, 0)); } enc.jump(this,cproj(0)); } @@ -55,7 +56,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( opLen==4 ) { - enc.patch4(opStart,arm.b_cond(arm.OP_BRANCH, delta, arm.make_condition(_bop))); + enc.patch4(opStart,Arm64.b_cond(Arm64.OP_BRANCH, delta, Arm64.make_condition(_bop))); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 427cf2e2..e1717cb3 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -30,7 +31,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); // BL - enc.add4(arm.b(arm.OP_CALL,0)); // Target patched at link time + enc.add4(Arm64.b(Arm64.OP_CALL,0)); // Target patched at link time } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -38,7 +39,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - enc.patch4(opStart,arm.b(arm.OP_CALL,delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_CALL,delta)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index c84aa9e5..1949ae46 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class CallRRARM extends CallNode implements MachNode { // Needs a register, typically a jump-and-link-register opcode // blr short self = enc.reg(this); - enc.add4(arm.blr(arm.OP_CALLRARM, self)); + enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index 794ff0c9..1bd9c372 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.FLAGS_MASK; } // SUBS (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,arm.OP_CMP); } + @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,Arm64.OP_CMP); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java index f84a1649..cd4dd9cf 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -28,7 +29,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public Node copy() { return new CmpIARM(this); } - @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), arm.OPI_CMP,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), Arm64.OPI_CMP,_imm); } // General form: "cmp rs1, 1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index de254eeb..e94b6491 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // SDIV - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_DIV,3); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_DIV,3); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 813bebe4..68ad6047 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } // FDIV (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_DIV); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_DIV); } // General form: "VDIF = dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java index 26a237d0..814a82c2 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,7 +23,7 @@ public class ExtendARM extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); // SBFM/UBFM aliases: sign/zero extend the low byte, short or int. - enc.add4(arm.imm_shift(_signed ? arm.OPI_ASR : arm.OPI_LSR,0,_bits-1,src,dst)); + enc.add4(Arm64.imm_shift(_signed ? Arm64.OPI_ASR : Arm64.OPI_LSR,0,_bits-1,src,dst)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java index b47b65ad..dc21e075 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -20,7 +21,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/); short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.add4(arm.load_pc(arm.OPF_ARM, 0, dst)); + enc.add4(Arm64.load_pc(Arm64.OPF_ARM, 0, dst)); } // Delta is from opcode start. @@ -29,7 +30,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.patch4(opStart, arm.load_pc(arm.OPF_ARM, delta, dst)); + enc.patch4(opStart, Arm64.load_pc(Arm64.OPF_ARM, delta, dst)); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java index b9e85202..17cafcde 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -16,6 +17,6 @@ public class FunARM extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(arm.imm_inst(arm.OPI_SUB, sz, arm.RSP, arm.RSP)); + enc.add4(Arm64.imm_inst(Arm64.OPI_SUB, sz, arm.RSP, arm.RSP)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index f1fa162f..b1c30afc 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,7 +14,7 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(arm.OP_FLOAT_C, 1, reg1, self); + int body = Arm64.float_cast(Arm64.OP_FLOAT_C, 1, reg1, self); enc.add4(body); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index ee74b95e..7a9e74c6 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,39 +22,7 @@ public class IntARM extends ConstantNode implements MachNode { @Override public void encoding( Encoding enc ) { short self = enc.reg(this); long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); - int nb0 = 0; - int nb1 = 0; - // Count number of 0000 and FFFF blocks - for (int i=0; i<64; i+=16) { - int block = (int)(x >> i) & 0xFFFF; - if (block == 0) nb0++; - if (block == 0xFFFF) nb1++; - } - int pattern; - int op; - if(nb0 >= nb1) { - // More 0 blocks then F blocks, use movz - pattern = 0; - op = arm.OP_MOVZ; - } else { - // More F blocks then 0 blocks, use movn - pattern = 0xFFFF; - op = arm.OP_MOVN; - } - int invert = pattern; - for (int i=0; i<4; i++) { - int block = (int)x & 0xFFFF; - x >>= 16; - if (block != pattern) { - enc.add4(arm.mov(op, i, block ^ invert, self)); - op = arm.OP_MOVK; - invert = 0; - } - } - if (op != arm.OP_MOVK) { - // All blocks are the same, special case - enc.add4(arm.mov(op, 0, 0, self)); - } + Arm64.constant(enc,self,x); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 8967d654..f3bbbbeb 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -18,9 +19,9 @@ public class LoadARM extends MemOpARM { @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } - private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; + private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, }; - private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; + private static final int[] OP_LOAD_RS = new int[]{ Arm64.OP_LOAD_R_8 , Arm64.OP_LOAD_R_16 , Arm64.OP_LOAD_R_32 , Arm64.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index 80ce493f..954cfac2 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSL); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSL); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << ").p(code.reg(in(2))); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java index 7fe16cbe..b32153ab 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -24,7 +25,7 @@ public class LslIARM extends MachConcreteNode implements MachNode { assert _imm > 0; // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) // immr must be (-<shift> MOD 64) = 64 - shift - enc.add4(arm.imm_shift(arm.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); } // General form: "lsli rd = rs1 << imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index fc005e04..91be34e3 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> ").p(code.reg(in(2))); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java index 78844b0a..243ce968 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_LSR,_imm, 0b111111, rn,rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSR,_imm, 0b111111, rn,rd)); } // General form: "lsri rd = rs1 >>> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index 9257f25b..dfbe5e06 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -64,8 +65,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { val -= arm.D0; } int body = off() == null - ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) - : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? Arm64.load_str_imm(opcode_imm, _off, ptr, val, size) + : Arm64.indr_adr(opcode_reg, off, Arm64.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index a23ec75b..f598cefb 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_MUL,31); } // General form: "rd = rs1 * rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 73ebbf00..a4f81fd4 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class MulFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_MUL); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_MUL); } // Default on double precision for now(64 bits) // General form: "VMUL.f32 rd = src1 * src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index c1aad15f..7110df62 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,8 +12,8 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { // BL(branch with link) enc.external(this,"calloc"). - add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1 - add4(arm.b(arm.OP_CALL, 0)); + add4(Arm64.mov(Arm64.OP_MOVZ, 0, 1, 0)). // movz x0,#1 + add4(Arm64.b(Arm64.OP_CALL, 0)); } // Patch is for running "new" in a JIT. @@ -24,7 +25,7 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void patch(Encoding enc, int opStart, int opLen, int delta ) { // Negative patches are JIT emulator targets. if( opStart+delta < 0 ) { - enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4)); + enc.patch4(opStart+4, Arm64.b_calloc(Arm64.OP_CALL, delta-4)); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index 027a8128..8cf72aaf 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -17,9 +18,9 @@ public class NotARM extends MachConcreteNode implements MachNode{ // subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int subs = arm.imm_inst(arm.OP_SUBS, 0, reg1, self); + int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(arm.OP_CSET, 31, arm.COND.EQ, 63, reg1); + int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 63, reg1); enc.add4(cset); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index e8245749..5b7264ec 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class OrARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "|"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_OR); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" | ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index a48caa51..86d07bee 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,7 +16,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm); + arm.imm_inst_n(enc, this, in(1), Arm64.OPI_OR, _imm); } // General form: "ori rd = rs1 | imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 4597666b..a7ed5073 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class RetARM extends ReturnNode implements MachNode { @Override public void encoding( Encoding enc ) { int frameAdjust = ((FunARM)fun())._frameAdjust; if( frameAdjust > 0 ) - enc.add4(arm.imm_inst(arm.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); - enc.add4(arm.ret(arm.OP_RET)); + enc.add4(Arm64.imm_inst(Arm64.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); + enc.add4(Arm64.ret(Arm64.OP_RET)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index 01b46b8d..1cda4787 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -20,7 +21,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop), 0b011111, enc.reg(this)); + int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index 5af45892..f93f0f24 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -26,7 +27,7 @@ public class SplitARM extends SplitNode { } int off = enc._fun.computeStackOffset(enc._code,dst); if( srcX ) src -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_STORE_IMM_64, off, arm.RSP, src, 8)); return; } @@ -34,26 +35,26 @@ public class SplitARM extends SplitNode { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); if( dstX ) dst -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); return; } // pick opcode based on regs if(!dstX && !srcX) { // GPR->GPR - enc.add4(arm.mov_reg(arm.OP_MOV, src, dst)); + enc.add4(Arm64.mov_reg(Arm64.OP_MOV, src, dst)); } else if(dstX && srcX) { // FPR->FPR // fmov reg - enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_reg(Arm64.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); } else if(!srcX && dstX) { // GPR->FPR // FMOV(general) 64 bits to DOUBLE-PRECISION - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); } else if( srcX && !dstX) { //FPF->GPR // FMOV(general) DOUBLE-PRECISION to 64 bits - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 4fd8ac79..2cc54f76 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.StoreNode; @@ -22,9 +23,9 @@ public class StoreARM extends MemOpARM { @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; + private static final int[] OP_STORES = new int[]{ Arm64.OP_STORE_IMM_8, Arm64.OP_STORE_IMM_16, Arm64.OP_STORE_IMM_32, Arm64.OP_STORE_IMM_64, }; - private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; + private static final int[] OP_STORE_RS = new int[]{ Arm64.OP_STORE_R_8, Arm64.OP_STORE_R_16, Arm64.OP_STORE_R_32, Arm64.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[_declaredType.log_size()], val(), size()); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index e3b95e50..fd5cd4de 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_SUB); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index a252e542..1a751434 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class SubFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_SUB); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_SUB); } // Default on double precision for now(64 bits) // General form: "vsub.f32 rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index b50107c9..b2c0b2ed 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -18,7 +19,7 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_SUB,_imm); } // General form: "subi rd = rs1 - imm" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 29d490ef..98a56089 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -19,10 +20,10 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { enc.relo(this); short self = enc.reg(this); // adrp x0, 0 - int adrp = arm.adrp(1,0, arm.OP_ADRP, 0,self); + int adrp = Arm64.adrp(1,0, Arm64.OP_ADRP, 0,self); // add x0, x0, 0 enc.add4(adrp); - arm.imm_inst(enc,arm.OPI_ADD,0, 0); + arm.imm_inst(enc,Arm64.OPI_ADD,0, 0); } @Override public byte encSize(int delta) { @@ -39,9 +40,9 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { delta = target-base; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); // low 12 bits via add - enc.patch4(opStart+4, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, rpc)); + enc.patch4(opStart+4, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, rpc)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java index cdcaa433..d1cafa96 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -19,9 +20,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { @@ -38,9 +39,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { delta = target-base; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, dst)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, dst)); // low 12 bits via add - enc.patch4(opStart+4, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, dst)); + enc.patch4(opStart+4, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, dst)); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java index ce4f523c..aecd02bb 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,7 +20,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - int body = arm.b(arm.OP_UJMP, 0); + int body = Arm64.b(Arm64.OP_UJMP, 0); enc.add4(body); } @@ -33,7 +34,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,arm.b(arm.OP_UJMP, delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_UJMP, delta)); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index 52bda021..d56397a3 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class XorARM extends MachConcreteNode implements MachNode{ @Override public String glabel() { return "^"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_XOR); } // General form: "rd = x1 ^ x2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ ").p(code.reg(in(2))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java index 23b29644..12143ccd 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -19,7 +20,7 @@ public class XorIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // General form: "xori rd = rs1 ^ imm" - @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), Arm64.OPI_XOR,_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index c39c5f74..e7119608 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; +import static com.seaofnodes.isa.Arm64.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -81,102 +83,6 @@ public class arm extends Machine { static final RegMask D6_MASK = new RegMask(D6); static final RegMask D7_MASK = new RegMask(D7); - // major opcode: OP - public static int OP_ADD = 0b10_001_011; - public static int OPF_ADD = 0b00_011_110; - public static int OPF_OP_ADD = 0b00_101_0; - public static int OPI_ADD = 0b10_010_00100; - - public static int OPI_SUB = 0b11_010_00100; - public static int OP_UJMP = 0b000101; - - public static int OP_ADRP = 0b10000; - - public static int OP_ASR = 0b1010; - public static int OPI_ASR = 0b10_0100_1101; - - public static int OP_LSL = 0b1000; - public static int OPI_LSL =0b1101001101; - - public static int OP_LSR = 0b1001; - public static int OPI_LSR = 0b1101001101; - - public static int OP_BRANCH = 0b01_0101_00; - public static int OP_CALL = 0b10_010_1; - - public static int OP_CALLRARM = 0b1101011000111111000000; - - public static int OP_SUBS = 0b1111000100; - public static int OP_CSET = 0b10011010100; - public static int OP_CMP = 0b11101011; - public static int OPI_CMP = 0b1111000100; - - public static int OP_DIV = 0b10011010110; - public static int OPF_DIV = 0b000110; - - public static int OP_MUL = 0b10011011000; - public static int OPF_MUL = 0b10; - - public static int OPF_ARM = 0b01011100; - - public static int OP_FLOAT_C = 0b10011110; - - public static int OP_XOR = 0b11001010; - public static int OPI_XOR = 0b110100100; - - public static int OP_AND = 0b10_0010_10; - public static int OPI_AND = 0b10_0100_100; - - public static int OP_OR = 0b10101010; - public static int OPI_OR = 0b101100100; - - public static int OP_SUB = 0b11001011; - public static int OPF_SUB = 0b1110; - - public static int OP_MOVK = 0b111100101; - public static int OP_MOVN = 0b100100101; - public static int OP_MOVZ = 0b110100101; - - public static int OP_RET = 0b1101011001011111000000; - // Store/load opcodes - public static int OP_LOAD_R_64 = 0b11111000011; - public static int OP_LOAD_R_32 = 0b10111000011; - public static int OP_LOAD_R_16 = 0b01111000010; - public static int OP_LOAD_R_8 = 0b00111000011; - - public static int OP_LOAD_IMM_64 = 0b1111100101; - public static int OP_LOAD_IMM_32 = 0b1011100101; - public static int OP_LOAD_IMM_16 = 0b0111100101; - public static int OP_LOAD_IMM_8 = 0b0011100101; - - // load - public static int OPF_LOAD_R_64 = 0b11111100011; - public static int OPF_LOAD_R_32 = 0b10111100011; - - public static int OPF_LOAD_IMM_64 = 0b1111110101; - public static int OPF_LOAD_IMM_32 = 0b1011110101; - - public static int OP_STORE_R_64 = 0b11111000001; - public static int OP_STORE_R_32 = 0b10111000001; - public static int OP_STORE_R_16 = 0b01111000001; - public static int OP_STORE_R_8 = 0b00111000001; - - public static int OP_STORE_IMM_64 = 0b1111100100; - public static int OP_STORE_IMM_32 = 0b1011100100; - public static int OP_STORE_IMM_16 = 0b0111100100; - public static int OP_STORE_IMM_8 = 0b0011100100; - - public static int OPF_STORE_R_64 = 0b11111100001; - public static int OPF_STORE_R_32 = 0b10111100001; - - public static int OPF_STORE_IMM_32 = 0b1011110100; - public static int OPF_STORE_IMM_64 = 0b1111110100; - - - public static int OP_FMOV = 0b10011110; - public static int OP_FMOV_REG = 0b00011110; - // https://docsmirror.github.io/A64/2023-06/mov_orr_log_shift.html - public static int OP_MOV = 0b10101010000; // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 @@ -202,54 +108,6 @@ public class arm extends Machine { }; // ARM ENCODING - public enum OPTION { - UXTB, - UXTH, - UXTX, - SXTB, - SXTH, - SXTW, - SXTX, - } - - static public int cset(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 15) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - static public int cset(int opcode, COND cond, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - public enum STORE_LOAD_OPTION { - UXTW, // base+ u32 index [<< logsize] - UXTX, // base+ u64 index [<< logsize] - SXTW, // base+ s32 index [<< logsize] - SXTX, // base+ s64 index [<< logsize] - } - - public enum COND { - EQ, - NE, - CS, - CC, - MI, - PL, - VS, - VC, - HI, - LS, - GE, - LT, - GT, - LE, - AL, - NV - } // True if signed 9-bit immediate private static boolean imm9(TypeInteger ti) { @@ -262,55 +120,10 @@ public class arm extends Machine { return ti.isConstant() && ((ti.value()<<52)>>52) == ti.value(); } - // Can we encode this in ARM's 12-bit LOGICAL immediate form? // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { - if( !ti.isConstant() ) return -1; - if( !ti.isConstant() ) return -1; - long val = ti.value(); - if (val == 0 || val == -1) return -1; // Special cases are not allowed - int immr = 0; - // Rotate until we have 0[...]1 - - // Rotate until: - // The number is negative (MSB is 1) - // Or the LSB is not 1 - while (val < 0 || (val & 1)==0) { - // circular rotation - val = (val >>> 63) | (val << 1); - immr++; - } - // Start by assuming that val might be made of two 32-bit chunks that repeat. - int size = 32; - long pattern = val; - // Is upper half of pattern the same as the lower? - while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { - // Then only take one half - pattern >>= size; - size >>= 1; - } - size <<= 1; - int imms = Long.bitCount(pattern); - // Pattern should now be zeros followed by ones 0000011111 - if (pattern != (1L<<imms)-1) return -1; - imms--; - if (size == 64) return 0x1000 | immr << 6 | imms; - return (32-size)<<1 | immr << 6 | imms; - } - - // sh is encoded in opcode - public static int imm_inst(int opcode, int imm12, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; - } - - public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + return ti.isConstant() ? Arm64.logicalImmediate(ti.value()) : -1; } public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) { @@ -322,64 +135,46 @@ public class arm extends Machine { opcode ^= OPI_ADD ^ OPI_SUB; imm12 = -imm12; } - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); enc.add4(body); } public static void imm_inst_subs(Encoding enc, Node n,Node n2, int opcode, int imm12) { short reg1 = enc.reg(n2); // 31 = 11111 - int body = imm_inst(opcode, imm12&0xFFF, reg1, 31); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, 31); enc.add4(body); } // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static void imm_inst(Encoding enc, int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, self, self); enc.add4(body); } public static void imm_inst_n(Encoding enc, Node n, Node n2, int opcode, int imm13) { short self = enc.reg(n); short reg1 = enc.reg(n2); - int body = imm_inst_n(opcode, imm13, reg1, self); + int body = Arm64.imm_inst_n(opcode, imm13, reg1, self); enc.add4(body); } - // nth bit comes from immediate and not opcode - public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= imm13 && imm13 <= 0x1FFF; - return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; - } - - public static int imm_inst_l(int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); - return body; - } - // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); return body; } // for normal add, reg1, reg2 cases (reg-to-reg) // using shifted-reg form - public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; - } + public static void r_reg(Encoding enc, Node n, int opcode) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); enc.add4(body); } @@ -387,187 +182,43 @@ public class arm extends Machine { short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); // 31 = 11111 - int body = r_reg(opcode, 0, reg2, 0, reg1, 31); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, 31); enc.add4(body); } - public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; - } public static void shift_reg(Encoding enc, Node n, int op2) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(0b10011010110, reg2, op2, reg1, self); + int body = Arm64.shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } // MUL can be considered an alias for MADD with the third operand Ra being set to 0 - public static int madd(int opcode, int rm, int ra, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; - } + public static void madd(Encoding enc, Node n, int opcode, int ra) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = madd(opcode, reg2, ra, reg1, self); + int body = Arm64.madd(opcode, reg2, ra, reg1, self); enc.add4(body); } - // encodes movk, movn, and movz - public static int mov(int opcode, int shift, int imm16, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; - } - - public static int mov_reg(int opcode, int src, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; - } - - public static int ret(int opcode) { - return (opcode << 10) | (X30 << 5); - } - - // FMOV (scalar, immediate) - public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; - } - - public static int f_mov_reg(int opcode, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; - } - public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; - } public static void f_scalar(Encoding enc, Node n, int op ) { short self = (short)(enc.reg(n) -D_OFFSET); short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); + int body = Arm64.f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } - // share same encoding with LDR (literal, SIMD&FP) flavour - public static int load_pc(int opcode, int offset, int rt) { - offset>>=2; - return (opcode << 24) | (offset << 5) | rt; - } - // int l - public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { - assert 0 <= rd && rd < 32; - return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; - } - - // [Rptr+Roff] - public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; - } - // [Rptr+imm9] - public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - - if(size == 8) imm12 = imm12 >> 3; - if(size == 4) imm12 = imm12 >> 2; - if(size == 2) imm12 = imm12 >> 1; - // size == 1 imm12 = imm12 - return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; - } - - // encoding for vcvt, size is encoded in operand - // <Qd>, <Qm> - // F32.S32 - //encoded as op = 0b00, size = 0b10. - // VCVT<c>.<Td>.<Tm> <Dd>, <Dm> - // opcode is broken down into 4 pieces - public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { - return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | - (vd << 12) | (0x01100010 << 4) | vm; - } - public static int float_cast(int opcode, int ftype, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; - } - - - // ftype = 3 - public static int f_cmp(int opcode, int ftype, int rm, int rn) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - // Todo: |8 is not needed - return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); - } public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_cmp(0b00011110, 3, reg1, reg2); + int body = Arm64.f_cmp(0b00011110, 3, reg1, reg2); enc.add4(body); } - public static COND make_condition(String bop) { - return switch (bop) { - case "==" -> COND.EQ; - case "!=" -> COND.NE; - case "<" -> COND.LT; - case "<=" -> COND.LE; - case ">=" -> COND.GE; - case ">" -> COND.GT; - default -> throw Utils.TODO(); - }; - } - - public static int b_cond(int opcode, int delta, COND cond) { - // 24-5 == 19bits offset range - assert -(1<<19) <= delta && delta < (1<<19); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<19)-1; // Zero extend - return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); - } - - public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - // Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4. - public static int blr(int opcode, int rd) { - assert 0 <= rd && rd < 32; - return opcode << 10 | rd << 5; - } - public static int b(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - // no aligned assert(assert (delta&3)==0;) - public static int b_calloc(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; @@ -591,29 +242,6 @@ public class arm extends Machine { throw Utils.TODO(); // Pass on stack slot } - public static long decodeImm12(int imm12) { - int immr = (imm12 >> 6) & 0x3F; - int imms = imm12 & 0x3F; - int size; - if ((imm12 & 0x1000) != 0) { - size = 64; - } else { - size = 31-(imms >> 1); - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size++; - imms &= ~((32-size) << 1); - } - long val = (2L << imms)-1; - while (size < 64) { - val |= val << size; - size <<= 1; - } - val = (val >>> immr) | val << (64-immr); - return val; - } - // Return the max stack slot used by this signature, or 0 @Override public short maxArgSlot( TypeFunPtr tfp ) { int icnt=0, fcnt=0; // Count of ints, floats @@ -793,7 +421,6 @@ public class arm extends Machine { : new LsrARM(lsr); } - private static int off; private static Node idx; private Node st(StoreNode st) { @@ -819,7 +446,6 @@ public class arm extends Machine { return mop; } - private Node prj(ProjNode prj) { TypeInteger ret = cReturn(prj); return ret==null ? new ProjARM(prj) : new ExtendARM(prj,ret); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 2cd00845..14581111 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -18,7 +19,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); short dst = enc.reg(this); - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -29,7 +30,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { //short rpc = enc.reg(this); //// High half is where the TFP constant used to be, the last input //short auipc = enc.reg(in(_inputs._len-1)); - //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + //enc.patch4(opStart,RiscV.i_type(0x67, rpc, 0, auipc, delta)); throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java index 8636df9f..d87e49b9 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AddFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,1); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,1); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java index 511b0583..8012b61e 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -8,7 +9,7 @@ public class AddIRISC extends ImmRISC { public AddIRISC( Node add, int imm12, boolean pop ) { super(add,imm12,pop); } @Override public String op() { return "addi"; } @Override public String glabel() { return "+"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 0;} @Override public AddIRISC copy() { // Clone the AddI, using the same inputs-only code used during inst select. diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java index 842c8bdc..9fd65e7d 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,6 +8,6 @@ public class AndIRISC extends ImmRISC { public AndIRISC( Node and, int imm) { super(and,imm); } @Override public String op() { return "andi"; } @Override public String glabel() { return "&"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 7;} } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java index b8664679..a9d03da5 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -46,12 +47,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { if( in(1)==null && _bop=="!=" ) return; // Inverted never-node, no code enc.jump(this,cproj(0)); if( in(1)==null ) // Never node - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); else { // Todo: relocs (for offset - immf) short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); - enc.add4(riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, 0)); + enc.add4(RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, 0)); } } @@ -67,12 +68,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( in(1)==null ) { // Never node - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); if( opLen==4 ) { - enc.patch4(opStart,riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, delta)); + enc.patch4(opStart,RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, delta)); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index bd5dabe5..f0ad8e88 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -33,7 +34,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); short rpc = enc.reg(this); - enc.add4(riscv.j_type(riscv.OP_JAL, rpc, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, rpc, 0)); } // Delta is from opcode start @@ -47,7 +48,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short rpc = enc.reg(this); if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, rpc, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, rpc, delta)); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index 298789e8..5eee596d 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -18,7 +19,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(riscv.OP_JALR, rpc, 0, src, 0); + int body = RiscV.i_type(RiscV.OP_JALR, rpc, 0, src, 0); enc.add4(body); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java index 68ed6f6c..8eb4fb3b 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivFRISC extends MachConcreteNode implements MachNode{ @Override public String op() { return "divf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RUP,13); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RUP,13); } // Default on double precision for now(64 bits) // General form: "fdiv.d rd = src1 / src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java index 22ac2a69..5bd3ec1c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,8 +23,8 @@ public class ExtendRISC extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); int shift = 64-_bits; - enc.add4(riscv.i_type(riscv.OP_IMM,dst,1,src,shift)); - enc.add4(riscv.i_type(riscv.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,1,src,shift)); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index 81726200..51ddc9db 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -20,9 +21,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -34,9 +35,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java index 6fce6244..d3d64b06 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -17,6 +18,6 @@ public class FunRISC extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java index db0547fe..1b53ab0f 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,7 +15,7 @@ public class I2F8RISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this )-riscv.F_OFFSET); short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.RM.RNE.ordinal(),src1,0,0x69); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.RM.RNE.ordinal(),src1,0,0x69); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index b4c87872..ee247c3e 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -41,7 +42,7 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); + enc.add4(RiscV.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); } // General form: "addi rd = rs1 + imm" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java index edd1850f..23ac8481 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -23,9 +24,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short tmp = (short)riscv.T6; enc.largeConstant(this,_con, 0, -1); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -34,9 +35,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index f8af913a..9088abbd 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class IntRISC extends ConstantNode implements MachNode { int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 7333f2b7..aedd8b47 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class LUI extends ConstantNode implements MachNode { long x = ((TypeInteger)_con).value(); int imm20 = (int)(x>>12) & 0xFFFFF; short dst = enc.reg(this); - int lui = riscv.u_type(riscv.OP_LUI, dst, imm20); + int lui = RiscV.u_type(RiscV.OP_LUI, dst, imm20); enc.add4(lui); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index 7e08a01d..2e3dfd8d 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,9 +18,9 @@ public class LoadRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short ptr = enc.reg(ptr()); - int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dst >= riscv.F_OFFSET ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, func3(), ptr, _off)); + enc.add4(RiscV.i_type(op, dst, func3(), ptr, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java index 5cc40079..dacec2b5 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class MulFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,9); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,9); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java index d8183d09..3070c56c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,7 +13,7 @@ public class NegRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - riscv.r_type(riscv.OP,dst,0,0,src,0x20); + RiscV.r_type(RiscV.OP,dst,0,0,src,0x20); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = -").p(code.reg(in(1))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index 6c03bda6..965a3c7c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.print.ASMPrinter; @@ -14,9 +15,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.i_type(riscv.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); - enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); } // Patch is for running "new" in a JIT. @@ -32,8 +33,8 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { int imm20 = delta>>12; if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension int imm12 = delta&0xFFF; - enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); - enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + enc.patch4(opStart+4,RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); } else throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java index 1369ee76..dbe9ceb0 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -14,7 +15,7 @@ public class NotRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 2, src, 1)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java index 963b9d50..937595a3 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class OrIRISC extends ImmRISC { public OrIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 6; } @Override public String glabel() { return "|"; } @Override public String op() { return "ori"; } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 7e4631d3..33143c6b 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -14,8 +15,8 @@ public class RetRISC extends ReturnNode implements MachNode { int sz = fun()._frameAdjust; if( sz >= 1L<<12 ) throw Utils.TODO(); if( sz != 0 ) - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); short rpc = enc.reg(rpc()); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.ZERO, 0, rpc, 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR, riscv.ZERO, 0, rpc, 0)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 3424cd01..d037dd5c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.BoolNode; import com.seaofnodes.simple.node.MachConcreteNode; @@ -23,7 +24,7 @@ public class SetFRISC extends MachConcreteNode implements MachNode { short dst = enc.reg(this ); short src1 = (short)(enc.reg(in(1))-riscv.F_OFFSET); short src2 = (short)(enc.reg(in(2))-riscv.F_OFFSET); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java index 12c0ddec..1425caa2 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SllIRISC extends ImmRISC { public SllIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 1; } @Override public String glabel() { return "<<"; } @Override public String op() { return "slli"; } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 6082cbbf..8a16f6b7 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -25,36 +26,36 @@ public class SplitRISC extends SplitNode { throw Utils.TODO(); // Very rare stack-stack move } int off = enc._fun.computeStackOffset(enc._code,dst); - int op = srcX ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = srcX ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( srcX ) src -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, 0b011, riscv.RSP, src, off)); + enc.add4(RiscV.s_type(op, 0b011, riscv.RSP, src, off)); return; } if( src >= riscv.MAX_REG ) { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); - int op = dstX ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dstX ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dstX ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, 0b011, riscv.RSP, off)); + enc.add4(RiscV.i_type(op, dst, 0b011, riscv.RSP, off)); return; } // pick opcode based on regs if( !dstX && !srcX ) { // GPR->GPR - enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + enc.add4(RiscV.r_type(RiscV.OP,dst,0,src,riscv.ZERO,0)); } else if( dstX && srcX ) { // FPR->FPR src -= riscv.F_OFFSET; dst -= riscv.F_OFFSET; - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) } else if(!srcX && dstX) { //GPR->FPR // fmv.d.x - enc.add4(riscv.r_type(riscv.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); } else if(srcX && !dstX) { //FPR->GPR //fmv.x.d - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java index fcfa0774..b316b303 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,7 +8,7 @@ public class SraIRISC extends ImmRISC { public SraIRISC( Node and, int imm) { super(and,imm | (0x20 << 5)); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5;} @Override public String glabel() { return ">>"; } @Override public String op() { return "srai"; } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java index 2f73e139..d0ea6b18 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SrlIRISC extends ImmRISC { public SrlIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5; } @Override public String glabel() { return ">>>"; } @Override public String op() { return "srli"; } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index df83ce1c..48cb7c78 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.node.*; @@ -36,9 +37,9 @@ public class StoreRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short val = enc.reg(val()); short ptr = enc.reg(ptr()); - int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = val >= riscv.F_OFFSET ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); + enc.add4(RiscV.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java index da3e92f4..044820cf 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,5); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,5); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index db140304..e57f6e09 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,9 +22,9 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; // auipc t0,0 - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi t1,t0 + #0 - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -33,8 +34,8 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short rpc = enc.reg(this); if( opLen==8 ) { // ADDI sign-extends its low 12 bits, so round the AUIPC high part. - enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, (delta+0x800)>>12)); - enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); + enc.patch4(opStart ,RiscV.u_type(RiscV.OP_AUIPC, rpc, (delta+0x800)>>12)); + enc.patch4(opStart+4,RiscV.i_type(RiscV.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java index 94f0da0e..7bc2db7e 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -18,9 +19,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -29,9 +30,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = enc.reg(this); // Round the high part because ADDI's low 12 bits are signed. - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, (delta+0x800)>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, dst, (delta+0x800)>>12)); // ADDI dst,dst,#low12_constant_pool - enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, dst, 0, dst, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java index 160895df..448d9ec3 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -21,7 +22,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.jump(this,uctrl()); - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); } // Delta is from opcode start @@ -34,7 +35,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { throw Utils.TODO(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 19ea6bc7..f4323cae 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -1,12 +1,13 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } public XorIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } @Override public String op() { return "xori"; } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 88ec9ebd..6be0376a 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; +import static com.seaofnodes.isa.RiscV.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -68,7 +70,6 @@ public class riscv extends Machine { static final RegMask SPLIT_MASK = new RegMask( WR_BITS | FP_BITS, -1L ); - // Arguments masks public static RegMask A0_MASK = new RegMask(A0); public static RegMask A1_MASK = new RegMask(A1); @@ -114,40 +115,13 @@ public class riscv extends Machine { FA7_MASK }; - // major opcode: OP - public static int OP_LOAD = 0b00_000_11; - public static int OP_LOADFP = 0b00_001_11; - public static int OP_CUSTOM0 = 0b00_010_11; - public static int OP_IMM = 0b00_100_11; - public static int OP_AUIPC = 0b00_101_11; - - public static int OP_STORE = 0b01_000_11; - public static int OP_STOREFP = 0b01_001_11; - public static int OP_CUSTOM1 = 0b01_010_11; - public static int OP = 0b01_100_11; - public static int OP_LUI = 0b01_101_11; - - public static int OP_CUSTOM2 = 0b10_010_11; - public static int OP_FP = 0b10_100_11; - - public static int OP_BRANCH = 0b11_000_11; - public static int OP_JALR = 0b11_001_11; - public static int OP_RESERVED= 0b11_010_11; - public static int OP_JAL = 0b11_011_11; - - // Since riscv instructions are fixed we can just or them together - public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= rd && rd < 32; - return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } + public static void r_type(Encoding enc, Node n, int func3, int func7) { short dst = enc.reg(n); short src1 = enc.reg(n.in(1)); short src2 = enc.reg(n.in(2)); - int body = r_type(OP,dst,func3,src1,src2,func7); + int body = RiscV.r_type(OP,dst,func3,src1,src2,func7); enc.add4(body); } @@ -155,103 +129,10 @@ public class riscv extends Machine { short dst = (short)(enc.reg(n )-F_OFFSET); short src1 = (short)(enc.reg(n.in(1))-F_OFFSET); short src2 = (short)(enc.reg(n.in(2))-F_OFFSET); - int body = r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); + int body = RiscV.r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); enc.add4(body); } - - public static int u_type(int opcode, int rd, int imm20) { - assert 0 <= rd && rd < 32; - return (imm20 << 12) | (rd << 7) | opcode; - } - - public static int j_type(int opcode, int rd, int delta) { - assert -(1L<<20) <= delta && delta < (1L<<20); - assert 0 <= rd && rd < 32; - // Messy branch offset encoding - // 31 30-21 20 19-12 11-7 6-0 - // 20 10- 1 11 19-12 rpc JAL - assert (delta&1)==0; // Low bit is always zero, not encoded - int imm10_01 = (delta>> 1) & 0x3FF; - int imm11 = (delta>>11) & 1; - int imm12_19 = (delta>>12) & 0xFF; - int imm20 = (delta>>19) & 1; - int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; - return bits << 12 | rd << 7 | opcode; - } - - - public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { - assert 0 <= rd && rd < 32; - assert 0 <= rs1 && rs1 < 32; - assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller - return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } - - // S-type instructions(store) - public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= func3; - - assert imm12 >= 0; // Masked to high zero bits by caller - int imm_lo = imm12 & 0x1F; - int imm_hi = imm12 >> 5; - return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; - } - - // BRANCH - public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert -4*1024 <= delta && delta < 4*1024; - assert (delta&1)==0; // Low bit is always zero, not encoded - // Messy branch offset encoding - // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 - // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP - int imm4_1 = (delta>> 1) & 0xF; - int imm10_5= (delta>> 5) &0x3F; - int imm11 = (delta>>11) & 1; - int imm12 = (delta>>12) & 1; - int imm5 = imm4_1<<1 | imm11; - int imm7 = imm12<<6 | imm10_5; - return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; - } - - public enum RM { - RNE, // Round to Nearest, ties to Even - RTZ, // Round towards Zero - RDN, // Round Down - RUP, // Round Up - DIRECT, // Round to Nearest, ties to Max Magnitude - RESERVED1, // Reserved for futue use - RESERVED2, // Reserved for future use - DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved - } - - // Since opcode is the same just return back func3 - static public int jumpop(String op) { - return switch(op) { - case "==" -> 0x0; - case "!=" -> 0x1; - case "<" -> 0x4; - case ">=" -> 0x5; - case "u<" -> 0x6; - case "u<=" -> 0x7; - default -> throw Utils.TODO(); - }; - } - - // Since opcode is the same just return back func3 - static public int fsetop(String op) { - return switch(op) { - case "<" -> 1; - case "<=" -> 0; - case "==" -> 2; - default -> throw Utils.TODO(); - }; - } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; @@ -301,7 +182,6 @@ public class riscv extends Machine { } @Override public int rpc() { return RPC; } - // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index 2513de37..974f690f 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -20,19 +21,7 @@ public class AddFMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // addsd xmm0, DWORD PTR [rdi+0xc] - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - // F opcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, ptr, idx, false, enc); - - // FP ADD - enc.add1(0x0F).add1(0x58); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst = src + [base + idx<<2 + 12]" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index 02e0c7ea..c7d0cf9c 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,17 +14,7 @@ public class AddFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 58 /r ADDSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x58); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "addf dst += src" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java index 0ba390c6..0e652a93 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.SB; @@ -16,9 +17,7 @@ public class AddIX86 extends ImmX86 { @Override public final void encoding( Encoding enc ) { if( _imm== 1 || _imm== -1 ) { short dst = enc.reg(this); // Also src1 - enc.add1( x86_64_v2.rex(0,dst,0)); - enc.add1(0xFF); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, _imm==1 ? 0 : 1, dst) ); + X86.unary(enc,0xFF,_imm==1 ? 0 : 1,dst); } else super.encoding(enc); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java index 3ee721e3..ed65b0a8 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class AddMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // add something to register from memory - // add eax,DWORD PTR [rdi+0xc] - // REX.W + 03 /r ADD r64, r/m64 - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - // opcode - enc.add1(0x03); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0,0x03,true,enc.reg(this),enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst += [base + idx<<2 + 12]" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 460f568b..f97163eb 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; import com.seaofnodes.simple.node.MachNode; @@ -16,11 +17,7 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // FF /2 CALL r/m64 - // calls the function in the register - short src = enc.reg(fptr()); - enc.add1(0xFF); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT,2,src)); + X86.callRegister(enc,enc.reg(fptr())); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index d74e3833..d1a43b83 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -28,7 +29,7 @@ public class CallX86 extends CallNode implements MachNode, RIPRelSize { FunNode fun = CodeGen.CODE.link(_tfp); if( fun==null ) enc.external(this,_name); else enc.relo(this); - enc.add1(0xe8).add4(0); + X86.call(enc); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java index 5b97ef63..5ef7a476 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,16 +12,7 @@ public class CmpFX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // UCOMISD - short src1 = (short)(enc.reg(in(1)) - x86_64_v2.XMM_OFFSET); - short src2 = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // float opcode - enc.add1(0x66); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(src1, src2, 0, false, enc); - - enc.add1(0x0F).add1(0x2E); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src1, src2)); + X86.sse(enc,0x66,0x0F2E,false,enc.reg(in(1))-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "cmp src1,src2" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 8b8318eb..151f8ca8 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -26,14 +27,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode { @Override public Node copy() { return new CmpIX86(this); } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,0x81,7,enc.reg(in(1)),_imm); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index 278bf0e6..7b7d98d5 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -16,51 +17,16 @@ public class CmpMemX86 extends MemOpX86 { @Override public String op() { return ((val()==null && _imm==0) ? "test" : "cmp") + _sz; } @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64 - // CMP [mem], imm32 - - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if(src == -1) { + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) { assert !_swap; - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch(log) { - case 0: enc.add1(0x80); break; - case 1: enc.add1(0x66).add1(0x81); break; - case 2: enc.add1(0x81); break; - case 3: enc.add1(0x81); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc); - switch(log) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; - } - } else { - encVal(enc, _declaredType, ptr, idx, src, _off, _scale, _swap); - } + X86.cmpImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + } else encVal(enc,_declaredType,ptr,idx,src,_off,_scale,_swap); } static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale, boolean _swap) { - if(decl instanceof TypeFloat) { - src -= (short)x86_64_v2.XMM_OFFSET; - enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2); - } else { - int log = decl.log_size(); - x86_64_v2.rexF(src, ptr, idx, log == 3, enc); - int swap = _swap ? 2 : 0; - switch(log) { - case 0: enc.add1(0x38+swap); break; - case 1: enc.add1(0x66).add1(0x39+swap); break; - case 2: enc.add1(0x39+swap); break; - case 3: enc.add1(0x39+swap); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + assert !(decl instanceof TypeFloat); // Selected separately as CmpFX86. + X86.cmpMem(enc,decl.log_size(),src,ptr,idx,off,scale,_swap); } // General form: "cmp dst = src, [base + idx<<2 + 12]" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index e7305cdf..7faea17b 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,12 +18,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); - short src = enc.reg(in(2)); - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x3B); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x3B,enc.reg(in(1)),enc.reg(in(2))); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index 3427aea5..7bbb5102 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class DivFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5E /r DIVSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5E); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5E,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java index b5904a7f..9f375a80 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,16 +15,7 @@ public class DivX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.RDX_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + F7 /7 IDIV r/m64 - short src = enc.reg(in(2)); - // sign extend rax before 128/64 bits division - // sign extend rax to rdx:rax - enc.add1(x86_64_v2.REX_W); - enc.add1(0x99); - enc.add1(x86_64_v2.rex(0, src, 0)); - // divide - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x07, src)); + X86.divide(enc,enc.reg(in(2))); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java index e905e2e3..1a6ae123 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -20,12 +21,7 @@ public class ExtendX86 extends MachConcreteNode { @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this), src = enc.reg(in(1)); - // MOVSX/MOVZX for bytes and shorts; MOVSXD/MOV r32 for ints. - enc.add1(x86_64_v2.rex(dst,src,0,_signed || _bits<32)); - if( _bits==32 ) enc.add1(_signed ? 0x63 : 0x8b); - else enc.add1(0x0f).add1((_signed ? 0xbe : 0xb6) + (_bits==16 ? 1 : 0)); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,dst,src)); + X86.extend(enc,_bits,_signed,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index 9bcbac8f..da9bdce7 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,20 +15,8 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public Node copy() { return new FltX86(this); } @Override public void encoding( Encoding enc ) { - // Load the constant into a FPR - // movsd xmm, [rip + 0] - // F2 0F 10 /r MOVSD xmm1, m64 - _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - _encSize += x86_64_v2.rexF(dst, 0, 0, false, enc); - enc.add1(0x0F).add1(0x10); - // hard-code rip here - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); - enc.add4(0); - enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); + _encSize=X86.rip(enc,0xF2,0x0F10,false,enc.reg(this)-x86_64_v2.XMM_OFFSET); + enc.largeConstant(this,_con,_encSize-4,2/*ELF PC32*/); } // Delta is from opcode start diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index cbd5fdbf..c7a20e4d 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.FunNode; @@ -24,11 +25,7 @@ public class FunX86 extends FunNode implements MachNode { @Override public void encoding( Encoding enc ) { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust - // opcode: 0x83, addi rsp with immediate 8 - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b101, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); + X86.imm(enc,0x81,5,x86_64_v2.RSP,sz); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java index 9f3d7905..ee357901 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,18 +12,7 @@ public class I2f8X86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public void encoding( Encoding enc ) { - // F2 0F 2A /r CVTSI2SD xmm1, r32/m32 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = enc.reg(in(1)); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, true, enc); - - enc.add1(0x0F).add1(0x2A); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F2A,true,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java index 5e406911..5a4ff4b2 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -21,14 +22,7 @@ public abstract class ImmX86 extends MachConcreteNode implements MachNode { abstract int mod(); @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( opcode() + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,opcode(),mod(),enc.reg(this),_imm); } // General form: "addi dst += #imm" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 3f2f696c..656b1543 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -22,44 +23,7 @@ public class IntX86 extends ConstantNode implements MachNode { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL || _con==TypeInteger.ZERO ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // Simply move the constant into a GPR - // Conditional encoding based on 64 or 32 bits - //REX.W + C7 /0 id MOV r/m64, imm32 - - long imm = ((TypeInteger)_con).value(); - if (Integer.MIN_VALUE <= imm && imm < 0) { - // We need sign extension, so use imm32 into 64 bit register - // REX.W + C7 /0 id MOV r/m64, imm32 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xC7); // 32 bits encoding - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x00, dst)); - enc.add4((int)imm); - } else if (0 <= imm && imm <= 0xFFFFFFFFL) { - // We want zero extension into 64 bit register - // so move 32 bit into 32 bit register which zeros - // the upper bits in the 64 bit register. - // B8+ rd id MOV r32, imm32 - if (dst >= 8) enc.add1(0x41); - enc.add1(0xB8 + (dst & 0x07)); - enc.add4((int)imm); - } else { - // Just write the full 64 bit constant - // REX.W + B8+ rd io MOV r64, imm64 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xB8 + (dst & 0x07)); - enc.add8(imm); // 64 bits encoding - } + X86.constant(enc,enc.reg(this),_con==Type.NIL ? 0 : ((TypeInteger)_con).value()); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index de27aa5c..10cee059 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -30,38 +31,21 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { @Override public void negate() { _bop = negate(_bop); } @Override public void encoding( Encoding enc ) { - if( in(1)!=null ) { - int op = x86_64_v2.jumpop(_bop); - enc.add1(op-16).add1(0); // Short form jump - } else { - if( _bop=="!=" ) return; // Inverted, no code - enc.add1(0xEB).add1(0); // Never-node - } + if( in(1)==null && _bop=="!=" ) return; + X86.branch(enc,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); enc.jump(this,cproj(0)); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding @Override public byte encSize(int delta) { - if( in(1)==null && _bop=="!=" ) return 0; // Inverted never-node, no code - return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 6); + if( in(1)==null && _bop=="!=" ) return 0; + return X86.branchSize(delta,in(1)!=null); } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 6; // Offset from opcode END - bits[opStart] = 0x0F; - bits[opStart+1] = (byte)(in(1)==null ? 0xE9 : x86_64_v2.jumpop(_bop)); - enc.patch4(opStart+2,delta); - } + assert !(in(1)==null && _bop=="!="); + X86.patchBranch(enc.bits(),opStart,opLen,delta,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java index 2cd6018f..4b00e4dd 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -23,25 +24,7 @@ public class LeaX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 8D /r LEA r64,m - short dst = enc.reg(this); - short ptr = enc.reg(in(1)); - short idx = enc.reg(in(2)); - // ptr is null - // just do: [(index * s) + disp32] - if( ptr == -1 ) { - enc.add1(x86_64_v2.rex(dst, 0, idx)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x04)); - enc.add1(x86_64_v2.sib(_scale, idx, x86_64_v2.RBP)); - enc.add4(_offset); - return; - } - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - enc.add1(0x8D); // opcode - // rsp is hard-coded here(0x04) - x86_64_v2.indirectAdr(_scale, idx, ptr, _offset, dst, enc); + X86.lea(enc,enc.reg(this),enc.reg(in(1)),enc.reg(in(2)),_offset,_scale); } // General form: "lea dst = base + 4*idx + 12" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java index d0fb0081..d4f1413e 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -24,33 +25,14 @@ public class LoadX86 extends MemOpX86 { } static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) { - // Allocation may put a full-width integer in an XMM register (or a - // floating value in a GPR). Move its bits using the selected register bank. - if( dst>=x86_64_v2.XMM_OFFSET && decl.log_size()==3 ) decl=TypeFloat.F64; - else if( dst<x86_64_v2.XMM_OFFSET && decl instanceof TypeFloat ) - decl = decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; - if( decl == TypeFloat.F32) enc.add1(0xF3); - if( decl == TypeFloat.F64) enc.add1(0xF2); - - if( decl.isa(TypeFloat.F64) ) - dst -= (short)x86_64_v2.XMM_OFFSET; - - x86_64_v2.rexF(dst, ptr, idx, decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64, enc); - - if( false ) ; - else if( decl == TypeFloat.F32 ) enc.add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32 - else if( decl == TypeFloat.F64 ) enc.add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64 - else if( decl.isa(TypeInteger.I8)) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8 - else if( decl == TypeInteger.I16 ) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16 - else if( decl == TypeInteger.I32 ) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32 - else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8 - else if( decl == TypeInteger.U16 ) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16 - // Covers U32, I64/BOT, TMP - else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32 - else throw Utils.TODO(); - - // includes modrm internally - x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc); + // The chapter chooses the register bank and extension from its own type facts. + boolean xmm=dst>=x86_64_v2.XMM_OFFSET; + if( xmm && decl.log_size()==3 ) decl=TypeFloat.F64; + else if( !xmm && decl instanceof TypeFloat ) + decl=decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; + boolean signed=decl.isa(TypeInteger.I8) || decl==TypeInteger.I16 || decl==TypeInteger.I32; + X86.load(enc,decl.log_size(),signed,xmm, + xmm ? dst-x86_64_v2.XMM_OFFSET : dst,ptr,idx,off,scale); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index bd56d022..2e18a058 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,20 +16,7 @@ public class MemAddX86 extends MemOpX86 { @Override public RegMask outregmap() { return null; } @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // add something to memory - // REX.W + 01 /r | REX.W + 81 /0 id - // ADD [mem], imm32/reg - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - enc.add1(x86_64_v2.rex(src, ptr, idx)); - // opcode - enc.add1( src == -1 ? (_imm==1 ? 0xFF : 0x81): 0x01); - - // includes modrm - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc); - if( src == -1 && _imm!=1 ) enc.add4(_imm); + X86.addMem(enc,enc.reg(val()),_imm,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add [base + idx<<2 + 12] += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index 7932c893..74616db7 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,16 +14,7 @@ public class MulFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 59 /r MULSD xmm1,xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x59).add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F59,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "mulf dst *= src" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 1e9e708f..5dcb253d 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,15 +18,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } // Rare 3-address form @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // Also src1 - short src = enc.reg(in(1)); - enc.add1(x86_64_v2.rex(dst, src, 0)); - // opcode; 0x69 or 0x6B - enc.add1( 0x69 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imul(enc,enc.reg(this),enc.reg(in(1)),_imm); } // General form: "addi dst += #imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java index 4d2a11ed..6f3fcdeb 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,13 +14,7 @@ public class MulX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // REX.W + 0F AF /r IMUL r64, r/m64 - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xAF); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x0FAF,enc.reg(this),enc.reg(in(2))); } // General form: "mul dst *= src" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java index 0c2baced..86610f6d 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,10 +14,7 @@ public class NegX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 3, dst)); + X86.unary(enc,0xF7,3,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index fc896dce..1cfc1c42 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -10,11 +11,8 @@ public class NewX86 extends NewNode implements MachNode { NewX86( NewNode nnn ) { super(nnn); } @Override public void encoding( Encoding enc ) { enc.external(this,"calloc"); - // ldi rcx,#1 // number of elements to calloc - enc.add1(0xB8 + _arg2Reg).add4(1); - // E8 cd CALL rel32; - enc.add1(0xE8); - enc.add4(0); // offset + X86.constant(enc,_arg2Reg,1); + X86.call(enc); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java index 7db80299..1e4e7c26 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,25 +13,9 @@ public class NotX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - assert !(in(1) instanceof NotNode); // Cleared out by peeps - assert !(in(1) instanceof BoolNode); // Cleared out by peeps - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - - // test rdi,rdi - enc.add1(x86_64_v2.rex(src, src, 0)); - enc.add1(0x85); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src, src)); - - // setz dstb; then zero-extend the low byte into the full register. - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0x94); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0xB6); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + assert !(in(1) instanceof NotNode); // Cleared out by peeps + assert !(in(1) instanceof BoolNode); + X86.not(enc,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java index 5a475efe..06755143 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,13 +13,7 @@ public abstract class RegX86 extends MachConcreteNode { @Override public int twoAddress() { return 1; } abstract int opcode(); @Override public void encoding( Encoding enc ) { - // REX.W + 01 /r - short dst = enc.reg(in(1)); // src1 - short src = enc.reg(in(2)); // src2 - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); } // General form: "add dst += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index a35d43a2..e4467bb4 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -8,12 +9,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public void encoding( Encoding enc ) { int sz = fun()._frameAdjust; - if( sz != 0 ) { - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b000, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); - } - enc.add1(0xC3); + if( sz!=0 ) X86.imm(enc,0x81,0,x86_64_v2.RSP,sz); + X86.ret(enc); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index 95e0c336..cf6275dc 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,15 +23,7 @@ public class SarIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index 4cc8b558..92493712 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class SarX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst)); + X86.unary(enc,opcode(),7,enc.reg(this)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 0eff2afe..533d5652 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -24,26 +25,14 @@ public class SetX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX + 0F 94 - short dst = enc.reg(this ); - - // Optional rex, for dst - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(switch (_bop) { + int op=switch (_bop) { case "==" -> 0x94; // SETE case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE default -> throw Utils.TODO(); - }); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - - // low 8 bites are set, now zero extend for next instruction - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(0xB6); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + }; + X86.set(enc,op&15,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index f7b2f28a..1e62243e 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -23,15 +24,7 @@ public class ShlIX86 extends MachConcreteNode implements MachNode { @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java index 5fee72d9..768d97e7 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShlX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 4, dst)); + X86.unary(enc,opcode(),4,enc.reg(this)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 7e0378b1..8a0d1b58 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -18,15 +19,7 @@ public class ShrIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java index 67dcf055..1ba20fee 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShrX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 5, dst)); + X86.unary(enc,opcode(),5,enc.reg(this)); } } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index 4a14240a..e8281975 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -19,44 +20,17 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. @Override public void encoding( Encoding enc ) { - // REX.W + 8B /r MOV r64, r/m64 - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - if( dst == x86_64_v2.FLAGS ) { - // mov reg, flags - // push rcx - // popf (Pop the top of the stack into the FLAGS register) - // 50+rd PUSH r64 - x86_64_v2.rexF(0,src,0,false,enc); - enc.add1(0x50 + src); - // popf - enc.add1(0x9D); - return; - } - if( src == x86_64_v2.FLAGS ) { - // mov flags, reg - // pushf; pop reg - enc.add1(0x9C); - // 58+ rd POP r64 - x86_64_v2.rexF(0,dst,0,false, enc); - enc.add1(0x58 + dst); - return; - } - - // Flag for being either XMM or stack - boolean dstX = dst >= x86_64_v2.XMM_OFFSET; - boolean srcX = src >= x86_64_v2.XMM_OFFSET; - + short dst=enc.reg(this), src=enc.reg(in(1)); + if( dst==x86_64_v2.FLAGS ) { X86.flags(enc,src,true); return; } + if( src==x86_64_v2.FLAGS ) { X86.flags(enc,dst,false); return; } + boolean dstX=dst>=x86_64_v2.XMM_OFFSET, srcX=src>=x86_64_v2.XMM_OFFSET; // Stack spills if( dst >= x86_64_v2.MAX_REG ) { int off = enc._fun.computeStackOffset(enc._code,dst); if( src >= x86_64_v2.MAX_REG ) { // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] int soff = enc._fun.computeStackOffset(enc._code,src); - enc.add1(0xFF); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); - enc.add1(0x8F); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + X86.stackCopy(enc,soff,off); return; } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); @@ -68,35 +42,8 @@ public class SplitX86 extends SplitNode { return; } - // reg-reg move. Adjust numbering for GPR vs FPR reg set - if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; - if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; - - // 0x66 if moving between register classes - if( dstX ^ srcX ) enc.add1(0x66); - if( !dstX && srcX ) - { short tmp=src; src=dst; dst=tmp; } - enc.add1(x86_64_v2.rex(dst, src, 0)); - - // pick opcode based on regs - if( !dstX && !srcX ) { - // reg->reg (MOV r64, r/m64) - enc.add1(0x8B); - } else if( dstX && srcX ) { - // xmm->xmm (NP 0F 28 /r MOVAPS xmm1, xmm2/m128) - enc.add1(0x0F); - enc.add1(0x28); - } else if( dstX && !srcX ) { - // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) - enc.add1(0x0F); - enc.add1(0x6E); - } else if( !dstX && srcX ) { - // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) - enc.add1(0x0F); - enc.add1(0x7E); - } - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.move(enc,dstX,srcX,dstX ? dst-x86_64_v2.XMM_OFFSET : dst, + srcX ? src-x86_64_v2.XMM_OFFSET : src); } // General form: "mov dst = src" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index b7b6c5d3..c83dfd44 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -25,55 +26,16 @@ public class StoreX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // REX.W + C7 /0 id MOV r/m64, imm32 | - // REX.W + 89 /r MOV r/m64, r64 - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if( src == -1 ) { - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch( log ) { - case 0: enc .add1(0xC6); break; - case 1: enc.add1(0x66).add1(0xC7); break; - case 2: enc .add1(0xC7); break; - case 3: enc .add1(0xC7); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc); - switch( log ) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate - } - } else { - encVal(enc,_declaredType,ptr,idx,src,_off,_scale); - } + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) X86.storeImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + else encVal(enc,_declaredType,ptr,idx,src,_off,_scale); } // Non-immediate encoding static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) { - int log = decl.log_size(); - // Float reg being stored - if( src >= x86_64_v2.XMM_OFFSET ) { - src -= (short)x86_64_v2.XMM_OFFSET; - assert log == 2 || log == 3; - enc.add1( log==2 ? 0xF3 : 0xF2 ); - x86_64_v2.rexF(src,ptr,idx,false,enc); - enc.add1(0x0F).add1(0x11); - } else { - // byte stores from sil, dil, bpl, spl need a rex - if( log == 0 && src >= x86_64_v2.RSP ) enc.add1(x86_64_v2.rex(src,ptr,idx,false)); - else x86_64_v2.rexF(src,ptr,idx,log==3,enc); - switch( log ) { - case 0: enc .add1(0x88); break; - case 1: enc.add1(0x66).add1(0x89); break; - case 2: enc .add1(0x89); break; - case 3: enc .add1(0x89); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + boolean xmm=src>=x86_64_v2.XMM_OFFSET; + X86.store(enc,decl.log_size(),xmm, + xmm ? src-x86_64_v2.XMM_OFFSET : src,ptr,idx,off,scale); } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index b6530a87..29f0033a 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,16 +13,7 @@ public class SubFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5C /r SUBSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5C); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5C,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "subf dst -= src" diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index 359b6d83..fff2fb04 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.cpus.riscv.riscv; @@ -23,24 +24,9 @@ public class TFPX86 extends ConstantNode implements MachNode, RIPRelSize { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // lea to load function pointer address - // lea rax, [rip+disp32] + if( _con==Type.NIL ) { X86.constant(enc,enc.reg(this),0); return; } enc.relo(this); - enc.add1(x86_64_v2.rex(dst, 0, 0)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); - enc.add4(0); + X86.rip(enc,0,0x8D,true,enc.reg(this)); } @Override public byte encSize(int delta) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java index c23f6c5f..c78ac6de 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeMemPtr; @@ -15,8 +16,8 @@ public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { short dst = enc.reg(this); - x86_64_v2.rexF(dst, 0, 0, true, enc); - enc.add1(0x8D).add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)).add4(0); + X86.rexF(dst, 0, 0, true, enc); + enc.add1(0x8D).add1(X86.modrm(X86.MOD.INDIRECT, dst, 0b101)).add4(0); int opLen = 1/*rexF*/+1/*opcode 0x8D*/+1/*modrm*/+4/*pc rel offset*/; // Base of constant array TypeMemPtr tmp = (TypeMemPtr)_con; diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java index 6f538d27..591a51c3 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,29 +20,17 @@ public class UJmpX86 extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - // Short-form jump - enc.add1(0xEB).add1(0); - //// E9 cd JMP rel32 - //enc.add1(0xE9).add4(0); + X86.branch(enc,-1); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding - @Override public byte encSize(int delta) { return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 5); } + @Override public byte encSize(int delta) { + return X86.branchSize(delta,false); + } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert bits[opStart] == (byte)0xEB; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert bits[opStart] == (byte)0xEB; - bits[opStart] = (byte)0xE9; // Long form - delta -= 5; // Offset from opcode END - enc.patch4(opStart+1,delta); - } + X86.patchBranch(enc.bits(),opStart,opLen,delta,-1); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index cf9288b8..4beef793 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -69,13 +69,6 @@ public class x86_64_v2 extends Machine { public static int REX_WRB= 0x4D; public static int REX_WB = 0x49; - public enum MOD { - INDIRECT, // [mem] - INDIRECT_disp8, // [mem + 0x12] - INDIRECT_disp32, // [mem + 0x12345678] - DIRECT, // mem - }; - // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -95,90 +88,6 @@ public class x86_64_v2 extends Machine { }; } - public static int modrm(MOD mod, int reg, int m_r) { - if( reg == -1 ) reg=0; // Missing reg in this flavor - // combine all the bits - assert 0 <= reg && reg < 16; - assert 0 <= m_r && m_r < 16; - return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07; - } - - // 00 000 000 - // same bit-layout as modrm - public static int sib(int scale, int index, int base) { - assert 0 <= base && base < 16; - assert 0 <= index && index < 16; - return (scale << 6) | ((index & 0x07) << 3) | base & 0x07; - } - - // reg1 is reg(R) - // reg2 is r/mem(B) - // reg3 is X(index) - // reg4 is X(base) - - // 0 denotes no direct register - public static int rex(int reg, int ptr, int idx, boolean wide) { - // assuming 64 bit by default so: 0100 1000 - assert -1 <= reg && reg < 16; - assert -1 <= ptr && ptr < 16; - assert -1 <= idx && idx < 16; - - int rex = wide ? REX_W : REX; - if( 8 <= reg ) rex |= 0b00000100; // REX.R - if( 8 <= ptr ) rex |= 0b00000001; // REX.B - if( 8 <= idx ) rex |= 0b00000010; // REX.X - return rex; - } - - public static int rex(int reg, int ptr, int idx) { - return rex(reg, ptr, idx, true); - } - - // rex for floats. Return size (0 or 1) - // don't need to use REX if 0x40. - public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { - int rex = rex(reg, ptr, idx, wide); - if (rex == REX) return 0; - enc.add1(rex); - return 1; - } - // Function used for encoding indirect memory addresses - // Does not always generate SIB byte e.g index == -1. - // -1 denotes empty value, not set - note 0 is different from -1 as it can represent rax. - // Looks for best mod locally - public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { - // Assume indirect - assert 0 <= base && base < 16; - assert -1 <= index && index < 16 && index != RSP; - - MOD mod = MOD.INDIRECT; - // is 1 byte enough or need more? - if( offset != 0 ) - mod = imm8(offset) - ? MOD.INDIRECT_disp8 - : MOD.INDIRECT_disp32; - - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { - mod = MOD.INDIRECT_disp8; - } else if( index == -1 && (base == RSP || base == R12) ) { - index = RSP; - } - - if( index == -1 ) { - enc.add1(modrm(mod, reg, base)); - } else { - enc.add1(modrm(mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, index, base)); - } - - if( mod == MOD.INDIRECT_disp8 ) { - enc.add1(offset); - } else if( mod == MOD.INDIRECT_disp32 ) { - enc.add4(offset); - } - } - - // Limit of float args passed in registers static RegMask[] XMMS8 = new RegMask[]{ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3), diff --git a/chapter23/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter23/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index bf809d2a..9f626805 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; import com.seaofnodes.simple.node.cpus.riscv.riscv; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter23/src/test/java/com/seaofnodes/simple/Chapter21Test.java index 14f9fdb8..9aa18821 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java index def21258..46457b40 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import java.io.IOException; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java index 41f0df6e..10d27ac8 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter23/src/test/java/com/seaofnodes/simple/EvalArm64.java deleted file mode 100644 index e0cbdcff..00000000 --- a/chapter23/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ /dev/null @@ -1,766 +0,0 @@ -package com.seaofnodes.simple; - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.arm.arm; -import com.seaofnodes.simple.util.Utils; -import java.io.ByteArrayOutputStream; - -public class EvalArm64 { - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - // flags - boolean N = false; - boolean Z = false; - boolean C = false; - boolean V = false; - - EvalArm64(byte[] buf, int stackSize) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[arm.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - public int step(int maxops) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for(int icount = 0; icount < maxops; icount++) { - int ir = 0; - rval = 0; - frval = 0; - cycle++; - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - - // Load instruction from image buffer at PC - ir = ld4s( pc ); - - int rdid = ir & 0x1f; - // [31:24] - int opcode1 = (ir >> 24) & 0xFF; - - // for the opcode we just match for bits[31:24]; - switch( opcode1 ) { - case 0x14, 0x15, 0x16, 0x17: { //b - int imm26 = ir << 6 >> 6; - pc = pc + (imm26 * 4) - 4; - rdid = -1; - break; - } - case 0x1E: { // floats - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - int rs2 = (ir >> 16) & 0x1F; - - int op = (ir >> 10) & 0x3F; - switch(op) { - case 16: frval = fregs[rs1]; break; // fmov - case 10:frval = fregs[rs1] + fregs[rs2]; break; // fadd - - case 6: if (fregs[rs2] == 0) frval = 0; else frval = fregs[rs1] / fregs[rs2]; break; // fdiv - case 8: { - // fcmp - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - - Z = (lhs == rhs); - N = (lhs < rhs); - C = lhs >= rhs; - V = Double.isNaN(lhs) || Double.isNaN(rhs); - rdid = -1; - - break; - } - case 2: frval = fregs[rs1] * fregs[rs2]; break; // fmul - case 14: frval = fregs[rs1] - fregs[rs2]; break; // fsub - default: trap = (2+1); - } - break; - } - - case 0x38: { - // STRB/LDRB(register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch( ir >> 21 & 0x7 ) { - case 0x1 -> { // store - if( opcode1 == arm.OP_STORE_R_8 ) st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - else trap = (2+1); - rdid = -1; - } - case 0x3 -> { // load - if( opcode1 == arm.OP_LOAD_R_8 ) rval = ld1s((int)regs[rn] + (int)regs[rm]); - else trap = (2+1); - } - default -> trap = (2+1); - } - break; - } - case 0x39: { - // STRB/LDRB(immediate) - // str/ldr(immediate) - // rn - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_8) { - st1((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_8) { - rval = ld1s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - case 0x54: { - // b.cond - int imm19 = ir << 8 >> 13; - imm19 = pc + (imm19 * 4) - 4; - rdid = -1; - - switch(ir & 0xF) { - case 0x0: if(Z) pc = imm19; break; // eq - case 0x1: if(!Z) pc = imm19; break; // ne - case 0x2: if(C) pc = imm19; break; // cs - case 0x3: if(!C) pc = imm19; break; - case 0x4: if(N) pc = imm19; break; // mi - case 0x5: if(!N) pc = imm19; break; // pl - case 0x6: if(V) pc = imm19; break; // vs - case 0x7: if(!V) pc = imm19; break; // vc - case 0x8: if(C && !Z) pc = imm19; break; // hi - case 0x9: if(!C || Z) pc = imm19; break; // ls - case 0xA: if(N == V) pc = imm19; break; // ge - case 0xB: if(N != V) pc = imm19; break; // lt - case 0xC: if(!Z && N == V) pc = imm19; break; // gt - case 0xD: if(Z || N != V) pc = imm19; break; // le - case 0xE: pc = imm19; break; // always executed(al) - default: trap = (2+1); - } - break; - } - - case 0x5c: { - // ldr - is_f = true; - // address = delta - int address = ir << 8 >> 13; - address *= 4; - if(address >= _buf.length-3) trap = (5 + 1); - frval = ld8f(pc + address); - break; - } - - case 0x78: { - // STRH/LDRH(register) - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - // store - if(opcode1 == arm.OP_STORE_R_16) { - st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_16) { - rval = ld1s((int)regs[rn] + (int)regs[rm]); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - break; - } - - case 0x79: { - // STRH/LDRH(immediate) - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 2; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_16) { - st2((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_16) { - rval = ld2s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - - case 0x8A: { // AND - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] & regs[rm]; - break; - } - - case 0x8B, 0xCB: { - // add/sub(register), unshifted form emitted by Simple - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = opcode1==0x8B ? lhs + rhs : lhs - rhs; - break; - } - - case 0x90: { // adrp - int immhi = ( (ir& ~0x1F) << 8 ) >> 8; - int immlo = (ir>>29)& 3; - int imm = ((immhi<<2) | immlo) << 12; - rval = (pc & ~0xFFF) + imm; - break; - } - - case 0x91, 0xD1: { // ADD/SUB (immediate), unsigned imm12, optional LSL #12 - int rn = (ir >> 5) & 0x1F; - long immediate = (ir >>> 10) & 0xFFF; - if( (ir & (1<<22))!=0 ) immediate <<= 12; - rval = opcode1==0x91 ? regs[rn] + immediate : regs[rn] - immediate; - break; - } - case 0x92: { // and(immediate) - int imm12 = (ir >> 10) & 0x1FFF; - long immediate = arm.decodeImm12(imm12); - int rn = (ir >> 5) & 0x1F; - rval = regs[rn] & immediate; - break; - } - case 0x93, 0xD3: { // SBFM/UBFM: shifts and signed/unsigned extracts - int immr = (ir >>> 16) & 63; - int imms = (ir >>> 10) & 63; - int rn = (ir >>> 5) & 31; - boolean signed = (ir & 0x40000000)==0; - long value = regs[rn] << (63-imms); - value = signed ? value >> (63-imms) : value >>> (63-imms); - rval = immr > imms ? value << (64-immr) - : signed ? value >> immr : value >>> immr; - break; - } - - case 0x94, 0x95, 0x96, 0x97: { // bl - rdid = -1; // BL writes only X30, not a displacement-selected register. - rval = pc + 4; - regs[arm.X30] = rval; - int imm26 = (ir & 0x03FFFFFF); - int imm = (imm26 << 6) >> 6; - pc = pc + (imm << 2) ; - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - long size = regs[arm.X0]*regs[arm.X1]; - size = (size+7) & -8; // 8-byte aligned - regs[arm.X0] = _heap; - _heap += (int)size; - pc = (int)rval; - rdid = -1; - } - if( pc == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[0]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[1],(int)regs[2]); - regs[0] = regs[2]; - pc = (int)rval; - rdid = -1; - } - pc -= 4; - break; - } - - case 0x9A: { - // conditional select(csel) - int rm = (ir >> 16) & 0x1F; - switch((ir >> 12) & 0xF) { - case 0x0: if(Z) rval = regs[rm]; break; // eq - case 0x1: if(!Z) rval = regs[rm]; break; // ne - case 0x2: if(C) rval = regs[rm]; break; // cs - case 0x3: if(!C) rval = regs[rm]; break; - case 0x4: if(N) rval = regs[rm]; break; // mi - case 0x5: if(!N) rval = regs[rm]; break; // pl - case 0x6: if(V) rval = regs[rm]; break; // vs - case 0x7: if(!V) rval = regs[rm]; break; // vc - case 0x8: if(C && !Z) rval = regs[rm]; break; // hi - case 0x9: if(!C || Z) rval = regs[rm]; break; // ls - case 0xA: if(N == V) rval = regs[rm]; break; // ge - case 0xB: if(N != V) rval = regs[rm]; break; // lt - case 0xC: if(!Z && N == V) rval = regs[rm]; break; // gt - case 0xD: if(Z || N != V) rval = regs[rm]; break; // le - case 0xE: rval = regs[rm]; break; // always executed(al) - default: rval = regs[(ir >> 5) & 0x1F]; - } - break; - } - case 0x9B: { // mul - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] * regs[rm]; - break; - } - case 0x9E: { - // scvtf - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - frval = (double)regs[rs1]; - break; - } - - case 0xAA: { - // MOV(register) - int rm = (ir >> 16) & 0x1F; - rval = regs[rm]; - break; - } - - case 0xB8: { - // LDR/STR (register + index) 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if( opcode1 == arm.OP_LOAD_R_32) { - rval = ld4s((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xB9: { - // str/ldr(immediate) 32 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 4; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_32) { - rval = ld4s((int) rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xBC: { - // LDR/STR (register + index) float 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_32) { - frval = ld4f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xBD: { - // LDR/STR(immediate) 32 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 4; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xD2: // MOVZ - case 0xF2: { // MOVK preserves the other halfwords - // movz - // get immediate - int shift = ((ir >> 21) & 3)*16; - rval = ((ir >> 5) & 0xFFFFL) << shift; - if( opcode1==0xF2 ) rval |= regs[rdid] & ~(0xFFFFL << shift); - break; - } - - case 0xEB: { - // subs(shifted register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = lhs - rhs; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= rhs; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (rhs >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - - case 0xD6: { - int op = ir & 0xFFFFFC1F; - int rn = (ir >>> 5) & 31; - int target = (int)regs[rn]; // Read before BLR overwrites X30. - rdid = -1; - if( op==0xD63F0000 ) regs[arm.X30] = pc+4; // BLR - else if( op!=0xD65F0000 ) { trap = 3; break; } // RET - pc = target; - if( op==0xD65F0000 && pc==0 ) break outer; - pc -= 4; - break; - } - - case 0xF1: { - // subs(immediate) - int rn = (ir >> 5) & 0x1F; - int immediate = ir << 10 >> 20; - long lhs = regs[rn]; - - rval = lhs - immediate; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= immediate; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (immediate >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - case 0xF8: { - // LDR/STR (register + index) 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_64) { - rval = ld8((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xF9: { - // str/ldr(immediate) 64 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_64) { - st8((int)rval, regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_64) { - rval = ld8((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xFC: { - // LDR/STR (register + index) float 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_64) { - frval = ld8f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xFD: { - // LDR/STR(immediate) 64 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - default: trap = (2+1); - } - - if(trap != 0) { - _pc = pc; - break; - } - if(rdid != -1) { - if(is_f) {fregs[rdid] = frval; is_f = false;} - else regs[rdid] = rval; - } - - pc += 4; - } - // Handle traps and interrupts. - if(trap != 0) { - return trap; - } - _cycle = cycle; - _pc = pc; - return 0; - } - - -} diff --git a/chapter23/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java b/chapter23/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java index 0f09b7f0..11881194 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.RegAllocTestSupport; import com.seaofnodes.simple.node.*; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter23/src/test/java/com/seaofnodes/simple/MergeSortTest.java index d1fbd7df..39cacd98 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.node.cpus.riscv.riscv; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter23/src/test/java/com/seaofnodes/simple/TestArm64.java index edce92f3..a22063eb 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter23/src/test/java/com/seaofnodes/simple/TestRisc5.java index adb256eb..ace2a7ea 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter23/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.FunNode; diff --git a/chapter24/Makefile b/chapter24/Makefile index 1c3f409f..e02c8096 100644 --- a/chapter24/Makefile +++ b/chapter24/Makefile @@ -66,6 +66,7 @@ test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java) main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas)) include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk)) include $(firstword $(wildcard ../print/print.mk print/print.mk)) +include $(firstword $(wildcard ../isa/isa.mk isa/isa.mk)) test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas)) test_cp := $(patsubst $(TST)/$(SIMPLE)/%.java,com.seaofnodes.simple.%,$(wildcard $(TST)/$(SIMPLE)/*Test.java)) com.seaofnodes.simple.codegen.X86EncodingTest classes = $(main_classes) $(test_classes) @@ -108,8 +109,8 @@ $(main_classes): $(CLZDIR)/main/.mtag ####################################################### -OODT := -$(CLZDIR)/test/.ttag: $(test_classes) $(test_javas) $(CLZDIR)/main/.mtag +OODT := $(isa_test_javas) +$(CLZDIR)/test/.ttag: $(test_classes) $(test_javas) $(isa_test_javas) $(CLZDIR)/main/.mtag @[ -d $(CLZDIR)/test ] || mkdir -p $(CLZDIR)/test $(file >.argsT.txt,$(OODT)) @if [ ! -z "$(OODT)" ] ; then \ diff --git a/chapter24/pom.xml b/chapter24/pom.xml index 07a943f9..f16562a8 100644 --- a/chapter24/pom.xml +++ b/chapter24/pom.xml @@ -15,4 +15,32 @@ <simple.graph.directory>${project.basedir}/../graph</simple.graph.directory> <simple.print.directory>${project.basedir}/../print</simple.print.directory> </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>shared-isa-sources</id> + <phase>generate-sources</phase> + <goals><goal>add-source</goal></goals> + <configuration> + <sources> + <source>${project.basedir}/../isa/src/main/java</source> + </sources> + </configuration> + </execution> + <execution> + <id>shared-isa-test-sources</id> + <phase>generate-test-sources</phase> + <goals><goal>add-test-source</goal></goals> + <configuration><sources> + <source>${project.basedir}/../isa/src/test-support/java</source> + </sources></configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 4e7166fa..b5a8e148 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -19,7 +19,7 @@ import java.util.*; * There are also a bunch of generic utilities for managing bits and bytes * common in all encodings. */ -public class Encoding { +public class Encoding implements com.seaofnodes.isa.CodeSink { // Top-level program graph structure public final CodeGen _code; diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index 1c865254..76e47ca2 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // ADD (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_ADD); } // General form: "rd = rs1 + rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index eb75c1a0..67a10b48 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } //FADD (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);} + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_OP_ADD);} // Default on double precision for now(64 bits) // General form: "addf rd = src1 + src2 diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index 93c9e8c3..4c635d07 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class AddIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } //ADD (immediate) @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_ADD,_imm); } // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index 77115d54..1a0365ad 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -13,7 +14,7 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // AND (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_AND); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_AND); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb){ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java index 5b739cd3..6292e98e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,10 +16,10 @@ public class AndIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc,this, in(1), arm.OPI_AND,_imm); + arm.imm_inst_n(enc,this, in(1), Arm64.OPI_AND,_imm); } // General form: "andi rd = rs1 & imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm)); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(Arm64.decodeImm12(_imm)); } }
\ No newline at end of file diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index b83fb3cb..77f14d4c 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sar"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_ASR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_ASR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> ").p(code.reg(in(2))); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java index 38373e67..7cb42eec 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,7 +23,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_ASR,_imm, 0b111111, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_ASR,_imm, 0b111111, rn, rd)); } // General form: "asri rd = rs1 >> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index b9ede544..127f17ff 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -35,10 +36,10 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // by comparison (or sub). No need for regs because it uses flags if( in(1)!=null ) { // B.cond - enc.add4( arm.b_cond(arm.OP_BRANCH, 0, arm.make_condition(_bop)) ); + enc.add4( Arm64.b_cond(Arm64.OP_BRANCH, 0, Arm64.make_condition(_bop)) ); } else { if( _bop=="!=" ) return; // Inverted, no code - enc.add4(arm.b(arm.OP_UJMP, 0)); + enc.add4(Arm64.b(Arm64.OP_UJMP, 0)); } enc.jump(this,cproj(0)); } @@ -55,7 +56,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( opLen==4 ) { - enc.patch4(opStart,arm.b_cond(arm.OP_BRANCH, delta, arm.make_condition(_bop))); + enc.patch4(opStart,Arm64.b_cond(Arm64.OP_BRANCH, delta, Arm64.make_condition(_bop))); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 427cf2e2..e1717cb3 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -30,7 +31,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); // BL - enc.add4(arm.b(arm.OP_CALL,0)); // Target patched at link time + enc.add4(Arm64.b(Arm64.OP_CALL,0)); // Target patched at link time } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -38,7 +39,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - enc.patch4(opStart,arm.b(arm.OP_CALL,delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_CALL,delta)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index c84aa9e5..1949ae46 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class CallRRARM extends CallNode implements MachNode { // Needs a register, typically a jump-and-link-register opcode // blr short self = enc.reg(this); - enc.add4(arm.blr(arm.OP_CALLRARM, self)); + enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index 794ff0c9..1bd9c372 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.FLAGS_MASK; } // SUBS (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,arm.OP_CMP); } + @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,Arm64.OP_CMP); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java index f84a1649..cd4dd9cf 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -28,7 +29,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public Node copy() { return new CmpIARM(this); } - @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), arm.OPI_CMP,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), Arm64.OPI_CMP,_imm); } // General form: "cmp rs1, 1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index de254eeb..e94b6491 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // SDIV - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_DIV,3); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_DIV,3); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 813bebe4..68ad6047 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } // FDIV (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_DIV); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_DIV); } // General form: "VDIF = dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java index 26a237d0..814a82c2 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,7 +23,7 @@ public class ExtendARM extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); // SBFM/UBFM aliases: sign/zero extend the low byte, short or int. - enc.add4(arm.imm_shift(_signed ? arm.OPI_ASR : arm.OPI_LSR,0,_bits-1,src,dst)); + enc.add4(Arm64.imm_shift(_signed ? Arm64.OPI_ASR : Arm64.OPI_LSR,0,_bits-1,src,dst)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java index b47b65ad..dc21e075 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FloatARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -20,7 +21,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/); short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.add4(arm.load_pc(arm.OPF_ARM, 0, dst)); + enc.add4(Arm64.load_pc(Arm64.OPF_ARM, 0, dst)); } // Delta is from opcode start. @@ -29,7 +30,7 @@ public class FloatARM extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.patch4(opStart, arm.load_pc(arm.OPF_ARM, delta, dst)); + enc.patch4(opStart, Arm64.load_pc(Arm64.OPF_ARM, delta, dst)); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java index b9e85202..17cafcde 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -16,6 +17,6 @@ public class FunARM extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(arm.imm_inst(arm.OPI_SUB, sz, arm.RSP, arm.RSP)); + enc.add4(Arm64.imm_inst(Arm64.OPI_SUB, sz, arm.RSP, arm.RSP)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index f1fa162f..b1c30afc 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,7 +14,7 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(arm.OP_FLOAT_C, 1, reg1, self); + int body = Arm64.float_cast(Arm64.OP_FLOAT_C, 1, reg1, self); enc.add4(body); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index ee74b95e..7a9e74c6 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,39 +22,7 @@ public class IntARM extends ConstantNode implements MachNode { @Override public void encoding( Encoding enc ) { short self = enc.reg(this); long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); - int nb0 = 0; - int nb1 = 0; - // Count number of 0000 and FFFF blocks - for (int i=0; i<64; i+=16) { - int block = (int)(x >> i) & 0xFFFF; - if (block == 0) nb0++; - if (block == 0xFFFF) nb1++; - } - int pattern; - int op; - if(nb0 >= nb1) { - // More 0 blocks then F blocks, use movz - pattern = 0; - op = arm.OP_MOVZ; - } else { - // More F blocks then 0 blocks, use movn - pattern = 0xFFFF; - op = arm.OP_MOVN; - } - int invert = pattern; - for (int i=0; i<4; i++) { - int block = (int)x & 0xFFFF; - x >>= 16; - if (block != pattern) { - enc.add4(arm.mov(op, i, block ^ invert, self)); - op = arm.OP_MOVK; - invert = 0; - } - } - if (op != arm.OP_MOVK) { - // All blocks are the same, special case - enc.add4(arm.mov(op, 0, 0, self)); - } + Arm64.constant(enc,self,x); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 8967d654..f3bbbbeb 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -18,9 +19,9 @@ public class LoadARM extends MemOpARM { @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } - private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; + private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, }; - private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; + private static final int[] OP_LOAD_RS = new int[]{ Arm64.OP_LOAD_R_8 , Arm64.OP_LOAD_R_16 , Arm64.OP_LOAD_R_32 , Arm64.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index 80ce493f..954cfac2 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSL); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSL); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << ").p(code.reg(in(2))); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java index 7fe16cbe..b32153ab 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -24,7 +25,7 @@ public class LslIARM extends MachConcreteNode implements MachNode { assert _imm > 0; // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) // immr must be (-<shift> MOD 64) = 64 - shift - enc.add4(arm.imm_shift(arm.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); } // General form: "lsli rd = rs1 << imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index fc005e04..91be34e3 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> ").p(code.reg(in(2))); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java index 78844b0a..243ce968 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_LSR,_imm, 0b111111, rn,rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSR,_imm, 0b111111, rn,rd)); } // General form: "lsri rd = rs1 >>> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index 9257f25b..dfbe5e06 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -64,8 +65,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { val -= arm.D0; } int body = off() == null - ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) - : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? Arm64.load_str_imm(opcode_imm, _off, ptr, val, size) + : Arm64.indr_adr(opcode_reg, off, Arm64.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index a23ec75b..f598cefb 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_MUL,31); } // General form: "rd = rs1 * rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 73ebbf00..a4f81fd4 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class MulFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_MUL); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_MUL); } // Default on double precision for now(64 bits) // General form: "VMUL.f32 rd = src1 * src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index c1aad15f..7110df62 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,8 +12,8 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { // BL(branch with link) enc.external(this,"calloc"). - add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1 - add4(arm.b(arm.OP_CALL, 0)); + add4(Arm64.mov(Arm64.OP_MOVZ, 0, 1, 0)). // movz x0,#1 + add4(Arm64.b(Arm64.OP_CALL, 0)); } // Patch is for running "new" in a JIT. @@ -24,7 +25,7 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void patch(Encoding enc, int opStart, int opLen, int delta ) { // Negative patches are JIT emulator targets. if( opStart+delta < 0 ) { - enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4)); + enc.patch4(opStart+4, Arm64.b_calloc(Arm64.OP_CALL, delta-4)); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index d78421ca..ac21c706 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -17,9 +18,9 @@ public class NotARM extends MachConcreteNode implements MachNode{ // subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int subs = arm.imm_inst(arm.OP_SUBS, 0, reg1, self); + int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(arm.OP_CSET, 31, arm.COND.EQ, 31, reg1); + int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 31, reg1); enc.add4(cset); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index e8245749..5b7264ec 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class OrARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "|"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_OR); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" | ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index a48caa51..86d07bee 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,7 +16,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm); + arm.imm_inst_n(enc, this, in(1), Arm64.OPI_OR, _imm); } // General form: "ori rd = rs1 | imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 4597666b..a7ed5073 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class RetARM extends ReturnNode implements MachNode { @Override public void encoding( Encoding enc ) { int frameAdjust = ((FunARM)fun())._frameAdjust; if( frameAdjust > 0 ) - enc.add4(arm.imm_inst(arm.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); - enc.add4(arm.ret(arm.OP_RET)); + enc.add4(Arm64.imm_inst(Arm64.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); + enc.add4(Arm64.ret(Arm64.OP_RET)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index e1b3b3b6..afbbd3bf 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -21,7 +22,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { // Using RM==RN==31 implies a *zero* value, not R31. - int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop), 0b011111, enc.reg(this)); + int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index 5af45892..f93f0f24 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -26,7 +27,7 @@ public class SplitARM extends SplitNode { } int off = enc._fun.computeStackOffset(enc._code,dst); if( srcX ) src -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_STORE_IMM_64, off, arm.RSP, src, 8)); return; } @@ -34,26 +35,26 @@ public class SplitARM extends SplitNode { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); if( dstX ) dst -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); return; } // pick opcode based on regs if(!dstX && !srcX) { // GPR->GPR - enc.add4(arm.mov_reg(arm.OP_MOV, src, dst)); + enc.add4(Arm64.mov_reg(Arm64.OP_MOV, src, dst)); } else if(dstX && srcX) { // FPR->FPR // fmov reg - enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_reg(Arm64.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); } else if(!srcX && dstX) { // GPR->FPR // FMOV(general) 64 bits to DOUBLE-PRECISION - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); } else if( srcX && !dstX) { //FPF->GPR // FMOV(general) DOUBLE-PRECISION to 64 bits - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 4fd8ac79..2cc54f76 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.StoreNode; @@ -22,9 +23,9 @@ public class StoreARM extends MemOpARM { @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; + private static final int[] OP_STORES = new int[]{ Arm64.OP_STORE_IMM_8, Arm64.OP_STORE_IMM_16, Arm64.OP_STORE_IMM_32, Arm64.OP_STORE_IMM_64, }; - private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; + private static final int[] OP_STORE_RS = new int[]{ Arm64.OP_STORE_R_8, Arm64.OP_STORE_R_16, Arm64.OP_STORE_R_32, Arm64.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[_declaredType.log_size()], val(), size()); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index e3b95e50..fd5cd4de 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_SUB); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index a252e542..1a751434 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class SubFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_SUB); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_SUB); } // Default on double precision for now(64 bits) // General form: "vsub.f32 rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index b50107c9..b2c0b2ed 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -18,7 +19,7 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_SUB,_imm); } // General form: "subi rd = rs1 - imm" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 29d490ef..98a56089 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -19,10 +20,10 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { enc.relo(this); short self = enc.reg(this); // adrp x0, 0 - int adrp = arm.adrp(1,0, arm.OP_ADRP, 0,self); + int adrp = Arm64.adrp(1,0, Arm64.OP_ADRP, 0,self); // add x0, x0, 0 enc.add4(adrp); - arm.imm_inst(enc,arm.OPI_ADD,0, 0); + arm.imm_inst(enc,Arm64.OPI_ADD,0, 0); } @Override public byte encSize(int delta) { @@ -39,9 +40,9 @@ public class TFPARM extends ConstantNode implements MachNode, RIPRelSize { delta = target-base; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, rpc)); // low 12 bits via add - enc.patch4(opStart+4, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, rpc)); + enc.patch4(opStart+4, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, rpc)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java index cdcaa433..d1cafa96 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -19,9 +20,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { @@ -38,9 +39,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { delta = target-base; int adrp_delta = delta >> 12; // patch upper 20 bits via adrp - enc.patch4(opStart, arm.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, dst)); + enc.patch4(opStart, Arm64.adrp(1, adrp_delta & 0b11, 0b10000, adrp_delta >> 2, dst)); // low 12 bits via add - enc.patch4(opStart+4, arm.imm_inst_l(arm.OPI_ADD, delta & 0xfff, dst)); + enc.patch4(opStart+4, Arm64.imm_inst_l(Arm64.OPI_ADD, delta & 0xfff, dst)); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java index ce4f523c..aecd02bb 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,7 +20,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - int body = arm.b(arm.OP_UJMP, 0); + int body = Arm64.b(Arm64.OP_UJMP, 0); enc.add4(body); } @@ -33,7 +34,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,arm.b(arm.OP_UJMP, delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_UJMP, delta)); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index 52bda021..d56397a3 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class XorARM extends MachConcreteNode implements MachNode{ @Override public String glabel() { return "^"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_XOR); } // General form: "rd = x1 ^ x2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ ").p(code.reg(in(2))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java index 23b29644..12143ccd 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -19,7 +20,7 @@ public class XorIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // General form: "xori rd = rs1 ^ imm" - @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), Arm64.OPI_XOR,_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index eab72947..f512f467 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; +import static com.seaofnodes.isa.Arm64.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -81,102 +83,6 @@ public class arm extends Machine { static final RegMask D6_MASK = new RegMask(D6); static final RegMask D7_MASK = new RegMask(D7); - // major opcode: OP - public static int OP_ADD = 0b10_001_011; - public static int OPF_ADD = 0b00_011_110; - public static int OPF_OP_ADD = 0b00_101_0; - public static int OPI_ADD = 0b10_010_00100; - - public static int OPI_SUB = 0b11_010_00100; - public static int OP_UJMP = 0b000101; - - public static int OP_ADRP = 0b10000; - - public static int OP_ASR = 0b1010; - public static int OPI_ASR = 0b10_0100_1101; - - public static int OP_LSL = 0b1000; - public static int OPI_LSL =0b1101001101; - - public static int OP_LSR = 0b1001; - public static int OPI_LSR = 0b1101001101; - - public static int OP_BRANCH = 0b01_0101_00; - public static int OP_CALL = 0b10_010_1; - - public static int OP_CALLRARM = 0b1101011000111111000000; - - public static int OP_SUBS = 0b1111000100; - public static int OP_CSET = 0b10011010100; - public static int OP_CMP = 0b11101011; - public static int OPI_CMP = 0b1111000100; - - public static int OP_DIV = 0b10011010110; - public static int OPF_DIV = 0b000110; - - public static int OP_MUL = 0b10011011000; - public static int OPF_MUL = 0b10; - - public static int OPF_ARM = 0b01011100; - - public static int OP_FLOAT_C = 0b10011110; - - public static int OP_XOR = 0b11001010; - public static int OPI_XOR = 0b110100100; - - public static int OP_AND = 0b10_0010_10; - public static int OPI_AND = 0b10_0100_100; - - public static int OP_OR = 0b10101010; - public static int OPI_OR = 0b101100100; - - public static int OP_SUB = 0b11001011; - public static int OPF_SUB = 0b1110; - - public static int OP_MOVK = 0b111100101; - public static int OP_MOVN = 0b100100101; - public static int OP_MOVZ = 0b110100101; - - public static int OP_RET = 0b1101011001011111000000; - // Store/load opcodes - public static int OP_LOAD_R_64 = 0b11111000011; - public static int OP_LOAD_R_32 = 0b10111000011; - public static int OP_LOAD_R_16 = 0b01111000010; - public static int OP_LOAD_R_8 = 0b00111000011; - - public static int OP_LOAD_IMM_64 = 0b1111100101; - public static int OP_LOAD_IMM_32 = 0b1011100101; - public static int OP_LOAD_IMM_16 = 0b0111100101; - public static int OP_LOAD_IMM_8 = 0b0011100101; - - // load - public static int OPF_LOAD_R_64 = 0b11111100011; - public static int OPF_LOAD_R_32 = 0b10111100011; - - public static int OPF_LOAD_IMM_64 = 0b1111110101; - public static int OPF_LOAD_IMM_32 = 0b1011110101; - - public static int OP_STORE_R_64 = 0b11111000001; - public static int OP_STORE_R_32 = 0b10111000001; - public static int OP_STORE_R_16 = 0b01111000001; - public static int OP_STORE_R_8 = 0b00111000001; - - public static int OP_STORE_IMM_64 = 0b1111100100; - public static int OP_STORE_IMM_32 = 0b1011100100; - public static int OP_STORE_IMM_16 = 0b0111100100; - public static int OP_STORE_IMM_8 = 0b0011100100; - - public static int OPF_STORE_R_64 = 0b11111100001; - public static int OPF_STORE_R_32 = 0b10111100001; - - public static int OPF_STORE_IMM_32 = 0b1011110100; - public static int OPF_STORE_IMM_64 = 0b1111110100; - - - public static int OP_FMOV = 0b10011110; - public static int OP_FMOV_REG = 0b00011110; - // https://docsmirror.github.io/A64/2023-06/mov_orr_log_shift.html - public static int OP_MOV = 0b10101010000; // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 @@ -202,56 +108,6 @@ public class arm extends Machine { }; // ARM ENCODING - public enum OPTION { - UXTB, - UXTH, - UXTX, - SXTB, - SXTH, - SXTW, - SXTX, - } - - static public int cset(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - // Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least significant bit inverted. - int actualCond = cond.ordinal() ^ 1; - return (opcode << 21) | (rm << 16) | (actualCond << 12) | (0b01 << 10) | (rn << 5) | rd; - } - - static public int cset(int opcode, COND cond, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - public enum STORE_LOAD_OPTION { - UXTW, // base+ u32 index [<< logsize] - UXTX, // base+ u64 index [<< logsize] - SXTW, // base+ s32 index [<< logsize] - SXTX, // base+ s64 index [<< logsize] - } - - public enum COND { - EQ, - NE, - CS, - CC, - MI, - PL, - VS, - VC, - HI, - LS, - GE, - LT, - GT, - LE, - AL, - NV - } // True if signed 9-bit immediate private static boolean imm9(TypeInteger ti) { @@ -264,55 +120,10 @@ public class arm extends Machine { return ti.isConstant() && ((ti.value()<<52)>>52) == ti.value(); } - // Can we encode this in ARM's 12-bit LOGICAL immediate form? // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { - if( !ti.isConstant() ) return -1; - if( !ti.isConstant() ) return -1; - long val = ti.value(); - if (val == 0 || val == -1) return -1; // Special cases are not allowed - int immr = 0; - // Rotate until we have 0[...]1 - - // Rotate until: - // The number is negative (MSB is 1) - // Or the LSB is not 1 - while (val < 0 || (val & 1)==0) { - // circular rotation - val = (val >>> 63) | (val << 1); - immr++; - } - // Start by assuming that val might be made of two 32-bit chunks that repeat. - int size = 32; - long pattern = val; - // Is upper half of pattern the same as the lower? - while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { - // Then only take one half - pattern >>= size; - size >>= 1; - } - size <<= 1; - int imms = Long.bitCount(pattern); - // Pattern should now be zeros followed by ones 0000011111 - if (pattern != (1L<<imms)-1) return -1; - imms--; - if (size == 64) return 0x1000 | immr << 6 | imms; - return (32-size)<<1 | immr << 6 | imms; - } - - // sh is encoded in opcode - public static int imm_inst(int opcode, int imm12, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; - } - - public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + return ti.isConstant() ? Arm64.logicalImmediate(ti.value()) : -1; } public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) { @@ -324,64 +135,46 @@ public class arm extends Machine { opcode ^= OPI_ADD ^ OPI_SUB; imm12 = -imm12; } - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); enc.add4(body); } public static void imm_inst_subs(Encoding enc, Node n,Node n2, int opcode, int imm12) { short reg1 = enc.reg(n2); // 31 = 11111 - int body = imm_inst(opcode, imm12&0xFFF, reg1, 31); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, 31); enc.add4(body); } // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static void imm_inst(Encoding enc, int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, self, self); enc.add4(body); } public static void imm_inst_n(Encoding enc, Node n, Node n2, int opcode, int imm13) { short self = enc.reg(n); short reg1 = enc.reg(n2); - int body = imm_inst_n(opcode, imm13, reg1, self); + int body = Arm64.imm_inst_n(opcode, imm13, reg1, self); enc.add4(body); } - // nth bit comes from immediate and not opcode - public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= imm13 && imm13 <= 0x1FFF; - return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; - } - - public static int imm_inst_l(int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); - return body; - } - // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); return body; } // for normal add, reg1, reg2 cases (reg-to-reg) // using shifted-reg form - public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; - } + public static void r_reg(Encoding enc, Node n, int opcode) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); enc.add4(body); } @@ -389,210 +182,43 @@ public class arm extends Machine { short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); // 31 = 11111 - int body = r_reg(opcode, 0, reg2, 0, reg1, 31); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, 31); enc.add4(body); } - public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; - } public static void shift_reg(Encoding enc, Node n, int op2) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(0b10011010110, reg2, op2, reg1, self); + int body = Arm64.shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } // MUL can be considered an alias for MADD with the third operand Ra being set to 0 - public static int madd(int opcode, int rm, int ra, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; - } + public static void madd(Encoding enc, Node n, int opcode, int ra) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = madd(opcode, reg2, ra, reg1, self); + int body = Arm64.madd(opcode, reg2, ra, reg1, self); enc.add4(body); } - // encodes movk, movn, and movz - public static int mov(int opcode, int shift, int imm16, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; - } - - public static int mov_reg(int opcode, int src, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; - } - - public static int ret(int opcode) { - return (opcode << 10) | (X30 << 5); - } - - // FMOV (scalar, immediate) - public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; - } - - public static int f_mov_reg(int opcode, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; - } - public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; - } public static void f_scalar(Encoding enc, Node n, int op ) { short self = (short)(enc.reg(n) -D_OFFSET); short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); + int body = Arm64.f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } - // share same encoding with LDR (literal, SIMD&FP) flavour - public static int load_pc(int opcode, int offset, int rt) { - offset>>=2; - return (opcode << 24) | (offset << 5) | rt; - } - // int l - public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { - assert 0 <= rd && rd < 32; - return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; - } - - // [Rptr+Roff] - public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; - } - // [Rptr+imm9] - public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - - if(size == 8) imm12 = imm12 >> 3; - if(size == 4) imm12 = imm12 >> 2; - if(size == 2) imm12 = imm12 >> 1; - // size == 1 imm12 = imm12 - return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; - } - - // encoding for vcvt, size is encoded in operand - // <Qd>, <Qm> - // F32.S32 - //encoded as op = 0b00, size = 0b10. - // VCVT<c>.<Td>.<Tm> <Dd>, <Dm> - // opcode is broken down into 4 pieces - public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { - return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | - (vd << 12) | (0x01100010 << 4) | vm; - } - public static int float_cast(int opcode, int ftype, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; - } - - - // ftype = 3 - public static int f_cmp(int opcode, int ftype, int rm, int rn) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - // Todo: |8 is not needed - return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); - } public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_cmp(0b00011110, 3, reg1, reg2); + int body = Arm64.f_cmp(0b00011110, 3, reg1, reg2); enc.add4(body); } - public static COND make_condition(String bop) { - return switch (bop) { - case "==" -> COND.EQ; - case "!=" -> COND.NE; - case "<" -> COND.LT; - case "<=" -> COND.LE; - case ">=" -> COND.GE; - case ">" -> COND.GT; - default -> throw Utils.TODO(); - }; - } - - public static int b_cond(int opcode, int delta, COND cond) { - // 24-5 == 19bits offset range - assert -(1<<19) <= delta && delta < (1<<19); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<19)-1; // Zero extend - return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); - } - - public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - // Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4. - public static int blr(int opcode, int rd) { - assert 0 <= rd && rd < 32; - return opcode << 10 | rd << 5; - } - public static int b(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - // no aligned assert(assert (delta&3)==0;) - public static int b_calloc(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - - public static long decodeImm12(int imm12) { - int immr = (imm12 >> 6) & 0x3F; - int imms = imm12 & 0x3F; - int size; - if ((imm12 & 0x1000) != 0) { - size = 64; - } else { - size = 31-(imms >> 1); - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size++; - imms &= ~((32-size) << 1); - } - long val = (2L << imms)-1; - while (size < 64) { - val |= val << size; - size <<= 1; - } - val = (val >>> immr) | val << (64-immr); - return val; - } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; @@ -797,7 +423,6 @@ public class arm extends Machine { : new LsrARM(lsr); } - private static int off; private static Node idx; private Node st(StoreNode st) { @@ -823,7 +448,6 @@ public class arm extends Machine { return mop; } - private Node prj(ProjNode prj) { TypeInteger ret = cReturn(prj); return ret==null ? new ProjARM(prj) : new ExtendARM(prj,ret); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 2cd00845..14581111 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -18,7 +19,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); short dst = enc.reg(this); - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -29,7 +30,7 @@ public class AUIPC extends ConstantNode implements MachNode, RIPRelSize { //short rpc = enc.reg(this); //// High half is where the TFP constant used to be, the last input //short auipc = enc.reg(in(_inputs._len-1)); - //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + //enc.patch4(opStart,RiscV.i_type(0x67, rpc, 0, auipc, delta)); throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java index 8636df9f..d87e49b9 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AddFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,1); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,1); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java index 511b0583..8012b61e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -8,7 +9,7 @@ public class AddIRISC extends ImmRISC { public AddIRISC( Node add, int imm12, boolean pop ) { super(add,imm12,pop); } @Override public String op() { return "addi"; } @Override public String glabel() { return "+"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 0;} @Override public AddIRISC copy() { // Clone the AddI, using the same inputs-only code used during inst select. diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java index 842c8bdc..9fd65e7d 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,6 +8,6 @@ public class AndIRISC extends ImmRISC { public AndIRISC( Node and, int imm) { super(and,imm); } @Override public String op() { return "andi"; } @Override public String glabel() { return "&"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 7;} } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java index b8664679..a9d03da5 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -46,12 +47,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { if( in(1)==null && _bop=="!=" ) return; // Inverted never-node, no code enc.jump(this,cproj(0)); if( in(1)==null ) // Never node - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); else { // Todo: relocs (for offset - immf) short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); - enc.add4(riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, 0)); + enc.add4(RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, 0)); } } @@ -67,12 +68,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( in(1)==null ) { // Never node - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); if( opLen==4 ) { - enc.patch4(opStart,riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, delta)); + enc.patch4(opStart,RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, delta)); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index bd5dabe5..f0ad8e88 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -33,7 +34,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); short rpc = enc.reg(this); - enc.add4(riscv.j_type(riscv.OP_JAL, rpc, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, rpc, 0)); } // Delta is from opcode start @@ -47,7 +48,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short rpc = enc.reg(this); if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, rpc, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, rpc, delta)); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index 298789e8..5eee596d 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -18,7 +19,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(riscv.OP_JALR, rpc, 0, src, 0); + int body = RiscV.i_type(RiscV.OP_JALR, rpc, 0, src, 0); enc.add4(body); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java index 68ed6f6c..8eb4fb3b 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivFRISC extends MachConcreteNode implements MachNode{ @Override public String op() { return "divf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RUP,13); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RUP,13); } // Default on double precision for now(64 bits) // General form: "fdiv.d rd = src1 / src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java index 22ac2a69..5bd3ec1c 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,8 +23,8 @@ public class ExtendRISC extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); int shift = 64-_bits; - enc.add4(riscv.i_type(riscv.OP_IMM,dst,1,src,shift)); - enc.add4(riscv.i_type(riscv.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,1,src,shift)); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index 81726200..51ddc9db 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -20,9 +21,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -34,9 +35,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java index 6fce6244..d3d64b06 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -17,6 +18,6 @@ public class FunRISC extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java index db0547fe..1b53ab0f 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,7 +15,7 @@ public class I2F8RISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this )-riscv.F_OFFSET); short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.RM.RNE.ordinal(),src1,0,0x69); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.RM.RNE.ordinal(),src1,0,0x69); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index b4c87872..ee247c3e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -41,7 +42,7 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); + enc.add4(RiscV.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); } // General form: "addi rd = rs1 + imm" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java index edd1850f..23ac8481 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -23,9 +24,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short tmp = (short)riscv.T6; enc.largeConstant(this,_con, 0, -1); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -34,9 +35,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index f8af913a..9088abbd 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class IntRISC extends ConstantNode implements MachNode { int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 7333f2b7..aedd8b47 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class LUI extends ConstantNode implements MachNode { long x = ((TypeInteger)_con).value(); int imm20 = (int)(x>>12) & 0xFFFFF; short dst = enc.reg(this); - int lui = riscv.u_type(riscv.OP_LUI, dst, imm20); + int lui = RiscV.u_type(RiscV.OP_LUI, dst, imm20); enc.add4(lui); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index 7e08a01d..2e3dfd8d 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,9 +18,9 @@ public class LoadRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short ptr = enc.reg(ptr()); - int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dst >= riscv.F_OFFSET ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, func3(), ptr, _off)); + enc.add4(RiscV.i_type(op, dst, func3(), ptr, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java index 5cc40079..dacec2b5 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class MulFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,9); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,9); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java index d8183d09..3070c56c 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,7 +13,7 @@ public class NegRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - riscv.r_type(riscv.OP,dst,0,0,src,0x20); + RiscV.r_type(RiscV.OP,dst,0,0,src,0x20); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = -").p(code.reg(in(1))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index 6c03bda6..965a3c7c 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.print.ASMPrinter; @@ -14,9 +15,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.i_type(riscv.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); - enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); } // Patch is for running "new" in a JIT. @@ -32,8 +33,8 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { int imm20 = delta>>12; if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension int imm12 = delta&0xFFF; - enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); - enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + enc.patch4(opStart+4,RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); } else throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java index 1369ee76..dbe9ceb0 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -14,7 +15,7 @@ public class NotRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 2, src, 1)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java index 963b9d50..937595a3 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class OrIRISC extends ImmRISC { public OrIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 6; } @Override public String glabel() { return "|"; } @Override public String op() { return "ori"; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 7e4631d3..33143c6b 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -14,8 +15,8 @@ public class RetRISC extends ReturnNode implements MachNode { int sz = fun()._frameAdjust; if( sz >= 1L<<12 ) throw Utils.TODO(); if( sz != 0 ) - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); short rpc = enc.reg(rpc()); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.ZERO, 0, rpc, 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR, riscv.ZERO, 0, rpc, 0)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 3424cd01..d037dd5c 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.BoolNode; import com.seaofnodes.simple.node.MachConcreteNode; @@ -23,7 +24,7 @@ public class SetFRISC extends MachConcreteNode implements MachNode { short dst = enc.reg(this ); short src1 = (short)(enc.reg(in(1))-riscv.F_OFFSET); short src2 = (short)(enc.reg(in(2))-riscv.F_OFFSET); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java index 12c0ddec..1425caa2 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SllIRISC extends ImmRISC { public SllIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 1; } @Override public String glabel() { return "<<"; } @Override public String op() { return "slli"; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 6082cbbf..8a16f6b7 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -25,36 +26,36 @@ public class SplitRISC extends SplitNode { throw Utils.TODO(); // Very rare stack-stack move } int off = enc._fun.computeStackOffset(enc._code,dst); - int op = srcX ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = srcX ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( srcX ) src -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, 0b011, riscv.RSP, src, off)); + enc.add4(RiscV.s_type(op, 0b011, riscv.RSP, src, off)); return; } if( src >= riscv.MAX_REG ) { // Load from SP int off = enc._fun.computeStackOffset(enc._code,src); - int op = dstX ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dstX ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dstX ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, 0b011, riscv.RSP, off)); + enc.add4(RiscV.i_type(op, dst, 0b011, riscv.RSP, off)); return; } // pick opcode based on regs if( !dstX && !srcX ) { // GPR->GPR - enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + enc.add4(RiscV.r_type(RiscV.OP,dst,0,src,riscv.ZERO,0)); } else if( dstX && srcX ) { // FPR->FPR src -= riscv.F_OFFSET; dst -= riscv.F_OFFSET; - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) } else if(!srcX && dstX) { //GPR->FPR // fmv.d.x - enc.add4(riscv.r_type(riscv.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); } else if(srcX && !dstX) { //FPR->GPR //fmv.x.d - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java index fcfa0774..b316b303 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,7 +8,7 @@ public class SraIRISC extends ImmRISC { public SraIRISC( Node and, int imm) { super(and,imm | (0x20 << 5)); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5;} @Override public String glabel() { return ">>"; } @Override public String op() { return "srai"; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java index 2f73e139..d0ea6b18 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SrlIRISC extends ImmRISC { public SrlIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5; } @Override public String glabel() { return ">>>"; } @Override public String op() { return "srli"; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index df83ce1c..48cb7c78 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.node.*; @@ -36,9 +37,9 @@ public class StoreRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short val = enc.reg(val()); short ptr = enc.reg(ptr()); - int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = val >= riscv.F_OFFSET ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); + enc.add4(RiscV.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java index da3e92f4..044820cf 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,5); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,5); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index db140304..e57f6e09 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,9 +22,9 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); TypeFunPtr tfp = (TypeFunPtr)_con; // auipc t0,0 - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi t1,t0 + #0 - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -33,8 +34,8 @@ public class TFPRISC extends ConstantNode implements MachNode, RIPRelSize { short rpc = enc.reg(this); if( opLen==8 ) { // ADDI sign-extends its low 12 bits, so round the AUIPC high part. - enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, (delta+0x800)>>12)); - enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); + enc.patch4(opStart ,RiscV.u_type(RiscV.OP_AUIPC, rpc, (delta+0x800)>>12)); + enc.patch4(opStart+4,RiscV.i_type(RiscV.OP_IMM, rpc, 0, rpc, delta & 0xFFF)); } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. throw Utils.TODO(); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java index 94f0da0e..7bc2db7e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -18,9 +19,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -29,9 +30,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = enc.reg(this); // Round the high part because ADDI's low 12 bits are signed. - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, (delta+0x800)>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, dst, (delta+0x800)>>12)); // ADDI dst,dst,#low12_constant_pool - enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, dst, 0, dst, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java index 160895df..448d9ec3 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -21,7 +22,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.jump(this,uctrl()); - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); } // Delta is from opcode start @@ -34,7 +35,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { throw Utils.TODO(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 19ea6bc7..f4323cae 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -1,12 +1,13 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } public XorIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } @Override public String op() { return "xori"; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 88ec9ebd..6be0376a 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; +import static com.seaofnodes.isa.RiscV.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -68,7 +70,6 @@ public class riscv extends Machine { static final RegMask SPLIT_MASK = new RegMask( WR_BITS | FP_BITS, -1L ); - // Arguments masks public static RegMask A0_MASK = new RegMask(A0); public static RegMask A1_MASK = new RegMask(A1); @@ -114,40 +115,13 @@ public class riscv extends Machine { FA7_MASK }; - // major opcode: OP - public static int OP_LOAD = 0b00_000_11; - public static int OP_LOADFP = 0b00_001_11; - public static int OP_CUSTOM0 = 0b00_010_11; - public static int OP_IMM = 0b00_100_11; - public static int OP_AUIPC = 0b00_101_11; - - public static int OP_STORE = 0b01_000_11; - public static int OP_STOREFP = 0b01_001_11; - public static int OP_CUSTOM1 = 0b01_010_11; - public static int OP = 0b01_100_11; - public static int OP_LUI = 0b01_101_11; - - public static int OP_CUSTOM2 = 0b10_010_11; - public static int OP_FP = 0b10_100_11; - - public static int OP_BRANCH = 0b11_000_11; - public static int OP_JALR = 0b11_001_11; - public static int OP_RESERVED= 0b11_010_11; - public static int OP_JAL = 0b11_011_11; - - // Since riscv instructions are fixed we can just or them together - public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= rd && rd < 32; - return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } + public static void r_type(Encoding enc, Node n, int func3, int func7) { short dst = enc.reg(n); short src1 = enc.reg(n.in(1)); short src2 = enc.reg(n.in(2)); - int body = r_type(OP,dst,func3,src1,src2,func7); + int body = RiscV.r_type(OP,dst,func3,src1,src2,func7); enc.add4(body); } @@ -155,103 +129,10 @@ public class riscv extends Machine { short dst = (short)(enc.reg(n )-F_OFFSET); short src1 = (short)(enc.reg(n.in(1))-F_OFFSET); short src2 = (short)(enc.reg(n.in(2))-F_OFFSET); - int body = r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); + int body = RiscV.r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); enc.add4(body); } - - public static int u_type(int opcode, int rd, int imm20) { - assert 0 <= rd && rd < 32; - return (imm20 << 12) | (rd << 7) | opcode; - } - - public static int j_type(int opcode, int rd, int delta) { - assert -(1L<<20) <= delta && delta < (1L<<20); - assert 0 <= rd && rd < 32; - // Messy branch offset encoding - // 31 30-21 20 19-12 11-7 6-0 - // 20 10- 1 11 19-12 rpc JAL - assert (delta&1)==0; // Low bit is always zero, not encoded - int imm10_01 = (delta>> 1) & 0x3FF; - int imm11 = (delta>>11) & 1; - int imm12_19 = (delta>>12) & 0xFF; - int imm20 = (delta>>19) & 1; - int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; - return bits << 12 | rd << 7 | opcode; - } - - - public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { - assert 0 <= rd && rd < 32; - assert 0 <= rs1 && rs1 < 32; - assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller - return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } - - // S-type instructions(store) - public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= func3; - - assert imm12 >= 0; // Masked to high zero bits by caller - int imm_lo = imm12 & 0x1F; - int imm_hi = imm12 >> 5; - return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; - } - - // BRANCH - public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert -4*1024 <= delta && delta < 4*1024; - assert (delta&1)==0; // Low bit is always zero, not encoded - // Messy branch offset encoding - // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 - // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP - int imm4_1 = (delta>> 1) & 0xF; - int imm10_5= (delta>> 5) &0x3F; - int imm11 = (delta>>11) & 1; - int imm12 = (delta>>12) & 1; - int imm5 = imm4_1<<1 | imm11; - int imm7 = imm12<<6 | imm10_5; - return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; - } - - public enum RM { - RNE, // Round to Nearest, ties to Even - RTZ, // Round towards Zero - RDN, // Round Down - RUP, // Round Up - DIRECT, // Round to Nearest, ties to Max Magnitude - RESERVED1, // Reserved for futue use - RESERVED2, // Reserved for future use - DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved - } - - // Since opcode is the same just return back func3 - static public int jumpop(String op) { - return switch(op) { - case "==" -> 0x0; - case "!=" -> 0x1; - case "<" -> 0x4; - case ">=" -> 0x5; - case "u<" -> 0x6; - case "u<=" -> 0x7; - default -> throw Utils.TODO(); - }; - } - - // Since opcode is the same just return back func3 - static public int fsetop(String op) { - return switch(op) { - case "<" -> 1; - case "<=" -> 0; - case "==" -> 2; - default -> throw Utils.TODO(); - }; - } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; @@ -301,7 +182,6 @@ public class riscv extends Machine { } @Override public int rpc() { return RPC; } - // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index 2513de37..974f690f 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -20,19 +21,7 @@ public class AddFMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // addsd xmm0, DWORD PTR [rdi+0xc] - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - // F opcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, ptr, idx, false, enc); - - // FP ADD - enc.add1(0x0F).add1(0x58); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst = src + [base + idx<<2 + 12]" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index 02e0c7ea..c7d0cf9c 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,17 +14,7 @@ public class AddFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 58 /r ADDSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x58); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "addf dst += src" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java index 0ba390c6..0e652a93 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.SB; @@ -16,9 +17,7 @@ public class AddIX86 extends ImmX86 { @Override public final void encoding( Encoding enc ) { if( _imm== 1 || _imm== -1 ) { short dst = enc.reg(this); // Also src1 - enc.add1( x86_64_v2.rex(0,dst,0)); - enc.add1(0xFF); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, _imm==1 ? 0 : 1, dst) ); + X86.unary(enc,0xFF,_imm==1 ? 0 : 1,dst); } else super.encoding(enc); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java index 3ee721e3..ed65b0a8 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class AddMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // add something to register from memory - // add eax,DWORD PTR [rdi+0xc] - // REX.W + 03 /r ADD r64, r/m64 - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - // opcode - enc.add1(0x03); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0,0x03,true,enc.reg(this),enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst += [base + idx<<2 + 12]" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 460f568b..f97163eb 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; import com.seaofnodes.simple.node.MachNode; @@ -16,11 +17,7 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // FF /2 CALL r/m64 - // calls the function in the register - short src = enc.reg(fptr()); - enc.add1(0xFF); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT,2,src)); + X86.callRegister(enc,enc.reg(fptr())); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index d74e3833..d1a43b83 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -28,7 +29,7 @@ public class CallX86 extends CallNode implements MachNode, RIPRelSize { FunNode fun = CodeGen.CODE.link(_tfp); if( fun==null ) enc.external(this,_name); else enc.relo(this); - enc.add1(0xe8).add4(0); + X86.call(enc); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java index 5b97ef63..5ef7a476 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,16 +12,7 @@ public class CmpFX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // UCOMISD - short src1 = (short)(enc.reg(in(1)) - x86_64_v2.XMM_OFFSET); - short src2 = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // float opcode - enc.add1(0x66); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(src1, src2, 0, false, enc); - - enc.add1(0x0F).add1(0x2E); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src1, src2)); + X86.sse(enc,0x66,0x0F2E,false,enc.reg(in(1))-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "cmp src1,src2" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 8b8318eb..151f8ca8 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -26,14 +27,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode { @Override public Node copy() { return new CmpIX86(this); } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,0x81,7,enc.reg(in(1)),_imm); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index 278bf0e6..7b7d98d5 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -16,51 +17,16 @@ public class CmpMemX86 extends MemOpX86 { @Override public String op() { return ((val()==null && _imm==0) ? "test" : "cmp") + _sz; } @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64 - // CMP [mem], imm32 - - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if(src == -1) { + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) { assert !_swap; - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch(log) { - case 0: enc.add1(0x80); break; - case 1: enc.add1(0x66).add1(0x81); break; - case 2: enc.add1(0x81); break; - case 3: enc.add1(0x81); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc); - switch(log) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; - } - } else { - encVal(enc, _declaredType, ptr, idx, src, _off, _scale, _swap); - } + X86.cmpImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + } else encVal(enc,_declaredType,ptr,idx,src,_off,_scale,_swap); } static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale, boolean _swap) { - if(decl instanceof TypeFloat) { - src -= (short)x86_64_v2.XMM_OFFSET; - enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2); - } else { - int log = decl.log_size(); - x86_64_v2.rexF(src, ptr, idx, log == 3, enc); - int swap = _swap ? 2 : 0; - switch(log) { - case 0: enc.add1(0x38+swap); break; - case 1: enc.add1(0x66).add1(0x39+swap); break; - case 2: enc.add1(0x39+swap); break; - case 3: enc.add1(0x39+swap); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + assert !(decl instanceof TypeFloat); // Selected separately as CmpFX86. + X86.cmpMem(enc,decl.log_size(),src,ptr,idx,off,scale,_swap); } // General form: "cmp dst = src, [base + idx<<2 + 12]" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index e7305cdf..7faea17b 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,12 +18,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); - short src = enc.reg(in(2)); - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x3B); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x3B,enc.reg(in(1)),enc.reg(in(2))); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index 3427aea5..7bbb5102 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class DivFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5E /r DIVSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5E); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5E,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java index b5904a7f..9f375a80 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,16 +15,7 @@ public class DivX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.RDX_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + F7 /7 IDIV r/m64 - short src = enc.reg(in(2)); - // sign extend rax before 128/64 bits division - // sign extend rax to rdx:rax - enc.add1(x86_64_v2.REX_W); - enc.add1(0x99); - enc.add1(x86_64_v2.rex(0, src, 0)); - // divide - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x07, src)); + X86.divide(enc,enc.reg(in(2))); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java index e905e2e3..1a6ae123 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -20,12 +21,7 @@ public class ExtendX86 extends MachConcreteNode { @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this), src = enc.reg(in(1)); - // MOVSX/MOVZX for bytes and shorts; MOVSXD/MOV r32 for ints. - enc.add1(x86_64_v2.rex(dst,src,0,_signed || _bits<32)); - if( _bits==32 ) enc.add1(_signed ? 0x63 : 0x8b); - else enc.add1(0x0f).add1((_signed ? 0xbe : 0xb6) + (_bits==16 ? 1 : 0)); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,dst,src)); + X86.extend(enc,_bits,_signed,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index 9bcbac8f..da9bdce7 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,20 +15,8 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public Node copy() { return new FltX86(this); } @Override public void encoding( Encoding enc ) { - // Load the constant into a FPR - // movsd xmm, [rip + 0] - // F2 0F 10 /r MOVSD xmm1, m64 - _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - _encSize += x86_64_v2.rexF(dst, 0, 0, false, enc); - enc.add1(0x0F).add1(0x10); - // hard-code rip here - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); - enc.add4(0); - enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); + _encSize=X86.rip(enc,0xF2,0x0F10,false,enc.reg(this)-x86_64_v2.XMM_OFFSET); + enc.largeConstant(this,_con,_encSize-4,2/*ELF PC32*/); } // Delta is from opcode start diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index cbd5fdbf..c7a20e4d 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.FunNode; @@ -24,11 +25,7 @@ public class FunX86 extends FunNode implements MachNode { @Override public void encoding( Encoding enc ) { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust - // opcode: 0x83, addi rsp with immediate 8 - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b101, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); + X86.imm(enc,0x81,5,x86_64_v2.RSP,sz); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java index 9f3d7905..ee357901 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,18 +12,7 @@ public class I2f8X86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public void encoding( Encoding enc ) { - // F2 0F 2A /r CVTSI2SD xmm1, r32/m32 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = enc.reg(in(1)); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, true, enc); - - enc.add1(0x0F).add1(0x2A); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F2A,true,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java index 5e406911..5a4ff4b2 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -21,14 +22,7 @@ public abstract class ImmX86 extends MachConcreteNode implements MachNode { abstract int mod(); @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( opcode() + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,opcode(),mod(),enc.reg(this),_imm); } // General form: "addi dst += #imm" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 3f2f696c..656b1543 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -22,44 +23,7 @@ public class IntX86 extends ConstantNode implements MachNode { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL || _con==TypeInteger.ZERO ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // Simply move the constant into a GPR - // Conditional encoding based on 64 or 32 bits - //REX.W + C7 /0 id MOV r/m64, imm32 - - long imm = ((TypeInteger)_con).value(); - if (Integer.MIN_VALUE <= imm && imm < 0) { - // We need sign extension, so use imm32 into 64 bit register - // REX.W + C7 /0 id MOV r/m64, imm32 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xC7); // 32 bits encoding - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x00, dst)); - enc.add4((int)imm); - } else if (0 <= imm && imm <= 0xFFFFFFFFL) { - // We want zero extension into 64 bit register - // so move 32 bit into 32 bit register which zeros - // the upper bits in the 64 bit register. - // B8+ rd id MOV r32, imm32 - if (dst >= 8) enc.add1(0x41); - enc.add1(0xB8 + (dst & 0x07)); - enc.add4((int)imm); - } else { - // Just write the full 64 bit constant - // REX.W + B8+ rd io MOV r64, imm64 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xB8 + (dst & 0x07)); - enc.add8(imm); // 64 bits encoding - } + X86.constant(enc,enc.reg(this),_con==Type.NIL ? 0 : ((TypeInteger)_con).value()); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index de27aa5c..10cee059 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -30,38 +31,21 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { @Override public void negate() { _bop = negate(_bop); } @Override public void encoding( Encoding enc ) { - if( in(1)!=null ) { - int op = x86_64_v2.jumpop(_bop); - enc.add1(op-16).add1(0); // Short form jump - } else { - if( _bop=="!=" ) return; // Inverted, no code - enc.add1(0xEB).add1(0); // Never-node - } + if( in(1)==null && _bop=="!=" ) return; + X86.branch(enc,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); enc.jump(this,cproj(0)); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding @Override public byte encSize(int delta) { - if( in(1)==null && _bop=="!=" ) return 0; // Inverted never-node, no code - return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 6); + if( in(1)==null && _bop=="!=" ) return 0; + return X86.branchSize(delta,in(1)!=null); } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 6; // Offset from opcode END - bits[opStart] = 0x0F; - bits[opStart+1] = (byte)(in(1)==null ? 0xE9 : x86_64_v2.jumpop(_bop)); - enc.patch4(opStart+2,delta); - } + assert !(in(1)==null && _bop=="!="); + X86.patchBranch(enc.bits(),opStart,opLen,delta,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java index 2cd6018f..4b00e4dd 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -23,25 +24,7 @@ public class LeaX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 8D /r LEA r64,m - short dst = enc.reg(this); - short ptr = enc.reg(in(1)); - short idx = enc.reg(in(2)); - // ptr is null - // just do: [(index * s) + disp32] - if( ptr == -1 ) { - enc.add1(x86_64_v2.rex(dst, 0, idx)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x04)); - enc.add1(x86_64_v2.sib(_scale, idx, x86_64_v2.RBP)); - enc.add4(_offset); - return; - } - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - enc.add1(0x8D); // opcode - // rsp is hard-coded here(0x04) - x86_64_v2.indirectAdr(_scale, idx, ptr, _offset, dst, enc); + X86.lea(enc,enc.reg(this),enc.reg(in(1)),enc.reg(in(2)),_offset,_scale); } // General form: "lea dst = base + 4*idx + 12" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java index d0fb0081..d4f1413e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -24,33 +25,14 @@ public class LoadX86 extends MemOpX86 { } static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) { - // Allocation may put a full-width integer in an XMM register (or a - // floating value in a GPR). Move its bits using the selected register bank. - if( dst>=x86_64_v2.XMM_OFFSET && decl.log_size()==3 ) decl=TypeFloat.F64; - else if( dst<x86_64_v2.XMM_OFFSET && decl instanceof TypeFloat ) - decl = decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; - if( decl == TypeFloat.F32) enc.add1(0xF3); - if( decl == TypeFloat.F64) enc.add1(0xF2); - - if( decl.isa(TypeFloat.F64) ) - dst -= (short)x86_64_v2.XMM_OFFSET; - - x86_64_v2.rexF(dst, ptr, idx, decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64, enc); - - if( false ) ; - else if( decl == TypeFloat.F32 ) enc.add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32 - else if( decl == TypeFloat.F64 ) enc.add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64 - else if( decl.isa(TypeInteger.I8)) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8 - else if( decl == TypeInteger.I16 ) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16 - else if( decl == TypeInteger.I32 ) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32 - else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8 - else if( decl == TypeInteger.U16 ) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16 - // Covers U32, I64/BOT, TMP - else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32 - else throw Utils.TODO(); - - // includes modrm internally - x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc); + // The chapter chooses the register bank and extension from its own type facts. + boolean xmm=dst>=x86_64_v2.XMM_OFFSET; + if( xmm && decl.log_size()==3 ) decl=TypeFloat.F64; + else if( !xmm && decl instanceof TypeFloat ) + decl=decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; + boolean signed=decl.isa(TypeInteger.I8) || decl==TypeInteger.I16 || decl==TypeInteger.I32; + X86.load(enc,decl.log_size(),signed,xmm, + xmm ? dst-x86_64_v2.XMM_OFFSET : dst,ptr,idx,off,scale); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index bd56d022..2e18a058 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,20 +16,7 @@ public class MemAddX86 extends MemOpX86 { @Override public RegMask outregmap() { return null; } @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // add something to memory - // REX.W + 01 /r | REX.W + 81 /0 id - // ADD [mem], imm32/reg - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - enc.add1(x86_64_v2.rex(src, ptr, idx)); - // opcode - enc.add1( src == -1 ? (_imm==1 ? 0xFF : 0x81): 0x01); - - // includes modrm - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc); - if( src == -1 && _imm!=1 ) enc.add4(_imm); + X86.addMem(enc,enc.reg(val()),_imm,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add [base + idx<<2 + 12] += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index 7932c893..74616db7 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,16 +14,7 @@ public class MulFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 59 /r MULSD xmm1,xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x59).add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F59,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "mulf dst *= src" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 1e9e708f..5dcb253d 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,15 +18,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } // Rare 3-address form @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // Also src1 - short src = enc.reg(in(1)); - enc.add1(x86_64_v2.rex(dst, src, 0)); - // opcode; 0x69 or 0x6B - enc.add1( 0x69 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imul(enc,enc.reg(this),enc.reg(in(1)),_imm); } // General form: "addi dst += #imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java index 4d2a11ed..6f3fcdeb 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,13 +14,7 @@ public class MulX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // REX.W + 0F AF /r IMUL r64, r/m64 - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xAF); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x0FAF,enc.reg(this),enc.reg(in(2))); } // General form: "mul dst *= src" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java index 0c2baced..86610f6d 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,10 +14,7 @@ public class NegX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 3, dst)); + X86.unary(enc,0xF7,3,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index fc896dce..1cfc1c42 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -10,11 +11,8 @@ public class NewX86 extends NewNode implements MachNode { NewX86( NewNode nnn ) { super(nnn); } @Override public void encoding( Encoding enc ) { enc.external(this,"calloc"); - // ldi rcx,#1 // number of elements to calloc - enc.add1(0xB8 + _arg2Reg).add4(1); - // E8 cd CALL rel32; - enc.add1(0xE8); - enc.add4(0); // offset + X86.constant(enc,_arg2Reg,1); + X86.call(enc); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java index 7db80299..1e4e7c26 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,25 +13,9 @@ public class NotX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - assert !(in(1) instanceof NotNode); // Cleared out by peeps - assert !(in(1) instanceof BoolNode); // Cleared out by peeps - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - - // test rdi,rdi - enc.add1(x86_64_v2.rex(src, src, 0)); - enc.add1(0x85); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src, src)); - - // setz dstb; then zero-extend the low byte into the full register. - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0x94); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0xB6); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + assert !(in(1) instanceof NotNode); // Cleared out by peeps + assert !(in(1) instanceof BoolNode); + X86.not(enc,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java index 5a475efe..06755143 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,13 +13,7 @@ public abstract class RegX86 extends MachConcreteNode { @Override public int twoAddress() { return 1; } abstract int opcode(); @Override public void encoding( Encoding enc ) { - // REX.W + 01 /r - short dst = enc.reg(in(1)); // src1 - short src = enc.reg(in(2)); // src2 - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); } // General form: "add dst += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index a35d43a2..e4467bb4 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -8,12 +9,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public void encoding( Encoding enc ) { int sz = fun()._frameAdjust; - if( sz != 0 ) { - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b000, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); - } - enc.add1(0xC3); + if( sz!=0 ) X86.imm(enc,0x81,0,x86_64_v2.RSP,sz); + X86.ret(enc); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index 95e0c336..cf6275dc 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,15 +23,7 @@ public class SarIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index 4cc8b558..92493712 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class SarX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst)); + X86.unary(enc,opcode(),7,enc.reg(this)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 177e35ab..864c1b55 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -24,27 +25,15 @@ public class SetX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX + 0F 94 - short dst = enc.reg(this ); - - // Optional rex, for dst - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(switch (_bop) { + int op=switch (_bop) { case "==" -> 0x94; // SETE case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE case ">" -> _unsigned ? 0x97 : 0x9F; // SETA /SETG default -> throw Utils.TODO(); - }); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - - // low 8 bites are set, now zero extend for next instruction - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(0xB6); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + }; + X86.set(enc,op&15,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index f7b2f28a..1e62243e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -23,15 +24,7 @@ public class ShlIX86 extends MachConcreteNode implements MachNode { @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java index 5fee72d9..768d97e7 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShlX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 4, dst)); + X86.unary(enc,opcode(),4,enc.reg(this)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 7e0378b1..8a0d1b58 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -18,15 +19,7 @@ public class ShrIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java index 67dcf055..1ba20fee 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShrX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 5, dst)); + X86.unary(enc,opcode(),5,enc.reg(this)); } } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index 4a14240a..e8281975 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -19,44 +20,17 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. @Override public void encoding( Encoding enc ) { - // REX.W + 8B /r MOV r64, r/m64 - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - if( dst == x86_64_v2.FLAGS ) { - // mov reg, flags - // push rcx - // popf (Pop the top of the stack into the FLAGS register) - // 50+rd PUSH r64 - x86_64_v2.rexF(0,src,0,false,enc); - enc.add1(0x50 + src); - // popf - enc.add1(0x9D); - return; - } - if( src == x86_64_v2.FLAGS ) { - // mov flags, reg - // pushf; pop reg - enc.add1(0x9C); - // 58+ rd POP r64 - x86_64_v2.rexF(0,dst,0,false, enc); - enc.add1(0x58 + dst); - return; - } - - // Flag for being either XMM or stack - boolean dstX = dst >= x86_64_v2.XMM_OFFSET; - boolean srcX = src >= x86_64_v2.XMM_OFFSET; - + short dst=enc.reg(this), src=enc.reg(in(1)); + if( dst==x86_64_v2.FLAGS ) { X86.flags(enc,src,true); return; } + if( src==x86_64_v2.FLAGS ) { X86.flags(enc,dst,false); return; } + boolean dstX=dst>=x86_64_v2.XMM_OFFSET, srcX=src>=x86_64_v2.XMM_OFFSET; // Stack spills if( dst >= x86_64_v2.MAX_REG ) { int off = enc._fun.computeStackOffset(enc._code,dst); if( src >= x86_64_v2.MAX_REG ) { // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] int soff = enc._fun.computeStackOffset(enc._code,src); - enc.add1(0xFF); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); - enc.add1(0x8F); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + X86.stackCopy(enc,soff,off); return; } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); @@ -68,35 +42,8 @@ public class SplitX86 extends SplitNode { return; } - // reg-reg move. Adjust numbering for GPR vs FPR reg set - if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; - if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; - - // 0x66 if moving between register classes - if( dstX ^ srcX ) enc.add1(0x66); - if( !dstX && srcX ) - { short tmp=src; src=dst; dst=tmp; } - enc.add1(x86_64_v2.rex(dst, src, 0)); - - // pick opcode based on regs - if( !dstX && !srcX ) { - // reg->reg (MOV r64, r/m64) - enc.add1(0x8B); - } else if( dstX && srcX ) { - // xmm->xmm (NP 0F 28 /r MOVAPS xmm1, xmm2/m128) - enc.add1(0x0F); - enc.add1(0x28); - } else if( dstX && !srcX ) { - // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) - enc.add1(0x0F); - enc.add1(0x6E); - } else if( !dstX && srcX ) { - // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) - enc.add1(0x0F); - enc.add1(0x7E); - } - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.move(enc,dstX,srcX,dstX ? dst-x86_64_v2.XMM_OFFSET : dst, + srcX ? src-x86_64_v2.XMM_OFFSET : src); } // General form: "mov dst = src" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index b7b6c5d3..c83dfd44 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -25,55 +26,16 @@ public class StoreX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // REX.W + C7 /0 id MOV r/m64, imm32 | - // REX.W + 89 /r MOV r/m64, r64 - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if( src == -1 ) { - int log = _declaredType.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch( log ) { - case 0: enc .add1(0xC6); break; - case 1: enc.add1(0x66).add1(0xC7); break; - case 2: enc .add1(0xC7); break; - case 3: enc .add1(0xC7); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc); - switch( log ) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate - } - } else { - encVal(enc,_declaredType,ptr,idx,src,_off,_scale); - } + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) X86.storeImm(enc,_declaredType.log_size(),_imm,ptr,idx,_off,_scale); + else encVal(enc,_declaredType,ptr,idx,src,_off,_scale); } // Non-immediate encoding static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) { - int log = decl.log_size(); - // Float reg being stored - if( src >= x86_64_v2.XMM_OFFSET ) { - src -= (short)x86_64_v2.XMM_OFFSET; - assert log == 2 || log == 3; - enc.add1( log==2 ? 0xF3 : 0xF2 ); - x86_64_v2.rexF(src,ptr,idx,false,enc); - enc.add1(0x0F).add1(0x11); - } else { - // byte stores from sil, dil, bpl, spl need a rex - if( log == 0 && src >= x86_64_v2.RSP ) enc.add1(x86_64_v2.rex(src,ptr,idx,false)); - else x86_64_v2.rexF(src,ptr,idx,log==3,enc); - switch( log ) { - case 0: enc .add1(0x88); break; - case 1: enc.add1(0x66).add1(0x89); break; - case 2: enc .add1(0x89); break; - case 3: enc .add1(0x89); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + boolean xmm=src>=x86_64_v2.XMM_OFFSET; + X86.store(enc,decl.log_size(),xmm, + xmm ? src-x86_64_v2.XMM_OFFSET : src,ptr,idx,off,scale); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index b6530a87..29f0033a 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,16 +13,7 @@ public class SubFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5C /r SUBSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5C); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5C,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "subf dst -= src" diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index 359b6d83..fff2fb04 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.cpus.riscv.riscv; @@ -23,24 +24,9 @@ public class TFPX86 extends ConstantNode implements MachNode, RIPRelSize { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - - // lea to load function pointer address - // lea rax, [rip+disp32] + if( _con==Type.NIL ) { X86.constant(enc,enc.reg(this),0); return; } enc.relo(this); - enc.add1(x86_64_v2.rex(dst, 0, 0)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); - enc.add4(0); + X86.rip(enc,0,0x8D,true,enc.reg(this)); } @Override public byte encSize(int delta) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java index c23f6c5f..c78ac6de 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeMemPtr; @@ -15,8 +16,8 @@ public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { short dst = enc.reg(this); - x86_64_v2.rexF(dst, 0, 0, true, enc); - enc.add1(0x8D).add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)).add4(0); + X86.rexF(dst, 0, 0, true, enc); + enc.add1(0x8D).add1(X86.modrm(X86.MOD.INDIRECT, dst, 0b101)).add4(0); int opLen = 1/*rexF*/+1/*opcode 0x8D*/+1/*modrm*/+4/*pc rel offset*/; // Base of constant array TypeMemPtr tmp = (TypeMemPtr)_con; diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java index 6f538d27..591a51c3 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,29 +20,17 @@ public class UJmpX86 extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - // Short-form jump - enc.add1(0xEB).add1(0); - //// E9 cd JMP rel32 - //enc.add1(0xE9).add4(0); + X86.branch(enc,-1); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding - @Override public byte encSize(int delta) { return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 5); } + @Override public byte encSize(int delta) { + return X86.branchSize(delta,false); + } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert bits[opStart] == (byte)0xEB; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert bits[opStart] == (byte)0xEB; - bits[opStart] = (byte)0xE9; // Long form - delta -= 5; // Offset from opcode END - enc.patch4(opStart+1,delta); - } + X86.patchBranch(enc.bits(),opStart,opLen,delta,-1); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index cf9288b8..4beef793 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -69,13 +69,6 @@ public class x86_64_v2 extends Machine { public static int REX_WRB= 0x4D; public static int REX_WB = 0x49; - public enum MOD { - INDIRECT, // [mem] - INDIRECT_disp8, // [mem + 0x12] - INDIRECT_disp32, // [mem + 0x12345678] - DIRECT, // mem - }; - // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -95,90 +88,6 @@ public class x86_64_v2 extends Machine { }; } - public static int modrm(MOD mod, int reg, int m_r) { - if( reg == -1 ) reg=0; // Missing reg in this flavor - // combine all the bits - assert 0 <= reg && reg < 16; - assert 0 <= m_r && m_r < 16; - return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07; - } - - // 00 000 000 - // same bit-layout as modrm - public static int sib(int scale, int index, int base) { - assert 0 <= base && base < 16; - assert 0 <= index && index < 16; - return (scale << 6) | ((index & 0x07) << 3) | base & 0x07; - } - - // reg1 is reg(R) - // reg2 is r/mem(B) - // reg3 is X(index) - // reg4 is X(base) - - // 0 denotes no direct register - public static int rex(int reg, int ptr, int idx, boolean wide) { - // assuming 64 bit by default so: 0100 1000 - assert -1 <= reg && reg < 16; - assert -1 <= ptr && ptr < 16; - assert -1 <= idx && idx < 16; - - int rex = wide ? REX_W : REX; - if( 8 <= reg ) rex |= 0b00000100; // REX.R - if( 8 <= ptr ) rex |= 0b00000001; // REX.B - if( 8 <= idx ) rex |= 0b00000010; // REX.X - return rex; - } - - public static int rex(int reg, int ptr, int idx) { - return rex(reg, ptr, idx, true); - } - - // rex for floats. Return size (0 or 1) - // don't need to use REX if 0x40. - public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { - int rex = rex(reg, ptr, idx, wide); - if (rex == REX) return 0; - enc.add1(rex); - return 1; - } - // Function used for encoding indirect memory addresses - // Does not always generate SIB byte e.g index == -1. - // -1 denotes empty value, not set - note 0 is different from -1 as it can represent rax. - // Looks for best mod locally - public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { - // Assume indirect - assert 0 <= base && base < 16; - assert -1 <= index && index < 16 && index != RSP; - - MOD mod = MOD.INDIRECT; - // is 1 byte enough or need more? - if( offset != 0 ) - mod = imm8(offset) - ? MOD.INDIRECT_disp8 - : MOD.INDIRECT_disp32; - - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { - mod = MOD.INDIRECT_disp8; - } else if( index == -1 && (base == RSP || base == R12) ) { - index = RSP; - } - - if( index == -1 ) { - enc.add1(modrm(mod, reg, base)); - } else { - enc.add1(modrm(mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, index, base)); - } - - if( mod == MOD.INDIRECT_disp8 ) { - enc.add1(offset); - } else if( mod == MOD.INDIRECT_disp32 ) { - enc.add4(offset); - } - } - - // Limit of float args passed in registers static RegMask[] XMMS8 = new RegMask[]{ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3), diff --git a/chapter24/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter24/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index 43758f8b..a3b98fe0 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import java.io.IOException; import java.nio.file.Files; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter24/src/test/java/com/seaofnodes/simple/Chapter21Test.java index b57c7ddd..65b59fab 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter24/src/test/java/com/seaofnodes/simple/Chapter22Test.java index b1b5ad3e..cb4b286c 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import java.io.IOException; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter24/src/test/java/com/seaofnodes/simple/Chapter23Test.java index 118607c9..118015e0 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/Chapter23Test.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/Chapter23Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java b/chapter24/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java index f8c88fd7..a56c823a 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/Chapter24AllocTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import java.io.IOException; import java.nio.file.*; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java index b98a95b7..82bfd31f 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter24/src/test/java/com/seaofnodes/simple/EvalArm64.java deleted file mode 100644 index c24b47bb..00000000 --- a/chapter24/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ /dev/null @@ -1,773 +0,0 @@ -package com.seaofnodes.simple; - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.arm.arm; -import com.seaofnodes.simple.util.Utils; -import java.io.ByteArrayOutputStream; - -public class EvalArm64 { - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - // flags - boolean N = false; - boolean Z = false; - boolean C = false; - boolean V = false; - - EvalArm64(byte[] buf, int stackSize) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[arm.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - public int step(int maxops) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for(int icount = 0; icount < maxops; icount++) { - int ir = 0; - rval = 0; - frval = 0; - cycle++; - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - - // Load instruction from image buffer at PC - ir = ld4s( pc ); - - int rdid = ir & 0x1f; - // [31:24] - int opcode1 = (ir >> 24) & 0xFF; - - // for the opcode we just match for bits[31:24]; - switch( opcode1 ) { - case 0x14, 0x15, 0x16, 0x17: { //b - int imm26 = ir << 6 >> 6; - pc = pc + (imm26 * 4) - 4; - rdid = -1; - break; - } - case 0x1E: { // floats - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - int rs2 = (ir >> 16) & 0x1F; - - int op = (ir >> 10) & 0x3F; - switch(op) { - case 16: frval = fregs[rs1]; break; // fmov - case 10:frval = fregs[rs1] + fregs[rs2]; break; // fadd - - case 6: if (fregs[rs2] == 0) frval = 0; else frval = fregs[rs1] / fregs[rs2]; break; // fdiv - case 8: { - // fcmp - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - - Z = (lhs == rhs); - N = (lhs < rhs); - C = lhs >= rhs; - V = Double.isNaN(lhs) || Double.isNaN(rhs); - rdid = -1; - - break; - } - case 2: frval = fregs[rs1] * fregs[rs2]; break; // fmul - case 14: frval = fregs[rs1] - fregs[rs2]; break; // fsub - default: trap = (2+1); - } - break; - } - - case 0x38: { - // STRB/LDRB(register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch( ir >> 21 & 0x7 ) { - case 0x1 -> { // store - if( opcode1 == arm.OP_STORE_R_8 ) st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - else trap = (2+1); - rdid = -1; - } - case 0x3 -> { // load - if( opcode1 == arm.OP_LOAD_R_8 ) rval = ld1s((int)regs[rn] + (int)regs[rm]); - else trap = (2+1); - } - default -> trap = (2+1); - } - break; - } - case 0x39: { - // STRB/LDRB(immediate) - // str/ldr(immediate) - // rn - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_8) { - st1((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_8) { - rval = ld1s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - case 0x54: { - // b.cond - int imm19 = ir << 8 >> 13; - imm19 = pc + (imm19 * 4) - 4; - rdid = -1; - - switch(ir & 0xF) { - case 0x0: if(Z) pc = imm19; break; // eq - case 0x1: if(!Z) pc = imm19; break; // ne - case 0x2: if(C) pc = imm19; break; // cs - case 0x3: if(!C) pc = imm19; break; - case 0x4: if(N) pc = imm19; break; // mi - case 0x5: if(!N) pc = imm19; break; // pl - case 0x6: if(V) pc = imm19; break; // vs - case 0x7: if(!V) pc = imm19; break; // vc - case 0x8: if(C && !Z) pc = imm19; break; // hi - case 0x9: if(!C || Z) pc = imm19; break; // ls - case 0xA: if(N == V) pc = imm19; break; // ge - case 0xB: if(N != V) pc = imm19; break; // lt - case 0xC: if(!Z && N == V) pc = imm19; break; // gt - case 0xD: if(Z || N != V) pc = imm19; break; // le - case 0xE: pc = imm19; break; // always executed(al) - default: trap = (2+1); - } - break; - } - - case 0x5c: { - // ldr - is_f = true; - // address = delta - int address = ir << 8 >> 13; - address *= 4; - if(address >= _buf.length-3) trap = (5 + 1); - frval = ld8f(pc + address); - break; - } - - case 0x78: { - // STRH/LDRH(register) - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - // store - if(opcode1 == arm.OP_STORE_R_16) { - st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_16) { - rval = ld1s((int)regs[rn] + (int)regs[rm]); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - break; - } - - case 0x79: { - // STRH/LDRH(immediate) - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 2; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_16) { - st2((int)rval, (int)regs[rdid]); - } else trap = (2+1); - rdid = -1; - - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_16) { - rval = ld2s((int)rval); - } else trap = (2+1); - rdid = -1; - break; - } - default: trap = (2+1); - } - break; - } - - case 0x8A: { // AND - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] & regs[rm]; - break; - } - - case 0x8B, 0xCB: { - // add/sub(register), unshifted form emitted by Simple - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = opcode1==0x8B ? lhs + rhs : lhs - rhs; - break; - } - - case 0x90: { // adrp - int immhi = ( (ir& ~0x1F) << 8 ) >> 8; - int immlo = (ir>>29)& 3; - int imm = ((immhi<<2) | immlo) << 12; - rval = (pc & ~0xFFF) + imm; - break; - } - - case 0x91, 0xD1: { // ADD/SUB (immediate), unsigned imm12, optional LSL #12 - int rn = (ir >> 5) & 0x1F; - long immediate = (ir >>> 10) & 0xFFF; - if( (ir & (1<<22))!=0 ) immediate <<= 12; - rval = opcode1==0x91 ? regs[rn] + immediate : regs[rn] - immediate; - break; - } - case 0x92: { // and(immediate) - int imm12 = (ir >> 10) & 0x1FFF; - long immediate = arm.decodeImm12(imm12); - int rn = (ir >> 5) & 0x1F; - rval = regs[rn] & immediate; - break; - } - case 0x93, 0xD3: { // SBFM/UBFM: shifts and signed/unsigned extracts - int immr = (ir >>> 16) & 63; - int imms = (ir >>> 10) & 63; - int rn = (ir >>> 5) & 31; - boolean signed = (ir & 0x40000000)==0; - long value = regs[rn] << (63-imms); - value = signed ? value >> (63-imms) : value >>> (63-imms); - rval = immr > imms ? value << (64-immr) - : signed ? value >> immr : value >>> immr; - break; - } - - case 0x94, 0x95, 0x96, 0x97: { // bl - rdid = -1; // BL writes only X30, not a displacement-selected register. - rval = pc + 4; - regs[arm.X30] = rval; - int imm26 = (ir & 0x03FFFFFF); - int imm = (imm26 << 6) >> 6; - pc = pc + (imm << 2) ; - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - long size = regs[arm.X0]*regs[arm.X1]; - size = (size+7) & -8; // 8-byte aligned - regs[arm.X0] = _heap; - _heap += (int)size; - pc = (int)rval; - } - if( pc == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[0]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[1],(int)regs[2]); - regs[0] = regs[2]; - pc = (int)rval; - } - pc -= 4; - rdid = -1; - break; - } - - case 0x9A: { - int encodedCond = (ir >> 12) & 0xF; - int decodedCond = encodedCond ^ 1; - // conditional select(csel) - int rm = (ir >> 16) & 0x1F; - int rn = (ir >> 5) & 0x1F; - boolean cond = switch (decodedCond) { - case 0x0 -> Z ; // eq - case 0x1 -> !Z ; // ne - case 0x2 -> C ; // cs - case 0x3 -> !C ; - case 0x4 -> N ; // mi - case 0x5 -> !N ; // pl - case 0x6 -> V ; // vs - case 0x7 -> !V ; // vc - case 0x8 -> ( C && !Z ) ; // hi - case 0x9 -> (!C || Z ) ; // ls - case 0xA -> ( N == V) ; // ge - case 0xB -> ( N != V) ; // lt - case 0xC -> (!Z && N == V) ; // gt - case 0xD -> ( Z || N != V ); // le - case 0xE -> true ; // always - case 0xF -> false ; // never - default -> throw Utils.TODO(); - }; -// int reg = cond ? rn : rm; -// rval = reg==31 ? 0 : regs[reg]; -// if( cond ) rval++; - if(cond) rval = 1; - else rval = 0; - break; - } - case 0x9B: { // mul - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - rval = regs[rn] * regs[rm]; - break; - } - case 0x9E: { - // scvtf - is_f = true; - int rs1 = (ir >> 5) & 0x1F; - frval = (double)regs[rs1]; - break; - } - - case 0xAA: { - // MOV(register) - int rm = (ir >> 16) & 0x1F; - rval = regs[rm]; - break; - } - - case 0xB8: { - // LDR/STR (register + index) 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if( opcode1 == arm.OP_LOAD_R_32) { - rval = ld4s((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xB9: { - // str/ldr(immediate) 32 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - imm *= 4; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_32) { - rval = ld4s((int) rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xBC: { - // LDR/STR (register + index) float 32 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_32) { - frval = ld4f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - - case 0xBD: { - // LDR/STR(immediate) 32 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 4; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xD2: // MOVZ - case 0xF2: { // MOVK preserves the other halfwords - // movz - // get immediate - int shift = ((ir >> 21) & 3)*16; - rval = ((ir >> 5) & 0xFFFFL) << shift; - if( opcode1==0xF2 ) rval |= regs[rdid] & ~(0xFFFFL << shift); - break; - } - - case 0xEB: { - // subs(shifted register) - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - long lhs = regs[rn]; - long rhs = regs[rm]; - rval = lhs - rhs; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= rhs; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (rhs >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - - case 0xD6: { - int op = ir & 0xFFFFFC1F; - int rn = (ir >>> 5) & 31; - int target = (int)regs[rn]; // Read before BLR overwrites X30. - rdid = -1; - if( op==0xD63F0000 ) regs[arm.X30] = pc+4; // BLR - else if( op!=0xD65F0000 ) { trap = 3; break; } // RET - pc = target; - if( op==0xD65F0000 && pc==0 ) break outer; - pc -= 4; - break; - } - - case 0xF1: { - // subs(immediate) - int rn = (ir >> 5) & 0x1F; - int immediate = ir << 10 >> 20; - long lhs = regs[rn]; - - rval = lhs - immediate; - - // set flags as a side effect - Z = (rval == 0); - N = (rval < 0); - C = lhs >= immediate; - - boolean sign_lhs = (lhs >>> 63) != 0; - boolean sign_rhs = (immediate >>> 63) != 0; - boolean sign_res = (rval >>> 63) != 0; - V = (sign_lhs != sign_rhs) && (sign_res != sign_lhs); - rdid = -1; - break; - } - case 0xF8: { - // LDR/STR (register + index) 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OP_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], regs[rdid]); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OP_LOAD_R_64) { - rval = ld8((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xF9: { - // str/ldr(immediate) 64 bits - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OP_STORE_IMM_64) { - st8((int)rval, regs[rdid]); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_64) { - rval = ld8((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - case 0xFC: { - // LDR/STR (register + index) float 64 bits - int opc = ir >> 21 & 0x7; - int rn = (ir >> 5) & 0x1F; - int rm = (ir >> 16) & 0x1F; - is_f = true; - // full opcode - opcode1 = (ir >> 21) & 0x7FF; - switch(opc) { - case 0x1: { - if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); - }else { - trap = (2+1); - } - // store(expected to store the length here) - - rdid = -1; - break; - } - case 0x3: { - // load - if(opcode1 == arm.OPF_LOAD_R_64) { - frval = ld8f((int) (regs[rn] + regs[rm])); - } else { - trap = (2+1); - } - break; - } - default: trap = (2+1); - } - - break; - } - case 0xFD: { - // LDR/STR(immediate) 64 bits floats - int base = ir >> 5 & 0x1F; - int imm = (ir >> 10) & 0xFFF; - - imm *= 8; - is_f = true; - rval = regs[base] + imm; - int opc = (ir >> 22) & 0x3; - // full opcode - opcode1 = (ir >> 22) & 0x3FF; - switch(opc) { - case 0x0: { - // store - if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); - } else trap = (2+1); - - rdid = -1; - break; - } - case 0x1: { - // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8f((int)rval); - } else trap = (2+1); - break; - } - default: trap = (2+1); - } - break; - } - - default: trap = (2+1); - } - - if(trap != 0) { - _pc = pc; - break; - } - if(rdid != -1) { - if(is_f) {fregs[rdid] = frval; is_f = false;} - else regs[rdid] = rval; - } - - pc += 4; - } - // Handle traps and interrupts. - if(trap != 0) { - return trap; - } - _cycle = cycle; - _pc = pc; - return 0; - } - - -} diff --git a/chapter24/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter24/src/test/java/com/seaofnodes/simple/EvalRisc5.java deleted file mode 100644 index 633e931e..00000000 --- a/chapter24/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ /dev/null @@ -1,368 +0,0 @@ - package com.seaofnodes.simple; - -/** Simple RISC5 CPU Emulator - * - * Original works credit Charles Lohr. - * This is a complete rewrite in Java. - * - * Load code into memory and go! - */ - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.riscv.riscv; -import com.seaofnodes.simple.util.Utils; -import java.io.ByteArrayOutputStream; -import java.util.Arrays; - -public class EvalRisc5 { - - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - // PC - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - EvalRisc5( byte[] buf, int stackSize ) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[riscv.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) {st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - // Note: only a few bits are used. (Machine = 3, User = 0) - // Bits 0..1 = privilege. - // Bit 2 = WFI (Wait for interrupt) - // Bit 3+ = Load/Store reservation LSBs. - int _extraflags; - - public int step( int maxops ) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for( int icount = 0; icount < maxops; icount++ ) { - int ir = 0; - rval = 0; - cycle++; - - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - // Load instruction from image buffer at PC - ir = ld4s( pc ); - int rdid = (ir >> 7) & 0x1f; - - switch( ir & 0x7f ) { - case 0x37: // LUI (0b0110111) - rval = ( ir & 0xfffff000 ); - break; - case 0x17: // AUIPC (0b0010111) - rval = pc + ( ir & 0xfffff000 ); - break; - case 0x6F: { // JAL (0b1101111) - int reladdy = ((ir & 0x80000000)>>11) | ((ir & 0x7fe00000)>>20) | ((ir & 0x00100000)>>9) | ((ir&0x000ff000)); - if( (reladdy & 0x00100000)!=0 ) reladdy |= 0xffe00000; // Sign extension. - rval = pc + 4; - pc = pc + reladdy - 4; - if( pc+4 == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[10]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[11],(int)regs[12]); - regs[10] = regs[12]; - rdid = 0; - pc = (int)(rval - 4); // Unwind PC, as-if returned from write - } - break; - } - case 0x67: { // JALR (0b1100111) - int imm_se = ir >> 20; // Sign extend 12 bits - rval = pc + 4; - pc = ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1; - // Return from top-level ; exit sim - if( pc==0 ) { - if( rdid!=0 ) regs[rdid] = rval; // Write PC into register before exit - break outer; - } - // Inline CALLOC effect - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - int size = (int)(regs[10]*regs[11]); - size = (size+7) & -8; // 8-byte aligned - regs[10] = _heap; // Return next free address - _heap += size; - pc = (int)(rval - 4); // Unwind PC, as-if returned from calloc - } else - pc -= 4; - break; - } - case 0x63: { // Branch (0b1100011) - int immm4 = ((ir & 0xf00)>>7) | ((ir & 0x7e000000)>>20) | ((ir & 0x80) << 4) | ((ir >> 31)<<12); - if( (immm4 & 0x1000)!=0 ) immm4 |= 0xffffe000; - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - immm4 = pc + immm4 - 4; - rdid = 0; - if( switch( (ir >> 12) & 0x7 ) { - case 0 -> rs1 == rs2; - case 1 -> rs1 != rs2; - case 4 -> rs1 < rs2; - case 5 -> rs1 >= rs2; - case 6 -> Long.compareUnsigned(rs1,rs2) < 0; //BLTU - case 7 -> Long.compareUnsigned(rs1,rs2) >= 0; //BGEU - default -> { trap = (2+1); yield false; } - } ) pc = immm4; - break; - } - case 0x03: { // Load (0b0000011) - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - //LB, LH, LW, LBU, LHU - case 0: rval = ld1s( rsval ); break; - case 1: rval = ld2s( rsval ); break; - case 2: rval = ld4s( rsval ); break; - case 3: rval = ld8 ( rsval ); break; - case 4: rval = ld1z( rsval ); break; - case 5: rval = ld2z( rsval ); break; - case 6: rval = ld4s( rsval ); break; - default: trap = (2+1); - } - } - break; - } - // floats - case 0x7: { - is_f = true; - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - case 2: frval = ld4f( rsval ); break; - case 3: frval = ld8f( rsval ); break; - default: trap = (2+1); - } - } - break; - } - - case 0x23: { // Store 0b0100011 - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - long rs2 = regs[(ir >> 20) & 0x1f]; - int addy = ( ( ir >> 7 ) & 0x1f ) | ( ( ir & 0xfe000000 ) >> 20 ); - if( (addy & 0x800)!=0 ) addy |= 0xfffff000; - addy += rs1; - rdid = 0; - if( addy >= _buf.length-3 ) { - trap = (7+1); // Store access fault. - rval = addy; - } else { - switch( ( ir >> 12 ) & 0x7 ) { //SB, SH, SW - case 0: st1( addy, (int)rs2 ); break; - case 1: st2( addy, (int)rs2 ); break; - case 2: st4( addy, (int)rs2 ); break; - case 3: st8( addy, rs2 ); break; - default: trap = (2+1); - } - } - break; - } - case 0x13: // Op-immediate 0b0010011 - case 0x33: { // Op 0b0110011 - int imm = ir >> 20; - imm = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); - long rs1 = regs[(ir >> 15) & 0x1f]; - boolean is_reg = (ir & 0x20)!=0; - long rs2 = is_reg ? regs[imm & 0x1f] : imm; - - // Insert the detection here - int rs1id = (ir >> 15) & 0x1f; - int funct3 = (ir >> 12) & 0x7; - - if( is_reg && ( ir & 0x02000000 )!=0 ) { - switch( (ir>>12)&7 ) { //0x02000000 = RV32M - case 0: rval = rs1 * rs2; break; // MUL - case 1: rval = (int)((long)((int)rs1) * (long)((int)rs2)) >> 32; break; // MULH - case 2: rval = (int)((long)((int)rs1) * (long)rs2) >> 32; break; // MULHSU - case 3: rval = (int)((long)rs1 * (long)rs2) >> 32; break; // MULHU - case 4: if( rs2 == 0 ) rval = -1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? rs1 : ((int)rs1 / (int)rs2); break; // DIV - case 5: if( rs2 == 0 ) rval = 0xffffffff; else rval = rs1 / rs2; break; // DIVU - case 6: if( rs2 == 0 ) rval = rs1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? 0 : ((int)((int)rs1 % (int)rs2)); break; // REM - case 7: if( rs2 == 0 ) rval = rs1; else rval = rs1 % rs2; break; // REMU - } - } else { - rval = switch( (ir >> 12) & 7 ) { // These could be either op-immediate or op commands. Be careful. - case 0 -> (is_reg && (ir & 0x40000000) != 0) ? (rs1 - rs2) : (rs1 + rs2); - case 1 -> rs1 << (rs2 & 0x3F); - case 2 -> (rs1 < rs2) ? 1 : 0; - case 3 -> (rs1 < rs2) ? 1 : 0; - case 4 -> rs1 ^ rs2; - case 5 -> (ir & 0x40000000) != 0 ? (rs1 >> (rs2 & 0x3F)) : (rs1 >>> (rs2 & 0x3F)); - case 6 -> rs1 | rs2; - case 7 -> rs1 & rs2; - default -> rval; - }; - } - break; - } - case 0x0f: // 0b0001111 - rdid = 0; // fencetype = (ir >> 12) & 0b111; We ignore fences in this impl. - break; - case 0x73: // Zifencei+Zicsr (0b1110011) - trap = (2+1); // Note micrrop 0b100 == undefined. - break; - - case 0x2f: { // RV32A (0b00101111) - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - int irmid = ( ir>>27 ) & 0x1f; - - // We don't implement load/store from UART or CLNT with RV32A here. - if( rs1 >= _buf.length-3 ) { - trap = (7+1); //Store/AMO access fault - rval = rs1; - } else { - rval = ld4s( (int)rs1 ); - - // Referenced a little bit of https://github.com/franzflasch/riscv_em/blob/master/src/core/core.c - boolean dowrite = true; - switch( irmid ) { - case 2: //LR.W (0b00010) - dowrite = false; - _extraflags = (_extraflags & 0x07) | (int)(rs1<<3); - break; - case 3: { //SC.W (0b00011) (Make sure we have a slot, and, it's valid) - boolean xflag = _extraflags >> 3 != ( rs1 & 0x1fffffff ); - rval = xflag ? 1 : 0; // Validate that our reservation slot is OK. - dowrite = !xflag; // Only write if slot is valid. - break; - } - case 0: rs2 += rval; break; // AMOADD.W (0b00000) - case 1: break; // AMOSWAP.W (0b00001) - case 4: rs2 ^= rval; break; // AMOXOR.W (0b00100) - case 8: rs2 |= rval; break; // AMOOR.W (0b01000) - case 12: rs2 &= rval; break; // AMOAND.W (0b01100) - case 16: rs2 = Math.min( rs2, rval ); break; //AMOMIN.W (0b10000) - case 20: rs2 = Math.max( rs2, rval ); break; //AMOMAX.W (0b10100) - case 24: rs2 = Math.min( rs2, rval ); break; //AMOMINU.W (0b11000) - case 28: rs2 = Math.max( rs2, rval ); break; //AMOMAXU.W (0b11100) - default: trap = (2+1); dowrite = false; break; //Not supported. - } - if( dowrite ) st4( (int)rs1, (int)rs2 ); - } - break; - } - - case 0x53: { - is_f = true; - int rs1 = (ir >> 15) & 0x1F; - int rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - int func5 = (ir >> 27) & 0x1F; - int func2 = (ir >> 25) & 0x3; - if( func2 != 1 ) throw Utils.TODO(); // 1==double - switch( func5 ) { - case 0: frval = lhs + rhs; break; // fadd.d - case 1: frval = lhs - rhs; break; // fsub.d - case 2: frval = lhs * rhs; break; // fmul.d - case 3: frval = lhs / rhs; break; // fdiv.d - case 5: frval = Math.min(lhs,rhs); break; // fmin.d, also used for move - case 20: - is_f = false; // Output into a GPR - rval = switch( (ir >> 12) & 7 ) { - case 0 -> lhs <= rhs ? 1 : 0; - case 1 -> lhs == rhs ? 1 : 0; - case 2 -> lhs < rhs ? 1 : 0; - default -> throw Utils.TODO(); - }; - break; - case 26: frval = (double)regs[rs1]; break; // fcvt.w.d - default: - trap = (2+1); // Fault: Invalid opcode. - throw Utils.TODO(); - } - break; - } - - default: trap = (2+1); // Fault: Invalid opcode. - } - - // If there was a trap, do NOT allow register writeback. - if( trap!=0 ) { - _pc = pc; - break; - } - - if( rdid!=0 || is_f) { - if(is_f) {fregs[rdid] = frval; is_f = false;} // Write back register. - else regs[rdid] = rval; // Write back register. - } - - pc += 4; - } - - // Handle traps and interrupts. - if( trap!=0 ) - return trap; - - _cycle = cycle; - _pc = pc; - return 0; - } -} diff --git a/chapter24/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java b/chapter24/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java index cd1c972d..c5ad164e 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.RegAllocTestSupport; import com.seaofnodes.simple.node.*; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter24/src/test/java/com/seaofnodes/simple/MergeSortTest.java index 19a1facf..55ef5821 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.riscv.riscv; import com.seaofnodes.simple.util.SB; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter24/src/test/java/com/seaofnodes/simple/TestArm64.java index 02b15171..086bf9c7 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; diff --git a/chapter24/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter24/src/test/java/com/seaofnodes/simple/TestRisc5.java index ceba3157..f55e7d0b 100644 --- a/chapter24/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter24/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.FunNode; diff --git a/chapter25/Makefile b/chapter25/Makefile index 5b2b2531..980342c8 100644 --- a/chapter25/Makefile +++ b/chapter25/Makefile @@ -67,6 +67,7 @@ simple_driver := $(TST)/$(SIMPLE)/Simple.java main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas)) include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk)) include $(firstword $(wildcard ../print/print.mk print/print.mk)) +include $(firstword $(wildcard ../isa/isa.mk isa/isa.mk)) test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas)) # These tests do not rely on the stdlib test_alone := com.seaofnodes.simple.BrainFuckTest com.seaofnodes.simple.MergeSortTest com.seaofnodes.simple.TypeTest @@ -127,9 +128,9 @@ $(CLZDIR)/main/.mtag: $(main_javas) ####################################################### -$(CLZDIR)/test/.ttag: $(test_javas) $(CLZDIR)/main/.mtag +$(CLZDIR)/test/.ttag: $(test_javas) $(isa_test_javas) $(CLZDIR)/main/.mtag @[ -d $(CLZDIR)/test ] || mkdir -p $(CLZDIR)/test - $(file > .argsT.txt, $(test_javas)) + $(file > .argsT.txt, $(test_javas) $(isa_test_javas)) @echo "compiling test " `wc -w < .argsT.txt` " files" @if ! javac $(JAVAC_ARGS) -cp "$(CLZDIR)/test$(SEP)$(CLZDIR)/main$(SEP)$(jars)" -sourcepath $(TST) -d $(CLZDIR)/test @.argsT.txt >& .out.txt ; then \ cat .out.txt ; \ diff --git a/chapter25/pom.xml b/chapter25/pom.xml index a60f824b..c60ec7a2 100644 --- a/chapter25/pom.xml +++ b/chapter25/pom.xml @@ -15,4 +15,32 @@ <simple.graph.directory>${project.basedir}/../graph</simple.graph.directory> <simple.print.directory>${project.basedir}/../print</simple.print.directory> </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>shared-isa-sources</id> + <phase>generate-sources</phase> + <goals><goal>add-source</goal></goals> + <configuration> + <sources> + <source>${project.basedir}/../isa/src/main/java</source> + </sources> + </configuration> + </execution> + <execution> + <id>shared-isa-test-sources</id> + <phase>generate-test-sources</phase> + <goals><goal>add-test-source</goal></goals> + <configuration><sources> + <source>${project.basedir}/../isa/src/test-support/java</source> + </sources></configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index 215fd694..7cb92884 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -17,7 +17,7 @@ import java.util.*; * There are also a bunch of generic utilities for managing bits and bytes * common in all encodings. */ -public class Encoding { +public class Encoding implements com.seaofnodes.isa.CodeSink { // Top-level program graph structure public final CodeGen _code; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java index 1c865254..76e47ca2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // ADD (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_ADD); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_ADD); } // General form: "rd = rs1 + rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java index eb75c1a0..67a10b48 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class AddFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } //FADD (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_OP_ADD);} + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_OP_ADD);} // Default on double precision for now(64 bits) // General form: "addf rd = src1 + src2 diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java index 93c9e8c3..4c635d07 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AddIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -18,7 +19,7 @@ public class AddIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } //ADD (immediate) @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_ADD,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_ADD,_imm); } // General form: "addi rd = rs1 + imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java index 77115d54..1a0365ad 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -13,7 +14,7 @@ public class AndARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // AND (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_AND); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_AND); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb){ sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java index 5b739cd3..6292e98e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AndIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,10 +16,10 @@ public class AndIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc,this, in(1), arm.OPI_AND,_imm); + arm.imm_inst_n(enc,this, in(1), Arm64.OPI_AND,_imm); } // General form: "andi rd = rs1 & imm" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(arm.decodeImm12(_imm)); + sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" & #").p(Arm64.decodeImm12(_imm)); } }
\ No newline at end of file diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java index b83fb3cb..77f14d4c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AsrARM extends MachConcreteNode implements MachNode { @Override public String op() { return "sar"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_ASR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_ASR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >> ").p(code.reg(in(2))); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java index 38373e67..7cb42eec 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/AsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,7 +23,7 @@ public class AsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_ASR,_imm, 0b111111, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_ASR,_imm, 0b111111, rn, rd)); } // General form: "asri rd = rs1 >> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index 5cf8a89c..31bbde86 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -37,10 +38,10 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { // by comparison (or sub). No need for regs because it uses flags if( in(1)!=null ) { // B.cond - enc.add4( arm.b_cond(arm.OP_BRANCH, 0, arm.make_condition(_bop, _fp)) ); + enc.add4( Arm64.b_cond(Arm64.OP_BRANCH, 0, Arm64.make_condition(_bop, _fp)) ); } else { if( _bop=="!=" ) return; // Inverted, no code - enc.add4(arm.b(arm.OP_UJMP, 0)); + enc.add4(Arm64.b(Arm64.OP_UJMP, 0)); } enc.jump(this,cproj(0)); } @@ -57,7 +58,7 @@ public class BranchARM extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( opLen==4 ) { - enc.patch4(opStart,arm.b_cond(arm.OP_BRANCH, delta, arm.make_condition(_bop, _fp))); + enc.patch4(opStart,Arm64.b_cond(Arm64.OP_BRANCH, delta, Arm64.make_condition(_bop, _fp))); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 8f070525..4de28f3a 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -29,7 +30,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); // BL - enc.add4(arm.b(arm.OP_CALL,0)); // Target patched at link time + enc.add4(Arm64.b(Arm64.OP_CALL,0)); // Target patched at link time } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -37,7 +38,7 @@ public class CallARM extends CallNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - enc.patch4(opStart,arm.b(arm.OP_CALL,delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_CALL,delta)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java index c84aa9e5..1949ae46 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallRRARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class CallRRARM extends CallNode implements MachNode { // Needs a register, typically a jump-and-link-register opcode // blr short self = enc.reg(this); - enc.add4(arm.blr(arm.OP_CALLRARM, self)); + enc.add4(Arm64.blr(Arm64.OP_CALLRARM, self)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java index 794ff0c9..1bd9c372 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class CmpARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.FLAGS_MASK; } // SUBS (shifted register) - @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,arm.OP_CMP); } + @Override public void encoding( Encoding enc ) { arm.r_reg_subs(enc,this,Arm64.OP_CMP); } // General form: "cmp rs1, rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java index f84a1649..cd4dd9cf 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/CmpIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -28,7 +29,7 @@ public class CmpIARM extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public Node copy() { return new CmpIARM(this); } - @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), arm.OPI_CMP,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_subs(enc,in(1),in(1), Arm64.OPI_CMP,_imm); } // General form: "cmp rs1, 1" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java index de254eeb..e94b6491 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } // SDIV - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_DIV,3); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_DIV,3); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java index 813bebe4..68ad6047 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/DivFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class DivFARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.DMASK; } // FDIV (scalar) - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_DIV); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_DIV); } // General form: "VDIF = dst /= src" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java index 26a237d0..814a82c2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/ExtendARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,7 +23,7 @@ public class ExtendARM extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); // SBFM/UBFM aliases: sign/zero extend the low byte, short or int. - enc.add4(arm.imm_shift(_signed ? arm.OPI_ASR : arm.OPI_LSR,0,_bits-1,src,dst)); + enc.add4(Arm64.imm_shift(_signed ? Arm64.OPI_ASR : Arm64.OPI_LSR,0,_bits-1,src,dst)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java index 42553868..db2540f7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FltARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class FltARM extends ConstantNode implements MachNode, RIPRelSize { if( _ext!=null ) throw Utils.TODO(); enc.largeConstant(this,_con,0,-1/*TODO: ARM-style ELF patching*/); short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.add4(arm.load_pc(arm.OPF_ARM, 0, dst)); + enc.add4(Arm64.load_pc(Arm64.OPF_ARM, 0, dst)); } // Delta is from opcode start. @@ -30,7 +31,7 @@ public class FltARM extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = (short)(enc.reg(this) - arm.D_OFFSET); - enc.patch4(opStart, arm.load_pc(arm.OPF_ARM, delta, dst)); + enc.patch4(opStart, Arm64.load_pc(Arm64.OPF_ARM, delta, dst)); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java index b9e85202..17cafcde 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/FunARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -16,6 +17,6 @@ public class FunARM extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(arm.imm_inst(arm.OPI_SUB, sz, arm.RSP, arm.RSP)); + enc.add4(Arm64.imm_inst(Arm64.OPI_SUB, sz, arm.RSP, arm.RSP)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java index f1fa162f..b1c30afc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/I2F8ARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,7 +14,7 @@ public class I2F8ARM extends MachConcreteNode implements MachNode { // SCVTF short self = (short)(enc.reg(this )-arm.D_OFFSET); short reg1 = enc.reg(in(1)); - int body = arm.float_cast(arm.OP_FLOAT_C, 1, reg1, self); + int body = Arm64.float_cast(Arm64.OP_FLOAT_C, 1, reg1, self); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index dbed9487..72b76edd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -24,39 +25,7 @@ public class IntARM extends ConstantNode implements MachNode { if( _ext!=null ) throw Utils.TODO(); short self = enc.reg(this); long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); - int nb0 = 0; - int nb1 = 0; - // Count number of 0000 and FFFF blocks - for (int i=0; i<64; i+=16) { - int block = (int)(x >> i) & 0xFFFF; - if (block == 0) nb0++; - if (block == 0xFFFF) nb1++; - } - int pattern; - int op; - if(nb0 >= nb1) { - // More 0 blocks then F blocks, use movz - pattern = 0; - op = arm.OP_MOVZ; - } else { - // More F blocks then 0 blocks, use movn - pattern = 0xFFFF; - op = arm.OP_MOVN; - } - int invert = pattern; - for (int i=0; i<4; i++) { - int block = (int)x & 0xFFFF; - x >>= 16; - if (block != pattern) { - enc.add4(arm.mov(op, i, block ^ invert, self)); - op = arm.OP_MOVK; - invert = 0; - } - } - if (op != arm.OP_MOVK) { - // All blocks are the same, special case - enc.add4(arm.mov(op, 0, 0, self)); - } + Arm64.constant(enc,self,x); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index 827db545..4fbd6840 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -18,9 +19,9 @@ public class LoadARM extends MemOpARM { @Override public String op() { return "ld"+_sz; } @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } - private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; + private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, }; - private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; + private static final int[] OP_LOAD_RS = new int[]{ Arm64.OP_LOAD_R_8 , Arm64.OP_LOAD_R_16 , Arm64.OP_LOAD_R_32 , Arm64.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java index 80ce493f..954cfac2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LslARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSL); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSL); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" << ").p(code.reg(in(2))); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java index 7fe16cbe..b32153ab 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LslIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -24,7 +25,7 @@ public class LslIARM extends MachConcreteNode implements MachNode { assert _imm > 0; // UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>) // immr must be (-<shift> MOD 64) = 64 - shift - enc.add4(arm.imm_shift(arm.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSL, 64 - _imm, (64 - _imm) - 1, rn, rd)); } // General form: "lsli rd = rs1 << imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java index fc005e04..91be34e3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class LsrARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,arm.OP_LSR); } + @Override public void encoding( Encoding enc ) { arm.shift_reg(enc,this,Arm64.OP_LSR); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" >>> ").p(code.reg(in(2))); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java index 78844b0a..243ce968 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LsrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -19,7 +20,7 @@ public class LsrIARM extends MachConcreteNode implements MachNode { short rd = enc.reg(this); short rn = enc.reg(in(1)); assert _imm > 0; - enc.add4(arm.imm_shift(arm.OPI_LSR,_imm, 0b111111, rn,rd)); + enc.add4(Arm64.imm_shift(Arm64.OPI_LSR,_imm, 0b111111, rn,rd)); } // General form: "lsri rd = rs1 >>> imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index a26f385a..14eaf510 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -66,8 +67,8 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { val -= arm.D0; } int body = off() == null - ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) - : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); + ? Arm64.load_str_imm(opcode_imm, _off, ptr, val, size) + : Arm64.indr_adr(opcode_reg, off, Arm64.STORE_LOAD_OPTION.SXTX, 0, ptr, val); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java index a23ec75b..f598cefb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class MulARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.madd(enc,this,arm.OP_MUL,31); } + @Override public void encoding( Encoding enc ) { arm.madd(enc,this,Arm64.OP_MUL,31); } // General form: "rd = rs1 * rs2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java index 73ebbf00..a4f81fd4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MulFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class MulFARM extends MachConcreteNode implements MachNode{ @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_MUL); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_MUL); } // Default on double precision for now(64 bits) // General form: "VMUL.f32 rd = src1 * src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java index df2a6bc9..8bb8983e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NewARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,8 +12,8 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { // BL(branch with link) enc.external(this,"calloc"). - add4(arm.mov(arm.OP_MOVZ, 0, 1, 0)). // movz x0,#1 - add4(arm.b(arm.OP_CALL, 0)); + add4(Arm64.mov(Arm64.OP_MOVZ, 0, 1, 0)). // movz x0,#1 + add4(Arm64.b(Arm64.OP_CALL, 0)); } // Patch is for running "new" in a JIT. @@ -24,7 +25,7 @@ public class NewARM extends NewNode implements MachNode, RIPRelSize { @Override public void patch(Encoding enc, int opStart, int opLen, int delta ) { // Negative patches are JIT emulator targets. if( opStart+delta < 0 ) { - enc.patch4(opStart+4, arm.b_calloc(arm.OP_CALL, delta-4)); + enc.patch4(opStart+4, Arm64.b_calloc(Arm64.OP_CALL, delta-4)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java index d78421ca..ac21c706 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -17,9 +18,9 @@ public class NotARM extends MachConcreteNode implements MachNode{ // subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset short self = enc.reg(this ); short reg1 = enc.reg(in(1)); - int subs = arm.imm_inst(arm.OP_SUBS, 0, reg1, self); + int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self); enc.add4(subs); - int cset = arm.cond_set(arm.OP_CSET, 31, arm.COND.EQ, 31, reg1); + int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 31, reg1); enc.add4(cset); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java index e8245749..5b7264ec 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,7 +12,7 @@ public class OrARM extends MachConcreteNode implements MachNode { @Override public String glabel() { return "|"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_OR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_OR); } // General form: #rd = rs1 & rs2 @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" | ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java index a48caa51..86d07bee 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/OrIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,7 +16,7 @@ public class OrIARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst_n(enc, this, in(1), arm.OPI_OR, _imm); + arm.imm_inst_n(enc, this, in(1), Arm64.OPI_OR, _imm); } // General form: "ori rd = rs1 | imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java index 4597666b..a7ed5073 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/RetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -9,7 +10,7 @@ public class RetARM extends ReturnNode implements MachNode { @Override public void encoding( Encoding enc ) { int frameAdjust = ((FunARM)fun())._frameAdjust; if( frameAdjust > 0 ) - enc.add4(arm.imm_inst(arm.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); - enc.add4(arm.ret(arm.OP_RET)); + enc.add4(Arm64.imm_inst(Arm64.OPI_ADD, frameAdjust, arm.RSP, arm.RSP)); + enc.add4(Arm64.ret(Arm64.OP_RET)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java index c597b9dd..e5b06c39 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SetARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -23,7 +24,7 @@ public class SetARM extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { // Using RM==RN==31 implies a *zero* value, not R31. - int body = arm.cset(arm.OP_CSET,0b11111, arm.make_condition(_bop, _fp), 0b011111, enc.reg(this)); + int body = Arm64.cset(Arm64.OP_CSET,0b11111, Arm64.make_condition(_bop, _fp), 0b011111, enc.reg(this)); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java index be975fb6..dcfeb5d8 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SplitARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -26,7 +27,7 @@ public class SplitARM extends SplitNode { } int off = fun(enc).computeStackOffset(enc._code,dst); if( srcX ) src -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_STORE_IMM_64, off, arm.RSP, src, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_STORE_IMM_64, off, arm.RSP, src, 8)); return; } @@ -34,26 +35,26 @@ public class SplitARM extends SplitNode { // Load from SP int off = fun(enc).computeStackOffset(enc._code,src); if( dstX ) dst -= arm.D_OFFSET; - enc.add4(arm.load_str_imm(arm.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); + enc.add4(Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64, off, arm.RSP, dst, 8)); return; } // pick opcode based on regs if(!dstX && !srcX) { // GPR->GPR - enc.add4(arm.mov_reg(arm.OP_MOV, src, dst)); + enc.add4(Arm64.mov_reg(Arm64.OP_MOV, src, dst)); } else if(dstX && srcX) { // FPR->FPR // fmov reg - enc.add4(arm.f_mov_reg(arm.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_reg(Arm64.OP_FMOV_REG, src - arm.D_OFFSET,dst - arm.D_OFFSET)); } else if(!srcX && dstX) { // GPR->FPR // FMOV(general) 64 bits to DOUBLE-PRECISION - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b111, src, dst - arm.D_OFFSET)); } else if( srcX && !dstX) { //FPF->GPR // FMOV(general) DOUBLE-PRECISION to 64 bits - enc.add4(arm.f_mov_general(arm.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); + enc.add4(Arm64.f_mov_general(Arm64.OP_FMOV, 0b01, 0, 0b110, src - arm.D_OFFSET, dst)); } } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index 36b6bcdb..0b90ac8b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.StoreNode; @@ -22,9 +23,9 @@ public class StoreARM extends MemOpARM { @Override public String op() { return "st"+_sz; } @Override public RegMask outregmap() { return null; } - private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; + private static final int[] OP_STORES = new int[]{ Arm64.OP_STORE_IMM_8, Arm64.OP_STORE_IMM_16, Arm64.OP_STORE_IMM_32, Arm64.OP_STORE_IMM_64, }; - private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; + private static final int[] OP_STORE_RS = new int[]{ Arm64.OP_STORE_R_8, Arm64.OP_STORE_R_16, Arm64.OP_STORE_R_32, Arm64.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[Integer.numberOfTrailingZeros(_bytes)], val(), size()); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java index e3b95e50..fd5cd4de 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubARM extends MachConcreteNode implements MachNode { @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_SUB); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_SUB); } // General form: "sub # rd = rs1 - rs2" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java index a252e542..1a751434 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubFARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -9,7 +10,7 @@ public class SubFARM extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { return arm.DMASK; } @Override public RegMask outregmap() { return arm.DMASK; } - @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,arm.OPF_SUB); } + @Override public void encoding( Encoding enc ) { arm.f_scalar(enc,this,Arm64.OPF_SUB); } // Default on double precision for now(64 bits) // General form: "vsub.f32 rd = src1 + src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java index b50107c9..b2c0b2ed 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/SubIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -18,7 +19,7 @@ public class SubIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } @Override public void encoding( Encoding enc ) { - arm.imm_inst(enc,this, in(1), arm.OPI_SUB,_imm); + arm.imm_inst(enc,this, in(1), Arm64.OPI_SUB,_imm); } // General form: "subi rd = rs1 - imm" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java index 9d490c8b..a053ba46 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TFPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -22,9 +23,9 @@ public class TFPARM extends FunPtrNode implements MachNode, RIPRelSize { else enc.external(this,_ext); // ELF-file external patch short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java index 8209eb4b..b2531f97 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/TMPARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,9 +22,9 @@ public class TMPARM extends ConstantNode implements MachNode, RIPRelSize { else enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // adrp x0, 0 - enc.add4(arm.adrp(1,0, arm.OP_ADRP, 0,dst)); + enc.add4(Arm64.adrp(1,0, Arm64.OP_ADRP, 0,dst)); // add x0, x0, 0 - arm.imm_inst(enc,arm.OPI_ADD,0, dst); + arm.imm_inst(enc,Arm64.OPI_ADD,0, dst); } @Override public byte encSize(int delta) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java index ce4f523c..aecd02bb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/UJmpARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,7 +20,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - int body = arm.b(arm.OP_UJMP, 0); + int body = Arm64.b(Arm64.OP_UJMP, 0); enc.add4(body); } @@ -33,7 +34,7 @@ public class UJmpARM extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,arm.b(arm.OP_UJMP, delta)); + enc.patch4(opStart,Arm64.b(Arm64.OP_UJMP, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java index 52bda021..d56397a3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class XorARM extends MachConcreteNode implements MachNode{ @Override public String glabel() { return "^"; } @Override public RegMask regmap(int i) { return arm.RMASK; } @Override public RegMask outregmap() { return arm.WMASK; } - @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,arm.OP_XOR); } + @Override public void encoding( Encoding enc ) { arm.r_reg(enc,this,Arm64.OP_XOR); } // General form: "rd = x1 ^ x2" @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ ").p(code.reg(in(2))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java index 23b29644..12143ccd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/XorIARM.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.MachConcreteNode; @@ -19,7 +20,7 @@ public class XorIARM extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return arm.WMASK; } // General form: "xori rd = rs1 ^ imm" - @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), arm.OPI_XOR,_imm); } + @Override public void encoding( Encoding enc ) { arm.imm_inst_n(enc,this, in(1), Arm64.OPI_XOR,_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" ^ #").p(_imm); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 044d0352..2ba2d62e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.arm; +import com.seaofnodes.isa.Arm64; +import static com.seaofnodes.isa.Arm64.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -81,102 +83,6 @@ public class arm extends Machine { static final RegMask D6_MASK = new RegMask(D6); static final RegMask D7_MASK = new RegMask(D7); - // major opcode: OP - public static int OP_ADD = 0b10_001_011; - public static int OPF_ADD = 0b00_011_110; - public static int OPF_OP_ADD = 0b00_101_0; - public static int OPI_ADD = 0b10_010_00100; - - public static int OPI_SUB = 0b11_010_00100; - public static int OP_UJMP = 0b000101; - - public static int OP_ADRP = 0b10000; - - public static int OP_ASR = 0b1010; - public static int OPI_ASR = 0b10_0100_1101; - - public static int OP_LSL = 0b1000; - public static int OPI_LSL =0b1101001101; - - public static int OP_LSR = 0b1001; - public static int OPI_LSR = 0b1101001101; - - public static int OP_BRANCH = 0b01_0101_00; - public static int OP_CALL = 0b10_010_1; - - public static int OP_CALLRARM = 0b1101011000111111000000; - - public static int OP_SUBS = 0b1111000100; - public static int OP_CSET = 0b10011010100; - public static int OP_CMP = 0b11101011; - public static int OPI_CMP = 0b1111000100; - - public static int OP_DIV = 0b10011010110; - public static int OPF_DIV = 0b000110; - - public static int OP_MUL = 0b10011011000; - public static int OPF_MUL = 0b10; - - public static int OPF_ARM = 0b01011100; - - public static int OP_FLOAT_C = 0b10011110; - - public static int OP_XOR = 0b11001010; - public static int OPI_XOR = 0b110100100; - - public static int OP_AND = 0b10_0010_10; - public static int OPI_AND = 0b10_0100_100; - - public static int OP_OR = 0b10101010; - public static int OPI_OR = 0b101100100; - - public static int OP_SUB = 0b11001011; - public static int OPF_SUB = 0b1110; - - public static int OP_MOVK = 0b111100101; - public static int OP_MOVN = 0b100100101; - public static int OP_MOVZ = 0b110100101; - - public static int OP_RET = 0b1101011001011111000000; - // Store/load opcodes - public static int OP_LOAD_R_64 = 0b11111000011; - public static int OP_LOAD_R_32 = 0b10111000011; - public static int OP_LOAD_R_16 = 0b01111000010; - public static int OP_LOAD_R_8 = 0b00111000011; - - public static int OP_LOAD_IMM_64 = 0b1111100101; - public static int OP_LOAD_IMM_32 = 0b1011100101; - public static int OP_LOAD_IMM_16 = 0b0111100101; - public static int OP_LOAD_IMM_8 = 0b0011100101; - - // load - public static int OPF_LOAD_R_64 = 0b11111100011; - public static int OPF_LOAD_R_32 = 0b10111100011; - - public static int OPF_LOAD_IMM_64 = 0b1111110101; - public static int OPF_LOAD_IMM_32 = 0b1011110101; - - public static int OP_STORE_R_64 = 0b11111000001; - public static int OP_STORE_R_32 = 0b10111000001; - public static int OP_STORE_R_16 = 0b01111000001; - public static int OP_STORE_R_8 = 0b00111000001; - - public static int OP_STORE_IMM_64 = 0b1111100100; - public static int OP_STORE_IMM_32 = 0b1011100100; - public static int OP_STORE_IMM_16 = 0b0111100100; - public static int OP_STORE_IMM_8 = 0b0011100100; - - public static int OPF_STORE_R_64 = 0b11111100001; - public static int OPF_STORE_R_32 = 0b10111100001; - - public static int OPF_STORE_IMM_32 = 0b1011110100; - public static int OPF_STORE_IMM_64 = 0b1111110100; - - - public static int OP_FMOV = 0b10011110; - public static int OP_FMOV_REG = 0b00011110; - // https://docsmirror.github.io/A64/2023-06/mov_orr_log_shift.html - public static int OP_MOV = 0b10101010000; // Calling convention; returns a machine-specific register // for incoming argument idx. // index 0 for control, 1 for memory, real args start at index 2 @@ -202,56 +108,6 @@ public class arm extends Machine { }; // ARM ENCODING - public enum OPTION { - UXTB, - UXTH, - UXTX, - SXTB, - SXTH, - SXTW, - SXTX, - } - - static public int cset(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - // Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least significant bit inverted. - int actualCond = cond.ordinal() ^ 1; - return (opcode << 21) | (rm << 16) | (actualCond << 12) | (0b01 << 10) | (rn << 5) | rd; - } - - static public int cset(int opcode, COND cond, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - public enum STORE_LOAD_OPTION { - UXTW, // base+ u32 index [<< logsize] - UXTX, // base+ u64 index [<< logsize] - SXTW, // base+ s32 index [<< logsize] - SXTX, // base+ s64 index [<< logsize] - } - - public enum COND { - EQ, - NE, - CS, - CC, - MI, - PL, - VS, - VC, - HI, - LS, - GE, - LT, - GT, - LE, - AL, - NV - } // True if signed 9-bit immediate private static boolean imm9(TypeInteger ti) { @@ -264,55 +120,10 @@ public class arm extends Machine { return ti.isConstant() && ((ti.value()<<52)>>52) == ti.value(); } - // Can we encode this in ARM's 12-bit LOGICAL immediate form? // Some combination of shifted bit-masks. private static int imm12Logical(TypeInteger ti) { - if( !ti.isConstant() ) return -1; - if( !ti.isConstant() ) return -1; - long val = ti.value(); - if (val == 0 || val == -1) return -1; // Special cases are not allowed - int immr = 0; - // Rotate until we have 0[...]1 - - // Rotate until: - // The number is negative (MSB is 1) - // Or the LSB is not 1 - while (val < 0 || (val & 1)==0) { - // circular rotation - val = (val >>> 63) | (val << 1); - immr++; - } - // Start by assuming that val might be made of two 32-bit chunks that repeat. - int size = 32; - long pattern = val; - // Is upper half of pattern the same as the lower? - while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { - // Then only take one half - pattern >>= size; - size >>= 1; - } - size <<= 1; - int imms = Long.bitCount(pattern); - // Pattern should now be zeros followed by ones 0000011111 - if (pattern != (1L<<imms)-1) return -1; - imms--; - if (size == 64) return 0x1000 | immr << 6 | imms; - return (32-size)<<1 | immr << 6 | imms; - } - - // sh is encoded in opcode - public static int imm_inst(int opcode, int imm12, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits - return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; - } - - public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + return ti.isConstant() ? Arm64.logicalImmediate(ti.value()) : -1; } public static void imm_inst(Encoding enc, Node n,Node n2, int opcode, int imm12) { @@ -324,64 +135,46 @@ public class arm extends Machine { opcode ^= OPI_ADD ^ OPI_SUB; imm12 = -imm12; } - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); enc.add4(body); } public static void imm_inst_subs(Encoding enc, Node n,Node n2, int opcode, int imm12) { short reg1 = enc.reg(n2); // 31 = 11111 - int body = imm_inst(opcode, imm12&0xFFF, reg1, 31); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, 31); enc.add4(body); } // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static void imm_inst(Encoding enc, int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, self, self); enc.add4(body); } public static void imm_inst_n(Encoding enc, Node n, Node n2, int opcode, int imm13) { short self = enc.reg(n); short reg1 = enc.reg(n2); - int body = imm_inst_n(opcode, imm13, reg1, self); + int body = Arm64.imm_inst_n(opcode, imm13, reg1, self); enc.add4(body); } - // nth bit comes from immediate and not opcode - public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= imm13 && imm13 <= 0x1FFF; - return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; - } - - public static int imm_inst_l(int opcode, int imm12, int self) { - int body = imm_inst(opcode, imm12&0xFFF, self, self); - return body; - } - // for cases where rs1 and dst are the same, eg add x0, x0, 1 public static int imm_inst_l(Encoding enc, Node n, int opcode, int imm12) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); - int body = imm_inst(opcode, imm12&0xFFF, reg1, self); + int body = Arm64.imm_inst(opcode, imm12&0xFFF, reg1, self); return body; } // for normal add, reg1, reg2 cases (reg-to-reg) // using shifted-reg form - public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { - assert 0 <= rm && rm < 32; - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; - } + public static void r_reg(Encoding enc, Node n, int opcode) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, self >= 32 ? reg1: self); enc.add4(body); } @@ -389,232 +182,51 @@ public class arm extends Machine { short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); // 31 = 11111 - int body = r_reg(opcode, 0, reg2, 0, reg1, 31); + int body = Arm64.r_reg(opcode, 0, reg2, 0, reg1, 31); enc.add4(body); } - public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - assert 0 <= rd && rd < 32; - return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; - } public static void shift_reg(Encoding enc, Node n, int op2) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = shift_reg(0b10011010110, reg2, op2, reg1, self); + int body = Arm64.shift_reg(0b10011010110, reg2, op2, reg1, self); enc.add4(body); } // MUL can be considered an alias for MADD with the third operand Ra being set to 0 - public static int madd(int opcode, int rm, int ra, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; - } + public static void madd(Encoding enc, Node n, int opcode, int ra) { short self = enc.reg(n); short reg1 = enc.reg(n.in(1)); short reg2 = enc.reg(n.in(2)); - int body = madd(opcode, reg2, ra, reg1, self); + int body = Arm64.madd(opcode, reg2, ra, reg1, self); enc.add4(body); } - // encodes movk, movn, and movz - public static int mov(int opcode, int shift, int imm16, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; - } - - public static int mov_reg(int opcode, int src, int rd) { - assert 0 <= rd && rd < 32; - return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; - } - - public static int ret(int opcode) { - return (opcode << 10) | (X30 << 5); - } - - // FMOV (scalar, immediate) - public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - assert 0 <= rm && rm < 32; - return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; - } - - public static int f_mov_reg(int opcode, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; - } - public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { - assert 0 <= rn && rn < 32; - assert 0 <= rd && rd < 32; - return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; - } public static void f_scalar(Encoding enc, Node n, int op ) { short self = (short)(enc.reg(n) -D_OFFSET); short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_scalar(0b00011110, 1, reg2, op, reg1, self); + int body = Arm64.f_scalar(0b00011110, 1, reg2, op, reg1, self); enc.add4(body); } - // share same encoding with LDR (literal, SIMD&FP) flavour - public static int load_pc(int opcode, int offset, int rt) { - offset>>=2; - return (opcode << 24) | (offset << 5) | rt; - } - // int l - public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= imlo && imlo <= 0x3; // 2 bits - assert 0 <= imhi && imhi <= 0x7FFFF; // 19 bits - return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; - } - public static void patch_adrp_add(Encoding enc, int opStart, int delta, int rd) { int target = opStart + delta; int pageDelta = ((target & ~0xFFF) - (opStart & ~0xFFF)) >> 12; int imm21 = pageDelta & 0x1FFFFF; - enc.patch4(opStart , adrp(1, imm21 & 3, OP_ADRP, imm21 >>> 2, rd)); - enc.patch4(opStart+4, imm_inst_l(OPI_ADD, target & 0xFFF, rd)); - } - - // [Rptr+Roff] - public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; - } - // [Rptr+imm9] - public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { - assert 0 <= ptr && ptr < 32; - assert 0 <= rt && rt < 32; - - if(size == 8) imm12 = imm12 >> 3; - if(size == 4) imm12 = imm12 >> 2; - if(size == 2) imm12 = imm12 >> 1; - // size == 1 imm12 = imm12 - return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; - } - - // encoding for vcvt, size is encoded in operand - // <Qd>, <Qm> - // F32.S32 - //encoded as op = 0b00, size = 0b10. - // VCVT<c>.<Td>.<Tm> <Dd>, <Dm> - // opcode is broken down into 4 pieces - public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { - return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | - (vd << 12) | (0x01100010 << 4) | vm; - } - public static int float_cast(int opcode, int ftype, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; + enc.patch4(opStart , Arm64.adrp(1, imm21 & 3, OP_ADRP, imm21 >>> 2, rd)); + enc.patch4(opStart+4, Arm64.imm_inst_l(OPI_ADD, target & 0xFFF, rd)); } - - // ftype = 3 - public static int f_cmp(int opcode, int ftype, int rm, int rn) { - assert 0 <= rn && rn < 32; - assert 0 <= rm && rm < 32; - // Todo: |8 is not needed - return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); - } public static void f_cmp(Encoding enc, Node n) { short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET); short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET); - int body = f_cmp(0b00011110, 3, reg2, reg1); + int body = Arm64.f_cmp(0b00011110, 3, reg2, reg1); enc.add4(body); } - public static COND make_condition(String bop, boolean fp) { - // One of {N,Z,C} and !V - // OR { !N, !Z, C, V } - return fp - ? switch (bop) { // FP uses unsigned encodings - case "==" -> COND.EQ; // Z - case "!=" -> COND.NE; // !Z - case "<" -> COND.MI; // N - case "<=" -> COND.LS; // Z || !C - case ">=" -> COND.PL; // !N - case ">" -> COND.HI; // !Z && C - default -> throw Utils.TODO(); - } - : switch (bop) { - case "==" -> COND.EQ; // Z - case "!=" -> COND.NE; // !Z - case "<" -> COND.LT; // N != V - case "<=" -> COND.LE; // Z || N != V - case ">=" -> COND.GE; // N == V - case ">" -> COND.GT; // !Z && N == V - default -> throw Utils.TODO(); - }; - } - - public static int b_cond(int opcode, int delta, COND cond) { - // 24-5 == 19bits offset range - assert -(1<<19) <= delta && delta < (1<<19); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<19)-1; // Zero extend - return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); - } - - public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { - assert 0 <= rd && rd < 32; - assert 0 <= rn && rn < 32; - return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; - } - - // Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4. - public static int blr(int opcode, int rd) { - assert 0 <= rd && rd < 32; - return opcode << 10 | rd << 5; - } - public static int b(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - assert (delta&3)==0; - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - // no aligned assert(assert (delta&3)==0;) - public static int b_calloc(int opcode, int delta) { - assert -(1<<26) <= delta && delta < (1<<26); - delta>>=2; - delta &= (1L<<26)-1; // Zero extend - return (opcode << 26) | delta; - } - - public static long decodeImm12(int imm12) { - int immr = (imm12 >> 6) & 0x3F; - int imms = imm12 & 0x3F; - int size; - if ((imm12 & 0x1000) != 0) { - size = 64; - } else { - size = 31-(imms >> 1); - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size++; - imms &= ~((32-size) << 1); - } - long val = (2L << imms)-1; - while (size < 64) { - val |= val << size; - size <<= 1; - } - val = (val >>> immr) | val << (64-immr); - return val; - } - @Override public RegMask callArgMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask(TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return CodeGen.CODE._rpcMask; @@ -851,7 +463,6 @@ public class arm extends Machine { return prj.in(0) instanceof StartNode ? new ProjNode(prj) : new ProjARM(prj); } - private static int off; private static Node idx; private Node st(StoreNode st) { @@ -877,5 +488,4 @@ public class arm extends Machine { return mop; } - } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java index 1c157bc1..59bad64e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AUIPC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachNode; import com.seaofnodes.simple.node.FunPtrNode; @@ -18,7 +19,7 @@ public class AUIPC extends FunPtrNode implements MachNode, RIPRelSize { @Override public void encoding( Encoding enc ) { enc.relo(this); short dst = enc.reg(this); - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding @@ -29,7 +30,7 @@ public class AUIPC extends FunPtrNode implements MachNode, RIPRelSize { //short rpc = enc.reg(this); //// High half is where the TFP constant used to be, the last input //short auipc = enc.reg(in(_inputs._len-1)); - //enc.patch4(opStart,riscv.i_type(0x67, rpc, 0, auipc, delta)); + //enc.patch4(opStart,RiscV.i_type(0x67, rpc, 0, auipc, delta)); throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java index 8636df9f..d87e49b9 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class AddFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "addf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,1); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,1); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java index 511b0583..8012b61e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AddIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -8,7 +9,7 @@ public class AddIRISC extends ImmRISC { public AddIRISC( Node add, int imm12, boolean pop ) { super(add,imm12,pop); } @Override public String op() { return "addi"; } @Override public String glabel() { return "+"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 0;} @Override public AddIRISC copy() { // Clone the AddI, using the same inputs-only code used during inst select. diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java index 842c8bdc..9fd65e7d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/AndIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,6 +8,6 @@ public class AndIRISC extends ImmRISC { public AndIRISC( Node and, int imm) { super(and,imm); } @Override public String op() { return "andi"; } @Override public String glabel() { return "&"; } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() {return 7;} } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java index b8664679..a9d03da5 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -46,12 +47,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { if( in(1)==null && _bop=="!=" ) return; // Inverted never-node, no code enc.jump(this,cproj(0)); if( in(1)==null ) // Never node - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); else { // Todo: relocs (for offset - immf) short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); - enc.add4(riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, 0)); + enc.add4(RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, 0)); } } @@ -67,12 +68,12 @@ public class BranchRISC extends IfNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch if( in(1)==null ) { // Never node - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { short src1 = enc.reg(in(1)); short src2 = in(2)==null ? (short)riscv.ZERO : enc.reg(in(2)); if( opLen==4 ) { - enc.patch4(opStart,riscv.b_type(riscv.OP_BRANCH, riscv.jumpop(_bop), src1, src2, delta)); + enc.patch4(opStart,RiscV.b_type(RiscV.OP_BRANCH, RiscV.jumpop(_bop), src1, src2, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java index 8e1b4a48..b1426a3f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -32,7 +33,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { if( fun==null ) enc.external(this,_name); else enc.relo(this); short rpc = enc.reg(this); - enc.add4(riscv.j_type(riscv.OP_JAL, rpc, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, rpc, 0)); } // Delta is from opcode start @@ -46,7 +47,7 @@ public class CallRISC extends CallNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short rpc = enc.reg(this); if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, rpc, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, rpc, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java index 7369f9f5..cda4bc79 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/CallRRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -18,7 +19,7 @@ public class CallRRISC extends CallNode implements MachNode { @Override public void encoding( Encoding enc ) { short rpc = enc.reg(this); short src = enc.reg(in(_inputs._len-1)); - int body = riscv.i_type(riscv.OP_JALR, rpc, 0, src, 0); + int body = RiscV.i_type(RiscV.OP_JALR, rpc, 0, src, 0); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java index 68ed6f6c..8eb4fb3b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/DivFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class DivFRISC extends MachConcreteNode implements MachNode{ @Override public String op() { return "divf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RUP,13); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RUP,13); } // Default on double precision for now(64 bits) // General form: "fdiv.d rd = src1 / src2 @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java index 22ac2a69..5bd3ec1c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ExtendRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -22,8 +23,8 @@ public class ExtendRISC extends MachConcreteNode { @Override public void encoding(Encoding enc) { short dst = enc.reg(this), src = enc.reg(in(1)); int shift = 64-_bits; - enc.add4(riscv.i_type(riscv.OP_IMM,dst,1,src,shift)); - enc.add4(riscv.i_type(riscv.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,1,src,shift)); + enc.add4(RiscV.i_type(RiscV.OP_IMM,dst,5,dst,shift | (_signed ? 0x400 : 0))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java index c1a9b018..a110d156 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FltRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,9 +22,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -35,9 +36,9 @@ public class FltRISC extends ConstantNode implements MachNode, RIPRelSize { short dst = (short)(enc.reg(this) - riscv.F_OFFSET); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOADFP, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java index 6fce6244..d3d64b06 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/FunRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.MachNode; @@ -17,6 +18,6 @@ public class FunRISC extends FunNode implements MachNode { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust if( sz >= 1L<<12 ) throw Utils.TODO(); - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, -sz & 0xFFF)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java index db0547fe..1b53ab0f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/I2F8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,7 +15,7 @@ public class I2F8RISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = (short)(enc.reg(this )-riscv.F_OFFSET); short src1 = enc.reg(in(1)); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.RM.RNE.ordinal(),src1,0,0x69); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.RM.RNE.ordinal(),src1,0,0x69); enc.add4(body); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java index b4c87872..ee247c3e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -41,7 +42,7 @@ abstract public class ImmRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); + enc.add4(RiscV.i_type(opcode(), dst, func3(), src, _imm12 & 0xFFF)); } // General form: "addi rd = rs1 + imm" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java index e6b4c4ed..dd4a02a3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -25,9 +26,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short tmp = (short)riscv.T6; enc.largeConstant(this,_con, 0, -1); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, tmp, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, tmp, 0)); // Load dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, 0)); + enc.add4(RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, 0)); } @Override public RegMask killmap() { return new RegMask(riscv.T6); } @@ -36,9 +37,9 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { short dst = enc.reg(this); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, tmp, delta>>12)); // Load dst,[dst+#low12_constant_pool] - enc.patch4(opStart+4, riscv.i_type(riscv.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_LOAD, dst, 0b11, tmp, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index b795ba96..35d2bc65 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class IntRISC extends ConstantNode implements MachNode { int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 7333f2b7..aedd8b47 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -21,7 +22,7 @@ public class LUI extends ConstantNode implements MachNode { long x = ((TypeInteger)_con).value(); int imm20 = (int)(x>>12) & 0xFFFFF; short dst = enc.reg(this); - int lui = riscv.u_type(riscv.OP_LUI, dst, imm20); + int lui = RiscV.u_type(RiscV.OP_LUI, dst, imm20); enc.add4(lui); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java index 592cdb84..e9f3ec02 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LoadRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -19,9 +20,9 @@ public class LoadRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short ptr = enc.reg(ptr()); - int op = dst >= riscv.F_OFFSET ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dst >= riscv.F_OFFSET ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dst >= riscv.F_OFFSET ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, func3(), ptr, _off)); + enc.add4(RiscV.i_type(op, dst, func3(), ptr, _off)); } @Override int func3() { int func3 = -1; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java index 5cc40079..dacec2b5 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MulFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class MulFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "mulf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,9); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,9); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java index d8183d09..3070c56c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NegRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,7 +13,7 @@ public class NegRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - riscv.r_type(riscv.OP,dst,0,0,src,0x20); + RiscV.r_type(RiscV.OP,dst,0,0,src,0x20); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = -").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java index 4a6583ce..40d0359c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NewRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.print.ASMPrinter; @@ -14,9 +15,9 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { enc.external(this,"calloc"); // A1 is a caller-save, allowed to crush building external address // auipc - enc.add4(riscv.i_type(riscv.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); - enc.add4(riscv.u_type(riscv.OP_AUIPC, riscv.A2 , 0)); - enc.add4(riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM , _arg2Reg , 0, riscv.ZERO, 1)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, 0)); } // Patch is for running "new" in a JIT. @@ -32,8 +33,8 @@ public class NewRISC extends NewNode implements MachNode, RIPRelSize { int imm20 = delta>>12; if( ((delta>>11)&1)==1 ) imm20++; // Correct accidental sign extension int imm12 = delta&0xFFF; - enc.patch4(opStart+4,riscv.u_type(riscv.OP_AUIPC, riscv.A2 , imm20)); - enc.patch4(opStart+8,riscv.i_type(riscv.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); + enc.patch4(opStart+4,RiscV.u_type(RiscV.OP_AUIPC, riscv.A2 , imm20)); + enc.patch4(opStart+8,RiscV.i_type(RiscV.OP_JALR , riscv.RPC, 0, riscv.A2, imm12)); } else throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java index 1369ee76..dbe9ceb0 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.MachConcreteNode; import com.seaofnodes.simple.node.MachNode; @@ -14,7 +15,7 @@ public class NotRISC extends MachConcreteNode implements MachNode { @Override public void encoding( Encoding enc ) { short dst = enc.reg(this ); short src = enc.reg(in(1)); - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 2, src, 1)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java index 963b9d50..937595a3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/OrIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class OrIRISC extends ImmRISC { public OrIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 6; } @Override public String glabel() { return "|"; } @Override public String op() { return "ori"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java index 7e4631d3..33143c6b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/RetRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -14,8 +15,8 @@ public class RetRISC extends ReturnNode implements MachNode { int sz = fun()._frameAdjust; if( sz >= 1L<<12 ) throw Utils.TODO(); if( sz != 0 ) - enc.add4(riscv.i_type(riscv.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, riscv.RSP, 0, riscv.RSP, sz & 0xFFF)); short rpc = enc.reg(rpc()); - enc.add4(riscv.i_type(riscv.OP_JALR, riscv.ZERO, 0, rpc, 0)); + enc.add4(RiscV.i_type(RiscV.OP_JALR, riscv.ZERO, 0, rpc, 0)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java index 3424cd01..d037dd5c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.BoolNode; import com.seaofnodes.simple.node.MachConcreteNode; @@ -23,7 +24,7 @@ public class SetFRISC extends MachConcreteNode implements MachNode { short dst = enc.reg(this ); short src1 = (short)(enc.reg(in(1))-riscv.F_OFFSET); short src2 = (short)(enc.reg(in(2))-riscv.F_OFFSET); - int body = riscv.r_type(riscv.OP_FP,dst,riscv.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); + int body = RiscV.r_type(RiscV.OP_FP,dst,RiscV.fsetop(_bop),src1,src2,0b1010001/*FCMP*/); enc.add4(body); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java index 12c0ddec..1425caa2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SllIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SllIRISC extends ImmRISC { public SllIRISC( Node and, int imm) { super(and,imm); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 1; } @Override public String glabel() { return "<<"; } @Override public String op() { return "slli"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java index 58fa8a4b..d455337b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SplitRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -25,36 +26,36 @@ public class SplitRISC extends SplitNode { throw Utils.TODO(); // Very rare stack-stack move } int off = fun(enc).computeStackOffset(enc._code,dst); - int op = srcX ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = srcX ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( srcX ) src -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, 0b011, riscv.RSP, src, off)); + enc.add4(RiscV.s_type(op, 0b011, riscv.RSP, src, off)); return; } if( src >= riscv.MAX_REG ) { // Load from SP int off = fun(enc).computeStackOffset(enc._code,src); - int op = dstX ? riscv.OP_LOADFP : riscv.OP_LOAD; + int op = dstX ? RiscV.OP_LOADFP : RiscV.OP_LOAD; if( dstX ) dst -= riscv.F_OFFSET; - enc.add4(riscv.i_type(op, dst, 0b011, riscv.RSP, off)); + enc.add4(RiscV.i_type(op, dst, 0b011, riscv.RSP, off)); return; } // pick opcode based on regs if( !dstX && !srcX ) { // GPR->GPR - enc.add4(riscv.r_type(riscv.OP,dst,0,src,riscv.ZERO,0)); + enc.add4(RiscV.r_type(RiscV.OP,dst,0,src,riscv.ZERO,0)); } else if( dstX && srcX ) { // FPR->FPR src -= riscv.F_OFFSET; dst -= riscv.F_OFFSET; - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0b000, src, src, 0b0010101)); // dst = FMIN(src,src) } else if(!srcX && dstX) { //GPR->FPR // fmv.d.x - enc.add4(riscv.r_type(riscv.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst - riscv.F_OFFSET, 0, src, 0, 0b1111001)); } else if(srcX && !dstX) { //FPR->GPR //fmv.x.d - enc.add4(riscv.r_type(riscv.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); + enc.add4(RiscV.r_type(RiscV.OP_FP, dst, 0, src - riscv.F_OFFSET, 0, 0b1110001)); } } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java index fcfa0774..b316b303 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SraIRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -7,7 +8,7 @@ public class SraIRISC extends ImmRISC { public SraIRISC( Node and, int imm) { super(and,imm | (0x20 << 5)); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5;} @Override public String glabel() { return ">>"; } @Override public String op() { return "srai"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java index 2f73e139..d0ea6b18 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SrlIRISC.java @@ -1,11 +1,12 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class SrlIRISC extends ImmRISC { public SrlIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 5; } @Override public String glabel() { return ">>>"; } @Override public String op() { return "srli"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java index 100bbd2a..c3fcf4d3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/StoreRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.node.*; @@ -37,9 +38,9 @@ public class StoreRISC extends MemOpRISC { @Override public void encoding( Encoding enc ) { short val = enc.reg(val()); short ptr = enc.reg(ptr()); - int op = val >= riscv.F_OFFSET ? riscv.OP_STOREFP : riscv.OP_STORE; + int op = val >= riscv.F_OFFSET ? RiscV.OP_STOREFP : RiscV.OP_STORE; if( val >= riscv.F_OFFSET ) val -= riscv.F_OFFSET; - enc.add4(riscv.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); + enc.add4(RiscV.s_type(op, func3()&7, ptr, val == -1 ? riscv.ZERO : val, _off)); } // func3 is based on load/store size and extend diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java index da3e92f4..044820cf 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SubFRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -10,7 +11,7 @@ public class SubFRISC extends MachConcreteNode implements MachNode { @Override public String op() { return "subf"; } @Override public RegMask regmap(int i) { assert i==1 || i==2; return riscv.FMASK; } @Override public RegMask outregmap() { return riscv.FMASK; } - @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,riscv.RM.RNE,5); } + @Override public void encoding( Encoding enc ) { riscv.rf_type(enc,this,RiscV.RM.RNE,5); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java index 1f269152..44ef1a95 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TFPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -23,9 +24,9 @@ public class TFPRISC extends FunPtrNode implements MachNode, RIPRelSize { // TODO: 1 op encoding, plus a TODO if it does not fit short dst = enc.reg(this); // auipc t0,0 - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi t1,t0 + #0 - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -38,9 +39,9 @@ public class TFPRISC extends FunPtrNode implements MachNode, RIPRelSize { int lo12 = delta - (hi20 << 12); // AUIPC (upper 20 bits) // opstart of add - enc.patch4(opStart ,riscv.u_type(riscv.OP_AUIPC, rpc, hi20)); + enc.patch4(opStart ,RiscV.u_type(RiscV.OP_AUIPC, rpc, hi20)); // addi(low 12 bits) - enc.patch4(opStart+4,riscv.i_type(riscv.OP_IMM, rpc, 0, rpc, lo12 & 0xFFF)); + enc.patch4(opStart+4,RiscV.i_type(RiscV.OP_IMM, rpc, 0, rpc, lo12 & 0xFFF)); // addi } else { // should not happen as one instruction is 4 byte, and TFP arm encodes 2. diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java index 45c3eed2..a5ff3753 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/TMPRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; @@ -20,9 +21,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { else enc.largeConstant(this,((TypeMemPtr)_con)._obj,0,-1); short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.add4(riscv.u_type(riscv.OP_AUIPC, dst, 0)); + enc.add4(RiscV.u_type(RiscV.OP_AUIPC, dst, 0)); // addi dst,[dst+#low12_constant_pool] - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, dst, 0)); + enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, 0)); } @Override public byte encSize(int delta) { return 8; } @@ -31,9 +32,9 @@ public class TMPRISC extends ConstantNode implements MachNode, RIPRelSize { @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { short dst = enc.reg(this); // AUIPC dst,#hi20_constant_pool - enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, dst, (delta+0x800)>>12)); + enc.patch4(opStart , RiscV.u_type(RiscV.OP_AUIPC, dst, (delta+0x800)>>12)); // ADDI's low 12 bits are signed; round the AUIPC page accordingly. - enc.patch4(opStart+4, riscv.i_type(riscv.OP_IMM, dst, 0, dst, delta & 0xFFF)); + enc.patch4(opStart+4, RiscV.i_type(RiscV.OP_IMM, dst, 0, dst, delta & 0xFFF)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java index 160895df..448d9ec3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/UJmpRISC.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -21,7 +22,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] enc.jump(this,uctrl()); - enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); + enc.add4(RiscV.j_type(RiscV.OP_JAL, 0, 0)); } // Delta is from opcode start @@ -34,7 +35,7 @@ public class UJmpRISC extends CFGNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { if( opLen==4 ) { - enc.patch4(opStart,riscv.j_type(riscv.OP_JAL, 0, delta)); + enc.patch4(opStart,RiscV.j_type(RiscV.OP_JAL, 0, delta)); } else { throw Utils.TODO(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 19ea6bc7..f4323cae 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -1,12 +1,13 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } public XorIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } - @Override int opcode() { return riscv.OP_IMM; } + @Override int opcode() { return RiscV.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } @Override public String op() { return "xori"; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 03f7371b..808ad82e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple.node.cpus.riscv; +import com.seaofnodes.isa.RiscV; +import static com.seaofnodes.isa.RiscV.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -67,7 +69,6 @@ public class riscv extends Machine { static final RegMask SPLIT_MASK = new RegMask( WR_BITS | FP_BITS, -1L ); - // Arguments masks public static RegMask A0_MASK = new RegMask(A0); public static RegMask A1_MASK = new RegMask(A1); @@ -113,40 +114,13 @@ public class riscv extends Machine { FA7_MASK }; - // major opcode: OP - public static int OP_LOAD = 0b00_000_11; - public static int OP_LOADFP = 0b00_001_11; - public static int OP_CUSTOM0 = 0b00_010_11; - public static int OP_IMM = 0b00_100_11; - public static int OP_AUIPC = 0b00_101_11; - - public static int OP_STORE = 0b01_000_11; - public static int OP_STOREFP = 0b01_001_11; - public static int OP_CUSTOM1 = 0b01_010_11; - public static int OP = 0b01_100_11; - public static int OP_LUI = 0b01_101_11; - - public static int OP_CUSTOM2 = 0b10_010_11; - public static int OP_FP = 0b10_100_11; - - public static int OP_BRANCH = 0b11_000_11; - public static int OP_JALR = 0b11_001_11; - public static int OP_RESERVED= 0b11_010_11; - public static int OP_JAL = 0b11_011_11; - - // Since riscv instructions are fixed we can just or them together - public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= rd && rd < 32; - return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } + public static void r_type(Encoding enc, Node n, int func3, int func7) { short dst = enc.reg(n); short src1 = enc.reg(n.in(1)); short src2 = enc.reg(n.in(2)); - int body = r_type(OP,dst,func3,src1,src2,func7); + int body = RiscV.r_type(OP,dst,func3,src1,src2,func7); enc.add4(body); } @@ -154,103 +128,10 @@ public class riscv extends Machine { short dst = (short)(enc.reg(n )-F_OFFSET); short src1 = (short)(enc.reg(n.in(1))-F_OFFSET); short src2 = (short)(enc.reg(n.in(2))-F_OFFSET); - int body = r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); + int body = RiscV.r_type(OP_FP,dst,func3.ordinal(),src1,src2,func7); enc.add4(body); } - - public static int u_type(int opcode, int rd, int imm20) { - assert 0 <= rd && rd < 32; - return (imm20 << 12) | (rd << 7) | opcode; - } - - public static int j_type(int opcode, int rd, int delta) { - assert -(1L<<20) <= delta && delta < (1L<<20); - assert 0 <= rd && rd < 32; - // Messy branch offset encoding - // 31 30-21 20 19-12 11-7 6-0 - // 20 10- 1 11 19-12 rpc JAL - assert (delta&1)==0; // Low bit is always zero, not encoded - int imm10_01 = (delta>> 1) & 0x3FF; - int imm11 = (delta>>11) & 1; - int imm12_19 = (delta>>12) & 0xFF; - int imm20 = (delta>>19) & 1; - int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; - return bits << 12 | rd << 7 | opcode; - } - - - public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { - assert 0 <= rd && rd < 32; - assert 0 <= rs1 && rs1 < 32; - assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller - return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; - } - - // S-type instructions(store) - public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert 0 <= func3; - - assert imm12 >= 0; // Masked to high zero bits by caller - int imm_lo = imm12 & 0x1F; - int imm_hi = imm12 >> 5; - return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; - } - - // BRANCH - public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { - assert 0 <= rs1 && rs1 < 32; - assert 0 <= rs2 && rs2 < 32; - assert -4*1024 <= delta && delta < 4*1024; - assert (delta&1)==0; // Low bit is always zero, not encoded - // Messy branch offset encoding - // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 - // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP - int imm4_1 = (delta>> 1) & 0xF; - int imm10_5= (delta>> 5) &0x3F; - int imm11 = (delta>>11) & 1; - int imm12 = (delta>>12) & 1; - int imm5 = imm4_1<<1 | imm11; - int imm7 = imm12<<6 | imm10_5; - return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; - } - - public enum RM { - RNE, // Round to Nearest, ties to Even - RTZ, // Round towards Zero - RDN, // Round Down - RUP, // Round Up - DIRECT, // Round to Nearest, ties to Max Magnitude - RESERVED1, // Reserved for futue use - RESERVED2, // Reserved for future use - DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved - } - - // Since opcode is the same just return back func3 - static public int jumpop(String op) { - return switch(op) { - case "==" -> 0x0; - case "!=" -> 0x1; - case "<" -> 0x4; - case ">=" -> 0x5; - case "u<" -> 0x6; - case "u<=" -> 0x7; - default -> throw Utils.TODO(); - }; - } - - // Since opcode is the same just return back func3 - static public int fsetop(String op) { - return switch(op) { - case "<" -> 1; - case "<=" -> 0; - case "==" -> 2; - default -> throw Utils.TODO(); - }; - } - @Override public RegMask callArgMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { return callInMask(tfp,idx,maxArgSlot); } static RegMask callInMask( TypeFunPtr tfp, int idx, int maxArgSlot ) { if( idx==0 ) return RPC_MASK; @@ -309,7 +190,6 @@ public class riscv extends Machine { } @Override public int rpc() { return RPC; } - // Return a MachNode unconditional branch @Override public CFGNode jump() { return new UJmpRISC(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java index 093e2bd2..74af9266 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -20,19 +21,7 @@ public class AddFMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // addsd xmm0, DWORD PTR [rdi+0xc] - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - // F opcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, ptr, idx, false, enc); - - // FP ADD - enc.add1(0x0F).add1(0x58); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst = src + [base + idx<<2 + 12]" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index 02e0c7ea..c7d0cf9c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,17 +14,7 @@ public class AddFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 58 /r ADDSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x58); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F58,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "addf dst += src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java index 0ba390c6..0e652a93 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.SB; @@ -16,9 +17,7 @@ public class AddIX86 extends ImmX86 { @Override public final void encoding( Encoding enc ) { if( _imm== 1 || _imm== -1 ) { short dst = enc.reg(this); // Also src1 - enc.add1( x86_64_v2.rex(0,dst,0)); - enc.add1(0xFF); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, _imm==1 ? 0 : 1, dst) ); + X86.unary(enc,0xFF,_imm==1 ? 0 : 1,dst); } else super.encoding(enc); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java index 3ee721e3..ed65b0a8 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class AddMemX86 extends MemOpX86 { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public int twoAddress() { return 4; } @Override public void encoding( Encoding enc ) { - // add something to register from memory - // add eax,DWORD PTR [rdi+0xc] - // REX.W + 03 /r ADD r64, r/m64 - short dst = enc.reg(this ); - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - // opcode - enc.add1(0x03); - - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc); + X86.memory(enc,0,0x03,true,enc.reg(this),enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add dst += [base + idx<<2 + 12]" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java index 14b8e4da..f97163eb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallRX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.CallNode; import com.seaofnodes.simple.node.MachNode; @@ -16,11 +17,7 @@ public class CallRX86 extends CallNode implements MachNode { } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // FF /2 CALL r/m64 - // calls the function in the register - short src = enc.reg(fptr()); - enc.add1(0xFF); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,2,src)); + X86.callRegister(enc,enc.reg(fptr())); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java index 989895b2..6bafbf37 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CallX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -34,7 +35,7 @@ public class CallX86 extends CallNode implements MachNode, RIPRelSize { FunNode fun = CodeGen.CODE.link(_tfp); if( fun==null ) enc.external(this,_name); else enc.relo(this); - enc.add1(0xe8).add4(0); + X86.call(enc); } // Delta is from opcode start, but X86 measures from the end of the 5-byte encoding diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java index 5b97ef63..5ef7a476 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,16 +12,7 @@ public class CmpFX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // UCOMISD - short src1 = (short)(enc.reg(in(1)) - x86_64_v2.XMM_OFFSET); - short src2 = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // float opcode - enc.add1(0x66); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(src1, src2, 0, false, enc); - - enc.add1(0x0F).add1(0x2E); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src1, src2)); + X86.sse(enc,0x66,0x0F2E,false,enc.reg(in(1))-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "cmp src1,src2" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java index 8b8318eb..151f8ca8 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -26,14 +27,7 @@ public class CmpIX86 extends MachConcreteNode implements MachNode { @Override public Node copy() { return new CmpIX86(this); } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( 0x81 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,0x81,7,enc.reg(in(1)),_imm); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java index 9d131fc6..4014045b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -16,51 +17,16 @@ public class CmpMemX86 extends MemOpX86 { @Override public String op() { return ((val()==null && _imm==0) ? "test" : "cmp") + _sz; } @Override public RegMask outregmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 81 /7 id CMP r/m64, imm32 | REX.W + 39 /r CMP r/m64,r64 - // CMP [mem], imm32 - - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if(src == -1) { + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) { assert !_swap; - int log = _con.log_size(); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch(log) { - case 0: enc.add1(0x80); break; - case 1: enc.add1(0x66).add1(0x81); break; - case 2: enc.add1(0x81); break; - case 3: enc.add1(0x81); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, 7, enc); - switch(log) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; - } - } else { - encVal(enc, _con, ptr, idx, src, _off, _scale, _swap); - } + X86.cmpImm(enc,_con.log_size(),_imm,ptr,idx,_off,_scale); + } else encVal(enc,_con,ptr,idx,src,_off,_scale,_swap); } static void encVal(Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale, boolean _swap) { - if(decl instanceof TypeFloat) { - src -= (short)x86_64_v2.XMM_OFFSET; - enc.add1(decl==TypeFloat.F32 ? 0xF3 : 0xF2).add1(0x0F).add1(0xC2); - } else { - int log = decl.log_size(); - x86_64_v2.rexF(src, ptr, idx, log == 3, enc); - int swap = _swap ? 2 : 0; - switch(log) { - case 0: enc.add1(0x38+swap); break; - case 1: enc.add1(0x66).add1(0x39+swap); break; - case 2: enc.add1(0x39+swap); break; - case 3: enc.add1(0x39+swap); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + assert !(decl instanceof TypeFloat); // Selected separately as CmpFX86. + X86.cmpMem(enc,decl.log_size(),src,ptr,idx,off,scale,_swap); } // General form: "cmp dst = src, [base + idx<<2 + 12]" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java index e7305cdf..7faea17b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,12 +18,7 @@ public class CmpX86 extends MachConcreteNode implements MachNode { @Override public boolean isClone() { return true; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(in(1)); - short src = enc.reg(in(2)); - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x3B); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x3B,enc.reg(in(1)),enc.reg(in(2))); } @Override public void asm(CodeGen code, SB sb) { String dst = code.reg(this); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index 3427aea5..7bbb5102 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,18 +13,7 @@ public class DivFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5E /r DIVSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5E); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5E,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java index b5904a7f..9f375a80 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -14,16 +15,7 @@ public class DivX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.RDX_MASK; } @Override public void encoding( Encoding enc ) { - // REX.W + F7 /7 IDIV r/m64 - short src = enc.reg(in(2)); - // sign extend rax before 128/64 bits division - // sign extend rax to rdx:rax - enc.add1(x86_64_v2.REX_W); - enc.add1(0x99); - enc.add1(x86_64_v2.rex(0, src, 0)); - // divide - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x07, src)); + X86.divide(enc,enc.reg(in(2))); } // General form: "div dst /= src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java index e905e2e3..1a6ae123 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ExtendX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -20,12 +21,7 @@ public class ExtendX86 extends MachConcreteNode { @Override public RegMask regmap(int i) { return x86_64_v2.RMASK; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this), src = enc.reg(in(1)); - // MOVSX/MOVZX for bytes and shorts; MOVSXD/MOV r32 for ints. - enc.add1(x86_64_v2.rex(dst,src,0,_signed || _bits<32)); - if( _bits==32 ) enc.add1(_signed ? 0x63 : 0x8b); - else enc.add1(0x0f).add1((_signed ? 0xbe : 0xb6) + (_bits==16 ? 1 : 0)); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT,dst,src)); + X86.extend(enc,_bits,_signed,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index 15e95374..59f06341 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,20 +18,8 @@ public class FltX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { if( _ext!=null ) throw Utils.TODO(); - // Load the constant into a FPR - // movsd xmm, [rip + 0] - // F2 0F 10 /r MOVSD xmm1, m64 - _encSize = 1/*Fop*/+0/*REX*/+2/*op*/+1/*MODRM*/+4/*offset*/; - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - _encSize += x86_64_v2.rexF(dst, 0, 0, false, enc); - enc.add1(0x0F).add1(0x10); - // hard-code rip here - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x05)); - enc.add4(0); - enc.largeConstant(this,_con,_encSize-4,2/*ELF encoding PC32*/); + _encSize=X86.rip(enc,0xF2,0x0F10,false,enc.reg(this)-x86_64_v2.XMM_OFFSET); + enc.largeConstant(this,_con,_encSize-4,2/*ELF PC32*/); } // Delta is from opcode start diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java index 1724109a..0e44aee7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FunX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.FunNode; @@ -25,11 +26,7 @@ public class FunX86 extends FunNode implements MachNode { @Override public void encoding( Encoding enc ) { int sz = _frameAdjust; if( sz == 0 ) return; // Skip if no frame adjust - // opcode: 0x83, addi rsp with immediate 8 - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b101, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); + X86.imm(enc,0x81,5,x86_64_v2.RSP,sz); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java index 9f3d7905..ee357901 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/I2f8X86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -11,18 +12,7 @@ public class I2f8X86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.XMASK; } @Override public void encoding( Encoding enc ) { - // F2 0F 2A /r CVTSI2SD xmm1, r32/m32 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = enc.reg(in(1)); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, true, enc); - - enc.add1(0x0F).add1(0x2A); - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F2A,true,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java index 5e406911..5a4ff4b2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ImmX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeInteger; @@ -21,14 +22,7 @@ public abstract class ImmX86 extends MachConcreteNode implements MachNode { abstract int mod(); @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - // opcode; 0x81 or 0x83; 0x69 or 0x6B - enc.add1( opcode() + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imm(enc,opcode(),mod(),enc.reg(this),_imm); } // General form: "addi dst += #imm" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java index 1973ea4e..2ffaa3d1 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/IntX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -24,45 +25,8 @@ public class IntX86 extends ConstantNode implements MachNode { } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this); - // Short form for zero - if( _con==Type.NIL || _con==TypeInteger.ZERO ) { - // XOR dst,dst. Can skip REX is dst is low 8, makes this a 32b - // xor, which will also zero the high bits. - if( dst >= 8 ) enc.add1(x86_64_v2.rex(dst, dst, 0)); - enc.add1(0x33); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); - return; - } - if( _ext!=null ) throw Utils.TODO(); - // Simply move the constant into a GPR - // Conditional encoding based on 64 or 32 bits - //REX.W + C7 /0 id MOV r/m64, imm32 - - long imm = ((TypeInteger)_con).value(); - if (Integer.MIN_VALUE <= imm && imm < 0) { - // We need sign extension, so use imm32 into 64 bit register - // REX.W + C7 /0 id MOV r/m64, imm32 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xC7); // 32 bits encoding - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0x00, dst)); - enc.add4((int)imm); - } else if (0 <= imm && imm <= 0xFFFFFFFFL) { - // We want zero extension into 64 bit register - // so move 32 bit into 32 bit register which zeros - // the upper bits in the 64 bit register. - // B8+ rd id MOV r32, imm32 - if (dst >= 8) enc.add1(0x41); - enc.add1(0xB8 + (dst & 0x07)); - enc.add4((int)imm); - } else { - // Just write the full 64 bit constant - // REX.W + B8+ rd io MOV r64, imm64 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xB8 + (dst & 0x07)); - enc.add8(imm); // 64 bits encoding - } + X86.constant(enc,enc.reg(this),_con==Type.NIL ? 0 : ((TypeInteger)_con).value()); } // Human-readable form appended to the SB. Things like the encoding, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index de27aa5c..10cee059 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -30,38 +31,21 @@ public class JmpX86 extends IfNode implements MachNode, RIPRelSize { @Override public void negate() { _bop = negate(_bop); } @Override public void encoding( Encoding enc ) { - if( in(1)!=null ) { - int op = x86_64_v2.jumpop(_bop); - enc.add1(op-16).add1(0); // Short form jump - } else { - if( _bop=="!=" ) return; // Inverted, no code - enc.add1(0xEB).add1(0); // Never-node - } + if( in(1)==null && _bop=="!=" ) return; + X86.branch(enc,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); enc.jump(this,cproj(0)); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding @Override public byte encSize(int delta) { - if( in(1)==null && _bop=="!=" ) return 0; // Inverted never-node, no code - return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 6); + if( in(1)==null && _bop=="!=" ) return 0; + return X86.branchSize(delta,in(1)!=null); } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - assert !( in(1)==null && _bop=="!=" ); // Inverted never-node, no code no patch - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert in(1)==null || bits[opStart] == x86_64_v2.jumpop(_bop)-16; - delta -= 6; // Offset from opcode END - bits[opStart] = 0x0F; - bits[opStart+1] = (byte)(in(1)==null ? 0xE9 : x86_64_v2.jumpop(_bop)); - enc.patch4(opStart+2,delta); - } + assert !(in(1)==null && _bop=="!="); + X86.patchBranch(enc.bits(),opStart,opLen,delta,in(1)==null ? -1 : x86_64_v2.jumpop(_bop)&15); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java index 2cd6018f..4b00e4dd 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LeaX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -23,25 +24,7 @@ public class LeaX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX.W + 8D /r LEA r64,m - short dst = enc.reg(this); - short ptr = enc.reg(in(1)); - short idx = enc.reg(in(2)); - // ptr is null - // just do: [(index * s) + disp32] - if( ptr == -1 ) { - enc.add1(x86_64_v2.rex(dst, 0, idx)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0x04)); - enc.add1(x86_64_v2.sib(_scale, idx, x86_64_v2.RBP)); - enc.add4(_offset); - return; - } - - enc.add1(x86_64_v2.rex(dst, ptr, idx)); - enc.add1(0x8D); // opcode - // rsp is hard-coded here(0x04) - x86_64_v2.indirectAdr(_scale, idx, ptr, _offset, dst, enc); + X86.lea(enc,enc.reg(this),enc.reg(in(1)),enc.reg(in(2)),_offset,_scale); } // General form: "lea dst = base + 4*idx + 12" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java index aca0eea1..5c472dbe 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; @@ -24,33 +25,14 @@ public class LoadX86 extends MemOpX86 { } static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) { - // Allocation may put a full-width integer in an XMM register (or a - // floating value in a GPR). Move its bits using the selected register bank. - if( dst>=x86_64_v2.XMM_OFFSET && decl.log_size()==3 ) decl=TypeFloat.F64; - else if( dst<x86_64_v2.XMM_OFFSET && decl instanceof TypeFloat ) - decl = decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; - if( decl == TypeFloat.F32) enc.add1(0xF3); - if( decl == TypeFloat.F64) enc.add1(0xF2); - - if( decl.isa(TypeFloat.F64) ) - dst -= (short)x86_64_v2.XMM_OFFSET; - - x86_64_v2.rexF(dst, ptr, idx, decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64, enc); - - if( false ) ; - else if( decl == TypeFloat.F32 ) enc.add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32 - else if( decl == TypeFloat.F64 ) enc.add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64 - else if( decl.isa(TypeInteger.I8)) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8 - else if( decl == TypeInteger.I16 ) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16 - else if( decl == TypeInteger.I32 ) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32 - else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8 - else if( decl == TypeInteger.U16 ) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16 - // Covers U32, I64/BOT, TMP - else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32 - else throw Utils.TODO(); - - // includes modrm internally - x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc); + // The chapter chooses the register bank and extension from its own type facts. + boolean xmm=dst>=x86_64_v2.XMM_OFFSET; + if( xmm && decl.log_size()==3 ) decl=TypeFloat.F64; + else if( !xmm && decl instanceof TypeFloat ) + decl=decl==TypeFloat.F32 ? TypeInteger.U32 : TypeInteger.BOT; + boolean signed=decl.isa(TypeInteger.I8) || decl==TypeInteger.I16 || decl==TypeInteger.I32; + X86.load(enc,decl.log_size(),signed,xmm, + xmm ? dst-x86_64_v2.XMM_OFFSET : dst,ptr,idx,off,scale); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java index bd56d022..2e18a058 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemAddX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -15,20 +16,7 @@ public class MemAddX86 extends MemOpX86 { @Override public RegMask outregmap() { return null; } @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - // add something to memory - // REX.W + 01 /r | REX.W + 81 /0 id - // ADD [mem], imm32/reg - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - enc.add1(x86_64_v2.rex(src, ptr, idx)); - // opcode - enc.add1( src == -1 ? (_imm==1 ? 0xFF : 0x81): 0x01); - - // includes modrm - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src == -1 ? 0 : src, enc); - if( src == -1 && _imm!=1 ) enc.add4(_imm); + X86.addMem(enc,enc.reg(val()),_imm,enc.reg(ptr()),enc.reg(idx()),_off,_scale); } // General form: "add [base + idx<<2 + 12] += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index 7932c893..74616db7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,16 +14,7 @@ public class MulFX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // F2 0F 59 /r MULSD xmm1,xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x59).add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F59,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "mulf dst *= src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java index 1e9e708f..5dcb253d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -17,15 +18,7 @@ public class MulIX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } // Rare 3-address form @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // Also src1 - short src = enc.reg(in(1)); - enc.add1(x86_64_v2.rex(dst, src, 0)); - // opcode; 0x69 or 0x6B - enc.add1( 0x69 + (x86_64_v2.imm8(_imm) ? 2 : 0) ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src) ); - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.imul(enc,enc.reg(this),enc.reg(in(1)),_imm); } // General form: "addi dst += #imm" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java index 4d2a11ed..6f3fcdeb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,13 +14,7 @@ public class MulX86 extends MachConcreteNode implements MachNode { @Override public boolean commutes() { return true; } @Override public void encoding( Encoding enc ) { - // REX.W + 0F AF /r IMUL r64, r/m64 - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(0x0F); // opcode - enc.add1(0xAF); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,0x0FAF,enc.reg(this),enc.reg(in(2))); } // General form: "mul dst *= src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java index 0c2baced..86610f6d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -13,10 +14,7 @@ public class NegX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(0xF7); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 3, dst)); + X86.unary(enc,0xF7,3,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java index 40a38809..d6a06c2f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NewX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeFunPtr; @@ -10,11 +11,8 @@ public class NewX86 extends NewNode implements MachNode { NewX86( NewNode nnn ) { super(nnn); } @Override public void encoding( Encoding enc ) { enc.external(this,"calloc"); - // ldi rcx,#1 // number of elements to calloc - enc.add1(0xB8 + _arg2Reg).add4(1); - // E8 cd CALL rel32; - enc.add1(0xE8); - enc.add4(0); // offset + X86.constant(enc,_arg2Reg,1); + X86.call(enc); } // General form: "alloc #bytes PC" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java index 7db80299..1e4e7c26 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/NotX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,25 +13,9 @@ public class NotX86 extends MachConcreteNode implements MachNode { @Override public RegMask killmap() { return x86_64_v2.FLAGS_MASK; } @Override public void encoding( Encoding enc ) { - assert !(in(1) instanceof NotNode); // Cleared out by peeps - assert !(in(1) instanceof BoolNode); // Cleared out by peeps - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - - // test rdi,rdi - enc.add1(x86_64_v2.rex(src, src, 0)); - enc.add1(0x85); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, src, src)); - - // setz dstb; then zero-extend the low byte into the full register. - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0x94); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); - enc.add1(0xB6); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + assert !(in(1) instanceof NotNode); // Cleared out by peeps + assert !(in(1) instanceof BoolNode); + X86.not(enc,enc.reg(this),enc.reg(in(1))); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java index 5a475efe..06755143 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RegX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,13 +13,7 @@ public abstract class RegX86 extends MachConcreteNode { @Override public int twoAddress() { return 1; } abstract int opcode(); @Override public void encoding( Encoding enc ) { - // REX.W + 01 /r - short dst = enc.reg(in(1)); // src1 - short src = enc.reg(in(2)); // src2 - - enc.add1(x86_64_v2.rex(dst, src, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); } // General form: "add dst += src" @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java index a35d43a2..e4467bb4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/RetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -8,12 +9,7 @@ public class RetX86 extends ReturnNode implements MachNode { RetX86( ReturnNode ret, FunNode fun ) { super(ret, fun); fun.setRet(this); } @Override public void encoding( Encoding enc ) { int sz = fun()._frameAdjust; - if( sz != 0 ) { - enc.add1( x86_64_v2.REX_W ).add1( x86_64_v2.imm8(sz) ? 0x83 : 0x81 ); - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0b000, x86_64_v2.RSP) ); - if( x86_64_v2.imm8(sz) ) enc.add1(sz); - else enc.add4(sz); - } - enc.add1(0xC3); + if( sz!=0 ) X86.imm(enc,0x81,0,x86_64_v2.RSP,sz); + X86.ret(enc); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java index 95e0c336..cf6275dc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; @@ -22,15 +23,7 @@ public class SarIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java index 4cc8b558..92493712 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SarX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class SarX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 7, dst)); + X86.unary(enc,opcode(),7,enc.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 177e35ab..864c1b55 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -24,27 +25,15 @@ public class SetX86 extends MachConcreteNode implements MachNode { @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - // REX + 0F 94 - short dst = enc.reg(this ); - - // Optional rex, for dst - if( dst >= 4 ) enc.add1(x86_64_v2.rex(0, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(switch (_bop) { + int op=switch (_bop) { case "==" -> 0x94; // SETE case "<" -> _unsigned ? 0x92 : 0x9C; // SETB /SETL case "<=" -> _unsigned ? 0x96 : 0x9E; // SETBE/SETLE case ">=" -> _unsigned ? 0x93 : 0x9D; // SETAE/SETGE case ">" -> _unsigned ? 0x97 : 0x9F; // SETA /SETG default -> throw Utils.TODO(); - }); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); - - // low 8 bites are set, now zero extend for next instruction - if( dst >= 4 ) enc.add1(x86_64_v2.rex(dst, dst, 0, false)); - enc.add1(0x0F); // opcode - enc.add1(0xB6); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, dst)); + }; + X86.set(enc,op&15,enc.reg(this)); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java index f7b2f28a..1e62243e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -23,15 +24,7 @@ public class ShlIX86 extends MachConcreteNode implements MachNode { @Override public String op() { return "shli"; } @Override public String glabel() { return "<<"; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java index 5fee72d9..768d97e7 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShlX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShlX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 4, dst)); + X86.unary(enc,opcode(),4,enc.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java index 7e0378b1..8a0d1b58 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrIX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.node.Node; @@ -18,15 +19,7 @@ public class ShrIX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding(Encoding enc) { - short dst = enc.reg(this); // Also src1 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1( opcode()); - - enc.add1( x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, mod(), dst) ); - - // immediate(4 bytes) 32 bits or (1 byte)8 bits - if( x86_64_v2.imm8(_imm) ) enc.add1(_imm); - else enc.add4(_imm); + X86.shift(enc,mod(),enc.reg(this),_imm); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(" ").p(glabel()).p("= #").p(_imm); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java index 67dcf055..1ba20fee 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/ShrX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.util.Utils; @@ -15,10 +16,6 @@ public class ShrX86 extends RegX86 { } @Override int opcode() { return 0xD3; } @Override public final void encoding( Encoding enc ) { - short dst = enc.reg(this ); // src1 - short src = enc.reg(in(2)); // src2 - enc.add1(x86_64_v2.rex(0, dst, 0)); - enc.add1(opcode()); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 5, dst)); + X86.unary(enc,opcode(),5,enc.reg(this)); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index bc3d421d..b2b643d3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.FunNode; import com.seaofnodes.simple.node.Node; @@ -18,44 +19,17 @@ public class SplitX86 extends SplitNode { // Need to handle 8 cases: . reg->reg, reg->xmm, reg->flags, xmm->reg, xmm->xmm, xmm->flags, flags->reg, flags->xmm, // flags->flags. @Override public void encoding( Encoding enc ) { - // REX.W + 8B /r MOV r64, r/m64 - short dst = enc.reg(this ); - short src = enc.reg(in(1)); - if( dst == x86_64_v2.FLAGS ) { - // mov reg, flags - // push rcx - // popf (Pop the top of the stack into the FLAGS register) - // 50+rd PUSH r64 - x86_64_v2.rexF(0,src,0,false,enc); - enc.add1(0x50 + src); - // popf - enc.add1(0x9D); - return; - } - if( src == x86_64_v2.FLAGS ) { - // mov flags, reg - // pushf; pop reg - enc.add1(0x9C); - // 58+ rd POP r64 - x86_64_v2.rexF(0,dst,0,false, enc); - enc.add1(0x58 + dst); - return; - } - - // Flag for being either XMM or stack - boolean dstX = dst >= x86_64_v2.XMM_OFFSET; - boolean srcX = src >= x86_64_v2.XMM_OFFSET; - + short dst=enc.reg(this), src=enc.reg(in(1)); + if( dst==x86_64_v2.FLAGS ) { X86.flags(enc,src,true); return; } + if( src==x86_64_v2.FLAGS ) { X86.flags(enc,dst,false); return; } + boolean dstX=dst>=x86_64_v2.XMM_OFFSET, srcX=src>=x86_64_v2.XMM_OFFSET; // Stack spills if( dst >= x86_64_v2.MAX_REG ) { int off = fun(enc).computeStackOffset(enc._code,dst); if( src >= x86_64_v2.MAX_REG ) { // Rare stack-stack move. push [RSP+soff]; pop [RSP+doff] int soff = fun(enc).computeStackOffset(enc._code,src); - enc.add1(0xFF); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, soff, 6, enc); - enc.add1(0x8F); - x86_64_v2.indirectAdr(0, (short)-1/*index*/, (short)x86_64_v2.RSP, off, 0, enc); + X86.stackCopy(enc,soff,off); return; } StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0); @@ -67,34 +41,7 @@ public class SplitX86 extends SplitNode { return; } - // reg-reg move. Adjust numbering for GPR vs FPR reg set - if( dstX ) dst -= (short) x86_64_v2.XMM_OFFSET; - if( srcX ) src -= (short) x86_64_v2.XMM_OFFSET; - - // 0x66 if moving between register classes - if( dstX ^ srcX ) enc.add1(0x66); - if( !dstX && srcX ) - { short tmp=src; src=dst; dst=tmp; } - enc.add1(x86_64_v2.rex(dst, src, 0)); - - // pick opcode based on regs - if( !dstX && !srcX ) { - // reg->reg (MOV r64, r/m64) - enc.add1(0x8B); - } else if( dstX && srcX ) { - // xmm->xmm (NP 0F 28 /r MOVAPS xmm1, xmm2/m128) - enc.add1(0x0F); - enc.add1(0x28); - } else if( dstX && !srcX ) { - // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) - enc.add1(0x0F); - enc.add1(0x6E); - } else if( !dstX && srcX ) { - // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) - enc.add1(0x0F); - enc.add1(0x7E); - } - - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.move(enc,dstX,srcX,dstX ? dst-x86_64_v2.XMM_OFFSET : dst, + srcX ? src-x86_64_v2.XMM_OFFSET : src); } } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java index 7133e824..9ffa25fc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.*; @@ -25,55 +26,16 @@ public class StoreX86 extends MemOpX86 { // Register mask allowed as a result. 0 for no register. @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { - // REX.W + C7 /0 id MOV r/m64, imm32 | - // REX.W + 89 /r MOV r/m64, r64 - short ptr = enc.reg(ptr()); - short idx = enc.reg(idx()); - short src = enc.reg(val()); - - if( src == -1 ) { - int log = Integer.numberOfTrailingZeros(_sz-'0'); - x86_64_v2.rexF(-1, ptr, idx, log==3, enc); - switch( log ) { - case 0: enc .add1(0xC6); break; - case 1: enc.add1(0x66).add1(0xC7); break; - case 2: enc .add1(0xC7); break; - case 3: enc .add1(0xC7); break; - } - x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc); - switch( log ) { - case 0: enc.add1(_imm); break; - case 1: enc.add2(_imm); break; - case 2: enc.add4(_imm); break; - case 3: enc.add4(_imm); break; // Limit of a 4 byte immediate - } - } else { - encVal(enc,_con,ptr,idx,src,_off,_scale); - } + short ptr=enc.reg(ptr()), idx=enc.reg(idx()), src=enc.reg(val()); + if( src==-1 ) X86.storeImm(enc,Integer.numberOfTrailingZeros(_sz-'0'),_imm,ptr,idx,_off,_scale); + else encVal(enc,_con,ptr,idx,src,_off,_scale); } // Non-immediate encoding static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) { - int log = decl.log_size(); - // Float reg being stored - if( src >= x86_64_v2.XMM_OFFSET ) { - src -= (short)x86_64_v2.XMM_OFFSET; - assert log == 2 || log == 3; - enc.add1( log==2 ? 0xF3 : 0xF2 ); - x86_64_v2.rexF(src,ptr,idx,false,enc); - enc.add1(0x0F).add1(0x11); - } else { - // byte stores from sil, dil, bpl, spl need a rex - if( log == 0 && src >= x86_64_v2.RSP ) enc.add1(x86_64_v2.rex(src,ptr,idx,false)); - else x86_64_v2.rexF(src,ptr,idx,log==3,enc); - switch( log ) { - case 0: enc .add1(0x88); break; - case 1: enc.add1(0x66).add1(0x89); break; - case 2: enc .add1(0x89); break; - case 3: enc .add1(0x89); break; - } - } - x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc); + boolean xmm=src>=x86_64_v2.XMM_OFFSET; + X86.store(enc,decl.log_size(),xmm, + xmm ? src-x86_64_v2.XMM_OFFSET : src,ptr,idx,off,scale); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index b6530a87..29f0033a 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.util.SB; @@ -12,16 +13,7 @@ public class SubFX86 extends MachConcreteNode implements MachNode { @Override public int twoAddress() { return 1; } @Override public void encoding( Encoding enc ) { - // F2 0F 5C /r SUBSD xmm1, xmm2/m64 - short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); - short src = (short)(enc.reg(in(2)) - x86_64_v2.XMM_OFFSET); - // Fopcode - enc.add1(0xF2); - // rex prefix must come next (REX.W is not set) - x86_64_v2.rexF(dst, src, 0, false, enc); - - enc.add1(0x0F).add1(0x5C); - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); + X86.sse(enc,0xF2,0x0F5C,false,enc.reg(this)-x86_64_v2.XMM_OFFSET,enc.reg(in(2))-x86_64_v2.XMM_OFFSET); } // General form: "subf dst -= src" diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index fe2060ba..e3563713 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.Type; @@ -25,17 +26,9 @@ public class TFPX86 extends FunPtrNode implements MachNode, RIPRelSize { @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { - if( _ext==null ) enc.relo(this); // Internal patch - else enc.external(this,_ext); // ELF-file external patch - // lea to load function pointer address - // lea rax, [rip+disp32] - short dst = enc.reg(this); - // 0 or 1 for REX depending on the dst. - // Zero/sign extend should be fine, so not wide. - _opLen = (byte)(6+ x86_64_v2.rexF(dst, 0, 0, true, enc)); - enc.add1(0x8D); // opcode - enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)); - enc.add4(0); + if( _ext==null ) enc.relo(this); + else enc.external(this,_ext); + _opLen=X86.rip(enc,0,0x8D,true,enc.reg(this)); } @Override public byte encSize(int delta) { return _opLen; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java index fbd79dd7..682597f4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TMPX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.TypeMemPtr; @@ -18,8 +19,7 @@ public class TMPX86 extends ConstantNode implements MachNode, RIPRelSize{ @Override public void encoding( Encoding enc ) { short dst = enc.reg(this); // 0 or 1 for REX depending on the dst. - _opLen = (byte)(6+ x86_64_v2.rexF(dst, 0, 0, true, enc)); - enc.add1(0x8D).add1(x86_64_v2.modrm(x86_64_v2.MOD.INDIRECT, dst, 0b101)).add4(0); + _opLen = X86.rip(enc,0,0x8D,true,dst); if( _ext!=null ) enc.externalData(this,_ext); else enc.largeConstant(this,((TypeMemPtr)_con)._obj, _opLen-4, 2/*ELF encoding PC32*/); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java index 6f538d27..591a51c3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/UJmpX86.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.node.cpus.x86_64_v2; +import com.seaofnodes.isa.X86; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.*; @@ -19,29 +20,17 @@ public class UJmpX86 extends CFGNode implements MachNode, RIPRelSize { @Override public Node idealize() { throw Utils.TODO(); } @Override public void encoding( Encoding enc ) { enc.jump(this,uctrl()); - // Short-form jump - enc.add1(0xEB).add1(0); - //// E9 cd JMP rel32 - //enc.add1(0xE9).add4(0); + X86.branch(enc,-1); } // Delta is from opcode start, but X86 measures from the end of the 2-byte encoding - @Override public byte encSize(int delta) { return (byte)(x86_64_v2.imm8(delta-2) ? 2 : 5); } + @Override public byte encSize(int delta) { + return X86.branchSize(delta,false); + } // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - byte[] bits = enc.bits(); - if( opLen==2 ) { - assert bits[opStart] == (byte)0xEB; - delta -= 2; // Offset from opcode END - assert (byte)delta==delta; - bits[opStart+1] = (byte)delta; - } else { - assert bits[opStart] == (byte)0xEB; - bits[opStart] = (byte)0xE9; // Long form - delta -= 5; // Offset from opcode END - enc.patch4(opStart+1,delta); - } + X86.patchBranch(enc.bits(),opStart,opLen,delta,-1); } @Override public void asm(CodeGen code, SB sb) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 99010ffd..f006411e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -69,13 +69,6 @@ public class x86_64_v2 extends Machine { public static int REX_WRB= 0x4D; public static int REX_WB = 0x49; - public enum MOD { - INDIRECT, // [mem] - INDIRECT_disp8, // [mem + 0x12] - INDIRECT_disp32, // [mem + 0x12345678] - DIRECT, // mem - }; - // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -95,90 +88,6 @@ public class x86_64_v2 extends Machine { }; } - public static int modrm(MOD mod, int reg, int m_r) { - if( reg == -1 ) reg=0; // Missing reg in this flavor - // combine all the bits - assert 0 <= reg && reg < 16; - assert 0 <= m_r && m_r < 16; - return (mod.ordinal() << 6) | ((reg & 0x07) << 3) | m_r & 0x07; - } - - // 00 000 000 - // same bit-layout as modrm - public static int sib(int scale, int index, int base) { - assert 0 <= base && base < 16; - assert 0 <= index && index < 16; - return (scale << 6) | ((index & 0x07) << 3) | base & 0x07; - } - - // reg1 is reg(R) - // reg2 is r/mem(B) - // reg3 is X(index) - // reg4 is X(base) - - // 0 denotes no direct register - public static int rex(int reg, int ptr, int idx, boolean wide) { - // assuming 64 bit by default so: 0100 1000 - assert -1 <= reg && reg < 16; - assert -1 <= ptr && ptr < 16; - assert -1 <= idx && idx < 16; - - int rex = wide ? REX_W : REX; - if( 8 <= reg ) rex |= 0b00000100; // REX.R - if( 8 <= ptr ) rex |= 0b00000001; // REX.B - if( 8 <= idx ) rex |= 0b00000010; // REX.X - return rex; - } - - public static int rex(int reg, int ptr, int idx) { - return rex(reg, ptr, idx, true); - } - - // rex for floats. Return size (0 or 1) - // don't need to use REX if 0x40. - public static byte rexF(int reg, int ptr, int idx, boolean wide, Encoding enc) { - int rex = rex(reg, ptr, idx, wide); - if (rex == REX) return 0; - enc.add1(rex); - return 1; - } - // Function used for encoding indirect memory addresses - // Does not always generate SIB byte e.g index == -1. - // -1 denotes empty value, not set - note 0 is different from -1 as it can represent rax. - // Looks for best mod locally - public static void indirectAdr( int scale, short index, short base, int offset, int reg, Encoding enc ) { - // Assume indirect - assert 0 <= base && base < 16; - assert -1 <= index && index < 16 && index != RSP; - - MOD mod = MOD.INDIRECT; - // is 1 byte enough or need more? - if( offset != 0 ) - mod = imm8(offset) - ? MOD.INDIRECT_disp8 - : MOD.INDIRECT_disp32; - - if( mod == MOD.INDIRECT && (base == RBP || base == R13) ) { - mod = MOD.INDIRECT_disp8; - } else if( index == -1 && (base == RSP || base == R12) ) { - index = RSP; - } - - if( index == -1 ) { - enc.add1(modrm(mod, reg, base)); - } else { - enc.add1(modrm(mod, reg, x86_64_v2.RSP)); - enc.add1(sib(scale, index, base)); - } - - if( mod == MOD.INDIRECT_disp8 ) { - enc.add1(offset); - } else if( mod == MOD.INDIRECT_disp32 ) { - enc.add4(offset); - } - } - - // Limit of float args passed in registers static RegMask[] XMMS8 = new RegMask[]{ new RegMask(XMM0), new RegMask(XMM1), new RegMask(XMM2), new RegMask(XMM3), diff --git a/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index f3da1592..c2713e4f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import java.io.IOException; import org.junit.Test; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java index a400dc5f..c3d93188 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.cpus.arm.arm; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java index 35e0144a..82211985 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.util.Utils; import com.seaofnodes.simple.codegen.CodeGen; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java index 2f0490a5..dad1dde4 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java index a94f36f2..05dfe1c2 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java index 7158ace0..c05c13f1 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java @@ -1,5 +1,9 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.ElfReader; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java deleted file mode 100644 index 633e931e..00000000 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ /dev/null @@ -1,368 +0,0 @@ - package com.seaofnodes.simple; - -/** Simple RISC5 CPU Emulator - * - * Original works credit Charles Lohr. - * This is a complete rewrite in Java. - * - * Load code into memory and go! - */ - -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.riscv.riscv; -import com.seaofnodes.simple.util.Utils; -import java.io.ByteArrayOutputStream; -import java.util.Arrays; - -public class EvalRisc5 { - - // Memory image, always 0-based - public final byte[] _buf; - - // GPRs - final long[] regs; - // FRs - final double[] fregs; - // PC - int _pc; - - // Start of free memory for allocation - int _heap; - - // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; - - // Cycle counters - int _cycle; - - EvalRisc5( byte[] buf, int stackSize ) { - _buf = buf; - regs = new long[32]; - fregs = new double[32]; - // Stack grows down, heap grows up - regs[riscv.RSP] = _heap = stackSize; - _pc = 0; - } - - // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } - public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - - public float ld4f(int x) { return Float.intBitsToFloat(ld4s(x)); } - public double ld8f(int x) { return Double.longBitsToDouble(ld8(x)); } - - - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) {st2(x,val); st2(x+2,val>>16); } - public void st8(int x, long val) { st4(x,(int)val); st4(x+4,(int)(val>>32)); } - - // Note: only a few bits are used. (Machine = 3, User = 0) - // Bits 0..1 = privilege. - // Bit 2 = WFI (Wait for interrupt) - // Bit 3+ = Load/Store reservation LSBs. - int _extraflags; - - public int step( int maxops ) { - int trap = 0; - long rval = 0; - double frval = 0; - int pc = _pc; - int cycle = _cycle; - boolean is_f = false; - outer: - for( int icount = 0; icount < maxops; icount++ ) { - int ir = 0; - rval = 0; - cycle++; - - if( pc >= _buf.length ) { - trap = 1 + 1; // Handle access violation on instruction read. - break; - } - if( (pc & 3)!=0 ) { - trap = 1; // Handle PC-misaligned access - break; - } - // Load instruction from image buffer at PC - ir = ld4s( pc ); - int rdid = (ir >> 7) & 0x1f; - - switch( ir & 0x7f ) { - case 0x37: // LUI (0b0110111) - rval = ( ir & 0xfffff000 ); - break; - case 0x17: // AUIPC (0b0010111) - rval = pc + ( ir & 0xfffff000 ); - break; - case 0x6F: { // JAL (0b1101111) - int reladdy = ((ir & 0x80000000)>>11) | ((ir & 0x7fe00000)>>20) | ((ir & 0x00100000)>>9) | ((ir&0x000ff000)); - if( (reladdy & 0x00100000)!=0 ) reladdy |= 0xffe00000; // Sign extension. - rval = pc + 4; - pc = pc + reladdy - 4; - if( pc+4 == Encoding.SENTINEL_WRITE ) { - ByteArrayOutputStream baos = switch((int)regs[10]) { - case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; - case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; - default -> throw new IllegalArgumentException(); - }; - baos.write(_buf,(int)regs[11],(int)regs[12]); - regs[10] = regs[12]; - rdid = 0; - pc = (int)(rval - 4); // Unwind PC, as-if returned from write - } - break; - } - case 0x67: { // JALR (0b1100111) - int imm_se = ir >> 20; // Sign extend 12 bits - rval = pc + 4; - pc = ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1; - // Return from top-level ; exit sim - if( pc==0 ) { - if( rdid!=0 ) regs[rdid] = rval; // Write PC into register before exit - break outer; - } - // Inline CALLOC effect - if( pc == Encoding.SENTINEL_CALLOC ) { - assert (_heap&7) == 0; // 8-byte aligned - int size = (int)(regs[10]*regs[11]); - size = (size+7) & -8; // 8-byte aligned - regs[10] = _heap; // Return next free address - _heap += size; - pc = (int)(rval - 4); // Unwind PC, as-if returned from calloc - } else - pc -= 4; - break; - } - case 0x63: { // Branch (0b1100011) - int immm4 = ((ir & 0xf00)>>7) | ((ir & 0x7e000000)>>20) | ((ir & 0x80) << 4) | ((ir >> 31)<<12); - if( (immm4 & 0x1000)!=0 ) immm4 |= 0xffffe000; - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - immm4 = pc + immm4 - 4; - rdid = 0; - if( switch( (ir >> 12) & 0x7 ) { - case 0 -> rs1 == rs2; - case 1 -> rs1 != rs2; - case 4 -> rs1 < rs2; - case 5 -> rs1 >= rs2; - case 6 -> Long.compareUnsigned(rs1,rs2) < 0; //BLTU - case 7 -> Long.compareUnsigned(rs1,rs2) >= 0; //BGEU - default -> { trap = (2+1); yield false; } - } ) pc = immm4; - break; - } - case 0x03: { // Load (0b0000011) - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - //LB, LH, LW, LBU, LHU - case 0: rval = ld1s( rsval ); break; - case 1: rval = ld2s( rsval ); break; - case 2: rval = ld4s( rsval ); break; - case 3: rval = ld8 ( rsval ); break; - case 4: rval = ld1z( rsval ); break; - case 5: rval = ld2z( rsval ); break; - case 6: rval = ld4s( rsval ); break; - default: trap = (2+1); - } - } - break; - } - // floats - case 0x7: { - is_f = true; - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - int imm = ir >> 20; - int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); - int rsval = rs1 + imm_se; - - if( rsval >= _buf.length-3 ) { - trap = (5+1); - rval = rsval; - } else { - switch( ( ir >> 12 ) & 0x7 ) { - case 2: frval = ld4f( rsval ); break; - case 3: frval = ld8f( rsval ); break; - default: trap = (2+1); - } - } - break; - } - - case 0x23: { // Store 0b0100011 - int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b - long rs2 = regs[(ir >> 20) & 0x1f]; - int addy = ( ( ir >> 7 ) & 0x1f ) | ( ( ir & 0xfe000000 ) >> 20 ); - if( (addy & 0x800)!=0 ) addy |= 0xfffff000; - addy += rs1; - rdid = 0; - if( addy >= _buf.length-3 ) { - trap = (7+1); // Store access fault. - rval = addy; - } else { - switch( ( ir >> 12 ) & 0x7 ) { //SB, SH, SW - case 0: st1( addy, (int)rs2 ); break; - case 1: st2( addy, (int)rs2 ); break; - case 2: st4( addy, (int)rs2 ); break; - case 3: st8( addy, rs2 ); break; - default: trap = (2+1); - } - } - break; - } - case 0x13: // Op-immediate 0b0010011 - case 0x33: { // Op 0b0110011 - int imm = ir >> 20; - imm = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); - long rs1 = regs[(ir >> 15) & 0x1f]; - boolean is_reg = (ir & 0x20)!=0; - long rs2 = is_reg ? regs[imm & 0x1f] : imm; - - // Insert the detection here - int rs1id = (ir >> 15) & 0x1f; - int funct3 = (ir >> 12) & 0x7; - - if( is_reg && ( ir & 0x02000000 )!=0 ) { - switch( (ir>>12)&7 ) { //0x02000000 = RV32M - case 0: rval = rs1 * rs2; break; // MUL - case 1: rval = (int)((long)((int)rs1) * (long)((int)rs2)) >> 32; break; // MULH - case 2: rval = (int)((long)((int)rs1) * (long)rs2) >> 32; break; // MULHSU - case 3: rval = (int)((long)rs1 * (long)rs2) >> 32; break; // MULHU - case 4: if( rs2 == 0 ) rval = -1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? rs1 : ((int)rs1 / (int)rs2); break; // DIV - case 5: if( rs2 == 0 ) rval = 0xffffffff; else rval = rs1 / rs2; break; // DIVU - case 6: if( rs2 == 0 ) rval = rs1; else rval = ((int)rs1 == Integer.MIN_VALUE && (int)rs2 == -1) ? 0 : ((int)((int)rs1 % (int)rs2)); break; // REM - case 7: if( rs2 == 0 ) rval = rs1; else rval = rs1 % rs2; break; // REMU - } - } else { - rval = switch( (ir >> 12) & 7 ) { // These could be either op-immediate or op commands. Be careful. - case 0 -> (is_reg && (ir & 0x40000000) != 0) ? (rs1 - rs2) : (rs1 + rs2); - case 1 -> rs1 << (rs2 & 0x3F); - case 2 -> (rs1 < rs2) ? 1 : 0; - case 3 -> (rs1 < rs2) ? 1 : 0; - case 4 -> rs1 ^ rs2; - case 5 -> (ir & 0x40000000) != 0 ? (rs1 >> (rs2 & 0x3F)) : (rs1 >>> (rs2 & 0x3F)); - case 6 -> rs1 | rs2; - case 7 -> rs1 & rs2; - default -> rval; - }; - } - break; - } - case 0x0f: // 0b0001111 - rdid = 0; // fencetype = (ir >> 12) & 0b111; We ignore fences in this impl. - break; - case 0x73: // Zifencei+Zicsr (0b1110011) - trap = (2+1); // Note micrrop 0b100 == undefined. - break; - - case 0x2f: { // RV32A (0b00101111) - long rs1 = regs[(ir >> 15) & 0x1f]; - long rs2 = regs[(ir >> 20) & 0x1f]; - int irmid = ( ir>>27 ) & 0x1f; - - // We don't implement load/store from UART or CLNT with RV32A here. - if( rs1 >= _buf.length-3 ) { - trap = (7+1); //Store/AMO access fault - rval = rs1; - } else { - rval = ld4s( (int)rs1 ); - - // Referenced a little bit of https://github.com/franzflasch/riscv_em/blob/master/src/core/core.c - boolean dowrite = true; - switch( irmid ) { - case 2: //LR.W (0b00010) - dowrite = false; - _extraflags = (_extraflags & 0x07) | (int)(rs1<<3); - break; - case 3: { //SC.W (0b00011) (Make sure we have a slot, and, it's valid) - boolean xflag = _extraflags >> 3 != ( rs1 & 0x1fffffff ); - rval = xflag ? 1 : 0; // Validate that our reservation slot is OK. - dowrite = !xflag; // Only write if slot is valid. - break; - } - case 0: rs2 += rval; break; // AMOADD.W (0b00000) - case 1: break; // AMOSWAP.W (0b00001) - case 4: rs2 ^= rval; break; // AMOXOR.W (0b00100) - case 8: rs2 |= rval; break; // AMOOR.W (0b01000) - case 12: rs2 &= rval; break; // AMOAND.W (0b01100) - case 16: rs2 = Math.min( rs2, rval ); break; //AMOMIN.W (0b10000) - case 20: rs2 = Math.max( rs2, rval ); break; //AMOMAX.W (0b10100) - case 24: rs2 = Math.min( rs2, rval ); break; //AMOMINU.W (0b11000) - case 28: rs2 = Math.max( rs2, rval ); break; //AMOMAXU.W (0b11100) - default: trap = (2+1); dowrite = false; break; //Not supported. - } - if( dowrite ) st4( (int)rs1, (int)rs2 ); - } - break; - } - - case 0x53: { - is_f = true; - int rs1 = (ir >> 15) & 0x1F; - int rs2 = (ir >> 20) & 0x1F; - double lhs = fregs[rs1]; - double rhs = fregs[rs2]; - int func5 = (ir >> 27) & 0x1F; - int func2 = (ir >> 25) & 0x3; - if( func2 != 1 ) throw Utils.TODO(); // 1==double - switch( func5 ) { - case 0: frval = lhs + rhs; break; // fadd.d - case 1: frval = lhs - rhs; break; // fsub.d - case 2: frval = lhs * rhs; break; // fmul.d - case 3: frval = lhs / rhs; break; // fdiv.d - case 5: frval = Math.min(lhs,rhs); break; // fmin.d, also used for move - case 20: - is_f = false; // Output into a GPR - rval = switch( (ir >> 12) & 7 ) { - case 0 -> lhs <= rhs ? 1 : 0; - case 1 -> lhs == rhs ? 1 : 0; - case 2 -> lhs < rhs ? 1 : 0; - default -> throw Utils.TODO(); - }; - break; - case 26: frval = (double)regs[rs1]; break; // fcvt.w.d - default: - trap = (2+1); // Fault: Invalid opcode. - throw Utils.TODO(); - } - break; - } - - default: trap = (2+1); // Fault: Invalid opcode. - } - - // If there was a trap, do NOT allow register writeback. - if( trap!=0 ) { - _pc = pc; - break; - } - - if( rdid!=0 || is_f) { - if(is_f) {fregs[rdid] = frval; is_f = false;} // Write back register. - else regs[rdid] = rval; // Write back register. - } - - pc += 4; - } - - // Handle traps and interrupts. - if( trap!=0 ) - return trap; - - _cycle = cycle; - _pc = pc; - return 0; - } -} diff --git a/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java index ca33438a..ba8fc178 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.node.cpus.riscv.riscv; import com.seaofnodes.simple.util.SB; import java.io.IOException; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java index d2c6cde4..f1089cf0 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalArm64; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.FunNode; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java index 1de5e3bc..10c75d3f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -1,5 +1,7 @@ package com.seaofnodes.simple; +import com.seaofnodes.isa.eval.EvalRisc5; + import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; diff --git a/docs/chapter-backports.md b/docs/chapter-backports.md index 871c77f9..7332cb48 100644 --- a/docs/chapter-backports.md +++ b/docs/chapter-backports.md @@ -22,6 +22,41 @@ Splitting Chapter 25 is deferred, not an instruction to renumber. ## Pending corrections +### Shared ISA encoders and evaluators: Chapters 21-25 (review checkpoint) + +Issue #257's extraction is implemented in [`isa/`](../isa/README.md). `X86` +accepts concrete registers, widths, immediates and addresses; `Arm64` and `RiscV` +pack instruction words. Chapter `Encoding` classes implement `CodeSink` using +their existing byte writers. ARM logical immediates and constant construction +are shared too. None of these helpers imports compiler classes. + +Instruction selection and masks, compiler-type interpretation, frame and block +layout, branch relaxation, relocations, constants, and ELF remain chapter-local. +Branch byte sizes and patching are shared; the chapter still runs relaxation +and supplies targets. One shared `EvalArm64` and `EvalRisc5` replace the five +copies of each. Image construction and test assertions stay in chapter harnesses. +Evaluators compile as test support. Make continues to bundle tests in its release +jars; Maven and IDEA retain separate main/test dependencies. + +Direct byte tests also cover corrections exposed by consolidation: x86 legacy +prefix order for 16-bit memory operations, indirect register calls and their REX +bits, imm8 shift counts, high-register PUSH/POP, low-byte SETcc, and five-byte +unconditional near jumps. RISC-V JAL now takes its sign bit from displacement +bit 20. ARM masks negative literal-load offsets, checks byte displacement ranges +correctly, and its evaluator distinguishes MOVN from AND-immediate. +A disposable GNU assembler comparison agrees on all 5,760 tested x86 +load/store/LEA instructions (`build/IsaOracle.java`). Shared tests add fixed ARM +and RISC-V words and evaluator checks for multi-instruction ARM constants. +Make, Maven source paths, IDEA wiring, and linearized checkouts include `isa/` +starting at Chapter 21; Chapters 1-20 have no ISA dependency. + +Validation: full Chapter 21-25 Make suites pass, including native execution and +the existing allocator checks (`build/isa-final-tests.log`). The independent +shared ISA tests pass; a fresh linear Chapter 21 release contains all three +encoders and shared evaluators (`build/isa-linear21-complete-release.log`). +Maven/IDE XML parses; the standalone POM gains main and test ISA source roots +at Chapter 21 only. Shell syntax and LF checks pass. Nothing has been pushed. + ### Chapter 15 allocation design (implemented) Chapters 12-14 retain explicit initialization Stores. Chapter 15 replaces them diff --git a/isa/Makefile b/isa/Makefile new file mode 100644 index 00000000..b5a3f7b2 --- /dev/null +++ b/isa/Makefile @@ -0,0 +1,16 @@ +SHELL := /bin/bash +.DEFAULT_GOAL := tests +.DELETE_ON_ERROR: +main_javas := $(wildcard src/main/java/com/seaofnodes/isa/*.java) +test_javas := $(wildcard src/test/java/com/seaofnodes/isa/*.java) +eval_javas := $(wildcard src/test-support/java/com/seaofnodes/isa/eval/*.java) + +.PHONY: tests +tests: build/classes/.tag + java -ea -cp build/classes com.seaofnodes.isa.X86Test + java -ea -cp build/classes com.seaofnodes.isa.RiscTest + +build/classes/.tag: $(main_javas) $(test_javas) $(eval_javas) + @mkdir -p build/classes + javac -d build/classes $(main_javas) $(test_javas) $(eval_javas) + @touch $@ diff --git a/isa/README.md b/isa/README.md new file mode 100644 index 00000000..29c6e28b --- /dev/null +++ b/isa/README.md @@ -0,0 +1,79 @@ +# Shared instruction encoders + +This module contains the x86-64, AArch64, and RISC-V instruction encoders used +by Chapters 21-25, plus their ARM/RISC-V test evaluators. +It is compiler implementation code, shared because the same concrete instruction +should have the same encoding in every chapter. It requires only the JDK. + +The compiler still decides which instruction to select, which physical registers +to use, what an operand's width and extension mean, and where blocks, stack +slots, constants, and relocation targets belong. The shared encoder receives +those decisions as numbers and writes bytes. It imports no chapter classes and +has no knowledge of nodes, types, calling conventions, or compilation phases. + +## Follow one instruction + +Chapter 21's `AddX86` selects opcode `0x03` and retains its register masks and +two-address constraint. Its `RegX86` base obtains the allocated registers: + +```java +@Override public void encoding(Encoding enc) { + X86.reg(enc,opcode(),enc.reg(in(1)),enc.reg(in(2))); +} +``` + +The shared `X86.reg` emits REX.W, the opcode, and ModRM. For `add r9,r10`, those +bytes are `4d 03 ca`: REX extends both register fields, `03` selects ADD with the +destination in ModRM.reg, and `ca` selects register operands 1 and 2. Chapter 21 +records the resulting instruction offset and length, just as before. + +`Encoding` implements the small `CodeSink` interface using its existing `add1`, +`add2`, `add4`, and `add8` methods. Shared functions append directly to the compiler's +buffer; they do not allocate temporary instruction objects or byte arrays. + +## Current boundary + +`X86` owns prefixes and addresses, integer and scalar floating-point operations, +loads/stores, comparisons, constant materialization, register/stack copies, +calls, returns, and branch bytes. The chapter chooses branch targets and runs +relaxation; shared helpers calculate instruction lengths and patch displacements. + +Registers are hardware indices 0-15 in the explicitly selected GPR or XMM bank. +Memory operands take a base, an optional index (`-1` for absent), a displacement, +and a scale encoded as 0-3. LEA also supports an absent base. Sizes are log2 of +the byte width, 0-3. The chapter converts its own types and register numbering +to these concrete operands; the encoder never examines compiler types. + +`Arm64` and `RiscV` own opcode constants and instruction-field packing. ARM's +logical-immediate encoding and MOVZ/MOVN/MOVK constant construction are shared +too. Their chapter wrappers resolve node operands and register banks, then +append the resulting instruction words. Instruction selection, masks, scheduling, +frame layout, relocations, constant placement, and object-file writing remain +chapter-local. + +`src/test-support` contains one `EvalArm64` and one `EvalRisc5`. The chapter test +harness still builds the image, links it, sets arguments and checks results. +These small interpreters implement the tutorial's instruction subset, not full +system emulation. Their default test-runtime convention recognizes `calloc` at +address -4 and `write` at -8; an overload accepts different sentinel addresses. +They import no compiler classes and are compiled only with tests. + +## Tests and builds + +`make -C isa tests` runs byte-exact tests without building any compiler. Expected +bytes cover register extensions, low-byte register selection, signed loads, +immediate/displacement boundaries, SIB cases, calls, branches, and prefix order. +ARM/RISC-V checks use fixed instruction words, offset boundaries, and small +evaluator programs, including ARM constants that need several instructions. +The chapter suites continue to test compiler wiring and execute generated code. +The root `make tests` runs both shared and chapter tests. + +Chapter 21-25 Makefiles include `isa.mk`; their Maven builds explicitly add the +shared main and test-support source directories. Earlier chapters do not compile +ISA sources. The linearized Maven build adds them when it reaches Chapter 21. +`isa.iml` describes the IDEA encoder module; `src/test-support/isa-eval.iml` +describes the evaluators, which chapter modules depend on in test scope. +Linearized checkouts carry `isa/` beside the other shared modules. Release jars +include the compiled encoders. Make's existing release recipe also bundles the +chapter tests and their shared evaluators; Maven's ordinary main jar excludes +test classes. diff --git a/isa/isa.iml b/isa/isa.iml new file mode 100644 index 00000000..2319435e --- /dev/null +++ b/isa/isa.iml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <output url="file://$MODULE_DIR$/../build/idea/production/isa" /> + <output-test url="file://$MODULE_DIR$/../build/idea/test/isa" /> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/src/test-support" /> + <excludeFolder url="file://$MODULE_DIR$/build" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="module" module-name="isa-eval" scope="TEST" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> diff --git a/isa/isa.mk b/isa/isa.mk new file mode 100644 index 00000000..7f24618c --- /dev/null +++ b/isa/isa.mk @@ -0,0 +1,5 @@ +# Shared instruction encoders; works in both chapter and linearized checkouts. +ISA_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) +isa_javas := $(wildcard $(ISA_DIR)/src/main/java/com/seaofnodes/isa/*.java) +main_javas += $(isa_javas) +isa_test_javas := $(wildcard $(ISA_DIR)/src/test-support/java/com/seaofnodes/isa/eval/*.java) diff --git a/isa/src/main/java/com/seaofnodes/isa/Arm64.java b/isa/src/main/java/com/seaofnodes/isa/Arm64.java new file mode 100644 index 00000000..2c969da0 --- /dev/null +++ b/isa/src/main/java/com/seaofnodes/isa/Arm64.java @@ -0,0 +1,399 @@ +package com.seaofnodes.isa; + +/** Instruction fields and concrete operand encodings; no compiler state. */ +public final class Arm64 { + private Arm64() {} + + public static final int OP_ADD = 0b10_001_011; + public static final int OPF_ADD = 0b00_011_110; + public static final int OPF_OP_ADD = 0b00_101_0; + public static final int OPI_ADD = 0b10_010_00100; + public static final int OPI_SUB = 0b11_010_00100; + public static final int OP_UJMP = 0b000101; + public static final int OP_ADRP = 0b10000; + public static final int OP_ASR = 0b1010; + public static final int OPI_ASR = 0b10_0100_1101; + public static final int OP_LSL = 0b1000; + public static final int OPI_LSL =0b1101001101; + public static final int OP_LSR = 0b1001; + public static final int OPI_LSR = 0b1101001101; + public static final int OP_BRANCH = 0b01_0101_00; + public static final int OP_CALL = 0b10_010_1; + public static final int OP_CALLRARM = 0b1101011000111111000000; + public static final int OP_SUBS = 0b1111000100; + public static final int OP_CSET = 0b10011010100; + public static final int OP_CMP = 0b11101011; + public static final int OPI_CMP = 0b1111000100; + public static final int OP_DIV = 0b10011010110; + public static final int OPF_DIV = 0b000110; + public static final int OP_MUL = 0b10011011000; + public static final int OPF_MUL = 0b10; + public static final int OPF_ARM = 0b01011100; + public static final int OP_FLOAT_C = 0b10011110; + public static final int OP_XOR = 0b11001010; + public static final int OPI_XOR = 0b110100100; + public static final int OP_AND = 0b10_0010_10; + public static final int OPI_AND = 0b10_0100_100; + public static final int OP_OR = 0b10101010; + public static final int OPI_OR = 0b101100100; + public static final int OP_SUB = 0b11001011; + public static final int OPF_SUB = 0b1110; + public static final int OP_MOVK = 0b111100101; + public static final int OP_MOVN = 0b100100101; + public static final int OP_MOVZ = 0b110100101; + public static final int OP_RET = 0b1101011001011111000000; + public static final int OP_LOAD_R_64 = 0b11111000011; + public static final int OP_LOAD_R_32 = 0b10111000011; + public static final int OP_LOAD_R_16 = 0b01111000010; + public static final int OP_LOAD_R_8 = 0b00111000011; + public static final int OP_LOAD_IMM_64 = 0b1111100101; + public static final int OP_LOAD_IMM_32 = 0b1011100101; + public static final int OP_LOAD_IMM_16 = 0b0111100101; + public static final int OP_LOAD_IMM_8 = 0b0011100101; + public static final int OPF_LOAD_R_64 = 0b11111100011; + public static final int OPF_LOAD_R_32 = 0b10111100011; + public static final int OPF_LOAD_IMM_64 = 0b1111110101; + public static final int OPF_LOAD_IMM_32 = 0b1011110101; + public static final int OP_STORE_R_64 = 0b11111000001; + public static final int OP_STORE_R_32 = 0b10111000001; + public static final int OP_STORE_R_16 = 0b01111000001; + public static final int OP_STORE_R_8 = 0b00111000001; + public static final int OP_STORE_IMM_64 = 0b1111100100; + public static final int OP_STORE_IMM_32 = 0b1011100100; + public static final int OP_STORE_IMM_16 = 0b0111100100; + public static final int OP_STORE_IMM_8 = 0b0011100100; + public static final int OPF_STORE_R_64 = 0b11111100001; + public static final int OPF_STORE_R_32 = 0b10111100001; + public static final int OPF_STORE_IMM_32 = 0b1011110100; + public static final int OPF_STORE_IMM_64 = 0b1111110100; + public static final int OP_FMOV = 0b10011110; + public static final int OP_FMOV_REG = 0b00011110; + public static final int OP_MOV = 0b10101010000; + + public enum OPTION { + UXTB, + UXTH, + UXTX, + SXTB, + SXTH, + SXTW, + SXTX, + } + + public enum STORE_LOAD_OPTION { + UXTW, // base+ u32 index [<< logsize] + UXTX, // base+ u64 index [<< logsize] + SXTW, // base+ s32 index [<< logsize] + SXTX, // base+ s64 index [<< logsize] + } + + public enum COND { + EQ, + NE, + CS, + CC, + MI, + PL, + VS, + VC, + HI, + LS, + GE, + LT, + GT, + LE, + AL, + NV + } + + static public int cset(int opcode, int rm, COND cond, int rn, int rd) { + assert 0 <= rm && rm < 32; + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + // Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least significant bit inverted. + int actualCond = cond.ordinal() ^ 1; + return (opcode << 21) | (rm << 16) | (actualCond << 12) | (0b01 << 10) | (rn << 5) | rd; + } + + static public int cset(int opcode, COND cond, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + return (opcode << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; + } + + public static int imm_inst(int opcode, int imm12, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + assert opcode >=0 && imm12 >= 0; // Caller zeros high order bits + return (opcode << 22) | (imm12 << 10) | (rn << 5) | rd; + } + + public static int imm_shift(int opcode, int imm, int imms, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + return (opcode << 22) | (1 << 22) | (imm << 16) | (imms << 10) | (rn << 5) | rd; + } + + public static int imm_inst_n(int opcode, int imm13, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + assert 0 <= imm13 && imm13 <= 0x1FFF; + return (opcode << 23) | (imm13 << 10) | (rn << 5) | rd; + } + + public static int imm_inst_l(int opcode, int imm12, int self) { + int body = imm_inst(opcode, imm12&0xFFF, self, self); + return body; + } + + public static int r_reg(int opcode, int shift, int rm, int imm6, int rn, int rd) { + assert 0 <= rm && rm < 32; + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + return (opcode << 24) | (shift << 21) | (rm << 16) | (imm6 << 10) | (rn << 5) | rd; + } + + public static int shift_reg(int opcode, int rm, int op2, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rm && rm < 32; + assert 0 <= rd && rd < 32; + return (opcode << 21) | (rm << 16) | (op2 << 10) | (rn << 5) | rd; + } + + public static int madd(int opcode, int rm, int ra, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + assert 0 <= rm && rm < 32; + return (opcode << 21) | (rm << 16) | (ra << 10) | (rn << 5) | rd; + } + + public static int mov(int opcode, int shift, int imm16, int rd) { + assert 0 <= rd && rd < 32; + return (opcode << 23) | (shift << 21) | (imm16 << 5) | rd; + } + + public static int mov_reg(int opcode, int src, int rd) { + assert 0 <= rd && rd < 32; + return (opcode << 21) | (src << 16) | 0b11111 << 5 | rd; + } + + public static int ret(int opcode) { + return (opcode << 10) | (30 << 5); + } + + public static int f_scalar(int opcode, int ftype, int rm, int op, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + assert 0 <= rm && rm < 32; + return (opcode << 24) | (ftype << 22) | (1 << 21) | (rm << 16) | (op << 10) | (rn << 5) | rd; + } + + public static int f_mov_reg(int opcode, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + return (opcode << 24) | (0b01100000010000 << 10) | (rn << 5) | rd; + } + + public static int f_mov_general(int opcode, int ftype, int rmode, int opcode1, int rn, int rd) { + assert 0 <= rn && rn < 32; + assert 0 <= rd && rd < 32; + return (opcode << 24) |(ftype << 22) | (1 << 21) | (rmode << 19) | (opcode1 << 16) | (rn << 5) | rd; + } + + public static int load_pc(int opcode, int offset, int rt) { + assert -(1<<20) <= offset && offset < (1<<20); + assert (offset&3)==0; + offset = (offset>>2)&0x7FFFF; + return (opcode << 24) | (offset << 5) | rt; + } + + public static int adrp(int op, int imlo,int opcode, int imhi, int rd) { + assert 0 <= rd && rd < 32; + assert 0 <= imlo && imlo <= 0x3; // 2 bits + assert 0 <= imhi && imhi <= 0x7FFFF; // 19 bits + return (op << 31) | (imlo << 29) |(opcode << 24) | (imhi << 5) | rd; + } + + public static int indr_adr(int opcode, int off, STORE_LOAD_OPTION option, int s, int ptr, int rt) { + assert 0 <= ptr && ptr < 32; + assert 0 <= rt && rt < 32; + return (opcode << 21) | (off << 16) | (option.ordinal() << 13) | (s << 12) | (2 << 10) | (ptr << 5) | rt; + } + + public static int load_str_imm(int opcode, int imm12, int ptr, int rt, int size) { + assert 0 <= ptr && ptr < 32; + assert 0 <= rt && rt < 32; + + if(size == 8) imm12 = imm12 >> 3; + if(size == 4) imm12 = imm12 >> 2; + if(size == 2) imm12 = imm12 >> 1; + // size == 1 imm12 = imm12 + return (opcode << 22) | ((imm12) << 10) | (ptr << 5) | rt; + } + + public static int f_convert(int opcode_1, int opcode_2, int opcode_3, int opcode_4, int vd, int vm) { + return (opcode_1 << 28) | (opcode_2 << 24) | (opcode_3 << 20) | (opcode_4 << 16) | + (vd << 12) | (0x01100010 << 4) | vm; + } + + public static int float_cast(int opcode, int ftype, int rn, int rd) { + assert 0 <= rd && rd < 32; + assert 0 <= rn && rn < 32; + return (opcode << 24) | (ftype << 22) | (2176 << 10) | (rn << 5) | rd; + } + + public static int f_cmp(int opcode, int ftype, int rm, int rn) { + assert 0 <= rn && rn < 32; + assert 0 <= rm && rm < 32; + // Todo: |8 is not needed + return (opcode << 24) | (ftype << 21) | (rm << 16) | (8 << 10) | (rn << 5); + } + + public static COND make_condition(String bop) { return make_condition(bop,false); } + + public static COND make_condition(String bop, boolean fp) { + // One of {N,Z,C} and !V + // OR { !N, !Z, C, V } + return fp + ? switch (bop) { // FP uses unsigned encodings + case "==" -> COND.EQ; // Z + case "!=" -> COND.NE; // !Z + case "<" -> COND.MI; // N + case "<=" -> COND.LS; // Z || !C + case ">=" -> COND.PL; // !N + case ">" -> COND.HI; // !Z && C + default -> throw new UnsupportedOperationException(); + } + : switch (bop) { + case "==" -> COND.EQ; // Z + case "!=" -> COND.NE; // !Z + case "<" -> COND.LT; // N != V + case "<=" -> COND.LE; // Z || N != V + case ">=" -> COND.GE; // N == V + case ">" -> COND.GT; // !Z && N == V + default -> throw new UnsupportedOperationException(); + }; + } + + public static int b_cond(int opcode, int delta, COND cond) { + // 24-5 == 19bits offset range + assert -(1<<20) <= delta && delta < (1<<20); + assert (delta&3)==0; + delta>>=2; + delta &= (1L<<19)-1; // Zero extend + return (opcode << 24) | ((delta)<< 5) | cond.ordinal(); + } + + public static int cond_set(int opcode, int rm, COND cond, int rn, int rd) { + assert 0 <= rd && rd < 32; + assert 0 <= rn && rn < 32; + return (opcode << 21) | (rm << 16) | (cond.ordinal() << 12) | (rn << 5) | rd; + } + + public static int blr(int opcode, int rd) { + assert 0 <= rd && rd < 32; + return opcode << 10 | rd << 5; + } + + public static int b(int opcode, int delta) { + assert -(1<<27) <= delta && delta < (1<<27); + assert (delta&3)==0; + delta>>=2; + delta &= (1L<<26)-1; // Zero extend + return (opcode << 26) | delta; + } + + public static int b_calloc(int opcode, int delta) { + return b(opcode,delta); + } + + public static long decodeImm12(int imm12) { + int immr = (imm12 >> 6) & 0x3F; + int imms = imm12 & 0x3F; + int size; + if ((imm12 & 0x1000) != 0) { + size = 64; + } else { + size = 31-(imms >> 1); + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size++; + imms &= ~((32-size) << 1); + } + long val = (2L << imms)-1; + while (size < 64) { + val |= val << size; + size <<= 1; + } + val = (val >>> immr) | val << (64-immr); + return val; + } + + public static int logicalImmediate(long val) { + if (val == 0 || val == -1) return -1; // Special cases are not allowed + int immr = 0; + // Rotate until we have 0[...]1 + + // Rotate until: + // The number is negative (MSB is 1) + // Or the LSB is not 1 + while (val < 0 || (val & 1)==0) { + // circular rotation + val = (val >>> 63) | (val << 1); + immr++; + } + // Start by assuming that val might be made of two 32-bit chunks that repeat. + int size = 32; + long pattern = val; + // Is upper half of pattern the same as the lower? + while ((pattern & ((1L<<size)-1)) == (pattern >> size)) { + // Then only take one half + pattern >>= size; + size >>= 1; + } + size <<= 1; + int imms = Long.bitCount(pattern); + // Pattern should now be zeros followed by ones 0000011111 + if (pattern != (1L<<imms)-1) return -1; + imms--; + if (size == 64) return 0x1000 | immr << 6 | imms; + return (32-size)<<1 | immr << 6 | imms; + } + /** Materialize a 64-bit constant with MOVZ/MOVN and MOVK. */ + public static void constant(CodeSink out, int self, long x) { + int nb0 = 0; + int nb1 = 0; + // Count number of 0000 and FFFF blocks + for (int i=0; i<64; i+=16) { + int block = (int)(x >> i) & 0xFFFF; + if (block == 0) nb0++; + if (block == 0xFFFF) nb1++; + } + int pattern; + int op; + if(nb0 >= nb1) { + // More 0 blocks then F blocks, use movz + pattern = 0; + op = OP_MOVZ; + } else { + // More F blocks then 0 blocks, use movn + pattern = 0xFFFF; + op = OP_MOVN; + } + int invert = pattern; + for (int i=0; i<4; i++) { + int block = (int)x & 0xFFFF; + x >>= 16; + if (block != pattern) { + out.add4(mov(op, i, block ^ invert, self)); + op = OP_MOVK; + invert = 0; + } + } + if (op != OP_MOVK) { + // All blocks are the same, special case + out.add4(mov(op, 0, 0, self)); + } + } +} diff --git a/isa/src/main/java/com/seaofnodes/isa/CodeSink.java b/isa/src/main/java/com/seaofnodes/isa/CodeSink.java new file mode 100644 index 00000000..0c2d4936 --- /dev/null +++ b/isa/src/main/java/com/seaofnodes/isa/CodeSink.java @@ -0,0 +1,9 @@ +package com.seaofnodes.isa; + +/** Instruction bytes go straight into the chapter's code buffer. */ +public interface CodeSink { + CodeSink add1(int value); + default CodeSink add2(int value) { return add1(value).add1(value>>8); } + default CodeSink add4(int value) { return add2(value).add2(value>>16); } + default CodeSink add8(long value) { return add4((int)value).add4((int)(value>>32)); } +} diff --git a/isa/src/main/java/com/seaofnodes/isa/RiscV.java b/isa/src/main/java/com/seaofnodes/isa/RiscV.java new file mode 100644 index 00000000..cb446a6a --- /dev/null +++ b/isa/src/main/java/com/seaofnodes/isa/RiscV.java @@ -0,0 +1,117 @@ +package com.seaofnodes.isa; + +/** Instruction fields and concrete operand encodings; no compiler state. */ +public final class RiscV { + private RiscV() {} + + public static final int OP_LOAD = 0b00_000_11; + public static final int OP_LOADFP = 0b00_001_11; + public static final int OP_CUSTOM0 = 0b00_010_11; + public static final int OP_IMM = 0b00_100_11; + public static final int OP_AUIPC = 0b00_101_11; + public static final int OP_STORE = 0b01_000_11; + public static final int OP_STOREFP = 0b01_001_11; + public static final int OP_CUSTOM1 = 0b01_010_11; + public static final int OP = 0b01_100_11; + public static final int OP_LUI = 0b01_101_11; + public static final int OP_CUSTOM2 = 0b10_010_11; + public static final int OP_FP = 0b10_100_11; + public static final int OP_BRANCH = 0b11_000_11; + public static final int OP_JALR = 0b11_001_11; + public static final int OP_RESERVED= 0b11_010_11; + public static final int OP_JAL = 0b11_011_11; + + public enum RM { + RNE, // Round to Nearest, ties to Even + RTZ, // Round towards Zero + RDN, // Round Down + RUP, // Round Up + DIRECT, // Round to Nearest, ties to Max Magnitude + RESERVED1, // Reserved for futue use + RESERVED2, // Reserved for future use + DYN, // In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved + } + + public static int r_type(int opcode, int rd, int func3, int rs1, int rs2, int func7) { + assert 0 <= rs1 && rs1 < 32; + assert 0 <= rs2 && rs2 < 32; + assert 0 <= rd && rd < 32; + return (func7 << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; + } + + public static int u_type(int opcode, int rd, int imm20) { + assert 0 <= rd && rd < 32; + return (imm20 << 12) | (rd << 7) | opcode; + } + + public static int j_type(int opcode, int rd, int delta) { + assert -(1L<<20) <= delta && delta < (1L<<20); + assert 0 <= rd && rd < 32; + // Messy branch offset encoding + // 31 30-21 20 19-12 11-7 6-0 + // 20 10- 1 11 19-12 rpc JAL + assert (delta&1)==0; // Low bit is always zero, not encoded + int imm10_01 = (delta>> 1) & 0x3FF; + int imm11 = (delta>>11) & 1; + int imm12_19 = (delta>>12) & 0xFF; + int imm20 = (delta>>20) & 1; + int bits = imm20<<19 | imm10_01 << 9 | imm11 << 8 | imm12_19; + return bits << 12 | rd << 7 | opcode; + } + + public static int i_type(int opcode, int rd, int func3, int rs1, int imm12) { + assert 0 <= rd && rd < 32; + assert 0 <= rs1 && rs1 < 32; + assert opcode >= 0 && func3 >=0 && imm12 >= 0; // Zero-extend by caller + return (imm12 << 20) | (rs1 << 15) | (func3 << 12) | (rd << 7) | opcode; + } + + public static int s_type(int opcode, int func3, int rs1, int rs2, int imm12) { + assert 0 <= rs1 && rs1 < 32; + assert 0 <= rs2 && rs2 < 32; + assert 0 <= func3; + + assert imm12 >= 0; // Masked to high zero bits by caller + int imm_lo = imm12 & 0x1F; + int imm_hi = imm12 >> 5; + return (imm_hi << 25) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm_lo << 7) | opcode; + } + + public static int b_type(int opcode, int func3, short rs1, short rs2, int delta) { + assert 0 <= rs1 && rs1 < 32; + assert 0 <= rs2 && rs2 < 32; + assert -4*1024 <= delta && delta < 4*1024; + assert (delta&1)==0; // Low bit is always zero, not encoded + // Messy branch offset encoding + // 31 30 29 28 27 26 25 24-20 19-15 14-12 11 10 9 8 7 6-0 + // 12 10 9 8 7 6 5 SRC2 SRC1 FUNC3 4 3 2 1 11 OP + int imm4_1 = (delta>> 1) & 0xF; + int imm10_5= (delta>> 5) &0x3F; + int imm11 = (delta>>11) & 1; + int imm12 = (delta>>12) & 1; + int imm5 = imm4_1<<1 | imm11; + int imm7 = imm12<<6 | imm10_5; + return (imm7 << 25 ) | (rs2 << 20) | (rs1 << 15) | (func3 << 12) | (imm5 << 7) | opcode; + } + + static public int jumpop(String op) { + return switch(op) { + case "==" -> 0x0; + case "!=" -> 0x1; + case "<" -> 0x4; + case ">=" -> 0x5; + case "u<" -> 0x6; + case "u<=" -> 0x7; + default -> throw new UnsupportedOperationException(); + }; + } + + static public int fsetop(String op) { + return switch(op) { + case "<" -> 1; + case "<=" -> 0; + case "==" -> 2; + default -> throw new UnsupportedOperationException(); + }; + } +} diff --git a/isa/src/main/java/com/seaofnodes/isa/X86.java b/isa/src/main/java/com/seaofnodes/isa/X86.java new file mode 100644 index 00000000..99d61dff --- /dev/null +++ b/isa/src/main/java/com/seaofnodes/isa/X86.java @@ -0,0 +1,256 @@ +package com.seaofnodes.isa; + +/** x86-64 instruction bytes. Registers are hardware numbers 0..15, in the chosen bank. */ +public final class X86 { + private X86() {} + public enum MOD { INDIRECT, INDIRECT_disp8, INDIRECT_disp32, DIRECT } + + public static int modrm(MOD mod, int reg, int rm) { + if( reg==-1 ) reg=0; + assert 0<=reg && reg<16; + assert 0<=rm && rm<16; + return (mod.ordinal()<<6) | ((reg&7)<<3) | (rm&7); + } + public static int sib(int scale, int index, int base) { + assert 0<=scale && scale<=3; + assert 0<=index && index<16; + assert 0<=base && base<16; + return (scale<<6) | ((index&7)<<3) | (base&7); + } + public static int rex(int reg, int base, int index, boolean wide) { + assert -1<=reg && reg<16; + assert -1<=base && base<16; + assert -1<=index && index<16; + return (wide ? 0x48 : 0x40) | (reg>=8 ? 4 : 0) | + (index>=8 ? 2 : 0) | (base>=8 ? 1 : 0); + } + public static int rex(int reg, int base, int index) { return rex(reg,base,index,true); } + + /** Omit a redundant REX; byte-register instructions sometimes need it explicitly. */ + public static byte rexF(int reg, int base, int index, boolean wide, CodeSink out) { + int bits=rex(reg,base,index,wide); + if( bits==0x40 ) return 0; + out.add1(bits); + return 1; + } + + /** ModRM/SIB/displacement for [base + index*2^scale + offset]; -1 means no index. */ + public static void indirectAdr(int scale, int index, int base, int offset, int reg, CodeSink out) { + assert 0<=base && base<16; + assert -1<=index && index<16 && index!=4; + MOD mod=offset==0 ? MOD.INDIRECT : imm8(offset) ? MOD.INDIRECT_disp8 : MOD.INDIRECT_disp32; + // The no-displacement r/m=5 form is RIP-relative, even with REX.B. + if( mod==MOD.INDIRECT && (base==5 || base==13) ) mod=MOD.INDIRECT_disp8; + // r/m=4 always introduces SIB. Index=4 with no REX.X means no index. + if( index==-1 && (base==4 || base==12) ) index=4; + if( index==-1 ) out.add1(modrm(mod,reg,base)); + else out.add1(modrm(mod,reg,4)).add1(sib(scale,index,base)); + if( mod==MOD.INDIRECT_disp8 ) out.add1(offset); + if( mod==MOD.INDIRECT_disp32 ) out.add4(offset); + } + private static boolean imm8(int value) { return -128<=value && value<=127; } + public static void unary(CodeSink out, int op, int digit, int dst) { + out.add1(rex(0,dst,-1)).add1(op).add1(modrm(MOD.DIRECT,digit,dst)); + } + public static void shift(CodeSink out, int digit, int dst, int count) { + unary(out,0xC1,digit,dst); + out.add1(count); // A shift always takes imm8; the processor masks its count. + } + public static void divide(CodeSink out, int src) { + out.add1(0x48).add1(0x99); // CQO: sign-extend rax into rdx:rax. + unary(out,0xF7,7,src); + } + public static void sse(CodeSink out, int prefix, int op, boolean wide, int dst, int src) { + if( prefix!=0 ) out.add1(prefix); + rexF(dst,src,-1,wide,out); + opcode(out,op); + out.add1(modrm(MOD.DIRECT,dst,src)); + } + public static void memory(CodeSink out, int prefix, int op, boolean wide, + int reg, int base, int index, int offset, int scale) { + if( prefix!=0 ) out.add1(prefix); + rexF(reg,base,index,wide,out); + opcode(out,op); + indirectAdr(scale,index,base,offset,reg,out); + } + public static void cmpMem(CodeSink out, int logSize, int reg, int base, int index, + int offset, int scale, boolean swap) { + if( logSize==1 ) out.add1(0x66); + if( logSize==0 && reg>=4 ) out.add1(rex(reg,base,index,false)); + else rexF(reg,base,index,logSize==3,out); + out.add1((logSize==0 ? 0x38 : 0x39)+(swap ? 2 : 0)); + indirectAdr(scale,index,base,offset,reg,out); + } + public static void addMem(CodeSink out, int src, int value, int base, int index, int offset, int scale) { + memory(out,0,src==-1 ? (value==1 ? 0xFF : 0x81) : 0x01,true, + src==-1 ? 0 : src,base,index,offset,scale); + if( src==-1 && value!=1 ) out.add4(value); + } + public static void extend(CodeSink out, int bits, boolean signed, int dst, int src) { + out.add1(rex(dst,src,-1,signed || bits<32)); + opcode(out,bits==32 ? (signed ? 0x63 : 0x8B) : (signed ? 0x0FBE : 0x0FB6)+(bits==16 ? 1 : 0)); + out.add1(modrm(MOD.DIRECT,dst,src)); + } + /** SETcc dstb; MOVZX dst32,dstb. Condition is the low four bits of Jcc/SETcc. */ + public static void set(CodeSink out, int condition, int dst) { + if( dst>=4 ) out.add1(rex(0,dst,-1,false)); + out.add1(0x0F).add1(0x90|condition).add1(modrm(MOD.DIRECT,0,dst)); + if( dst>=4 ) out.add1(rex(dst,dst,-1,false)); + out.add1(0x0F).add1(0xB6).add1(modrm(MOD.DIRECT,dst,dst)); + } + public static void constant(CodeSink out, int dst, long value) { + if( value==0 ) { + if( dst>=8 ) out.add1(rex(dst,dst,-1)); + out.add1(0x33).add1(modrm(MOD.DIRECT,dst,dst)); + } else if( Integer.MIN_VALUE<=value && value<0 ) { + unary(out,0xC7,0,dst); + out.add4((int)value); + } else if( 0<=value && value<=0xFFFFFFFFL ) { + rexF(0,dst,-1,false,out); + out.add1(0xB8+(dst&7)).add4((int)value); + } else { + out.add1(rex(0,dst,-1)).add1(0xB8+(dst&7)).add8(value); + } + } + /** RIP-relative operand; returns length so the chapter can record its relocation. */ + public static byte rip(CodeSink out, int prefix, int op, boolean wide, int dst) { + int size=4+1+(op>255 ? 2 : 1); + if( prefix!=0 ) { out.add1(prefix); size++; } + size+=rexF(dst,-1,-1,wide,out); + opcode(out,op); + out.add1(modrm(MOD.INDIRECT,dst,5)).add4(0); + return (byte)size; + } + public static void call(CodeSink out) { out.add1(0xE8).add4(0); } + public static void callRegister(CodeSink out, int src) { + rexF(0,src,-1,false,out); + out.add1(0xFF).add1(modrm(MOD.DIRECT,2,src)); + } + public static void ret(CodeSink out) { out.add1(0xC3); } + public static void branch(CodeSink out, int condition) { + out.add1(condition<0 ? 0xEB : 0x70|condition).add1(0); + } + public static byte branchSize(int delta, boolean conditional) { + return (byte)(imm8(delta-2) ? 2 : conditional ? 6 : 5); + } + public static void patchBranch(byte[] bytes, int start, int size, int delta, int condition) { + delta-=size; + if( size==2 ) { + assert (byte)delta==delta; + bytes[start+1]=(byte)delta; + } else { + int pos=start; + if( condition<0 ) bytes[pos++]=(byte)0xE9; + else { bytes[pos++]=0x0F; bytes[pos++]=(byte)(0x80|condition); } + for( int i=0; i<4; i++ ) bytes[pos+i]=(byte)(delta>>(8*i)); + } + } + public static void flags(CodeSink out, int reg, boolean toFlags) { + if( !toFlags ) out.add1(0x9C); // PUSHF + rexF(0,reg,-1,false,out); + out.add1((toFlags ? 0x50 : 0x58)+(reg&7)); + if( toFlags ) out.add1(0x9D); // POPF + } + public static void stackCopy(CodeSink out, int srcOffset, int dstOffset) { + memory(out,0,0xFF,false,6,4,-1,srcOffset,0); // PUSH [rsp+srcOffset] + memory(out,0,0x8F,false,0,4,-1,dstOffset,0); // POP uses the restored rsp. + } + public static void move(CodeSink out, boolean dstXmm, boolean srcXmm, int dst, int src) { + if( dstXmm ^ srcXmm ) out.add1(0x66); + if( !dstXmm && srcXmm ) { int tmp=dst; dst=src; src=tmp; } + reg(out,!dstXmm && !srcXmm ? 0x8B : dstXmm && srcXmm ? 0x0F28 : dstXmm ? 0x0F6E : 0x0F7E,dst,src); + } + private static void opcode(CodeSink out, int op) { + if( op>255 ) out.add1(op>>8); + out.add1(op); + } + + /** REX.W + opcode + /r, with the destination in ModRM.reg. */ + public static void reg(CodeSink out, int op, int dst, int src) { + out.add1(rex(dst,src,-1)); + opcode(out,op); + out.add1(modrm(MOD.DIRECT,dst,src)); + } + /** Group-1 arithmetic: 81 /digit id or 83 /digit ib. */ + public static void imm(CodeSink out, int op, int digit, int dst, int value) { + out.add1(rex(0,dst,-1)).add1(op+(imm8(value) ? 2 : 0)); + out.add1(modrm(MOD.DIRECT,digit,dst)); + if( imm8(value) ) out.add1(value); else out.add4(value); + } + public static void imul(CodeSink out, int dst, int src, int value) { + out.add1(rex(dst,src,-1)).add1(imm8(value) ? 0x6B : 0x69); + out.add1(modrm(MOD.DIRECT,dst,src)); + if( imm8(value) ) out.add1(value); else out.add4(value); + } + public static void not(CodeSink out, int dst, int src) { + reg(out,0x85,src,src); // TEST src,src + set(out,4,dst); // SETZ; MOVZX + } + public static void lea(CodeSink out, int dst, int base, int index, int offset, int scale) { + out.add1(rex(dst,base,index)).add1(0x8D); + if( base==-1 ) { + assert 0<=index && index<16 && index!=4; + out.add1(modrm(MOD.INDIRECT,dst,4)).add1(sib(scale,index,5)).add4(offset); + } else indirectAdr(scale,index,base,offset,dst,out); + } + + /** Load into a GPR (extending to 64 bits) or an XMM register (scalar 32/64 bits). */ + public static void load(CodeSink out, int logSize, boolean signed, boolean xmm, + int dst, int base, int index, int offset, int scale) { + assert 0<=logSize && logSize<=3; + if( xmm ) { + assert logSize==2 || logSize==3; + out.add1(logSize==2 ? 0xF3 : 0xF2); + rexF(dst,base,index,false,out); + out.add1(0x0F).add1(0x10); + } else { + rexF(dst,base,index,logSize!=2 || signed,out); + int op=switch(logSize) { + case 0 -> signed ? 0x0FBE : 0x0FB6; + case 1 -> signed ? 0x0FBF : 0x0FB7; + case 2 -> signed ? 0x63 : 0x8B; + default -> 0x8B; + }; + opcode(out,op); + } + indirectAdr(scale,index,base,offset,dst,out); + } + public static void store(CodeSink out, int logSize, boolean xmm, + int src, int base, int index, int offset, int scale) { + assert 0<=logSize && logSize<=3; + if( xmm ) { + assert logSize==2 || logSize==3; + out.add1(logSize==2 ? 0xF3 : 0xF2); + rexF(src,base,index,false,out); + out.add1(0x0F).add1(0x11); + } else { + // Legacy prefixes precede REX, which must immediately precede the opcode. + if( logSize==1 ) out.add1(0x66); + if( logSize==0 && src>=4 ) out.add1(rex(src,base,index,false)); + else rexF(src,base,index,logSize==3,out); + out.add1(logSize==0 ? 0x88 : 0x89); + } + indirectAdr(scale,index,base,offset,src,out); + } + public static void storeImm(CodeSink out, int logSize, int value, + int base, int index, int offset, int scale) { + memImm(out,logSize,0xC6,0xC7,0,value,base,index,offset,scale); + } + public static void cmpImm(CodeSink out, int logSize, int value, + int base, int index, int offset, int scale) { + memImm(out,logSize,0x80,0x81,7,value,base,index,offset,scale); + } + private static void memImm(CodeSink out, int logSize, int op8, int op, int digit, int value, + int base, int index, int offset, int scale) { + assert 0<=logSize && logSize<=3; + if( logSize==1 ) out.add1(0x66); + rexF(-1,base,index,logSize==3,out); + out.add1(logSize==0 ? op8 : op); + indirectAdr(scale,index,base,offset,digit,out); + switch(logSize) { + case 0 -> out.add1(value); + case 1 -> out.add2(value); + default -> out.add4(value); // Even a 64-bit operand takes only imm32. + } + } +} diff --git a/isa/src/test-support/isa-eval.iml b/isa/src/test-support/isa-eval.iml new file mode 100644 index 00000000..733c5919 --- /dev/null +++ b/isa/src/test-support/isa-eval.iml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <output url="file://$MODULE_DIR$/../../../build/idea/production/isa-eval" /> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module" module-name="isa" /> + </component> +</module> diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java b/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalArm64.java index 1503adb5..2a4a2708 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ b/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalArm64.java @@ -1,8 +1,6 @@ -package com.seaofnodes.simple; +package com.seaofnodes.isa.eval; -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.arm.arm; -import com.seaofnodes.simple.util.Utils; +import com.seaofnodes.isa.Arm64; import java.io.ByteArrayOutputStream; public class EvalArm64 { @@ -10,33 +8,38 @@ public class EvalArm64 { public final byte[] _buf; // GPRs - final long[] regs; + public final long[] regs; // FRs - final double[] fregs; + public final double[] fregs; - int _pc; + public int _pc; // Start of free memory for allocation - int _heap; + public int _heap; // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; + public ByteArrayOutputStream _stdout, _stderr; // Cycle counters - int _cycle; + public int _cycle; // flags - boolean N = false; - boolean Z = false; - boolean C = false; - boolean V = false; - - EvalArm64(byte[] buf, int stackSize) { + public boolean N = false; + public boolean Z = false; + public boolean C = false; + public boolean V = false; + + // Default test-runtime entry points; callers can supply another link convention. + private final int _calloc, _write; + public EvalArm64(byte[] buf, int stackSize) { this(buf,stackSize,-4,-8); } + public EvalArm64(byte[] buf, int stackSize, int calloc, int write) { + _calloc = calloc; + _write = write; _buf = buf; regs = new long[32]; fregs = new double[32]; // Stack grows down, heap grows up - regs[arm.RSP] = _heap = stackSize; + regs[31] = _heap = stackSize; _pc = 0; } @@ -132,12 +135,12 @@ public class EvalArm64 { opcode1 = (ir >> 21) & 0x7FF; switch( ir >> 21 & 0x7 ) { case 0x1 -> { // store - if( opcode1 == arm.OP_STORE_R_8 ) st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); + if( opcode1 == Arm64.OP_STORE_R_8 ) st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); else trap = (2+1); rdid = -1; } case 0x3 -> { // load - if( opcode1 == arm.OP_LOAD_R_8 ) rval = ld1s((int)regs[rn] + (int)regs[rm]); + if( opcode1 == Arm64.OP_LOAD_R_8 ) rval = ld1s((int)regs[rn] + (int)regs[rm]); else trap = (2+1); } default -> trap = (2+1); @@ -158,7 +161,7 @@ public class EvalArm64 { switch(opc) { case 0x0: { // store - if(opcode1 == arm.OP_STORE_IMM_8) { + if(opcode1 == Arm64.OP_STORE_IMM_8) { st1((int)rval, (int)regs[rdid]); } else trap = (2+1); rdid = -1; @@ -167,7 +170,7 @@ public class EvalArm64 { } case 0x1: { // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_8) { + if(opcode1 == Arm64.OP_LOAD_IMM_8) { rval = ld1s((int)rval); } else trap = (2+1); rdid = -1; @@ -225,7 +228,7 @@ public class EvalArm64 { switch(opc) { case 0x1: { // store - if(opcode1 == arm.OP_STORE_R_16) { + if(opcode1 == Arm64.OP_STORE_R_16) { st1((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); }else { trap = (2+1); @@ -235,7 +238,7 @@ public class EvalArm64 { } case 0x3: { // load - if(opcode1 == arm.OP_LOAD_R_16) { + if(opcode1 == Arm64.OP_LOAD_R_16) { rval = ld1s((int)regs[rn] + (int)regs[rm]); } else { trap = (2+1); @@ -260,7 +263,7 @@ public class EvalArm64 { switch(opc) { case 0x0: { // store - if(opcode1 == arm.OP_STORE_IMM_16) { + if(opcode1 == Arm64.OP_STORE_IMM_16) { st2((int)rval, (int)regs[rdid]); } else trap = (2+1); rdid = -1; @@ -269,7 +272,7 @@ public class EvalArm64 { } case 0x1: { // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_16) { + if(opcode1 == Arm64.OP_LOAD_IMM_16) { rval = ld2s((int)rval); } else trap = (2+1); rdid = -1; @@ -314,9 +317,14 @@ public class EvalArm64 { rval = opcode1==0x91 ? regs[rn] + immediate : regs[rn] - immediate; break; } - case 0x92: { // and(immediate) + case 0x92: { // MOVN or AND (immediate) + if( (ir & 0x00800000)!=0 ) { + int shift = ((ir >> 21) & 3)*16; + rval = ~(((ir >> 5) & 0xFFFFL) << shift); + break; + } int imm12 = (ir >> 10) & 0x1FFF; - long immediate = arm.decodeImm12(imm12); + long immediate = Arm64.decodeImm12(imm12); int rn = (ir >> 5) & 0x1F; rval = regs[rn] & immediate; break; @@ -336,19 +344,19 @@ public class EvalArm64 { case 0x94, 0x95, 0x96, 0x97: { // bl rdid = -1; // BL writes only X30, not a displacement-selected register. rval = pc + 4; - regs[arm.X30] = rval; + regs[30] = rval; int imm26 = (ir & 0x03FFFFFF); int imm = (imm26 << 6) >> 6; pc = pc + (imm << 2) ; - if( pc == Encoding.SENTINEL_CALLOC ) { + if( pc == _calloc ) { assert (_heap&7) == 0; // 8-byte aligned - long size = regs[arm.X0]*regs[arm.X1]; + long size = regs[0]*regs[1]; size = (size+7) & -8; // 8-byte aligned - regs[arm.X0] = _heap; + regs[0] = _heap; _heap += (int)size; pc = (int)rval; } - if( pc == Encoding.SENTINEL_WRITE ) { + if( pc == _write ) { ByteArrayOutputStream baos = switch((int)regs[0]) { case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; @@ -384,7 +392,7 @@ public class EvalArm64 { case 0xD -> ( Z || N != V ); // le case 0xE -> true ; // always case 0xF -> false ; // never - default -> throw Utils.TODO(); + default -> throw new UnsupportedOperationException(); }; if( cond ) rval = 1; break; @@ -419,7 +427,7 @@ public class EvalArm64 { opcode1 = (ir >> 21) & 0x7FF; switch(opc) { case 0x1: { - if(opcode1 == arm.OP_STORE_R_32) { + if(opcode1 == Arm64.OP_STORE_R_32) { st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); }else { trap = (2+1); @@ -431,7 +439,7 @@ public class EvalArm64 { } case 0x3: { // load - if( opcode1 == arm.OP_LOAD_R_32) { + if( opcode1 == Arm64.OP_LOAD_R_32) { rval = ld4s((int) (regs[rn] + regs[rm])); } else { trap = (2+1); @@ -457,7 +465,7 @@ public class EvalArm64 { switch(opc) { case 0x0: { // store - if(opcode1 == arm.OP_STORE_IMM_32) { + if(opcode1 == Arm64.OP_STORE_IMM_32) { st4((int)rval, (int)regs[rdid]); } else trap = (2+1); @@ -466,7 +474,7 @@ public class EvalArm64 { } case 0x1: { // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_32) { + if(opcode1 == Arm64.OP_LOAD_IMM_32) { rval = ld4s((int) rval); } else trap = (2+1); break; @@ -486,7 +494,7 @@ public class EvalArm64 { opcode1 = (ir >> 21) & 0x7FF; switch(opc) { case 0x1: { - if(opcode1 == arm.OPF_STORE_R_32) { + if(opcode1 == Arm64.OPF_STORE_R_32) { st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); }else { trap = (2+1); @@ -498,7 +506,7 @@ public class EvalArm64 { } case 0x3: { // load - if(opcode1 == arm.OPF_LOAD_R_32) { + if(opcode1 == Arm64.OPF_LOAD_R_32) { frval = ld4f((int) (regs[rn] + regs[rm])); } else { trap = (2+1); @@ -525,7 +533,7 @@ public class EvalArm64 { switch(opc) { case 0x0: { // store - if(opcode1 == arm.OPF_STORE_IMM_32) { + if(opcode1 == Arm64.OPF_STORE_IMM_32) { st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); } else trap = (2+1); @@ -534,7 +542,7 @@ public class EvalArm64 { } case 0x1: { // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_32) { + if(opcode1 == Arm64.OPF_LOAD_IMM_32) { frval = ld4f((int)rval); } else trap = (2+1); break; @@ -580,7 +588,7 @@ public class EvalArm64 { int rn = (ir >>> 5) & 31; int target = (int)regs[rn]; // Read before BLR overwrites X30. rdid = -1; - if( op==0xD63F0000 ) regs[arm.X30] = pc+4; // BLR + if( op==0xD63F0000 ) regs[30] = pc+4; // BLR else if( op!=0xD65F0000 ) { trap = 3; break; } // RET pc = target; if( op==0xD65F0000 && pc==0 ) break outer; @@ -617,7 +625,7 @@ public class EvalArm64 { opcode1 = (ir >> 21) & 0x7FF; switch(opc) { case 0x1: { - if(opcode1 == arm.OP_STORE_R_64) { + if(opcode1 == Arm64.OP_STORE_R_64) { st8((int)regs[rn] + (int)regs[rm], regs[rdid]); }else { trap = (2+1); @@ -629,7 +637,7 @@ public class EvalArm64 { } case 0x3: { // load - if(opcode1 == arm.OP_LOAD_R_64) { + if(opcode1 == Arm64.OP_LOAD_R_64) { rval = ld8((int) (regs[rn] + regs[rm])); } else { trap = (2+1); @@ -655,7 +663,7 @@ public class EvalArm64 { switch(opc) { case 0x0: { // store - if(opcode1 == arm.OP_STORE_IMM_64) { + if(opcode1 == Arm64.OP_STORE_IMM_64) { st8((int)rval, regs[rdid]); } else trap = (2+1); @@ -664,7 +672,7 @@ public class EvalArm64 { } case 0x1: { // LDR (immediate) - if(opcode1 == arm.OP_LOAD_IMM_64) { + if(opcode1 == Arm64.OP_LOAD_IMM_64) { rval = ld8((int)rval); } else trap = (2+1); break; @@ -684,7 +692,7 @@ public class EvalArm64 { opcode1 = (ir >> 21) & 0x7FF; switch(opc) { case 0x1: { - if(opcode1 == arm.OPF_STORE_R_64) { + if(opcode1 == Arm64.OPF_STORE_R_64) { st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); }else { trap = (2+1); @@ -696,7 +704,7 @@ public class EvalArm64 { } case 0x3: { // load - if(opcode1 == arm.OPF_LOAD_R_64) { + if(opcode1 == Arm64.OPF_LOAD_R_64) { frval = ld8f((int) (regs[rn] + regs[rm])); } else { trap = (2+1); @@ -722,7 +730,7 @@ public class EvalArm64 { switch(opc) { case 0x0: { // store - if(opcode1 == arm.OPF_STORE_IMM_64) { + if(opcode1 == Arm64.OPF_STORE_IMM_64) { st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); } else trap = (2+1); @@ -731,7 +739,7 @@ public class EvalArm64 { } case 0x1: { // LDR (immediate) - if(opcode1 == arm.OPF_LOAD_IMM_64) { + if(opcode1 == Arm64.OPF_LOAD_IMM_64) { frval = ld8f((int)rval); } else trap = (2+1); break; diff --git a/chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalRisc5.java index 633e931e..f618075d 100644 --- a/chapter23/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ b/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalRisc5.java @@ -1,4 +1,4 @@ - package com.seaofnodes.simple; + package com.seaofnodes.isa.eval; /** Simple RISC5 CPU Emulator * @@ -8,9 +8,6 @@ * Load code into memory and go! */ -import com.seaofnodes.simple.codegen.Encoding; -import com.seaofnodes.simple.node.cpus.riscv.riscv; -import com.seaofnodes.simple.util.Utils; import java.io.ByteArrayOutputStream; import java.util.Arrays; @@ -20,27 +17,32 @@ public class EvalRisc5 { public final byte[] _buf; // GPRs - final long[] regs; + public final long[] regs; // FRs - final double[] fregs; + public final double[] fregs; // PC - int _pc; + public int _pc; // Start of free memory for allocation - int _heap; + public int _heap; // Standard out and err streams - ByteArrayOutputStream _stdout, _stderr; + public ByteArrayOutputStream _stdout, _stderr; // Cycle counters - int _cycle; - - EvalRisc5( byte[] buf, int stackSize ) { + public int _cycle; + + // Default test-runtime entry points; callers can supply another link convention. + private final int _calloc, _write; + public EvalRisc5(byte[] buf, int stackSize) { this(buf,stackSize,-4,-8); } + public EvalRisc5(byte[] buf, int stackSize, int calloc, int write) { + _calloc = calloc; + _write = write; _buf = buf; regs = new long[32]; fregs = new double[32]; // Stack grows down, heap grows up - regs[riscv.RSP] = _heap = stackSize; + regs[2] = _heap = stackSize; _pc = 0; } @@ -65,7 +67,7 @@ public class EvalRisc5 { // Bits 0..1 = privilege. // Bit 2 = WFI (Wait for interrupt) // Bit 3+ = Load/Store reservation LSBs. - int _extraflags; + public int _extraflags; public int step( int maxops ) { int trap = 0; @@ -104,7 +106,7 @@ public class EvalRisc5 { if( (reladdy & 0x00100000)!=0 ) reladdy |= 0xffe00000; // Sign extension. rval = pc + 4; pc = pc + reladdy - 4; - if( pc+4 == Encoding.SENTINEL_WRITE ) { + if( pc+4 == _write ) { ByteArrayOutputStream baos = switch((int)regs[10]) { case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; @@ -127,7 +129,7 @@ public class EvalRisc5 { break outer; } // Inline CALLOC effect - if( pc == Encoding.SENTINEL_CALLOC ) { + if( pc == _calloc ) { assert (_heap&7) == 0; // 8-byte aligned int size = (int)(regs[10]*regs[11]); size = (size+7) & -8; // 8-byte aligned @@ -316,7 +318,7 @@ public class EvalRisc5 { double rhs = fregs[rs2]; int func5 = (ir >> 27) & 0x1F; int func2 = (ir >> 25) & 0x3; - if( func2 != 1 ) throw Utils.TODO(); // 1==double + if( func2 != 1 ) throw new UnsupportedOperationException(); // 1==double switch( func5 ) { case 0: frval = lhs + rhs; break; // fadd.d case 1: frval = lhs - rhs; break; // fsub.d @@ -329,13 +331,13 @@ public class EvalRisc5 { case 0 -> lhs <= rhs ? 1 : 0; case 1 -> lhs == rhs ? 1 : 0; case 2 -> lhs < rhs ? 1 : 0; - default -> throw Utils.TODO(); + default -> throw new UnsupportedOperationException(); }; break; case 26: frval = (double)regs[rs1]; break; // fcvt.w.d default: trap = (2+1); // Fault: Invalid opcode. - throw Utils.TODO(); + throw new UnsupportedOperationException(); } break; } diff --git a/isa/src/test/java/com/seaofnodes/isa/RiscTest.java b/isa/src/test/java/com/seaofnodes/isa/RiscTest.java new file mode 100644 index 00000000..e26eb20b --- /dev/null +++ b/isa/src/test/java/com/seaofnodes/isa/RiscTest.java @@ -0,0 +1,59 @@ +package com.seaofnodes.isa; + +import com.seaofnodes.isa.eval.EvalArm64; +import com.seaofnodes.isa.eval.EvalRisc5; + +/** Fixed instruction words plus execution checks of the shared test emulators. */ +public class RiscTest { + static void word(int expected, int actual) { + assert expected==actual : String.format("Expected %08x, got %08x",expected,actual); + } + public static void main(String[] args) { + word(0x8B020020,Arm64.r_reg(Arm64.OP_ADD,0,2,0,1,0)); // add x0,x1,x2 + word(0x9100A420,Arm64.imm_inst(Arm64.OPI_ADD,41,1,0)); + word(0xD2800540,Arm64.mov(Arm64.OP_MOVZ,0,42,0)); + word(0xF9400BE0,Arm64.load_str_imm(Arm64.OP_LOAD_IMM_64,16,31,0,8)); + word(0xF9000BE0,Arm64.load_str_imm(Arm64.OP_STORE_IMM_64,16,31,0,8)); + word(0xD65F03C0,Arm64.ret(Arm64.OP_RET)); + word(0x17FFFFFF,Arm64.b(Arm64.OP_UJMP,-4)); + word(0x16000000,Arm64.b(Arm64.OP_UJMP,-(1<<27))); + word(0x54000040,Arm64.b_cond(Arm64.OP_BRANCH,8,Arm64.COND.EQ)); + word(0x54800001,Arm64.b_cond(Arm64.OP_BRANCH,-(1<<20),Arm64.COND.NE)); + word(0x5CFFFFE0,Arm64.load_pc(Arm64.OPF_ARM,-4,0)); + + word(0x002081B3,RiscV.r_type(RiscV.OP,3,0,1,2,0)); // add x3,x1,x2 + word(0x02A00513,RiscV.i_type(RiscV.OP_IMM,10,0,0,42)); + word(0x123451B7,RiscV.u_type(RiscV.OP_LUI,3,0x12345)); + word(0x00B13823,RiscV.s_type(RiscV.OP_STORE,3,2,11,16)); + word(0x00208463,RiscV.b_type(RiscV.OP_BRANCH,0,(short)1,(short)2,8)); + word(0xFE208EE3,RiscV.b_type(RiscV.OP_BRANCH,0,(short)1,(short)2,-4)); + word(0x008000EF,RiscV.j_type(RiscV.OP_JAL,1,8)); + word(0xFFDFF0EF,RiscV.j_type(RiscV.OP_JAL,1,-4)); + word(0x000800EF,RiscV.j_type(RiscV.OP_JAL,1,1<<19)); + word(0x800000EF,RiscV.j_type(RiscV.OP_JAL,1,-(1<<20))); + + // Constants exercise MOVN, MOVZ and multiple MOVK lanes, including all 0/1. + for( long x : new long[]{0,-1,42,0xFFFF0000FFFFL,0x1122334455667788L,Long.MIN_VALUE} ) { + var bytes=new X86Test.Bytes(); + Arm64.constant(bytes,0,x); + byte[] image=new byte[1024]; + System.arraycopy(bytes.toByteArray(),0,image,4,bytes.size()); + var arm=new EvalArm64(image,512); + arm._pc=4; + arm.step(bytes.size()/4); + assert arm.regs[0]==x : String.format("Constant %016x became %016x",x,arm.regs[0]); + } + // Raw instructions make these emulator checks independent of the encoder. + var arm=new EvalArm64(new byte[1024],512); + arm.st4(4,0xD2800540); // mov x0,#42 + arm._pc=4; + arm.step(1); + assert arm.regs[0]==42; + var risc=new EvalRisc5(new byte[1024],512); + risc.st4(4,0x02A00513); // addi a0,zero,42 + risc._pc=4; + risc.step(1); + assert risc.regs[10]==42; + System.out.println("Shared ARM/RISC-V encoding and evaluator tests passed"); + } +} diff --git a/isa/src/test/java/com/seaofnodes/isa/X86Test.java b/isa/src/test/java/com/seaofnodes/isa/X86Test.java new file mode 100644 index 00000000..e3aa2699 --- /dev/null +++ b/isa/src/test/java/com/seaofnodes/isa/X86Test.java @@ -0,0 +1,124 @@ +package com.seaofnodes.isa; + +import java.io.ByteArrayOutputStream; +import java.util.HexFormat; +import java.util.function.Consumer; + +/** Fixed instruction bytes, independent of the compiler and register allocator. */ +public class X86Test { + static class Bytes extends ByteArrayOutputStream implements CodeSink { + @Override public Bytes add1(int value) { write(value); return this; } + } + static void check(String expected, Consumer<CodeSink> emit) { + var bytes=new Bytes(); + emit.accept(bytes); + String actual=HexFormat.of().formatHex(bytes.toByteArray()); + assert expected.equals(actual) : "Expected "+expected+", got "+actual; + } + public static void main(String[] args) { + check("4d03ca", b -> X86.reg(b,0x03,9,10)); + check("4d0fafca", b -> X86.reg(b,0x0FAF,9,10)); + check("4981c17fffffff", b -> X86.imm(b,0x81,0,9,-129)); + check("4983c180", b -> X86.imm(b,0x81,0,9,-128)); + check("4983c17f", b -> X86.imm(b,0x81,0,9,127)); + check("4981c180000000", b -> X86.imm(b,0x81,0,9,128)); + check("4d6bca80", b -> X86.imul(b,9,10,-128)); + check("4d69ca80000000", b -> X86.imul(b,9,10,128)); + + // TEST; SETZ; MOVZX. Both overlapping and distinct input/output registers. + int[][] regs={{0,0},{1,1},{7,7},{9,9},{1,9},{9,1},{6,0},{15,8}}; + String[] not={"4885c00f94c00fb6c0","4885c90f94c10fb6c9", + "4885ff400f94c7400fb6ff","4d85c9410f94c1450fb6c9", + "4d85c90f94c10fb6c9","4885c9410f94c1450fb6c9", + "4885c0400f94c6400fb6f6","4d85c0410f94c7450fb6ff"}; + for( int i=0; i<regs.length; i++ ) { + int dst=regs[i][0], src=regs[i][1]; + check(not[i],b -> X86.not(b,dst,src)); + } + + // SIB, rbp/r13 zero displacement, displacement boundaries, and an extended index. + check("488b0424", b -> X86.load(b,3,false,false,0,4,-1,0,0)); + check("498b0424", b -> X86.load(b,3,false,false,0,12,-1,0,0)); + check("488b4500", b -> X86.load(b,3,false,false,0,5,-1,0,0)); + check("498b4500", b -> X86.load(b,3,false,false,0,13,-1,0,0)); + check("488b437f", b -> X86.load(b,3,false,false,0,3,-1,127,0)); + check("488b8380000000", b -> X86.load(b,3,false,false,0,3,-1,128,0)); + check("488b4380", b -> X86.load(b,3,false,false,0,3,-1,-128,0)); + check("488b837fffffff", b -> X86.load(b,3,false,false,0,3,-1,-129,0)); + check("4b8b44e508", b -> X86.load(b,3,false,false,0,13,12,8,3)); + check("4f8d4ca508", b -> X86.lea(b,9,13,12,8,2)); + check("4e8d0ce520000000", b -> X86.lea(b,9,-1,12,32,3)); + + check("480fbe03", b -> X86.load(b,0,true,false,0,3,-1,0,0)); + check("480fb603", b -> X86.load(b,0,false,false,0,3,-1,0,0)); + check("480fbf03", b -> X86.load(b,1,true,false,0,3,-1,0,0)); + check("480fb703", b -> X86.load(b,1,false,false,0,3,-1,0,0)); + check("486303", b -> X86.load(b,2,true,false,0,3,-1,0,0)); + check("8b03", b -> X86.load(b,2,false,false,0,3,-1,0,0)); + check("f3470f104ca508", b -> X86.load(b,2,false,true,9,13,12,8,2)); + check("f2470f104ca508", b -> X86.load(b,3,false,true,9,13,12,8,2)); + + check("408823", b -> X86.store(b,0,false,4,3,-1,0,0)); // spl, not ah + check("408833", b -> X86.store(b,0,false,6,3,-1,0,0)); // sil, not dh + check("44883b", b -> X86.store(b,0,false,15,3,-1,0,0)); + check("6647894ca508", b -> X86.store(b,1,false,9,13,12,8,2)); + check("47894ca508", b -> X86.store(b,2,false,9,13,12,8,2)); + check("4f894ca508", b -> X86.store(b,3,false,9,13,12,8,2)); + check("f3470f114ca508", b -> X86.store(b,2,true,9,13,12,8,2)); + check("f2470f114ca508", b -> X86.store(b,3,true,9,13,12,8,2)); + check("c603ff", b -> X86.storeImm(b,0,-1,3,-1,0,0)); + check("6643c744a5083412", b -> X86.storeImm(b,1,0x1234,13,12,8,2)); + check("c70378563412", b -> X86.storeImm(b,2,0x12345678,3,-1,0,0)); + check("48c703ffffffff", b -> X86.storeImm(b,3,-1,3,-1,0,0)); + check("803bff", b -> X86.cmpImm(b,0,-1,3,-1,0,0)); + check("6643817ca5083412", b -> X86.cmpImm(b,1,0x1234,13,12,8,2)); + check("813b78563412", b -> X86.cmpImm(b,2,0x12345678,3,-1,0,0)); + check("48813b15cd5b07", b -> X86.cmpImm(b,3,123456789,3,-1,0,0)); + check("49f7da", b -> X86.unary(b,0xF7,3,10)); + check("49c1e1ff", b -> X86.shift(b,4,9,255)); + check("489949f7fa", b -> X86.divide(b,10)); + check("f2450f58ca", b -> X86.sse(b,0xF2,0x0F58,false,9,10)); + check("f24d0f2aca", b -> X86.sse(b,0xF2,0x0F2A,true,9,10)); + check("66450f2eca", b -> X86.sse(b,0x66,0x0F2E,false,9,10)); + check("4d0fbeca", b -> X86.extend(b,8,true,9,10)); + check("4c0fb6ce", b -> X86.extend(b,8,false,9,6)); + check("6647394ca508", b -> X86.cmpMem(b,1,9,13,12,8,2,false)); + check("66473b4ca508", b -> X86.cmpMem(b,1,9,13,12,8,2,true)); + check("403833", b -> X86.cmpMem(b,0,6,3,-1,0,0,false)); + check("400f95c6400fb6f6", b -> X86.set(b,5,6)); + check("410f95c1450fb6c9", b -> X86.set(b,5,9)); + check("4d33c9", b -> X86.constant(b,9,0)); + check("49c7c1ffffffff", b -> X86.constant(b,9,-1)); + check("41b9ffffffff", b -> X86.constant(b,9,0xFFFFFFFFL)); + check("49b98877665544332211", b -> X86.constant(b,9,0x1122334455667788L)); + check("4c8d0d00000000", b -> { assert X86.rip(b,0,0x8D,true,9)==7; }); + check("f2440f100d00000000", b -> { assert X86.rip(b,0xF2,0x0F10,false,9)==9; }); + check("e800000000c3", b -> { X86.call(b); X86.ret(b); }); + check("ffd0", b -> X86.callRegister(b,0)); + check("41ffd2", b -> X86.callRegister(b,10)); + check("41519d", b -> X86.flags(b,9,true)); + check("9c4159", b -> X86.flags(b,9,false)); + check("ff7424088f442410", b -> X86.stackCopy(b,8,16)); + check("4d8bca", b -> X86.move(b,false,false,9,10)); + check("4d0f28ca", b -> X86.move(b,true,true,9,10)); + check("664d0f6eca", b -> X86.move(b,true,false,9,10)); + check("664d0f7ed1", b -> X86.move(b,false,true,9,10)); + branch("eb7f",129,-1); + branch("eb80",-126,-1); + branch("e97d000000",130,-1); + branch("e97cffffff",-127,-1); + branch("757f",129,5); + branch("0f857c000000",130,5); + branch("0f857bffffff",-127,5); + System.out.println("Shared x86 encoding tests passed"); + } + static void branch(String expected, int delta, int condition) { + int size=X86.branchSize(delta,condition>=0); + byte[] bytes=new byte[size]; + var shortForm=new Bytes(); + X86.branch(shortForm,condition); + System.arraycopy(shortForm.toByteArray(),0,bytes,0,2); + X86.patchBranch(bytes,0,size,delta,condition); + assert expected.equals(HexFormat.of().formatHex(bytes)); + } +} diff --git a/skills/chapter25-codex-notes.md b/skills/chapter25-codex-notes.md index c93266ab..208494e7 100644 --- a/skills/chapter25-codex-notes.md +++ b/skills/chapter25-codex-notes.md @@ -42,6 +42,15 @@ For shared viewer work, read [the graph viewer notes](graph-viewer-codex-notes.m ## Tutorial backports +- Shared ISA encoding lives in `isa/` for Chapters 21-25: x86 bytes behind + `CodeSink`, ARM/RISC-V word packing, and test-only evaluators. Chapter code still + owns machine nodes, register masks, operand/type interpretation, layouts and + relocations. Fix shared forms once there; keep their byte tests independent + of compiler IR and retain chapter execution tests. See `isa/README.md` for + the exact boundary. Only 21-25 add ISA main/test sources to their builds; + the linearized Maven build adds them at 21. Make's release jars still bundle + tests and their evaluators; Maven treats the evaluators as test sources. + - Chapter 10 is split into `chapter10a` (one bulk memory chain) and `chapter10b` (lazy graph partitioning). Both are standalone snapshots. Cliff reviewed and committed the forward port through Chapter 21. Chapters 22-24 now carry lazy |
