about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-05-13 07:53:31 -0700
committerKartik Agaram <vc@akkartik.com>2019-05-13 07:53:31 -0700
commit3f2c4fc564fc7169bb64107b5b7655d76c98204c (patch)
treeb3a72c5483e1f32a6d8c0b76511b4804085164bb /subx
parent63753f6e1dd3eb7abb638bf4db671b68c4adccb8 (diff)
downloadmu-3f2c4fc564fc7169bb64107b5b7655d76c98204c.tar.gz
.
Make the first instruction described something that doesn't touch flags,
so we don't introduce too much complexity all at once.
Diffstat (limited to 'subx')
-rw-r--r--subx/011run.cc44
-rw-r--r--subx/015immediate_addressing.cc26
2 files changed, 46 insertions, 24 deletions
diff --git a/subx/011run.cc b/subx/011run.cc
index ccc891c3..9c1bc4b0 100644
--- a/subx/011run.cc
+++ b/subx/011run.cc
@@ -65,19 +65,18 @@ void test_add_imm32_to_eax() {
       // opcode        ModR/M                    SIB                   displacement    immediate
       // instruction   mod, reg, Reg/Mem bits    scale, index, base
       // 1-3 bytes     0/1 byte                  0/1 byte              0/1/2/4 bytes   0/1/2/4 bytes
-      "  05            .                         .                     .               0a 0b 0c 0d\n"  // add 0x0d0c0b0a to EAX
+      "  b8            .                         .                     .               0a 0b 0c 0d\n"  // copy 0x0d0c0b0a to EAX
       // The periods are just to help the eye track long gaps between columns,
       // and are otherwise ignored.
   );
   // This program, when run, causes the following events in the trace:
   CHECK_TRACE_CONTENTS(
-      "load: 0x00000001 -> 05\n"
+      "load: 0x00000001 -> b8\n"
       "load: 0x00000002 -> 0a\n"
       "load: 0x00000003 -> 0b\n"
       "load: 0x00000004 -> 0c\n"
       "load: 0x00000005 -> 0d\n"
-      "run: add imm32 0x0d0c0b0a to reg EAX\n"
-      "run: storing 0x0d0c0b0a\n"
+      "run: copy imm32 0x0d0c0b0a to EAX\n"
   );
 }
 
@@ -350,30 +349,31 @@ void parse_and_load(const string& text_bytes) {
 //:: run
 
 :(before "End Initialize Op Names")
-put_new(Name, "05", "add imm32 to EAX (add)");
+put_new(Name, "b8", "copy imm32 to EAX (mov)");
 
-//: our first opcode
 :(before "End Single-Byte Opcodes")
-case 0x05: {  // add imm32 to EAX
-  int32_t signed_arg2 = next32();
-  trace(Callstack_depth+1, "run") << "add imm32 0x" << HEXWORD << signed_arg2 << " to reg EAX" << end();
-  int64_t signed_full_result = Reg[EAX].i + signed_arg2;
-  Reg[EAX].i += signed_arg2;
-  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[EAX].i << end();
-  SF = (Reg[EAX].i < 0);
-  ZF = (Reg[EAX].i == 0);
-  OF = (Reg[EAX].i != signed_full_result);
-  // set CF
-  uint32_t unsigned_arg1 = static_cast<uint32_t>(Reg[EAX].i);
-  uint32_t unsigned_arg2 = static_cast<uint32_t>(signed_arg2);
-  uint32_t unsigned_result = unsigned_arg1 + unsigned_arg2;
-  uint64_t unsigned_full_result = unsigned_arg1 + unsigned_arg2;
-  CF = (unsigned_result != unsigned_full_result);
-  trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
+case 0xb8: {  // copy imm32 to EAX
+  const int32_t src = next32();
+  trace(Callstack_depth+1, "run") << "copy imm32 0x" << HEXWORD << src << " to EAX" << end();
+  Reg[EAX].i = src;
   break;
 }
 
 :(code)
+void test_copy_imm32_to_EAX() {
+  run(
+      "== 0x1\n"  // code segment
+      // op     ModR/M  SIB   displacement  immediate
+      "  b8                                 0a 0b 0c 0d \n"  // copy 0x0d0c0b0a to EAX
+  );
+  CHECK_TRACE_CONTENTS(
+      "run: copy imm32 0x0d0c0b0a to EAX\n"
+  );
+}
+
+//: our first opcode
+
+:(code)
 // read a 32-bit int in little-endian order from the instruction stream
 int32_t next32() {
   int32_t result = read_mem_i32(EIP);
diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc
index 8a0ba020..f4762c2b 100644
--- a/subx/015immediate_addressing.cc
+++ b/subx/015immediate_addressing.cc
@@ -1,6 +1,29 @@
 //: instructions that (immediately) contain an argument to act with
 
 :(before "End Initialize Op Names")
+put_new(Name, "05", "add imm32 to EAX (add)");
+
+:(before "End Single-Byte Opcodes")
+case 0x05: {  // add imm32 to EAX
+  int32_t signed_arg2 = next32();
+  trace(Callstack_depth+1, "run") << "add imm32 0x" << HEXWORD << signed_arg2 << " to reg EAX" << end();
+  int64_t signed_full_result = Reg[EAX].i + signed_arg2;
+  Reg[EAX].i += signed_arg2;
+  trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[EAX].i << end();
+  SF = (Reg[EAX].i < 0);
+  ZF = (Reg[EAX].i == 0);
+  OF = (Reg[EAX].i != signed_full_result);
+  // set CF
+  uint32_t unsigned_arg1 = static_cast<uint32_t>(Reg[EAX].i);
+  uint32_t unsigned_arg2 = static_cast<uint32_t>(signed_arg2);
+  uint32_t unsigned_result = unsigned_arg1 + unsigned_arg2;
+  uint64_t unsigned_full_result = unsigned_arg1 + unsigned_arg2;
+  CF = (unsigned_result != unsigned_full_result);
+  trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end();
+  break;
+}
+
+:(before "End Initialize Op Names")
 put_new(Name, "81", "combine rm32 with imm32 based on subop (add/sub/and/or/xor/cmp)");
 
 :(code)
@@ -832,7 +855,7 @@ void test_compare_imm32_with_mem_at_r32_equal() {
 //:: copy (mov)
 
 :(before "End Initialize Op Names")
-put_new(Name, "b8", "copy imm32 to EAX (mov)");
+// b8 defined earlier to copy imm32 to EAX
 put_new(Name, "b9", "copy imm32 to ECX (mov)");
 put_new(Name, "ba", "copy imm32 to EDX (mov)");
 put_new(Name, "bb", "copy imm32 to EBX (mov)");
@@ -854,7 +877,6 @@ void test_copy_imm32_to_r32() {
 }
 
 :(before "End Single-Byte Opcodes")
-case 0xb8:
 case 0xb9:
 case 0xba:
 case 0xbb: