about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-10-23 23:19:55 -0700
committerKartik Agaram <vc@akkartik.com>2018-10-23 23:19:55 -0700
commitd27812594a85cbf6002cbe9e617b241eb00eedc1 (patch)
tree7acc6ae3d29428d2f7a7beb7c83be7c7275a33c4
parentbfc997cfdae6a043bfd01ffd6dc3c0b2214d108f (diff)
downloadmu-d27812594a85cbf6002cbe9e617b241eb00eedc1.tar.gz
4715 - support one more negation instruction
-rw-r--r--subx/013direct_addressing.cc47
-rw-r--r--subx/014indirect_addressing.cc2
2 files changed, 48 insertions, 1 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc
index bf736e01..8cf033bd 100644
--- a/subx/013direct_addressing.cc
+++ b/subx/013direct_addressing.cc
@@ -166,6 +166,49 @@ case 0xaf: {  // multiply r32 into r/m32
   break;
 }
 
+//:: negate
+
+:(scenario negate_r32)
+% Reg[EBX].i = 1;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  f7  db                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: negate
++run: storing 0xffffffff
+
+:(before "End Op f7 Subops")
+case 3: {  // negate r/m32
+  trace(90, "run") << "subop: negate" << end();
+  // one case that can overflow
+  if (static_cast<uint32_t>(*arg1) == 0x80000000) {
+    trace(90, "run") << "overflow" << end();
+    SF = true;
+    ZF = false;
+    OF = true;
+    break;
+  }
+  *arg1 = -(*arg1);
+  trace(90, "run") << "storing 0x" << HEXWORD << *arg1 << end();
+  SF = (*arg1 >> 31);
+  ZF = (*arg1 == 0);
+  OF = false;
+  break;
+}
+
+:(scenario negate_can_overflow)  // in exactly one situation
+% Reg[EBX].i = 0x80000000;  // INT_MIN
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  f7  db                                      # negate EBX
+# ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX)
++run: operate on r/m32
++run: r/m32 is EBX
++run: subop: negate
++run: overflow
+
 //:: and
 
 :(before "End Initialize Op Names")
@@ -440,6 +483,10 @@ case 0xff: {
       trace(90, "run") << "storing value 0x" << HEXWORD << *arg << end();
       break;
     }
+    default:
+      cerr << "unrecognized subop for ff: " << HEXBYTE << NUM(subop) << '\n';
+      DUMP("");
+      exit(1);
     // End Op ff Subops
   }
   break;
diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc
index b3e23fe1..c415c96c 100644
--- a/subx/014indirect_addressing.cc
+++ b/subx/014indirect_addressing.cc
@@ -231,7 +231,7 @@ case 0x33: {  // xor r/m32 with r32
 % Reg[EBX].i = 0x2000;
 == 0x1  # code segment
 # op  ModR/M  SIB   displacement  immediate
-  f7  13                                      # negate *EBX
+  f7  13                                      # not *EBX
 # ModR/M in binary: 00 (indirect mode) 010 (subop not) 011 (dest EBX)
 == 0x2000  # data segment
 ff 00 0f 0f  # 0x0f0f00ff