about summary refs log tree commit diff stats
path: root/subx
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
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')
-rw-r--r--subx/013direct_addressing.cc13
-rw-r--r--subx/014indirect_addressing.cc21
-rw-r--r--subx/015immediate_addressing.cc72
3 files changed, 52 insertions, 54 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;
 }
 
diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc
index bf00747a..5ac0845c 100644
--- a/subx/014indirect_addressing.cc
+++ b/subx/014indirect_addressing.cc
@@ -61,9 +61,9 @@ case 0x03: {  // add r/m32 to r32
   trace(Callstack_depth+1, "run") << "add r/m32 to " << rname(arg1) << end();
   const int32_t* signed_arg2 = effective_address(modrm);
   int32_t signed_result = Reg[arg1].i + *signed_arg2;
-  int64_t signed_full_result = static_cast<int64_t>(Reg[arg1].i) + *signed_arg2;
   SF = (signed_result < 0);
   ZF = (signed_result == 0);
+  int64_t signed_full_result = static_cast<int64_t>(Reg[arg1].i) + *signed_arg2;
   OF = (signed_result != signed_full_result);
   // set CF
   uint32_t unsigned_arg2 = static_cast<uint32_t>(*signed_arg2);
@@ -189,9 +189,9 @@ case 0x2b: {  // subtract r/m32 from r32
   trace(Callstack_depth+1, "run") << "subtract r/m32 from " << rname(arg1) << end();
   const int32_t* signed_arg2 = effective_address(modrm);
   const int32_t signed_result = Reg[arg1].i - *signed_arg2;
-  int64_t signed_full_result = static_cast<int64_t>(Reg[arg1].i) - *signed_arg2;
   SF = (signed_result < 0);
   ZF = (signed_result == 0);
+  int64_t signed_full_result = static_cast<int64_t>(Reg[arg1].i) - *signed_arg2;
   OF = (signed_result != signed_full_result);
   // set CF
   uint32_t unsigned_arg2 = static_cast<uint32_t>(*signed_arg2);
@@ -563,15 +563,14 @@ case 0x3b: {  // set SF if r32 < r/m32
   trace(Callstack_depth+1, "run") << "compare " << rname(reg1) << " with r/m32" << end();
   const int32_t signed_arg1 = Reg[reg1].i;
   const int32_t* signed_arg2 = effective_address(modrm);
-  const int32_t signed_difference = signed_arg1 - *signed_arg2;
+  const int32_t signed_difference = Reg[reg1].i - *signed_arg2;
   SF = (signed_difference < 0);
   ZF = (signed_difference == 0);
-  int64_t full_signed_difference = signed_arg1 - *signed_arg2;
+  int64_t full_signed_difference = static_cast<int64_t>(Reg[reg1].i) - *signed_arg2;
   OF = (signed_difference != full_signed_difference);
-  const uint32_t unsigned_arg1 = static_cast<uint32_t>(signed_arg1);
   const uint32_t unsigned_arg2 = static_cast<uint32_t>(*signed_arg2);
-  const uint32_t unsigned_difference = unsigned_arg1 - unsigned_arg2;
-  const uint64_t full_unsigned_difference = unsigned_arg1 - unsigned_arg2;
+  const uint32_t unsigned_difference = Reg[reg1].u - unsigned_arg2;
+  const uint64_t full_unsigned_difference = static_cast<uint64_t>(Reg[reg1].u) - unsigned_arg2;
   CF = (unsigned_difference != full_unsigned_difference);
   trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
   break;
@@ -584,7 +583,7 @@ void test_compare_r32_with_mem_at_r32_lesser() {
   run(
       "== 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
-      "  3b     18                                    \n"  // compare *EAX with EBX
+      "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
       "== 0x2000\n"  // data segment
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
@@ -592,18 +591,17 @@ void test_compare_r32_with_mem_at_r32_lesser() {
   CHECK_TRACE_CONTENTS(
       "run: compare EBX with r/m32\n"
       "run: effective address is 0x00002000 (EAX)\n"
-      "run: SF=1; ZF=0; CF=0; OF=0\n"
+      "run: SF=1; ZF=0; CF=1; OF=0\n"
   );
 }
 
-:(code)
 void test_compare_r32_with_mem_at_r32_equal() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
       "== 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
-      "  3b     18                                    \n"  // compare *EAX with EBX
+      "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
       "== 0x2000\n"  // data segment
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
@@ -617,7 +615,6 @@ void test_compare_r32_with_mem_at_r32_equal() {
 
 //:: copy (mov)
 
-:(code)
 void test_copy_r32_to_mem_at_r32() {
   Reg[EBX].i = 0xaf;
   Reg[EAX].i = 0x60;
diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc
index f4762c2b..7abf7951 100644
--- a/subx/015immediate_addressing.cc
+++ b/subx/015immediate_addressing.cc
@@ -7,19 +7,19 @@ put_new(Name, "05", "add imm32 to EAX (add)");
 case 0x05: {  // add imm32 to EAX
   int32_t signed_arg2 = next32();
   trace(Callstack_depth+1, "run") << "add imm32 0x" << HEXWORD << signed_arg2 << " to reg EAX" << end();
-  int64_t signed_full_result = Reg[EAX].i + signed_arg2;
-  Reg[EAX].i += signed_arg2;
-  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[EAX].i << end();
-  SF = (Reg[EAX].i < 0);
-  ZF = (Reg[EAX].i == 0);
-  OF = (Reg[EAX].i != signed_full_result);
+  int32_t signed_result = Reg[EAX].i + signed_arg2;
+  SF = (signed_result < 0);
+  ZF = (signed_result == 0);
+  int64_t signed_full_result = static_cast<int64_t>(Reg[EAX].i) + signed_arg2;
+  OF = (signed_result != signed_full_result);
   // set CF
-  uint32_t unsigned_arg1 = static_cast<uint32_t>(Reg[EAX].i);
   uint32_t unsigned_arg2 = static_cast<uint32_t>(signed_arg2);
-  uint32_t unsigned_result = unsigned_arg1 + unsigned_arg2;
-  uint64_t unsigned_full_result = unsigned_arg1 + unsigned_arg2;
+  uint32_t unsigned_result = Reg[EAX].u + unsigned_arg2;
+  uint64_t unsigned_full_result = static_cast<uint64_t>(Reg[EAX].u) + unsigned_arg2;
   CF = (unsigned_result != unsigned_full_result);
   trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
+  Reg[EAX].i = signed_result;
+  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[EAX].i << end();
   break;
 }
 
@@ -55,19 +55,20 @@ case 0x81: {  // combine imm32 with r/m32
   switch (subop) {
   case 0: {
     trace(Callstack_depth+1, "run") << "subop add" << end();
-    int64_t signed_full_result = *signed_arg1 + signed_arg2;
-    *signed_arg1 += signed_arg2;
-    trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end();
-    SF = (*signed_arg1 < 0);
-    ZF = (*signed_arg1 == 0);
-    OF = (*signed_arg1 != signed_full_result);
+    int32_t signed_result = *signed_arg1 + signed_arg2;
+    SF = (signed_result < 0);
+    ZF = (signed_result == 0);
+    int64_t signed_full_result = static_cast<int64_t>(*signed_arg1) + signed_arg2;
+    OF = (signed_result != signed_full_result);
     // set CF
     uint32_t unsigned_arg1 = static_cast<uint32_t>(*signed_arg1);
     uint32_t unsigned_arg2 = static_cast<uint32_t>(signed_arg2);
     uint32_t unsigned_result = unsigned_arg1 + unsigned_arg2;
-    uint64_t unsigned_full_result = unsigned_arg1 + unsigned_arg2;
+    uint64_t unsigned_full_result = static_cast<uint64_t>(unsigned_arg1) + unsigned_arg2;
     CF = (unsigned_result != unsigned_full_result);
     trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
+    *signed_arg1 = signed_result;
+    trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end();
     break;
   }
   // End Op 81 Subops
@@ -163,19 +164,20 @@ void test_subtract_imm32_from_mem_at_r32() {
 :(before "End Op 81 Subops")
 case 5: {
   trace(Callstack_depth+1, "run") << "subop subtract" << end();
-  int64_t signed_full_result = *signed_arg1 - signed_arg2;
-  *signed_arg1 -= signed_arg2;
-  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end();
-  SF = (*signed_arg1 < 0);
-  ZF = (*signed_arg1 == 0);
-  OF = (*signed_arg1 != signed_full_result);
+  int32_t signed_result = *signed_arg1 - signed_arg2;
+  SF = (signed_result < 0);
+  ZF = (signed_result == 0);
+  int64_t signed_full_result = static_cast<int64_t>(*signed_arg1) - signed_arg2;
+  OF = (signed_result != signed_full_result);
   // set CF
   uint32_t unsigned_arg1 = static_cast<uint32_t>(*signed_arg1);
   uint32_t unsigned_arg2 = static_cast<uint32_t>(signed_arg2);
   uint32_t unsigned_result = unsigned_arg1 - unsigned_arg2;
-  uint64_t unsigned_full_result = unsigned_arg1 - unsigned_arg2;
+  uint64_t unsigned_full_result = static_cast<uint64_t>(unsigned_arg1) - unsigned_arg2;
   CF = (unsigned_result != unsigned_full_result);
   trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
+  *signed_arg1 = signed_result;
+  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end();
   break;
 }
 
@@ -674,10 +676,10 @@ void test_compare_imm32_with_eax_greater() {
   run(
       "== 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
-      "  3d                                 07 0b 0c 0d \n"  // compare 0x0d0c0b07 with EAX
+      "  3d                                 07 0b 0c 0d \n"  // compare EAX with 0x0d0c0b07
   );
   CHECK_TRACE_CONTENTS(
-      "run: compare EAX and imm32 0x0d0c0b07\n"
+      "run: compare EAX with imm32 0x0d0c0b07\n"
       "run: SF=0; ZF=0; CF=0; OF=0\n"
   );
 }
@@ -686,36 +688,35 @@ void test_compare_imm32_with_eax_greater() {
 case 0x3d: {  // compare EAX with imm32
   const int32_t signed_arg1 = Reg[EAX].i;
   const int32_t signed_arg2 = next32();
-  trace(Callstack_depth+1, "run") << "compare EAX and imm32 0x" << HEXWORD << signed_arg2 << end();
+  trace(Callstack_depth+1, "run") << "compare EAX with imm32 0x" << HEXWORD << signed_arg2 << end();
   const int32_t signed_difference = signed_arg1 - signed_arg2;
   SF = (signed_difference < 0);
   ZF = (signed_difference == 0);
-  const int64_t full_signed_difference = signed_arg1 - signed_arg2;
+  const int64_t full_signed_difference = static_cast<int64_t>(signed_arg1) - signed_arg2;
   OF = (signed_difference != full_signed_difference);
   const uint32_t unsigned_arg1 = static_cast<uint32_t>(signed_arg1);
   const uint32_t unsigned_arg2 = static_cast<uint32_t>(signed_arg2);
   const uint32_t unsigned_difference = unsigned_arg1 - unsigned_arg2;
-  const uint64_t full_unsigned_difference = unsigned_arg1 - unsigned_arg2;
+  const uint64_t full_unsigned_difference = static_cast<uint64_t>(unsigned_arg1) - unsigned_arg2;
   CF = (unsigned_difference != full_unsigned_difference);
   trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
   break;
 }
 
 :(code)
-void test_compare_imm32_with_eax_lesser() {
+void test_compare_eax_with_imm32_lesser() {
   Reg[EAX].i = 0x0d0c0b07;
   run(
       "== 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
-      "  3d                                 0a 0b 0c 0d \n"  // compare 0x0d0c0b0a with EAX
+      "  3d                                 0a 0b 0c 0d \n"  // compare EAX with 0x0d0c0b0a
   );
   CHECK_TRACE_CONTENTS(
-      "run: compare EAX and imm32 0x0d0c0b0a\n"
-      "run: SF=1; ZF=0; CF=0; OF=0\n"
+      "run: compare EAX with imm32 0x0d0c0b0a\n"
+      "run: SF=1; ZF=0; CF=1; OF=0\n"
   );
 }
 
-:(code)
 void test_compare_imm32_with_eax_equal() {
   Reg[EAX].i = 0x0d0c0b0a;
   run(
@@ -724,14 +725,13 @@ void test_compare_imm32_with_eax_equal() {
       "  3d                                 0a 0b 0c 0d \n"  // compare 0x0d0c0b0a with EAX
   );
   CHECK_TRACE_CONTENTS(
-      "run: compare EAX and imm32 0x0d0c0b0a\n"
+      "run: compare EAX with imm32 0x0d0c0b0a\n"
       "run: SF=0; ZF=1; CF=0; OF=0\n"
   );
 }
 
 //:
 
-:(code)
 void test_compare_imm32_with_r32_greater() {
   Reg[EBX].i = 0x0d0c0b0a;
   run(
@@ -754,7 +754,7 @@ case 7: {
   const int32_t tmp1 = *signed_arg1 - signed_arg2;
   SF = (tmp1 < 0);
   ZF = (tmp1 == 0);
-  const int64_t tmp2 = *signed_arg1 - signed_arg2;
+  const int64_t tmp2 = static_cast<int64_t>(*signed_arg1) - signed_arg2;
   OF = (tmp1 != tmp2);
   trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
   break;