about summary refs log tree commit diff stats
path: root/subx/013direct_addressing.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-05-13 10:54:42 -0700
committerKartik Agaram <vc@akkartik.com>2019-05-13 10:54:42 -0700
commit40f4f1b454a3510c35dfa41db1dff323793ec895 (patch)
tree27543d94ec167d626bcc071671d6e95fe063abb3 /subx/013direct_addressing.cc
parent97ef7c4362b40609ec1c4881d2dedc58a9f12c41 (diff)
downloadmu-40f4f1b454a3510c35dfa41db1dff323793ec895.tar.gz
.
Standardize layout of some code fragments, and fix several bugs in computing
the overflow flag in the process. a64 = b32 + c32 doesn't benefit from
`a` being 64-bit without casting `b`.
Diffstat (limited to 'subx/013direct_addressing.cc')
-rw-r--r--subx/013direct_addressing.cc13
1 files changed, 7 insertions, 6 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc
index 7b3997f6..d4dcd92a 100644
--- a/subx/013direct_addressing.cc
+++ b/subx/013direct_addressing.cc
@@ -27,9 +27,9 @@ case 0x01: {  // add r32 to r/m32
   trace(Callstack_depth+1, "run") << "add " << rname(arg2) << " to r/m32" << end();
   int32_t* signed_arg1 = effective_address(modrm);
   int32_t signed_result = *signed_arg1 + Reg[arg2].i;
-  int64_t signed_full_result = static_cast<int64_t>(*signed_arg1) + Reg[arg2].i;
   SF = (signed_result < 0);
   ZF = (signed_result == 0);
+  int64_t signed_full_result = static_cast<int64_t>(*signed_arg1) + Reg[arg2].i;
   OF = (signed_result != signed_full_result);
   // set CF
   uint32_t unsigned_arg1 = static_cast<uint32_t>(*signed_arg1);
@@ -176,9 +176,9 @@ case 0x29: {  // subtract r32 from r/m32
   trace(Callstack_depth+1, "run") << "subtract " << rname(arg2) << " from r/m32" << end();
   int32_t* signed_arg1 = effective_address(modrm);
   int32_t signed_result = *signed_arg1 - Reg[arg2].i;
-  int64_t signed_full_result = static_cast<int64_t>(*signed_arg1) - Reg[arg2].i;
   SF = (signed_result < 0);
   ZF = (signed_result == 0);
+  int64_t signed_full_result = static_cast<int64_t>(*signed_arg1) - Reg[arg2].i;
   OF = (signed_result != signed_full_result);
   // set CF
   uint32_t unsigned_arg1 = static_cast<uint32_t>(*signed_arg1);
@@ -275,7 +275,7 @@ case 0xf7: {
   switch (subop) {
   case 4: {  // mul unsigned EAX by r/m32
     trace(Callstack_depth+1, "run") << "subop: multiply EAX by r/m32" << end();
-    const uint64_t result = Reg[EAX].u * static_cast<uint32_t>(*arg1);
+    const uint64_t result = static_cast<uint64_t>(Reg[EAX].u) * static_cast<uint32_t>(*arg1);
     Reg[EAX].u = result & 0xffffffff;
     Reg[EDX].u = result >> 32;
     OF = (Reg[EDX].u != 0);
@@ -318,14 +318,15 @@ case 0xaf: {  // multiply r32 by r/m32
   const uint8_t arg1 = (modrm>>3)&0x7;
   trace(Callstack_depth+1, "run") << "multiply " << rname(arg1) << " by r/m32" << end();
   const int32_t* arg2 = effective_address(modrm);
-  int64_t full_result = Reg[arg1].i * (*arg2);
-  Reg[arg1].i *= (*arg2);
-  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[arg1].i << end();
+  int32_t result = Reg[arg1].i * (*arg2);
   SF = (Reg[arg1].i < 0);
   ZF = (Reg[arg1].i == 0);
+  int64_t full_result = static_cast<int64_t>(Reg[arg1].i) * (*arg2);
   OF = (Reg[arg1].i != full_result);
   CF = OF;
   trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
+  Reg[arg1].i = result;
+  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[arg1].i << end();
   break;
 }