about summary refs log tree commit diff stats
path: root/subx/013direct_addressing.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-12-03 23:26:56 -0800
committerKartik Agaram <vc@akkartik.com>2018-12-03 23:26:56 -0800
commit5f3b3e7aea4174f13da9b430538564c68257b647 (patch)
tree64b0ca70a7508aa10a008ad7d996f5d4f38214c8 /subx/013direct_addressing.cc
parentee73f5eb31e9dd5a185da097bd990ac94c3d282b (diff)
downloadmu-5f3b3e7aea4174f13da9b430538564c68257b647.tar.gz
4830
New helper: printing a byte in textual (hex) form.

This required adding instructions for bitwise shift operations.
Diffstat (limited to 'subx/013direct_addressing.cc')
-rw-r--r--subx/013direct_addressing.cc160
1 files changed, 159 insertions, 1 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc
index 8d9f0555..c18b5f5c 100644
--- a/subx/013direct_addressing.cc
+++ b/subx/013direct_addressing.cc
@@ -117,7 +117,7 @@ put_new(Name, "f7", "negate/multiply rm32 (with EAX if necessary) depending on s
 +run: storing 0x0000000c
 
 :(before "End Single-Byte Opcodes")
-case 0xf7: {  // xor r32 with r/m32
+case 0xf7: {
   const uint8_t modrm = next();
   trace(90, "run") << "operate on r/m32" << end();
   int32_t* arg1 = effective_address(modrm);
@@ -209,6 +209,164 @@ case 3: {  // negate r/m32
 +run: subop: negate
 +run: overflow
 
+//:: shift left
+
+:(before "End Initialize Op Names")
+put_new(Name, "d3", "shift rm32 by CL bits depending on subop (sal/sar/shl/shr)");
+
+:(scenario shift_left_r32_with_cl)
+% Reg[EBX].i = 13;
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  e3                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 100 (subop shift left) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift left by CL bits
++run: storing 0x0000001a
+
+:(before "End Single-Byte Opcodes")
+case 0xd3: {
+  const uint8_t modrm = next();
+  trace(90, "run") << "operate on r/m32" << end();
+  int32_t* arg1 = effective_address(modrm);
+  const uint8_t subop = (modrm>>3)&0x7;  // middle 3 'reg opcode' bits
+  switch (subop) {
+  case 4: {  // shift left r/m32 by CL
+    trace(90, "run") << "subop: shift left by CL bits" << end();
+    uint8_t count = Reg[ECX].u & 0x1f;
+    // OF is only defined if count is 1
+    if (count == 1) {
+      bool msb = (*arg1 & 0x80000000) >> 1;
+      bool pnsb = (*arg1 & 0x40000000);
+      OF = (msb != pnsb);
+    }
+    *arg1 = (*arg1 << count);
+    ZF = (*arg1 == 0);
+    SF = (*arg1 < 0);
+    trace(90, "run") << "storing 0x" << HEXWORD << *arg1 << end();
+    break;
+  }
+  // End Op d3 Subops
+  default:
+    cerr << "unrecognized sub-opcode after d3: " << NUM(subop) << '\n';
+    exit(1);
+  }
+  break;
+}
+
+//:: shift right arithmetic
+
+:(scenario shift_right_arithmetic_r32_with_cl)
+% Reg[EBX].i = 26;
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  fb                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift right by CL bits, while preserving sign
++run: storing 0x0000000d
+
+:(before "End Op d3 Subops")
+case 7: {  // shift right r/m32 by CL, preserving sign
+  trace(90, "run") << "subop: shift right by CL bits, while preserving sign" << end();
+  uint8_t count = Reg[ECX].u & 0x1f;
+  *arg1 = (*arg1 >> count);
+  ZF = (*arg1 == 0);
+  SF = (*arg1 < 0);
+  // OF is only defined if count is 1
+  if (count == 1) OF = false;
+  trace(90, "run") << "storing 0x" << HEXWORD << *arg1 << end();
+  break;
+}
+
+:(scenario shift_right_arithmetic_odd_r32_with_cl)
+% Reg[EBX].i = 27;
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  fb                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift right by CL bits, while preserving sign
+# result: 13
++run: storing 0x0000000d
+
+:(scenario shift_right_arithmetic_negative_r32_with_cl)
+% Reg[EBX].i = 0xfffffffd;  // -3
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  fb                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift right by CL bits, while preserving sign
+# result: -2
++run: storing 0xfffffffe
+
+//:: shift right logical
+
+:(scenario shift_right_logical_r32_with_cl)
+% Reg[EBX].i = 26;
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  eb                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift right by CL bits, while padding zeroes
++run: storing 0x0000000d
+
+:(before "End Op d3 Subops")
+case 5: {  // shift right r/m32 by CL, preserving sign
+  trace(90, "run") << "subop: shift right by CL bits, while padding zeroes" << end();
+  uint8_t count = Reg[ECX].u & 0x1f;
+  // OF is only defined if count is 1
+  if (count == 1) {
+    bool msb = (*arg1 & 0x80000000) >> 1;
+    bool pnsb = (*arg1 & 0x40000000);
+    OF = (msb != pnsb);
+  }
+  uint32_t* uarg1 = reinterpret_cast<uint32_t*>(arg1);
+  *uarg1 = (*uarg1 >> count);
+  ZF = (*uarg1 == 0);
+  // result is always positive by definition
+  SF = false;
+  trace(90, "run") << "storing 0x" << HEXWORD << *arg1 << end();
+  break;
+}
+
+:(scenario shift_right_logical_odd_r32_with_cl)
+% Reg[EBX].i = 27;
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  eb                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift right by CL bits, while padding zeroes
+# result: 13
++run: storing 0x0000000d
+
+:(scenario shift_right_logical_negative_r32_with_cl)
+% Reg[EBX].i = 0xfffffffd;
+% Reg[ECX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  d3  eb                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: shift right by CL bits, while padding zeroes
++run: storing 0x7ffffffe
+
 //:: and
 
 :(before "End Initialize Op Names")