about summary refs log tree commit diff stats
path: root/subx/015immediate_addressing.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-09-07 22:13:10 -0700
committerKartik Agaram <vc@akkartik.com>2018-09-07 22:19:13 -0700
commite07a3f2886b117970b3cd58f7cd6806cbfe5cc4a (patch)
tree6fcddb741f3b15eaa7892b5ce0468a6f3695005a /subx/015immediate_addressing.cc
parent608a7fa8d0faf9a3e3d182d9eabe969804443aab (diff)
downloadmu-e07a3f2886b117970b3cd58f7cd6806cbfe5cc4a.tar.gz
4537
Streamline the factorial function; we don't need to save a stack variable
into a register before operating on it. All instructions can take a stack
variable directly.

In the process we found two bugs:

a) Opcode f7 was not implemented correctly. It was internally consistent
but I'd never validated it against a natively running program. Turns out
it encodes multiple instructions, not just 'not'.

b) The way we look up imm32 operands was sometimes reading them before
disp8/disp32 operands.
Diffstat (limited to 'subx/015immediate_addressing.cc')
-rw-r--r--subx/015immediate_addressing.cc61
1 files changed, 40 insertions, 21 deletions
diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc
index c75c419e..b1d97f1e 100644
--- a/subx/015immediate_addressing.cc
+++ b/subx/015immediate_addressing.cc
@@ -9,17 +9,19 @@ put(name, "81", "combine rm32 with imm32 based on subop");
 # op  ModR/M  SIB   displacement  immediate
   81  c3                          0a 0b 0c 0d  # add 0x0d0c0b0a to EBX
 # ModR/M in binary: 11 (direct mode) 000 (add imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b0a
 +run: subop add
 +run: storing 0x0d0c0b0b
 
 :(before "End Single-Byte Opcodes")
 case 0x81: {  // combine imm32 with r/m32
+  trace(90, "run") << "combine imm32 with r/m32" << end();
   uint8_t modrm = next();
-  int32_t arg2 = imm32();
-  trace(90, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with r/m32" << end();
   int32_t* arg1 = effective_address(modrm);
+  int32_t arg2 = imm32();
+  trace(90, "run") << "imm32 is 0x" << HEXWORD << arg2 << end();
   uint8_t subop = (modrm>>3)&0x7;  // middle 3 'reg opcode' bits
   switch (subop) {
   case 0:
@@ -44,8 +46,9 @@ case 0x81: {  // combine imm32 with r/m32
 # ModR/M in binary: 00 (indirect mode) 000 (add imm32) 011 (dest EBX)
 == 0x60  # data segment
 01 00 00 00  # 1
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 +run: subop add
 +run: storing 0x0d0c0b0b
 
@@ -80,8 +83,9 @@ case 0x2d: {  // subtract imm32 from EAX
 # ModR/M in binary: 00 (indirect mode) 101 (subtract imm32) 011 (dest EBX)
 == 0x60  # data segment
 0a 00 00 00  # 10
-+run: combine imm32 0x00000001 with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x00000001
 +run: subop subtract
 +run: storing 0x00000009
 
@@ -100,8 +104,9 @@ case 5: {
 # op  ModR/M  SIB   displacement  immediate
   81  eb                          01 00 00 00  # subtract 1 from EBX
 # ModR/M in binary: 11 (direct mode) 101 (subtract imm32) 011 (dest EBX)
-+run: combine imm32 0x00000001 with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x00000001
 +run: subop subtract
 +run: storing 0x00000009
 
@@ -136,8 +141,9 @@ case 0x25: {  // and imm32 with EAX
 # ModR/M in binary: 00 (indirect mode) 100 (and imm32) 011 (dest EBX)
 == 0x60  # data segment
 ff 00 00 00  # 0xff
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 +run: subop and
 +run: storing 0x0000000a
 
@@ -156,8 +162,9 @@ case 4: {
 # op  ModR/M  SIB   displacement  immediate
   81  e3                          0a 0b 0c 0d  # and 0x0d0c0b0a with EBX
 # ModR/M in binary: 11 (direct mode) 100 (and imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b0a
 +run: subop and
 +run: storing 0x0000000a
 
@@ -192,8 +199,9 @@ case 0x0d: {  // or imm32 with EAX
 # ModR/M in binary: 00 (indirect mode) 001 (or imm32) 011 (dest EBX)
 == 0x60  # data segment
 a0 b0 c0 d0  # 0xd0c0b0a0
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 +run: subop or
 +run: storing 0xddccbbaa
 
@@ -210,8 +218,9 @@ case 1: {
 # op  ModR/M  SIB   displacement  immediate
   81  cb                          0a 0b 0c 0d  # or 0x0d0c0b0a with EBX
 # ModR/M in binary: 11 (direct mode) 001 (or imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b0a
 +run: subop or
 +run: storing 0xddccbbaa
 
@@ -246,8 +255,9 @@ case 0x35: {  // xor imm32 with EAX
 # ModR/M in binary: 00 (indirect mode) 110 (xor imm32) 011 (dest EBX)
 == 0x60  # data segment
 a0 b0 c0 d0  # 0xd0c0b0a0
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 +run: subop xor
 +run: storing 0xddccbbaa
 
@@ -264,8 +274,9 @@ case 6: {
 # op  ModR/M  SIB   displacement  immediate
   81  f3                          0a 0b 0c 0d  # xor 0x0d0c0b0a with EBX
 # ModR/M in binary: 11 (direct mode) 110 (xor imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b0a
 +run: subop xor
 +run: storing 0xddccbbaa
 
@@ -320,8 +331,9 @@ case 0x3d: {  // subtract imm32 from EAX
 # op  ModR/M  SIB   displacement  immediate
   81  fb                          07 0b 0c 0d  # compare 0x0d0c0b07 with EBX
 # ModR/M in binary: 11 (direct mode) 111 (compare imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b07 with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b07
 +run: SF=0; ZF=0; OF=0
 
 :(before "End Op 81 Subops")
@@ -342,8 +354,9 @@ case 7: {
 # op  ModR/M  SIB   displacement  immediate
   81  fb                          0a 0b 0c 0d  # compare 0x0d0c0b0a with EBX
 # ModR/M in binary: 11 (direct mode) 111 (compare imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b0a
 +run: SF=1; ZF=0; OF=0
 
 :(scenario compare_imm32_with_r32_equal)
@@ -352,8 +365,9 @@ case 7: {
 # op  ModR/M  SIB   displacement  immediate
   81  fb                          0a 0b 0c 0d  # compare 0x0d0c0b0a with EBX
 # ModR/M in binary: 11 (direct mode) 111 (compare imm32) 011 (dest EBX)
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: r/m32 is EBX
++run: imm32 is 0x0d0c0b0a
 +run: SF=0; ZF=1; OF=0
 
 :(scenario compare_imm32_with_mem_at_r32_greater)
@@ -364,8 +378,9 @@ case 7: {
 # ModR/M in binary: 00 (indirect mode) 111 (compare imm32) 011 (dest EBX)
 == 0x60  # data segment
 0a 0b 0c 0d  # 0x0d0c0b0a
-+run: combine imm32 0x0d0c0b07 with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b07
 +run: SF=0; ZF=0; OF=0
 
 :(scenario compare_imm32_with_mem_at_r32_lesser)
@@ -376,8 +391,9 @@ case 7: {
 # ModR/M in binary: 00 (indirect mode) 111 (compare imm32) 011 (dest EBX)
 == 0x60  # data segment
 07 0b 0c 0d  # 0x0d0c0b07
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 +run: SF=1; ZF=0; OF=0
 
 :(scenario compare_imm32_with_mem_at_r32_equal)
@@ -389,8 +405,9 @@ case 7: {
 # ModR/M in binary: 00 (indirect mode) 111 (compare imm32) 011 (dest EBX)
 == 0x60  # data segment
 0a 0b 0c 0d  # 0x0d0c0b0a
-+run: combine imm32 0x0d0c0b0a with r/m32
++run: combine imm32 with r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 +run: SF=0; ZF=1; OF=0
 
 //:: copy (mov)
@@ -438,15 +455,17 @@ put(name, "c7", "copy imm32 to rm32");
 # op  ModR/M  SIB   displacement  immediate
   c7  03                          0a 0b 0c 0d  # copy 0x0d0c0b0a to *EBX
 # ModR/M in binary: 00 (indirect mode) 000 (unused) 011 (dest EBX)
-+run: copy imm32 0x0d0c0b0a to r/m32
++run: copy imm32 to r/m32
 +run: effective address is 0x60 (EBX)
++run: imm32 is 0x0d0c0b0a
 
 :(before "End Single-Byte Opcodes")
 case 0xc7: {  // copy imm32 to r32
   uint8_t modrm = next();
-  int32_t arg2 = imm32();
-  trace(90, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to r/m32" << end();
+  trace(90, "run") << "copy imm32 to r/m32" << end();
   int32_t* arg1 = effective_address(modrm);
+  int32_t arg2 = imm32();
+  trace(90, "run") << "imm32 is 0x" << HEXWORD << arg2 << end();
   *arg1 = arg2;
   break;
 }