diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-09-21 16:02:50 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-09-21 16:03:31 -0700 |
commit | 45967d2106335dbd595cb43ae5732ba88b5d0553 (patch) | |
tree | 49b750a77571037df44967f8c14a1a8553e8205c | |
parent | bd9f6d0cd069f3504c1825c6b25c7149c13ff57a (diff) | |
download | mu-45967d2106335dbd595cb43ae5732ba88b5d0553.tar.gz |
4578 - subx: implement inc/dec operations
-rw-r--r-- | subx/013direct_addressing.cc | 121 | ||||
-rw-r--r-- | subx/014indirect_addressing.cc | 23 | ||||
-rw-r--r-- | subx/031check_operands.cc | 18 | ||||
-rw-r--r-- | subx/opcodes | 18 |
4 files changed, 162 insertions, 18 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc index 2fb5c361..0ddb1ce8 100644 --- a/subx/013direct_addressing.cc +++ b/subx/013direct_addressing.cc @@ -370,6 +370,127 @@ case 0x87: { // exchange r32 with r/m32 break; } +//:: increment + +:(before "End Initialize Op Names(name)") +put(name, "40", "increment R0 (EAX)"); +put(name, "41", "increment R1 (ECX)"); +put(name, "42", "increment R2 (EDX)"); +put(name, "43", "increment R3 (EBX)"); +put(name, "44", "increment R4 (ESP)"); +put(name, "45", "increment R5 (EBP)"); +put(name, "46", "increment R6 (ESI)"); +put(name, "47", "increment R7 (EDI)"); + +:(scenario increment_r32) +% Reg[ECX].u = 0x1f; +== 0x1 # code segment +# op ModR/M SIB displacement immediate + 41 # increment ECX ++run: increment ECX ++run: storing value 0x00000020 + +:(before "End Single-Byte Opcodes") +case 0x40: +case 0x41: +case 0x42: +case 0x43: +case 0x44: +case 0x45: +case 0x46: +case 0x47: { // increment r32 + uint8_t reg = op & 0x7; + trace(90, "run") << "increment " << rname(reg) << end(); + ++Reg[reg].u; + trace(90, "run") << "storing value 0x" << HEXWORD << Reg[reg].u << end(); + break; +} + +:(before "End Initialize Op Names(name)") +put(name, "ff", "inc/dec/jump/push/call rm32 based on subop"); + +:(scenario increment_rm32) +% Reg[EAX].u = 0x20; +== 0x1 # code segment +# op ModR/M SIB displacement immediate + ff c0 # increment EAX +# ModR/M in binary: 11 (direct mode) 000 (subop inc) 000 (EAX) ++run: increment r/m32 ++run: r/m32 is EAX ++run: storing value 0x00000021 + +:(before "End Single-Byte Opcodes") +case 0xff: { + uint8_t modrm = next(); + uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits + switch (subop) { + case 0: { // increment r/m32 + trace(90, "run") << "increment r/m32" << end(); + int32_t* arg = effective_address(modrm); + ++*arg; + trace(90, "run") << "storing value 0x" << HEXWORD << *arg << end(); + break; + } + // End Op ff Subops + } + break; +} + +//:: decrement + +:(before "End Initialize Op Names(name)") +put(name, "48", "decrement R0 (EAX)"); +put(name, "49", "decrement R1 (ECX)"); +put(name, "4a", "decrement R2 (EDX)"); +put(name, "4b", "decrement R3 (EBX)"); +put(name, "4c", "decrement R4 (ESP)"); +put(name, "4d", "decrement R5 (EBP)"); +put(name, "4e", "decrement R6 (ESI)"); +put(name, "4f", "decrement R7 (EDI)"); + +:(scenario decrement_r32) +% Reg[ECX].u = 0x1f; +== 0x1 # code segment +# op ModR/M SIB displacement immediate + 49 # decrement ECX ++run: decrement ECX ++run: storing value 0x0000001e + +:(before "End Single-Byte Opcodes") +case 0x48: +case 0x49: +case 0x4a: +case 0x4b: +case 0x4c: +case 0x4d: +case 0x4e: +case 0x4f: { // decrement r32 + uint8_t reg = op & 0x7; + trace(90, "run") << "decrement " << rname(reg) << end(); + --Reg[reg].u; + trace(90, "run") << "storing value 0x" << HEXWORD << Reg[reg].u << end(); + break; +} + +:(scenario decrement_rm32) +% Reg[EAX].u = 0x20; +== 0x1 # code segment +# op ModR/M SIB displacement immediate + ff c8 # decrement EAX +# ModR/M in binary: 11 (direct mode) 001 (subop inc) 000 (EAX) ++run: decrement r/m32 ++run: r/m32 is EAX ++run: storing value 0x0000001f + +:(before "End Op ff Subops") +case 1: { // decrement r/m32 + trace(90, "run") << "decrement r/m32" << end(); + int32_t* arg = effective_address(modrm); + --*arg; + trace(90, "run") << "storing value 0x" << HEXWORD << *arg << end(); + break; +} + //:: push :(before "End Initialize Op Names(name)") diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc index 3a7bd3b6..9142728a 100644 --- a/subx/014indirect_addressing.cc +++ b/subx/014indirect_addressing.cc @@ -443,9 +443,6 @@ case 0x8a: { // copy r/m8 to r8 //:: jump -:(before "End Initialize Op Names(name)") -put(name, "ff", "jump/push/call rm32 based on subop"); - :(scenario jump_mem_at_r32) % Reg[EAX].i = 0x60; == 0x1 # code segment @@ -463,20 +460,12 @@ put(name, "ff", "jump/push/call rm32 based on subop"); +run: inst: 0x00000008 -run: inst: 0x00000003 -:(before "End Single-Byte Opcodes") -case 0xff: { - uint8_t modrm = next(); - uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits - switch (subop) { - case 4: { // jump to r/m32 - trace(90, "run") << "jump to r/m32" << end(); - int32_t* arg2 = effective_address(modrm); - EIP = *arg2; - trace(90, "run") << "jumping to 0x" << HEXWORD << EIP << end(); - break; - } - // End Op ff Subops - } +:(before "End Op ff Subops") +case 4: { // jump to r/m32 + trace(90, "run") << "jump to r/m32" << end(); + int32_t* arg2 = effective_address(modrm); + EIP = *arg2; + trace(90, "run") << "jumping to 0x" << HEXWORD << EIP << end(); break; } diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc index c56761ed..5f99f7b0 100644 --- a/subx/031check_operands.cc +++ b/subx/031check_operands.cc @@ -98,6 +98,24 @@ void init_permitted_operands() { //// Class A: just op, no operands // halt put(Permitted_operands, "f4", 0x00); + // inc + put(Permitted_operands, "40", 0x00); + put(Permitted_operands, "41", 0x00); + put(Permitted_operands, "42", 0x00); + put(Permitted_operands, "43", 0x00); + put(Permitted_operands, "44", 0x00); + put(Permitted_operands, "45", 0x00); + put(Permitted_operands, "46", 0x00); + put(Permitted_operands, "47", 0x00); + // dec + put(Permitted_operands, "48", 0x00); + put(Permitted_operands, "49", 0x00); + put(Permitted_operands, "4a", 0x00); + put(Permitted_operands, "4b", 0x00); + put(Permitted_operands, "4c", 0x00); + put(Permitted_operands, "4d", 0x00); + put(Permitted_operands, "4e", 0x00); + put(Permitted_operands, "4f", 0x00); // push put(Permitted_operands, "50", 0x00); put(Permitted_operands, "51", 0x00); diff --git a/subx/opcodes b/subx/opcodes index 77630208..41f2e65d 100644 --- a/subx/opcodes +++ b/subx/opcodes @@ -17,6 +17,22 @@ Opcodes currently supported by SubX: 39: compare: set SF if rm32 < r32 3b: compare: set SF if r32 < rm32 3d: compare: set SF if R0 < imm32 + 40: increment R0 (EAX) + 41: increment R1 (ECX) + 42: increment R2 (EDX) + 43: increment R3 (EBX) + 44: increment R4 (ESP) + 45: increment R5 (EBP) + 46: increment R6 (ESI) + 47: increment R7 (EDI) + 48: decrement R0 (EAX) + 49: decrement R1 (ECX) + 4a: decrement R2 (EDX) + 4b: decrement R3 (EBX) + 4c: decrement R4 (ESP) + 4d: decrement R5 (EBP) + 4e: decrement R6 (ESI) + 4f: decrement R7 (EDI) 50: push R0 (EAX) to stack 51: push R1 (ECX) to stack 52: push R2 (EDX) to stack @@ -63,7 +79,7 @@ Opcodes currently supported by SubX: eb: jump disp8 bytes away f4: halt f7: bitwise complement of rm32 - ff: jump/push/call rm32 based on subop + ff: inc/dec/jump/push/call rm32 based on subop 0f 84: jump disp16 bytes away if ZF is set 0f 85: jump disp16 bytes away if ZF is not set 0f 8c: jump disp16 bytes away if lesser (SF != OF) |