about summary refs log tree commit diff stats
path: root/subx/018jump_disp32.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-11-25 13:46:53 -0800
committerKartik Agaram <vc@akkartik.com>2018-11-25 13:46:53 -0800
commit50dcc0c122e7208fbddedac6f7939020c28e460d (patch)
treee24b92db5fe4e01ef7707448b34eed0afdcce9bb /subx/018jump_disp32.cc
parent33fdc60b168a04ca26b4924ecde2adb7c8059a13 (diff)
downloadmu-50dcc0c122e7208fbddedac6f7939020c28e460d.tar.gz
4776
Crenshaw compiler now runs natively as well.

It turns out I was misreading the Intel manual, and the jump instructions
that I thought take disp16 operands actually take disp32 operands by default
on both i686 and x86_64 processors. The disp16 versions are some holdover
from the 16-bit days.

This was the first time I've used one of these erstwhile-disp16 instructions,
but I still haven't tested most of them. We'll see if we run into future
issues.
Diffstat (limited to 'subx/018jump_disp32.cc')
-rw-r--r--subx/018jump_disp32.cc287
1 files changed, 287 insertions, 0 deletions
diff --git a/subx/018jump_disp32.cc b/subx/018jump_disp32.cc
new file mode 100644
index 00000000..fd0bc33d
--- /dev/null
+++ b/subx/018jump_disp32.cc
@@ -0,0 +1,287 @@
+//: jump to 32-bit offset
+
+//:: jump
+
+:(before "End Initialize Op Names")
+put_new(Name, "e9", "jump disp32 bytes away (jmp)");
+
+:(scenario jump_disp32)
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  e9                05 00 00 00               # skip 1 instruction
+  05                              00 00 00 01
+  05                              00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000b
+-run: inst: 0x00000006
+
+:(before "End Single-Byte Opcodes")
+case 0xe9: {  // jump disp32
+  const int32_t offset = next32();
+  trace(90, "run") << "jump " << offset << end();
+  EIP += offset;
+  break;
+}
+
+//:: jump if equal/zero
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "84", "jump disp32 bytes away if equal, if ZF is set (jcc/jz/je)");
+
+:(scenario je_disp32_success)
+% ZF = true;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 84                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x84: {  // jump disp32 if ZF
+  const int32_t offset = next32();
+  if (ZF) {
+    trace(90, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+
+:(scenario je_disp32_fail)
+% ZF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 84                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: inst: 0x00000007
++run: inst: 0x0000000c
+-run: jump 5
+
+//:: jump if not equal/not zero
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "85", "jump disp32 bytes away if not equal, if ZF is not set (jcc/jnz/jne)");
+
+:(scenario jne_disp32_success)
+% ZF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 85                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x85: {  // jump disp32 unless ZF
+  const int32_t offset = next32();
+  if (!ZF) {
+    trace(90, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+
+:(scenario jne_disp32_fail)
+% ZF = true;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 85                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: inst: 0x00000007
++run: inst: 0x0000000c
+-run: jump 5
+
+//:: jump if greater
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "8f", "jump disp32 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle)");
+
+:(scenario jg_disp32_success)
+% ZF = false;
+% SF = false;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8f                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x8f: {  // jump disp32 if !SF and !ZF
+  const int32_t offset = next32();
+  if (!ZF && SF == OF) {
+    trace(90, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+
+:(scenario jg_disp32_fail)
+% ZF = false;
+% SF = true;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8f                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: inst: 0x00000007
++run: inst: 0x0000000c
+-run: jump 5
+
+//:: jump if greater or equal
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "8d", "jump disp32 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)");
+
+:(scenario jge_disp32_success)
+% SF = false;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8d                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x8d: {  // jump disp32 if !SF
+  const int32_t offset = next32();
+  if (SF == OF) {
+    trace(90, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+
+:(scenario jge_disp32_fail)
+% SF = true;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8d                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: inst: 0x00000007
++run: inst: 0x0000000c
+-run: jump 5
+
+//:: jump if lesser
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "8c", "jump disp32 bytes away if lesser, if SF != OF (jcc/jl/jnge)");
+
+:(scenario jl_disp32_success)
+% ZF = false;
+% SF = true;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8c                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x8c: {  // jump disp32 if SF and !ZF
+  const int32_t offset = next32();
+  if (SF != OF) {
+    trace(90, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+
+:(scenario jl_disp32_fail)
+% ZF = false;
+% SF = false;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8c                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: inst: 0x00000007
++run: inst: 0x0000000c
+-run: jump 5
+
+//:: jump if lesser or equal
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "8e", "jump disp32 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng)");
+
+:(scenario jle_disp32_equal)
+% ZF = true;
+% SF = false;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8e                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(scenario jle_disp32_lesser)
+% ZF = false;
+% SF = true;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8e                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x0000000c
+-run: inst: 0x00000007
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x8e: {  // jump disp32 if SF or ZF
+  const int32_t offset = next32();
+  if (ZF || SF != OF) {
+    trace(90, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+
+:(scenario jle_disp32_greater)
+% ZF = false;
+% SF = false;
+% OF = false;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f 8e                 05 00 00 00               # skip 1 instruction
+  05                                  00 00 00 01
+  05                                  00 00 00 02
++run: inst: 0x00000001
++run: inst: 0x00000007
++run: inst: 0x0000000c
+-run: jump 5