about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/012direct_addressing.cc26
-rw-r--r--subx/022check_instruction.cc5
2 files changed, 31 insertions, 0 deletions
diff --git a/subx/012direct_addressing.cc b/subx/012direct_addressing.cc
index 43b1137b..aefe3214 100644
--- a/subx/012direct_addressing.cc
+++ b/subx/012direct_addressing.cc
@@ -87,6 +87,32 @@ case 0x29: {  // subtract r32 from r/m32
   break;
 }
 
+//:: multiply
+
+:(before "End Initialize Op Names(name)")
+put(name_0f, "af", "multiply r32 into rm32");
+
+:(scenario multiply_r32_into_r32)
+% Reg[EAX].i = 4;
+% Reg[EBX].i = 2;
+== 0x1
+# op      ModR/M  SIB   displacement  immediate
+  0f af   d8                                      # subtract EBX into EAX
+# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
++run: multiply EBX into r/m32
++run: r/m32 is EAX
++run: storing 0x00000008
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0xaf: {  // multiply r32 into r/m32
+  uint8_t modrm = next();
+  uint8_t arg2 = (modrm>>3)&0x7;
+  trace(90, "run") << "multiply " << rname(arg2) << " into r/m32" << end();
+  int32_t* arg1 = effective_address(modrm);
+  BINARY_ARITHMETIC_OP(*, *arg1, Reg[arg2].i);
+  break;
+}
+
 //:: and
 
 :(before "End Initialize Op Names(name)")
diff --git a/subx/022check_instruction.cc b/subx/022check_instruction.cc
index 31834b38..a4a4ec14 100644
--- a/subx/022check_instruction.cc
+++ b/subx/022check_instruction.cc
@@ -558,6 +558,11 @@ put(Permitted_operands_0f, "8d", 0x08);
 put(Permitted_operands_0f, "8e", 0x08);
 put(Permitted_operands_0f, "8f", 0x08);
 
+//// Class M: using ModR/M byte
+//  imm32 imm8  disp32 |disp16  disp8 subop modrm
+//  0     0     0      |0       0     0     1
+put(Permitted_operands_0f, "af", 0x01);
+
 :(code)
 void check_operands_0f(const line& inst, const word& op) {
   uint8_t expected_bitvector = get(Permitted_operands_0f, op.data);