about summary refs log tree commit diff stats
path: root/subx
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
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')
-rw-r--r--subx/018jump_disp32.cc (renamed from subx/018jump_disp16.cc)162
-rw-r--r--subx/031check_operands.cc26
-rwxr-xr-xsubx/apps/crenshaw2-1bbin7048 -> 7050 bytes
-rw-r--r--subx/apps/crenshaw2-1b.subx2
4 files changed, 90 insertions, 100 deletions
diff --git a/subx/018jump_disp16.cc b/subx/018jump_disp32.cc
index 38ac82ac..fd0bc33d 100644
--- a/subx/018jump_disp16.cc
+++ b/subx/018jump_disp32.cc
@@ -1,55 +1,49 @@
-//: jump to 16-bit offset
+//: jump to 32-bit offset
 
 //:: jump
 
 :(before "End Initialize Op Names")
-put_new(Name, "e9", "jump disp16 bytes away (jmp)");
+put_new(Name, "e9", "jump disp32 bytes away (jmp)");
 
-:(scenario jump_rel16)
+:(scenario jump_disp32)
 == 0x1
 # op  ModR/M  SIB   displacement  immediate
-  e9                05 00                     # skip 1 instruction
+  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: 0x00000009
--run: inst: 0x00000003
++run: inst: 0x0000000b
+-run: inst: 0x00000006
 
 :(before "End Single-Byte Opcodes")
-case 0xe9: {  // jump rel8
-  const int16_t offset = imm16();
+case 0xe9: {  // jump disp32
+  const int32_t offset = next32();
   trace(90, "run") << "jump " << offset << end();
   EIP += offset;
   break;
 }
-:(code)
-int16_t imm16() {
-  int16_t result = next();
-  result |= (next()<<8);
-  return result;
-}
 
 //:: jump if equal/zero
 
 :(before "End Initialize Op Names")
-put_new(Name_0f, "84", "jump disp16 bytes away if equal, if ZF is set (jcc/jz/je)");
+put_new(Name_0f, "84", "jump disp32 bytes away if equal, if ZF is set (jcc/jz/je)");
 
-:(scenario je_rel16_success)
+:(scenario je_disp32_success)
 % ZF = true;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 84                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
 :(before "End Two-Byte Opcodes Starting With 0f")
-case 0x84: {  // jump rel16 if ZF
-  const int16_t offset = imm16();
+case 0x84: {  // jump disp32 if ZF
+  const int32_t offset = next32();
   if (ZF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -57,38 +51,38 @@ case 0x84: {  // jump rel16 if ZF
   break;
 }
 
-:(scenario je_rel16_fail)
+:(scenario je_disp32_fail)
 % ZF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 84                 05 00                     # skip 1 instruction
+  0f 84                 05 00 00 00               # skip 1 instruction
   05                                  00 00 00 01
   05                                  00 00 00 02
 +run: inst: 0x00000001
-+run: inst: 0x00000005
-+run: inst: 0x0000000a
++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 disp16 bytes away if not equal, if ZF is not set (jcc/jnz/jne)");
+put_new(Name_0f, "85", "jump disp32 bytes away if not equal, if ZF is not set (jcc/jnz/jne)");
 
-:(scenario jne_rel16_success)
+:(scenario jne_disp32_success)
 % ZF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 85                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
 :(before "End Two-Byte Opcodes Starting With 0f")
-case 0x85: {  // jump rel16 unless ZF
-  const int16_t offset = imm16();
+case 0x85: {  // jump disp32 unless ZF
+  const int32_t offset = next32();
   if (!ZF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -96,40 +90,40 @@ case 0x85: {  // jump rel16 unless ZF
   break;
 }
 
-:(scenario jne_rel16_fail)
+:(scenario jne_disp32_fail)
 % ZF = true;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 85                 05 00                     # skip 1 instruction
+  0f 85                 05 00 00 00               # skip 1 instruction
   05                                  00 00 00 01
   05                                  00 00 00 02
 +run: inst: 0x00000001
-+run: inst: 0x00000005
-+run: inst: 0x0000000a
++run: inst: 0x00000007
++run: inst: 0x0000000c
 -run: jump 5
 
 //:: jump if greater
 
 :(before "End Initialize Op Names")
-put_new(Name_0f, "8f", "jump disp16 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle)");
+put_new(Name_0f, "8f", "jump disp32 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle)");
 
-:(scenario jg_rel16_success)
+:(scenario jg_disp32_success)
 % ZF = false;
 % SF = false;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8f                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
 :(before "End Two-Byte Opcodes Starting With 0f")
-case 0x8f: {  // jump rel16 if !SF and !ZF
-  const int16_t offset = imm16();
+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;
@@ -137,41 +131,41 @@ case 0x8f: {  // jump rel16 if !SF and !ZF
   break;
 }
 
-:(scenario jg_rel16_fail)
+:(scenario jg_disp32_fail)
 % ZF = false;
 % SF = true;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8f                 05 00                     # skip 1 instruction
+  0f 8f                 05 00 00 00               # skip 1 instruction
   05                                  00 00 00 01
   05                                  00 00 00 02
 +run: inst: 0x00000001
-+run: inst: 0x00000005
-+run: inst: 0x0000000a
++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 disp16 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)");
+put_new(Name_0f, "8d", "jump disp32 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)");
 
-:(scenario jge_rel16_success)
+:(scenario jge_disp32_success)
 % SF = false;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8d                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
 :(before "End Two-Byte Opcodes Starting With 0f")
-case 0x8d: {  // jump rel16 if !SF
-  const int16_t offset = imm16();
+case 0x8d: {  // jump disp32 if !SF
+  const int32_t offset = next32();
   if (SF == OF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -179,41 +173,41 @@ case 0x8d: {  // jump rel16 if !SF
   break;
 }
 
-:(scenario jge_rel16_fail)
+:(scenario jge_disp32_fail)
 % SF = true;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8d                 05 00                     # skip 1 instruction
+  0f 8d                 05 00 00 00               # skip 1 instruction
   05                                  00 00 00 01
   05                                  00 00 00 02
 +run: inst: 0x00000001
-+run: inst: 0x00000005
-+run: inst: 0x0000000a
++run: inst: 0x00000007
++run: inst: 0x0000000c
 -run: jump 5
 
 //:: jump if lesser
 
 :(before "End Initialize Op Names")
-put_new(Name_0f, "8c", "jump disp16 bytes away if lesser, if SF != OF (jcc/jl/jnge)");
+put_new(Name_0f, "8c", "jump disp32 bytes away if lesser, if SF != OF (jcc/jl/jnge)");
 
-:(scenario jl_rel16_success)
+:(scenario jl_disp32_success)
 % ZF = false;
 % SF = true;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8c                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
 :(before "End Two-Byte Opcodes Starting With 0f")
-case 0x8c: {  // jump rel16 if SF and !ZF
-  const int16_t offset = imm16();
+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;
@@ -221,56 +215,56 @@ case 0x8c: {  // jump rel16 if SF and !ZF
   break;
 }
 
-:(scenario jl_rel16_fail)
+:(scenario jl_disp32_fail)
 % ZF = false;
 % SF = false;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8c                 05 00                     # skip 1 instruction
+  0f 8c                 05 00 00 00               # skip 1 instruction
   05                                  00 00 00 01
   05                                  00 00 00 02
 +run: inst: 0x00000001
-+run: inst: 0x00000005
-+run: inst: 0x0000000a
++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 disp16 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng)");
+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_rel16_equal)
+:(scenario jle_disp32_equal)
 % ZF = true;
 % SF = false;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8e                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
-:(scenario jle_rel16_lesser)
+:(scenario jle_disp32_lesser)
 % ZF = false;
 % SF = true;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8e                 05 00                     # skip 1 instruction
+  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: 0x0000000a
--run: inst: 0x00000005
++run: inst: 0x0000000c
+-run: inst: 0x00000007
 
 :(before "End Two-Byte Opcodes Starting With 0f")
-case 0x8e: {  // jump rel16 if SF or ZF
-  const int16_t offset = imm16();
+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;
@@ -278,16 +272,16 @@ case 0x8e: {  // jump rel16 if SF or ZF
   break;
 }
 
-:(scenario jle_rel16_greater)
+:(scenario jle_disp32_greater)
 % ZF = false;
 % SF = false;
 % OF = false;
 == 0x1
 # op      ModR/M  SIB   displacement  immediate
-  0f 8e                 05 00                     # skip 1 instruction
+  0f 8e                 05 00 00 00               # skip 1 instruction
   05                                  00 00 00 01
   05                                  00 00 00 02
 +run: inst: 0x00000001
-+run: inst: 0x00000005
-+run: inst: 0x0000000a
++run: inst: 0x00000007
++run: inst: 0x0000000c
 -run: jump 5
diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc
index f5629a96..f59fb005 100644
--- a/subx/031check_operands.cc
+++ b/subx/031check_operands.cc
@@ -147,15 +147,11 @@ void init_permitted_operands() {
   put(Permitted_operands, "7e", 0x04);
   put(Permitted_operands, "7f", 0x04);
 
-  //// Class C: just op and disp16
-  //  imm32 imm8  disp32 |disp16  disp8 subop modrm
-  //  0     0     0      |1       0     0     0
-  put(Permitted_operands, "e9", 0x08);  // jump
-
   //// Class D: just op and disp32
   //  imm32 imm8  disp32 |disp16  disp8 subop modrm
   //  0     0     1      |0       0     0     0
   put(Permitted_operands, "e8", 0x10);  // call
+  put(Permitted_operands, "e9", 0x10);  // jump
 
   //// Class E: just op and imm8
   //  imm32 imm8  disp32 |disp16  disp8 subop modrm
@@ -492,27 +488,27 @@ void check_operands_f3(const line& /*unused*/) {
   raise << "no supported opcodes starting with f3\n" << end();
 }
 
-:(scenario check_missing_disp16_operand)
+:(scenario check_missing_disp32_operand)
 % Hide_errors = true;
 == 0x1
 # instruction                     effective address                                                   operand     displacement    immediate
 # op          subop               mod             rm32          base        index         scale       r32
 # 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
   0f 84                                                                                                                                             # jmp if ZF to ??
-+error: '0f 84' (jump disp16 bytes away if equal, if ZF is set): missing disp16 operand
++error: '0f 84' (jump disp32 bytes away if equal, if ZF is set): missing disp32 operand
 
 :(before "End Globals")
 map</*op*/string, /*bitvector*/uint8_t> Permitted_operands_0f;
 :(before "End Init Permitted Operands")
-//// Class C: just op and disp16
+//// Class D: just op and disp32
 //  imm32 imm8  disp32 |disp16  disp8 subop modrm
-//  0     0     0      |1       0     0     0
-put_new(Permitted_operands_0f, "84", 0x08);
-put_new(Permitted_operands_0f, "85", 0x08);
-put_new(Permitted_operands_0f, "8c", 0x08);
-put_new(Permitted_operands_0f, "8d", 0x08);
-put_new(Permitted_operands_0f, "8e", 0x08);
-put_new(Permitted_operands_0f, "8f", 0x08);
+//  0     0     1      |0       0     0     0
+put_new(Permitted_operands_0f, "84", 0x10);
+put_new(Permitted_operands_0f, "85", 0x10);
+put_new(Permitted_operands_0f, "8c", 0x10);
+put_new(Permitted_operands_0f, "8d", 0x10);
+put_new(Permitted_operands_0f, "8e", 0x10);
+put_new(Permitted_operands_0f, "8f", 0x10);
 
 //// Class M: using ModR/M byte
 //  imm32 imm8  disp32 |disp16  disp8 subop modrm
diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b
index 1396ede0..4e59c1b7 100755
--- a/subx/apps/crenshaw2-1b
+++ b/subx/apps/crenshaw2-1b
Binary files differdiff --git a/subx/apps/crenshaw2-1b.subx b/subx/apps/crenshaw2-1b.subx
index ef6996ee..1776b833 100644
--- a/subx/apps/crenshaw2-1b.subx
+++ b/subx/apps/crenshaw2-1b.subx
@@ -291,7 +291,7 @@ $get-num:loop-stage2:
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
   # if EAX loop
   3d/compare-EAX  0/imm32
-  0f 85/jump-if-not-equal  $get-num:loop/disp16
+  0f 85/jump-if-not-equal  $get-num:loop/disp32
 $get-num:loop-end:
   # persist necessary variables from registers
   89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # copy ECX to *EDI