about summary refs log tree commit diff stats
path: root/apps/sigils.subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-09-01 23:22:39 -0700
committerKartik Agaram <vc@akkartik.com>2019-09-01 23:22:39 -0700
commitb44c754bc0bd8ee5f91d32217aa91146b1a30ecc (patch)
tree41f557be7b2e6f289affa97f9f39673e61ad94d9 /apps/sigils.subx
parent6165d6ece9e4fff02b2d170805b33cd3f2e617c5 (diff)
downloadmu-b44c754bc0bd8ee5f91d32217aa91146b1a30ecc.tar.gz
5605 - sigils: support *disp32
Diffstat (limited to 'apps/sigils.subx')
-rw-r--r--apps/sigils.subx245
1 files changed, 241 insertions, 4 deletions
diff --git a/apps/sigils.subx b/apps/sigils.subx
index c8e7d478..d7fcecc4 100644
--- a/apps/sigils.subx
+++ b/apps/sigils.subx
@@ -30,6 +30,10 @@
 #   $ echo '*(eax+ecx<<2+4)'  |  ./subx run apps/sigils
 #   2/mod 4/rm32 0/base 1/index 2/scale 4/disp32
 #
+# 7.
+#   $ echo '*Foo'  |  ./subx run apps/sigils
+#   0/mod 5/rm32/.disp32 Foo/disp32
+#
 # Addition isn't commutative here. Template must always be (base+index<<scale+disp),
 # though some components are optional as described above.
 #
@@ -114,8 +118,11 @@ convert:  # in : (address buffered-file), out : (address buffered-file) -> <void
     #       if slice-starts-with?(word-slice, '%')        # direct mode
     #         emit-direct-mode(out, word-slice)
     #       else if slice-starts-with?(word-slice, '*')   # indirect mode
-    #         base, index, scale, disp = parse-effective-address(word-slice)
-    #         emit-indirect-mode(out, base, index, scale, disp)
+    #         if disp32-mode?(word-slice)
+    #           emit-indirect-disp32(out, word-slice)
+    #         else
+    #           base, index, scale, disp = parse-effective-address(word-slice)
+    #           emit-indirect-mode(out, base, index, scale, disp)
     #       else if slice-starts-with?(word-slice, '+')
     #         abort("'+' only permitted within '*(...)'")
     #       else
@@ -258,6 +265,28 @@ $convert:check-for-indirect-mode:
     # if (!slice-starts-with?(word-slice, "*")) goto next check
     3d/compare-eax-and  0x2a/imm32/asterisk
     75/jump-if-not-equal  $convert:check-for-invalid-addition/disp8
+    # if (!disp32-mode?(word-slice)) goto indirect mode
+    # . eax = disp32-mode?(word-slice)
+    # . . push args
+    52/push-edx
+    # . . call
+    e8/call  disp32-mode?/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # . if (eax == 0) goto indirect mode
+    3d/compare-eax-and  0/imm32
+    74/jump-if-equal  $convert:indirect-mode/disp8
+$convert:disp32-mode:
+    # emit-indirect-mode(out, word-slice)
+    # . . push args
+    52/push-edx
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+    # . . call
+    e8/call  emit-indirect-disp32/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # continue
+    e9/jump  $convert:next-word/disp32
 $convert:indirect-mode:
     # spill registers
     50/push-eax
@@ -1272,6 +1301,108 @@ test-convert-register-indirect-mode-with-sib-byte-negative-displacement:
     5d/pop-to-ebp
     c3/return
 
+test-convert-indirect-mode-without-register:
+    # . prolog
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # setup
+    # . clear-stream(_test-input-stream)
+    # . . push args
+    68/push  _test-input-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-input-buffered-file+4)
+    # . . push args
+    b8/copy-to-eax  _test-input-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
+    # . 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
+    # initialize input
+    # . write(_test-input-stream, "ab *Foo")
+    # . . push args
+    68/push  "ab *Foo"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # convert(_test-input-buffered-file, _test-output-buffered-file)
+    # . . push args
+    68/push  _test-output-buffered-file/imm32
+    68/push  _test-input-buffered-file/imm32
+    # . . call
+    e8/call  convert/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # check that the line just passed through
+    # . 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 _test-output-stream {{{
+#?     # . 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, "ab 0/mod/indirect 5/rm32/.disp32 Foo/disp32 \n", msg)
+    # . . push args
+    68/push  "F - test-convert-indirect-mode-without-register"/imm32
+    68/push  "ab 0/mod/indirect 5/rm32/.disp32 Foo/disp32 \n"/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
+
 emit-direct-mode:  # out : (address buffered-file), word-slice : (address slice)
     # . prolog
     55/push-ebp
@@ -1283,7 +1414,7 @@ emit-direct-mode:  # out : (address buffered-file), word-slice : (address slice)
     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
     ff          6/subop/push        0/mod/indirect  0/rm32/eax    .           .             .           .           .               .                 # push *eax
     89/copy                         3/mod/direct    0/rm32/eax    .           .             .           4/r32/esp   .               .                 # copy esp to eax
-    # ++local-slice->start
+    # ++local-slice->start to skip '%'
     # . ++(*eax)
     ff          0/subop/increment   0/mod/indirect  0/rm32/eax    .           .             .           .           .               .                 # increment *eax
     # local-slice = next-token-from-slice(local-slice->start, local-slice->end, "/")
@@ -1314,7 +1445,7 @@ emit-direct-mode:  # out : (address buffered-file), word-slice : (address slice)
     e8/call  write-buffered/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-    # print-int32-buffered(out, *eax)
+    # print-int32-buffered(out, *reg-num)
     # . . push args
     ff          6/subop/push        0/mod/indirect  0/rm32/eax    .           .             .           .           .               .                 # push *eax
     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
@@ -3774,6 +3905,112 @@ test-emit-indirect-mode-esp:
     5d/pop-to-ebp
     c3/return
 
+disp32-mode?:  # in : (address slice) -> reg/eax : boolean
+    # . prolog
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # . save registers
+    56/push-esi
+    57/push-edi
+    # var local-slice/esi : (address slice) = {in->start, in->end}
+    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+    ff          6/subop/push        1/mod/*+disp8   6/rm32/esi    .           .             .           .           4/disp8         .                 # push *(esi+4)
+    ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
+    89/copy                         3/mod/direct    6/rm32/esi    .           .             .           4/r32/esp   .               .                 # copy esp to esi
+    # ++local-slice->start to skip '*'
+    ff          0/subop/increment   0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # increment *esi
+    # if (*local-slice->start == '(') return false
+    8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
+    8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           0/r32/AL    .               .                 # copy byte at *eax to AL
+    81          4/subop/and         3/mod/direct    0/rm32/eax    .           .             .           .           .               0xff/imm32        # bitwise and of eax
+    3d/compare-eax-and  0x28/imm32/open-paren
+    74/jump-if-equal  $disp32-mode?:false/disp8
+$disp32-mode?:check-for-register:
+    # local-slice = next-token-from-slice(local-slice->start, local-slice->end, "/")
+    # . . push args
+    56/push-esi
+    68/push  0x2f/imm32/slash
+    ff          6/subop/push        1/mod/*+disp8   6/rm32/esi    .           .             .           .           4/disp8         .                 # push *(esi+4)
+    ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
+    # . . call
+    e8/call  next-token-from-slice/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+    # reg-num/eax = maybe-get-slice(Registers, local-slice, row-size=8)
+    # . . push args
+    68/push  8/imm32/row-size
+    56/push-esi
+    68/push  Registers/imm32
+    # . . cal
+    e8/call  maybe-get-slice/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+    # if (eax != 0) return false
+    3d/compare-eax-and  0/imm32
+    75/jump-if-not-equal  $disp32-mode?:false/disp8
+    # return true
+    b8/copy-to-eax  1/imm32/true
+    eb/jump  $disp32-mode?:end/disp8
+$disp32-mode?:false:
+    b8/copy-to-eax  0/imm32/false
+$disp32-mode?:end:
+    # reclaim locals
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . restore registers
+    5f/pop-to-edi
+    5e/pop-to-esi
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+    5d/pop-to-ebp
+    c3/return
+
+emit-indirect-disp32:  # out : (address buffered-file), word-slice : (address slice)
+    # . prolog
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # . save registers
+    56/push-esi
+    # var local-slice/esi : (address slice) = {in->start, in->end}
+    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0xc/disp8       .                 # copy *(ebp+12) to esi
+    ff          6/subop/push        1/mod/*+disp8   6/rm32/esi    .           .             .           .           4/disp8         .                 # push *(esi+4)
+    ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
+    89/copy                         3/mod/direct    6/rm32/esi    .           .             .           4/r32/esp   .               .                 # copy esp to esi
+    # ++local-slice->start to skip '*'
+    ff          0/subop/increment   0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # increment *esi
+    # write-buffered(out, "0/mod/indirect 5/rm32/.disp32 ")
+    # . . push args
+    68/push  "0/mod/indirect 5/rm32/.disp32 "/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # write-slice-buffered(out, local-slice)
+    # . . push args
+    56/push-esi
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+    # . . call
+    e8/call  write-slice-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # write-buffered(out, "/disp32")
+    # . . push args
+    68/push  "/disp32"/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+$emit-indirect-disp32:end:
+    # reclaim locals
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . restore registers
+    5e/pop-to-esi
+    # . 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)