about summary refs log tree commit diff stats
path: root/apps/sigils.subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-08-31 22:14:11 -0700
committerKartik Agaram <vc@akkartik.com>2019-08-31 22:14:11 -0700
commit3046e34da8fc798fc3d340b1356c231d37d26fdf (patch)
tree9d570a13fdb3ae4e9eaf0c8d08027cd0e397562a /apps/sigils.subx
parente97b446ac3023d39d190911074850e686aa5f3aa (diff)
downloadmu-3046e34da8fc798fc3d340b1356c231d37d26fdf.tar.gz
5595 - support ebp and esp in sigils
The x86 instruction set carves out exceptions for these registers.
Diffstat (limited to 'apps/sigils.subx')
-rw-r--r--apps/sigils.subx173
1 files changed, 173 insertions, 0 deletions
diff --git a/apps/sigils.subx b/apps/sigils.subx
index 40be4f98..828fc2e6 100644
--- a/apps/sigils.subx
+++ b/apps/sigils.subx
@@ -35,6 +35,10 @@
 #
 # No metadata allowed inside '*(...)'.
 # Whitespace inside '*(...)' is ok. But not immediately after the '*' or '%'.
+#
+# The code generated is sub-optimal:
+#   - displacements are always disp32, even when disp8 will do
+#   - *(...esp...) always uses SIB arguments even when redundant
 
 == code
 #   instruction                     effective address                                                   register    displacement    immediate
@@ -2857,13 +2861,24 @@ test-parse-effective-address-base-index-scale-displacement:
     c3/return
 
 # Code generation:
+#   if base is esp, then goto emit-sib
+#   if base is ebp, then goto emit-sib
 #   if index is none and disp is 0, then mod = 0 and rm32 = base
 #   if index is none, then mod = 2 and rm32 = base and disp32 = disp
+# emit-sib:
 #   if index is not none, then mod = 2 and rm32 = 4 and base = base and index = index and disp32 = disp
 emit-indirect-mode:  # out : (address buffered-file), base : int, index : int, scale : int, disp : int
     # . prolog
     55/push-ebp
     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+$emit-indirect-mode:check-for-ebp:
+    # if (base == 5) goto emit-sib
+    81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       5/imm32           # compare *(ebp+12)
+    74/jump-if-equal  $emit-indirect-mode:emit-sib/disp8
+$emit-indirect-mode:check-for-esp:
+    # if (base == 4) goto emit-sib
+    81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       4/imm32           # compare *(ebp+12)
+    74/jump-if-equal  $emit-indirect-mode:emit-sib/disp8
 $emit-indirect-mode:check-for-sib:
     # if (index == 4/none) goto next check
     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      4/imm32           # compare *(ebp+16)
@@ -3417,6 +3432,164 @@ test-emit-indirect-mode-with-sib:
     5d/pop-to-ebp
     c3/return
 
+test-emit-indirect-mode-ebp:
+    # . prolog
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # setup
+    # . clear-stream(_test-output-stream)
+    # . . push args
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  clear-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # . clear-stream(_test-output-buffered-file+4)
+    # . . push args
+    b8/copy-to-eax  _test-output-buffered-file/imm32
+    05/add-to-eax  4/imm32
+    50/push-eax
+    # . . call
+    e8/call  clear-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # emit-indirect-mode(_test-output-buffered-file, 5/base, 0/index, 0/scale, 0/disp)
+    # . . write args
+    68/push  0/imm32/.disp
+    68/push  0/imm32/.scale
+    68/push  0/imm32/.index
+    68/push  5/imm32/.base/ebp
+    68/push  _test-output-buffered-file/imm32
+    # . . call
+    e8/call  emit-indirect-mode/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
+    # . flush(_test-output-buffered-file)
+    # . . push args
+    68/push  _test-output-buffered-file/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+#?     # dump output {{{
+#?     # . write(2/stderr, "^")
+#?     # . . push args
+#?     68/push  "^"/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+#?     # . write-stream(2/stderr, _test-output-stream)
+#?     # . . push args
+#?     68/push  _test-output-stream/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write-stream/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+#?     # . write(2/stderr, "$\n")
+#?     # . . push args
+#?     68/push  "$\n"/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+#?     # }}}
+    # check-stream-equal(_test-output-stream, "2/mod/*+disp32 4/rm32/sib 5/base/ebp 0/index 0/scale 0/disp32", msg)
+    # . . push args
+    68/push  "F - test-emit-indirect-mode-ebp"/imm32
+    68/push  "2/mod/*+disp32 4/rm32/sib 0x00000005/base 0x00000000/index 0x00000000/scale 0x00000000/disp32"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-stream-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+    5d/pop-to-ebp
+    c3/return
+
+test-emit-indirect-mode-esp:
+    # . prolog
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # setup
+    # . clear-stream(_test-output-stream)
+    # . . push args
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  clear-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # . clear-stream(_test-output-buffered-file+4)
+    # . . push args
+    b8/copy-to-eax  _test-output-buffered-file/imm32
+    05/add-to-eax  4/imm32
+    50/push-eax
+    # . . call
+    e8/call  clear-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # emit-indirect-mode(_test-output-buffered-file, 4/base, 0/index, 0/scale, 0/disp)
+    # . . write args
+    68/push  0/imm32/.disp
+    68/push  0/imm32/.scale
+    68/push  0/imm32/.index
+    68/push  4/imm32/.base/esp
+    68/push  _test-output-buffered-file/imm32
+    # . . call
+    e8/call  emit-indirect-mode/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
+    # . flush(_test-output-buffered-file)
+    # . . push args
+    68/push  _test-output-buffered-file/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+#?     # dump output {{{
+#?     # . write(2/stderr, "^")
+#?     # . . push args
+#?     68/push  "^"/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+#?     # . write-stream(2/stderr, _test-output-stream)
+#?     # . . push args
+#?     68/push  _test-output-stream/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write-stream/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+#?     # . write(2/stderr, "$\n")
+#?     # . . push args
+#?     68/push  "$\n"/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+#?     # }}}
+    # check-stream-equal(_test-output-stream, "2/mod/*+disp32 4/rm32/sib 4/base/ebp 0/index 0/scale 0/disp32", msg)
+    # . . push args
+    68/push  "F - test-emit-indirect-mode-esp"/imm32
+    68/push  "2/mod/*+disp32 4/rm32/sib 0x00000004/base 0x00000000/index 0x00000000/scale 0x00000000/disp32"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-stream-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+    5d/pop-to-ebp
+    c3/return
+
 # update line->read to ')'
 # line->read ends at ')'
 skip-until-close-paren:  # line : (address stream)