about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-09-22 23:19:39 -0700
committerKartik Agaram <vc@akkartik.com>2018-09-22 23:19:39 -0700
commit7d4e351a0d1e3c4e71b58d3218b4e6b833f542f2 (patch)
tree8f8b8e62848b76ce5debf3ef89ad6f0e1c381de8
parent2b36eee9b13eb16fb2e4b05d7e26f6d09f431912 (diff)
downloadmu-7d4e351a0d1e3c4e71b58d3218b4e6b833f542f2.tar.gz
4503
Include LEA (load effective address) in the SubX subset of x86 ISA.
-rw-r--r--subx/013direct_addressing.cc18
-rw-r--r--subx/014indirect_addressing.cc23
-rw-r--r--subx/031check_operands.cc2
-rwxr-xr-xsubx/examples/ex5bin138 -> 139 bytes
-rw-r--r--subx/examples/ex5.subx7
-rwxr-xr-xsubx/examples/ex8bin149 -> 143 bytes
-rw-r--r--subx/examples/ex8.subx6
7 files changed, 42 insertions, 14 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc
index 0ddb1ce8..7b265a44 100644
--- a/subx/013direct_addressing.cc
+++ b/subx/013direct_addressing.cc
@@ -32,19 +32,31 @@ int32_t* effective_address(uint8_t modrm) {
   uint8_t mod = (modrm>>6);
   // ignore middle 3 'reg opcode' bits
   uint8_t rm = modrm & 0x7;
+  if (mod == 3) {
+    // mod 3 is just register direct addressing
+    trace(90, "run") << "r/m32 is " << rname(rm) << end();
+    return &Reg[rm].i;
+  }
+  return mem_addr_i32(effective_address_number(modrm));
+}
+
+uint32_t effective_address_number(uint8_t modrm) {
+  uint8_t mod = (modrm>>6);
+  // ignore middle 3 'reg opcode' bits
+  uint8_t rm = modrm & 0x7;
   uint32_t addr = 0;
   switch (mod) {
   case 3:
     // mod 3 is just register direct addressing
-    trace(90, "run") << "r/m32 is " << rname(rm) << end();
-    return &Reg[rm].i;
+    raise << "unexpected direct addressing mode\n" << end();
+    return 0;
   // End Mod Special-cases(addr)
   default:
     cerr << "unrecognized mod bits: " << NUM(mod) << '\n';
     exit(1);
   }
   //: other mods are indirect, and they'll set addr appropriately
-  return mem_addr_i32(addr);
+  return addr;
 }
 
 string rname(uint8_t r) {
diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc
index ccbf994c..b48cbd85 100644
--- a/subx/014indirect_addressing.cc
+++ b/subx/014indirect_addressing.cc
@@ -641,3 +641,26 @@ case 2:  // indirect + disp32 addressing
 +run: effective address is initially 0x61 (EAX)
 +run: effective address is 0x60 (after adding disp32)
 +run: storing 0x00000011
+
+//:: lea
+
+:(before "End Initialize Op Names(name)")
+put(name, "8d", "load effective address of memory in rm32 into r32");
+
+:(scenario lea)
+% Reg[EAX].u = 0x60;
+== 0x1
+# op  ModR/M  SIB   displacement  immediate
+  8d  18
+# ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX)
++run: lea into EBX
++run: effective address is 0x60 (EAX)
+
+:(before "End Single-Byte Opcodes")
+case 0x8d: {  // lea m32 to r32
+  uint8_t modrm = next();
+  uint8_t arg1 = (modrm>>3)&0x7;
+  trace(90, "run") << "lea into " << rname(arg1) << end();
+  Reg[arg1].u = effective_address_number(modrm);
+  break;
+}
diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc
index 5f99f7b0..f24eb62c 100644
--- a/subx/031check_operands.cc
+++ b/subx/031check_operands.cc
@@ -214,6 +214,8 @@ void init_permitted_operands() {
   put(Permitted_operands, "8b", 0x01);
   // swap
   put(Permitted_operands, "87", 0x01);
+  // lea
+  put(Permitted_operands, "8d", 0x01);
   // pop
   put(Permitted_operands, "8f", 0x01);
 
diff --git a/subx/examples/ex5 b/subx/examples/ex5
index 536ddcd6..906846db 100755
--- a/subx/examples/ex5
+++ b/subx/examples/ex5
Binary files differdiff --git a/subx/examples/ex5.subx b/subx/examples/ex5.subx
index faecdcfb..51bc19a0 100644
--- a/subx/examples/ex5.subx
+++ b/subx/examples/ex5.subx
@@ -10,9 +10,6 @@
 # 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
 
 # main:
-  # prolog
-  55/push-EBP
-  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
   # allocate x on the stack
   81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # subtract 4 bytes from ESP
 
@@ -20,7 +17,7 @@
     # fd = 0 (stdin)
   bb/copy                         .               .             .           .             .           .           .               0/imm32           # copy 0 to EBX
     # initialize x (location to write result to)
-  89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           5/r32/EBP   .               .                 # copy EBP to ECX
+  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              1/r32/ECX   4/disp8         .                 # copy ESP+4 to ECX
     # size = 1 character
   ba/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EDX
     # read(fd, x, size)
@@ -31,7 +28,7 @@
     # fd = 1 (stdout)
   bb/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EBX
     # initialize x (location to read from)
-  89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           5/r32/EBP   .               .                 # copy EBP to ECX
+  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              1/r32/ECX   4/disp8         .                 # copy ESP+4 to ECX
     # size = 1 character
   ba/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EDX
     # write(fd, x, size)
diff --git a/subx/examples/ex8 b/subx/examples/ex8
index c0aa5806..463f83b8 100755
--- a/subx/examples/ex8
+++ b/subx/examples/ex8
Binary files differdiff --git a/subx/examples/ex8.subx b/subx/examples/ex8.subx
index 8d9efcd7..fb35dc7e 100644
--- a/subx/examples/ex8.subx
+++ b/subx/examples/ex8.subx
@@ -21,18 +21,12 @@
   # var s = argv[1] (EBX)
   8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              3/r32/EBX   8/disp8         .                       # copy *(ESP+8) to EBX
   # call ascii_length(EBX)
-    # prepare call
-  55/push-EBP
-  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                       # copy ESP to EBP
     # push args
   53/push-EBX
     # call
   e8/call  ascii_length/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32                 # add 4 to ESP
-    # clean up after call
-  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                       # copy EBP to ESP
-  5d/pop-to-EBP
 
   # exit(EAX)
   89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                       # copy EAX to EBX