diff options
author | Kartik Agaram <vc@akkartik.com> | 2019-05-13 10:54:42 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2019-05-13 10:54:42 -0700 |
commit | 40f4f1b454a3510c35dfa41db1dff323793ec895 (patch) | |
tree | 27543d94ec167d626bcc071671d6e95fe063abb3 /subx | |
parent | 97ef7c4362b40609ec1c4881d2dedc58a9f12c41 (diff) | |
download | mu-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.cc | 13 | ||||
-rw-r--r-- | subx/014indirect_addressing.cc | 21 | ||||
-rw-r--r-- | subx/015immediate_addressing.cc | 72 |
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; |