about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/022div.cc38
-rw-r--r--subx/031check_operands.cc2
2 files changed, 40 insertions, 0 deletions
diff --git a/subx/022div.cc b/subx/022div.cc
new file mode 100644
index 00000000..0498d7ee
--- /dev/null
+++ b/subx/022div.cc
@@ -0,0 +1,38 @@
+//: helper for division operations: sign-extend EAX into EDX
+
+:(before "End Initialize Op Names")
+put_new(Name, "99", "sign-extend EAX into EDX (cdq)");
+
+:(code)
+void test_cdq() {
+  Reg[EAX].i = 10;
+  run(
+      "== 0x1\n"  // code segment
+      "99\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "run: sign-extend EAX into EDX\n"
+      "run: EDX is now 0x00000000\n"
+  );
+}
+
+:(before "End Single-Byte Opcodes")
+case 0x99: {  // sign-extend EAX into EDX
+  trace(Callstack_depth+1, "run") << "sign-extend EAX into EDX" << end();
+  Reg[EDX].i = (Reg[EAX].i < 0) ? -1 : 0;
+  trace(Callstack_depth+1, "run") << "EDX is now 0x" << HEXWORD << Reg[EDX].u << end();
+  break;
+}
+
+:(code)
+void test_cdq_negative() {
+  Reg[EAX].i = -10;
+  run(
+      "== 0x1\n"  // code segment
+      "99\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "run: sign-extend EAX into EDX\n"
+      "run: EDX is now 0xffffffff\n"
+  );
+}
diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc
index 475cda5c..9590979f 100644
--- a/subx/031check_operands.cc
+++ b/subx/031check_operands.cc
@@ -141,6 +141,8 @@ void init_permitted_operands() {
   put(Permitted_operands, "5d", 0x00);
   put(Permitted_operands, "5e", 0x00);
   put(Permitted_operands, "5f", 0x00);
+  // sign-extend EAX into EDX
+  put(Permitted_operands, "99", 0x00);
   // return
   put(Permitted_operands, "c3", 0x00);