diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-12-03 23:26:56 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-12-03 23:26:56 -0800 |
commit | 5f3b3e7aea4174f13da9b430538564c68257b647 (patch) | |
tree | 64b0ca70a7508aa10a008ad7d996f5d4f38214c8 /subx/013direct_addressing.cc | |
parent | ee73f5eb31e9dd5a185da097bd990ac94c3d282b (diff) | |
download | mu-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/013direct_addressing.cc')
-rw-r--r-- | subx/013direct_addressing.cc | 160 |
1 files changed, 159 insertions, 1 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc index 8d9f0555..c18b5f5c 100644 --- a/subx/013direct_addressing.cc +++ b/subx/013direct_addressing.cc @@ -117,7 +117,7 @@ put_new(Name, "f7", "negate/multiply rm32 (with EAX if necessary) depending on s +run: storing 0x0000000c :(before "End Single-Byte Opcodes") -case 0xf7: { // xor r32 with r/m32 +case 0xf7: { const uint8_t modrm = next(); trace(90, "run") << "operate on r/m32" << end(); int32_t* arg1 = effective_address(modrm); @@ -209,6 +209,164 @@ case 3: { // negate r/m32 +run: subop: negate +run: overflow +//:: shift left + +:(before "End Initialize Op Names") +put_new(Name, "d3", "shift rm32 by CL bits depending on subop (sal/sar/shl/shr)"); + +:(scenario shift_left_r32_with_cl) +% Reg[EBX].i = 13; +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 e3 # 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 0xd3: { + 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 = Reg[ECX].u & 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 d3 Subops + default: + cerr << "unrecognized sub-opcode after d3: " << NUM(subop) << '\n'; + exit(1); + } + break; +} + +//:: shift right arithmetic + +:(scenario shift_right_arithmetic_r32_with_cl) +% Reg[EBX].i = 26; +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 fb # 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 d3 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 = Reg[ECX].u & 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_cl) +% Reg[EBX].i = 27; +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 fb # 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_cl) +% Reg[EBX].i = 0xfffffffd; // -3 +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 fb # 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_cl) +% Reg[EBX].i = 26; +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 eb # 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 d3 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 = Reg[ECX].u & 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_cl) +% Reg[EBX].i = 27; +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 eb # 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_cl) +% Reg[EBX].i = 0xfffffffd; +% Reg[ECX].i = 1; +== 0x1 +# op ModR/M SIB displacement immediate + d3 eb # 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") |