diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2017-10-12 21:38:02 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2017-10-12 21:38:02 -0700 |
commit | bdcb8015d4bd32eaa6f3e21554afcae426b571a5 (patch) | |
tree | 8e9b86379b9d8c533829f6d28ba1625a17240bd1 /subx | |
parent | d4df57d62a51e26f81f2c6552c1b7b14ff38fe1f (diff) | |
download | mu-bdcb8015d4bd32eaa6f3e21554afcae426b571a5.tar.gz |
4040
subx: add immediate First example of a more complex opcode that needs to do its own decoding to decide what instruction to run.
Diffstat (limited to 'subx')
-rw-r--r-- | subx/010core.cc | 4 | ||||
-rw-r--r-- | subx/011add.cc | 36 |
2 files changed, 37 insertions, 3 deletions
diff --git a/subx/010core.cc b/subx/010core.cc index 2816f559..61ae583e 100644 --- a/subx/010core.cc +++ b/subx/010core.cc @@ -40,7 +40,7 @@ SF = ZF = OF = false; /* arg1 and arg2 must be signed */ \ int64_t tmp = arg1 op arg2; \ arg1 = arg1 op arg2; \ - trace(2, "run") << "storing 0x" << std::hex << arg1 << end(); \ + trace(2, "run") << "storing 0x" << HEXWORD << arg1 << end(); \ SF = (arg1 < 0); \ ZF = (arg1 == 0); \ OF = (arg1 != tmp); \ @@ -49,7 +49,7 @@ SF = ZF = OF = false; #define BINARY_BITWISE_OP(op, arg1, arg2) { \ /* arg1 and arg2 must be unsigned */ \ arg1 = arg1 op arg2; \ - trace(2, "run") << "storing 0x" << std::hex << arg1 << end(); \ + trace(2, "run") << "storing 0x" << HEXWORD << arg1 << end(); \ SF = (arg1 >> 31); \ ZF = (arg1 == 0); \ OF = false; \ diff --git a/subx/011add.cc b/subx/011add.cc index 836b227b..03e25c07 100644 --- a/subx/011add.cc +++ b/subx/011add.cc @@ -7,7 +7,7 @@ 01 18 # add EBX (reg 3) to *EAX (reg 0) +run: add reg 3 to effective address +run: effective address is mem at address 0x60 (reg 0) -+run: storing 0x11 ++run: storing 0x00000011 :(before "End Single-Byte Opcodes") case 0x01: { // add r32 to r/m32 @@ -47,3 +47,37 @@ int32_t* effective_address(uint8_t modrm) { } return result; } + +:(scenario add_imm32_to_rm32) +% Reg[3].i = 1; +# op ModRM SIB displacement immediate + 81 c3 0a 0b 0c 0d # add 0x0d0c0b0a to EBX (reg 3) ++run: add imm32 0x0d0c0b0a to effective address ++run: effective address is reg 3 ++run: storing 0x0d0c0b0b + +:(before "End Single-Byte Opcodes") +case 0x81: { // combine imm32 with r/m32 + uint8_t modrm = next(); + int32_t arg2 = imm32(); + trace(2, "run") << "add imm32 0x" << HEXWORD << arg2 << " to effective address" << end(); + int32_t* arg1 = effective_address(modrm); + uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits + switch (subop) { + case 0: + BINARY_ARITHMETIC_OP(+, *arg1, arg2); + break; + // End Op 81 Subops + default: + cerr << "unrecognized sub-opcode after 81: " << NUM(subop) << '\n'; + exit(1); + } + break; +} + +:(before "End Mod Special-cases") +case 3: + // mod 3 is just register direct addressing + trace(2, "run") << "effective address is reg " << NUM(rm) << end(); + result = &Reg[rm].i; + break; |