summaryrefslogtreecommitdiff
path: root/chapter23
diff options
context:
space:
mode:
Diffstat (limited to 'chapter23')
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/CmpMemX86.java2
-rw-r--r--chapter23/src/test/java/com/seaofnodes/simple/X86EncodingTest.java33
2 files changed, 34 insertions, 1 deletions
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 11f900ed..278bf0e6 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
@@ -38,7 +38,7 @@ public class CmpMemX86 extends MemOpX86 {
case 0: enc.add1(_imm); break;
case 1: enc.add2(_imm); break;
case 2: enc.add4(_imm); break;
- case 3: enc.add8(_imm); break;
+ case 3: enc.add4(_imm); break;
}
} else {
encVal(enc, _declaredType, ptr, idx, src, _off, _scale, _swap);
diff --git a/chapter23/src/test/java/com/seaofnodes/simple/X86EncodingTest.java b/chapter23/src/test/java/com/seaofnodes/simple/X86EncodingTest.java
new file mode 100644
index 00000000..54fa96a8
--- /dev/null
+++ b/chapter23/src/test/java/com/seaofnodes/simple/X86EncodingTest.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple;
+
+import com.seaofnodes.simple.codegen.CodeGen;
+import com.seaofnodes.simple.node.cpus.x86_64_v2.CmpMemX86;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class X86EncodingTest {
+ @Test
+ public void testMemoryCompare64Immediate32() {
+ for (int immediate : new int[]{123456789, -123456789}) {
+ String src = "int[] !a = new int[2]; a[0] = arg; return a[arg & 1] == " + immediate + ";";
+ CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding, "x86_64_v2", "SystemV");
+ var cmp = code._stop.walk(n -> n instanceof CmpMemX86 ? n : null);
+ assertNotNull("Must exercise a memory comparison", cmp);
+ var enc = code._encoding;
+ int start = enc._opStart[cmp._nid];
+
+ // REX.W, 81 /7, SIB with scale 8, disp8, and a sign-extended imm32.
+ assertEquals(0x48, enc.read1(start) & 0xF8);
+ assertEquals(0x81, enc.read1(start + 1));
+ assertEquals(0x7C, enc.read1(start + 2));
+ assertEquals(0xC0, enc.read1(start + 3) & 0xC0);
+ assertEquals(8, enc.read1(start + 4));
+ assertEquals(immediate, enc.read4(start + 5));
+ assertEquals("CMP r/m64 uses four immediate bytes", 9, enc._opLen[cmp._nid]);
+
+ // SETE must immediately follow the CPU's nine-byte CMP instruction.
+ assertEquals(0x0F, enc.read1(start + 9));
+ assertEquals(0x94, enc.read1(start + 10));
+ }
+ }
+}