summaryrefslogtreecommitdiff
path: root/chapter22/src/test/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-17 15:15:00 -0700
committerCliff Click <cliffc@acm.org>2026-09-17 15:15:00 -0700
commit5eb00d3306e6e8738b8033c5ba8401770f9d7ffd (patch)
treef59554f4d82ea7960b0c4d49ad73591efb96a454 /chapter22/src/test/java/com/seaofnodes
parent8331098d1904538a3a97d22e4d847cf2cc94e57d (diff)
downloadSimple-5eb00d3306e6e8738b8033c5ba8401770f9d7ffd.tar.gz
Simple-5eb00d3306e6e8738b8033c5ba8401770f9d7ffd.zip
Backport x86 Not encoding
Diffstat (limited to 'chapter22/src/test/java/com/seaofnodes')
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/codegen/X86EncodingTest.java44
1 files changed, 44 insertions, 0 deletions
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/codegen/X86EncodingTest.java b/chapter22/src/test/java/com/seaofnodes/simple/codegen/X86EncodingTest.java
index 389f0363..0914d916 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/codegen/X86EncodingTest.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/codegen/X86EncodingTest.java
@@ -2,6 +2,7 @@ package com.seaofnodes.simple.codegen;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.cpus.x86_64_v2.CmpMemX86;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.NotX86;
import com.seaofnodes.simple.node.cpus.x86_64_v2.MulIX86;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -9,6 +10,49 @@ import static org.junit.Assert.*;
public class X86EncodingTest {
@Test
+ public void testLogicalNotRegisters() {
+ CodeGen code = new CodeGen("return !arg;")
+ .driver(CodeGen.Phase.Select, "x86_64_v2", "SystemV");
+ var not = code._stop.walk(n -> n instanceof NotX86 ? (NotX86)n : null);
+ assertNotNull("Must exercise logical not", not);
+ int[][] registers = {{0,0}, {1,1}, {7,7}, {9,9}, {1,9}, {9,1}, {6,0}, {15,8}};
+ // TEST src,src; SETZ dstb; MOVZX dst32,dstb. Include overlapping
+ // registers, low-byte registers requiring REX, and extended registers.
+ String[] expected = {
+ "4885c00f94c00fb6c0", "4885c90f94c10fb6c9",
+ "4885ff400f94c7400fb6ff", "4d85c9410f94c1450fb6c9",
+ "4d85c90f94c10fb6c9", "4885c9410f94c1450fb6c9",
+ "4885c0400f94c6400fb6f6", "4d85c0410f94c7450fb6ff"
+ };
+ for (int i = 0; i < registers.length; i++) {
+ int dst = registers[i][0], src = registers[i][1];
+ var enc = new FixedRegisterEncoding(code, not, dst, not.in(1), src);
+ not.encoding(enc);
+ assertArrayEquals("Logical not dst=" + dst + ", src=" + src,
+ java.util.HexFormat.of().parseHex(expected[i]), enc._bits.toByteArray());
+ }
+ }
+
+ @Test
+ public void testLogicalNotExecution() throws java.io.IOException {
+ var dir = java.nio.file.Path.of("build/objs");
+ java.nio.file.Files.createDirectories(dir);
+ java.nio.file.Files.writeString(dir.resolve("x86LogicalNot.smp"),
+ "val logicalNot = { int x -> return !x; };");
+ java.nio.file.Files.writeString(dir.resolve("x86LogicalNot.c"), """
+ #include <limits.h>
+ extern long long logicalNot(long long);
+ int main(void) {
+ long long inputs[] = {0, 1, -1, LLONG_MIN, LLONG_MAX, 1LL << 32};
+ for (unsigned i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++)
+ if (logicalNot(inputs[i]) != (inputs[i] == 0)) return 1;
+ return 0;
+ }
+ """);
+ com.seaofnodes.simple.TestC.run("build/objs", "x86LogicalNot", "", -1);
+ }
+
+ @Test
public void testMultiplyImmediateRegisters() {
// Destination, source, expected REX and ModRM. Cross the register-8
// boundary in both directions, with low/low and high/high controls.