diff --git a/subx/021byte_addressing.cc b/subx/021byte_addressing.cc index cffc4050..fba9a827 100644 --- a/subx/021byte_addressing.cc +++ b/subx/021byte_addressing.cc @@ -48,7 +48,7 @@ put_new(Name, "88", "copy r8 to r8/m8-at-r32"); 88 18 # copy BL to the byte at *EAX # ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX) == 0x2000 -f0 cc bb aa # 0xf0 with more data in following bytes +f0 cc bb aa +run: copy BL to r8/m8-at-r32 +run: effective address is 0x00002000 (EAX) +run: storing 0xab @@ -114,3 +114,39 @@ case 0x8a: { // copy r/m8 to r8 +run: storing 0x44 # ensure ESI is unchanged % CHECK_EQ(Reg[ESI].u, 0xaabbccdd); + +//: + +:(before "End Initialize Op Names") +put_new(Name, "c6", "copy imm8 to r8/m8-at-r32 (mov)"); + +:(scenario copy_imm8_to_mem_at_r32) +% Reg[EAX].i = 0x2000; +== 0x1 +# op ModR/M SIB displacement immediate + c6 00 dd # copy to the byte at *EAX +# ModR/M in binary: 00 (indirect mode) 000 (unused) 000 (dest EAX) +== 0x2000 +f0 cc bb aa ++run: copy imm8 to r8/m8-at-r32 ++run: effective address is 0x00002000 (EAX) ++run: storing 0xdd +% CHECK_EQ(0xaabbccdd, read_mem_u32(0x2000)); + +:(before "End Single-Byte Opcodes") +case 0xc6: { // copy imm8 to r/m8 + const uint8_t modrm = next(); + const uint8_t src = next(); + trace(90, "run") << "copy imm8 to r8/m8-at-r32" << end(); + trace(90, "run") << "imm8 is 0x" << HEXWORD << src << end(); + const uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits + if (subop != 0) { + cerr << "unrecognized subop for opcode c6: " << NUM(subop) << " (only 0/copy currently implemented)\n"; + exit(1); + } + // use unsigned to zero-extend 8-bit value to 32 bits + uint8_t* dest = reinterpret_cast(effective_byte_address(modrm)); + *dest = src; + trace(90, "run") << "storing 0x" << HEXBYTE << NUM(*dest) << end(); + break; +} diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc index 1038bca9..4fd500fa 100644 --- a/subx/031check_operands.cc +++ b/subx/031check_operands.cc @@ -228,6 +228,7 @@ void init_permitted_operands() { // imm32 imm8 disp32 |disp16 disp8 subop modrm // 0 1 0 |0 0 1 1 put(Permitted_operands, "c1", 0x23); // combine + put(Permitted_operands, "c6", 0x23); // copy //// Class P: op, ModR/M, subop (not r32) and imm32 // imm32 imm8 disp32 |disp16 disp8 subop modrm diff --git a/subx/056write.subx b/subx/056write.subx index 395d33b5..8f5de6e9 100644 --- a/subx/056write.subx +++ b/subx/056write.subx @@ -107,9 +107,9 @@ $clear-stream:loop: 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX with ECX 7d/jump-if-greater-or-equal $clear-stream:end/disp8 # *EAX = 0 - c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX - # EAX += 4 - 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX + c6 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm8 # copy byte to *EAX + # ++EAX + 40/increment-EAX eb/jump $clear-stream:loop/disp8 $clear-stream:end: # . restore registers diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 5a28117c..efb462ec 100755 Binary files a/subx/apps/crenshaw2-1 and b/subx/apps/crenshaw2-1 differ diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index 46a26183..e6dceafa 100755 Binary files a/subx/apps/crenshaw2-1b and b/subx/apps/crenshaw2-1b differ diff --git a/subx/apps/factorial b/subx/apps/factorial index 679feb71..ac02aca4 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index 7bc762e4..17cdcc8f 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/hex b/subx/apps/hex index 93c9f27f..8680176c 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ