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-12-03 23:26:56 -0800
committerKartik Agaram <vc@akkartik.com>2018-12-03 23:26:56 -0800
commit5f3b3e7aea4174f13da9b430538564c68257b647 (patch)
tree64b0ca70a7508aa10a008ad7d996f5d4f38214c8 /subx/015immediate_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/015immediate_addressing.cc')
-rw-r--r--subx/015immediate_addressing.cc151
1 files changed, 151 insertions, 0 deletions
diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc
index a5d385b7..ce4bc4db 100644
--- a/subx/015immediate_addressing.cc
+++ b/subx/015immediate_addressing.cc
@@ -110,6 +110,157 @@ case 5: {
 +run: subop subtract
 +run: storing 0x00000009
 
+//:: shift left
+
+:(before "End Initialize Op Names")
+put_new(Name, "c1", "shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr)");
+
+:(scenario shift_left_r32_with_imm8)
+% Reg[EBX].i = 13;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  e3                          01          # 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 0xc1: {
+  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 = next() & 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 c1 Subops
+  default:
+    cerr << "unrecognized sub-opcode after c1: " << NUM(subop) << '\n';
+    exit(1);
+  }
+  break;
+}
+
+//:: shift right arithmetic
+
+:(scenario shift_right_arithmetic_r32_with_imm8)
+% Reg[EBX].i = 26;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  fb                          01          # 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 c1 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 = next() & 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_imm8)
+% Reg[EBX].i = 27;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  fb                          01          # 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_imm8)
+% Reg[EBX].i = 0xfffffffd;  // -3
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  fb                          01          # 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_imm8)
+% Reg[EBX].i = 26;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  eb                          01          # 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 c1 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 = next() & 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_imm8)
+% Reg[EBX].i = 27;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  eb                          01          # 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_imm8)
+% Reg[EBX].i = 0xfffffffd;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  c1  eb                          01          # 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")