about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-06-14 00:24:47 -0700
committerKartik Agaram <vc@akkartik.com>2020-06-14 00:28:23 -0700
commitad61776f498e8117756e4794eac840fab60cfac6 (patch)
tree73510284e749eab8c207aecef90084d0a5c57101
parentead3d08e774529f3026f8cd6f93b8a0d7c87ed08 (diff)
downloadmu-ad61776f498e8117756e4794eac840fab60cfac6.tar.gz
6520 - new app: parse-int
Several bugs fixed in the process, and expectation of further bugs is growing.
I'd somehow started assuming I don't need to have separate cases for rm32
as a register vs mem. That's not right. We might need more reg-reg Primitives.
-rw-r--r--075print-int-decimal.subx61
-rwxr-xr-xapps/assortbin44233 -> 44392 bytes
-rwxr-xr-xapps/bracesbin46096 -> 46255 bytes
-rwxr-xr-xapps/callsbin50743 -> 50902 bytes
-rwxr-xr-xapps/crenshaw2-1bin43574 -> 43733 bytes
-rwxr-xr-xapps/crenshaw2-1bbin44121 -> 44280 bytes
-rwxr-xr-xapps/dquotesbin47855 -> 48014 bytes
-rwxr-xr-xapps/factorialbin42677 -> 42836 bytes
-rwxr-xr-xapps/hexbin46413 -> 46572 bytes
-rwxr-xr-xapps/mubin278754 -> 280373 bytes
-rw-r--r--apps/mu.subx187
-rwxr-xr-xapps/packbin56548 -> 56707 bytes
-rw-r--r--apps/parse-int.mu50
-rwxr-xr-xapps/sigilsbin58465 -> 58624 bytes
-rwxr-xr-xapps/surveybin54165 -> 54324 bytes
-rwxr-xr-xapps/testsbin43005 -> 43164 bytes
16 files changed, 290 insertions, 8 deletions
diff --git a/075print-int-decimal.subx b/075print-int-decimal.subx
index 62d9b6e0..38edd445 100644
--- a/075print-int-decimal.subx
+++ b/075print-int-decimal.subx
@@ -402,4 +402,65 @@ test-is-decimal-digit-above-9:
     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
     c3/return
 
+to-decimal-digit:  # in: byte -> out/eax: int
+    # . prologue
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # eax = in
+    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
+$to-decimal-digit:check0:
+    # if (eax < '0') goto abort
+    3d/compare-eax-with  0x30/imm32/0
+    7c/jump-if-<  $to-decimal-digit:abort/disp8
+$to-decimal-digit:check1:
+    # if (eax > '9') goto abort
+    3d/compare-eax-with  0x39/imm32/f
+    7f/jump-if->  $to-decimal-digit:abort/disp8
+$to-decimal-digit:digit:
+    # return eax - '0'
+    2d/subtract-from-eax  0x30/imm32/0
+$to-decimal-digit:end:
+    # . epilogue
+    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+    5d/pop-to-ebp
+    c3/return
+
+$to-decimal-digit:abort:
+    # . write-buffered(stderr, error)
+    # . . push args
+    68/push  "to-decimal-digit: not a digit character: "/imm32
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . write-byte-buffered(stderr, %eax)
+    # . . push args
+    50/push-eax
+    68/push  Stderr/imm32
+    # . . call
+#?     e8/call  write-byte-buffered/disp32
+    e8/call  print-int32-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . write-buffered(stderr, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . flush(Stderr)
+    # . . push args
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # . syscall(exit, 1)
+    bb/copy-to-ebx  1/imm32
+    e8/call  syscall_exit/disp32
+    # never gets here
+
 # . . vim:nowrap:textwidth=0
diff --git a/apps/assort b/apps/assort
index 37b188ee..f6b0c31d 100755
--- a/apps/assort
+++ b/apps/assort
Binary files differdiff --git a/apps/braces b/apps/braces
index d3111278..2254389c 100755
--- a/apps/braces
+++ b/apps/braces
Binary files differdiff --git a/apps/calls b/apps/calls
index 500c9009..1b3202f0 100755
--- a/apps/calls
+++ b/apps/calls
Binary files differdiff --git a/apps/crenshaw2-1 b/apps/crenshaw2-1
index 41429db7..104c787f 100755
--- a/apps/crenshaw2-1
+++ b/apps/crenshaw2-1
Binary files differdiff --git a/apps/crenshaw2-1b b/apps/crenshaw2-1b
index 81bbd4f7..ec4c777c 100755
--- a/apps/crenshaw2-1b
+++ b/apps/crenshaw2-1b
Binary files differdiff --git a/apps/dquotes b/apps/dquotes
index 90bcf0b3..7f935bb2 100755
--- a/apps/dquotes
+++ b/apps/dquotes
Binary files differdiff --git a/apps/factorial b/apps/factorial
index 79c0e8da..34a2c970 100755
--- a/apps/factorial
+++ b/apps/factorial
Binary files differdiff --git a/apps/hex b/apps/hex
index 794ce191..ebbafb6a 100755
--- a/apps/hex
+++ b/apps/hex
Binary files differdiff --git a/apps/mu b/apps/mu
index dc9ce88d..5b65cf19 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index 5b6d712f..3658f332 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -6138,6 +6138,7 @@ parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack live-var), out:
     {
       0f 84/jump-if-= break/disp32
       # TODO: disallow vars of type 'byte' in registers 'esi' or 'edi'
+      # TODO: vars of type 'byte' should only be initialized by clearing to 0
       # ensure that the next word is '<-'
       (next-mu-token *(ebp+8) %ecx)
       (slice-equal? %ecx "<-")  # => eax
@@ -7968,17 +7969,24 @@ compute-size-of-type-id:  # t: type-id -> result/eax: int
     89/<- %ecx 4/r32/esp
     # eax = t
     8b/-> *(ebp+8) 0/r32/eax
-    # if v is a literal, return 0
+    # if t is a literal, return 0
     3d/compare-eax-and 0/imm32/literal
-    74/jump-if-= $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
-    # if v is a byte, return 1
+    0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
+    # if t is a byte, return 1
+    3d/compare-eax-and 8/imm32/byte
     {
-      3d/compare-eax-and 8/imm32/byte
       75/jump-if-!= break/disp8
       b8/copy-to-eax 1/imm32
       eb/jump $compute-size-of-type-id:end/disp8
     }
-    # if v has a user-defined type, compute its size
+    # if t is a handle, return 8
+    3d/compare-eax-and 4/imm32/handle
+    {
+      75/jump-if-!= break/disp8
+      b8/copy-to-eax 8/imm32
+      eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
+    }
+    # if t is a user-defined type, compute its size
     # TODO: support non-atom type
     (find-typeinfo %eax %ecx)
     {
@@ -8490,7 +8498,14 @@ size-of-type-id:  # t: type-id -> result/eax: int
     8b/-> *(ebp+8) 0/r32/eax
     # if t is a literal, return 0
     3d/compare-eax-and 0/imm32
-    74/jump-if-= $size-of-type-id:end/disp8  # eax changes type from type-id to int
+    0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
+    # if v is a byte, return 1
+    3d/compare-eax-and 8/imm32/byte
+    {
+      75/jump-if-!= break/disp8
+      b8/copy-to-eax 1/imm32
+      eb/jump $size-of-type-id:end/disp8
+    }
     # if t is a handle, return 8
     3d/compare-eax-and 4/imm32/handle
     {
@@ -9857,6 +9872,7 @@ translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err:
     {
       81 7/subop/compare %ecx 1/imm32
       75/jump-if-!= break/disp8
+$translate-mu-length-stmt:size-1:
       (emit-save-size-to *(ebp+8) %ebx %edx)
       e9/jump $translate-mu-length-stmt:end/disp32
     }
@@ -9867,6 +9883,7 @@ translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err:
       74/jump-if-= break/disp8
       81 7/subop/compare %ecx 0xff/imm32
       7f/jump-if-> break/disp8
+$translate-mu-length-stmt:size-power-of-2:
       (emit-save-size-to *(ebp+8) %ebx %edx)
       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
       e9/jump $translate-mu-length-stmt:end/disp32
@@ -9874,6 +9891,7 @@ translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err:
     # otherwise, the complex case
     # . emit register spills
     {
+$translate-mu-length-stmt:complex:
       (string-equal? %edx "eax")  # => eax
       3d/compare-eax-and 0/imm32/false
       75/break-if-!= break/disp8
@@ -11733,8 +11751,26 @@ _Primitive-address:  # (payload primitive)
     0/imm32/no-disp32
     1/imm32/output-is-write-only
     0x11/imm32/alloc-id:fake
-    _Primitive-compare-mem-with-reg/imm32/next
+    _Primitive-compare-reg-with-reg/imm32/next
 # - compare
+_Primitive-compare-reg-with-reg:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
+    0x11/imm32/alloc-id:fake
+    _string-compare/imm32/name
+    0x11/imm32/alloc-id:fake
+    Two-int-args-in-regs/imm32/inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_39_compare->/imm32/subx-name
+    1/imm32/rm32-is-first-inout
+    2/imm32/r32-is-second-inout
+    0/imm32/no-imm32
+    0/imm32/no-disp32
+    0/imm32/output-is-write-only
+    0x11/imm32/alloc-id:fake
+    _Primitive-compare-mem-with-reg/imm32/next
 _Primitive-compare-mem-with-reg:  # (payload primitive)
     0x11/imm32/alloc-id:fake:payload
     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
@@ -11824,8 +11860,26 @@ _Primitive-compare-mem-with-literal:  # (payload primitive)
     0/imm32/no-disp32
     0/imm32/output-is-write-only
     0x11/imm32/alloc-id:fake
-    _Primitive-multiply-reg-by-mem/imm32/next
+    _Primitive-multiply-reg-by-reg/imm32/next
 # - multiply
+_Primitive-multiply-reg-by-reg:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
+    0x11/imm32/alloc-id:fake
+    _string-multiply/imm32/name
+    0x11/imm32/alloc-id:fake
+    Single-int-var-in-some-register/imm32/inouts
+    0x11/imm32/alloc-id:fake
+    Single-int-var-in-some-register/imm32/outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_af_multiply/imm32/subx-name
+    1/imm32/rm32-is-first-inout
+    3/imm32/r32-is-first-output
+    0/imm32/no-imm32
+    0/imm32/no-disp32
+    0/imm32/output-is-write-only
+    0x11/imm32/alloc-id:fake
+    _Primitive-multiply-reg-by-mem/imm32/next
 _Primitive-multiply-reg-by-mem:  # (payload primitive)
     0x11/imm32/alloc-id:fake:payload
     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
@@ -13269,6 +13323,13 @@ Two-args-int-stack-int-reg:  # (payload list var)
     0x11/imm32/alloc-id:fake
     Single-int-var-in-some-register/imm32/next
 
+Two-int-args-in-regs:  # (payload list var)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    Int-var-in-some-register/imm32
+    0x11/imm32/alloc-id:fake
+    Single-int-var-in-some-register/imm32/next
+
 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
 Two-args-byte-stack-byte-reg:  # (payload list var)
     0x11/imm32/alloc-id:fake:payload
@@ -15671,6 +15732,116 @@ $test-add-literal-to-mem:initialize-stmt-operation:
     5d/pop-to-ebp
     c3/return
 
+test-compare-reg-with-reg:
+    #   compare var1/ecx, var2/eax
+    # =>
+    #   39/compare %ecx 0/r32/eax
+    #
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+$test-compare-reg-with-reg:initialize-type:
+    # var type/ecx: (payload tree type-id) = int
+    68/push 0/imm32/right:null
+    68/push 0/imm32/right:null
+    68/push 0/imm32/left:unused
+    68/push 1/imm32/value:int
+    68/push 1/imm32/is-atom?:true
+    68/push 0x11/imm32/alloc-id:fake:payload
+    89/<- %ecx 4/r32/esp
+$test-compare-reg-with-reg:initialize-var1:
+    # var var1/ecx: (payload var)
+    68/push 0/imm32/register
+    68/push 0/imm32/register
+    68/push 0/imm32/no-stack-offset
+    68/push 1/imm32/block-depth
+    51/push-ecx
+    68/push 0x11/imm32/alloc-id:fake
+    68/push 0/imm32/name
+    68/push 0/imm32/name
+    68/push 0x11/imm32/alloc-id:fake:payload
+    89/<- %ecx 4/r32/esp
+$test-compare-reg-with-reg:initialize-var1-name:
+    # var1->name = "var1"
+    8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
+    (copy-array Heap "var1" %eax)
+$test-compare-reg-with-reg:initialize-var1-register:
+    # var1->register = "ecx"
+    8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
+    (copy-array Heap "ecx" %eax)
+$test-compare-reg-with-reg:initialize-var2:
+    # var var2/edx: (payload var)
+    68/push 0/imm32/register
+    68/push 0/imm32/register
+    68/push 0/imm32/no-stack-offset
+    68/push 1/imm32/block-depth
+    ff 6/subop/push *(ecx+0x10)
+    68/push 0x11/imm32/alloc-id:fake
+    68/push 0/imm32/name
+    68/push 0/imm32/name
+    68/push 0x11/imm32/alloc-id:fake:payload
+    89/<- %edx 4/r32/esp
+$test-compare-reg-with-reg:initialize-var2-name:
+    # var2->name = "var2"
+    8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
+    (copy-array Heap "var2" %eax)
+$test-compare-reg-with-reg:initialize-var2-register:
+    # var2->register = "eax"
+    8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
+    (copy-array Heap "eax" %eax)
+$test-compare-reg-with-reg:initialize-inouts:
+    # var inouts/esi: (payload stmt-var) = [var2]
+    68/push 0/imm32/is-deref:false
+    68/push 0/imm32/next
+    68/push 0/imm32/next
+    52/push-edx/var2
+    68/push 0x11/imm32/alloc-id:fake
+    68/push 0x11/imm32/alloc-id:fake:payload
+    89/<- %esi 4/r32/esp
+    # inouts = [var1, var2]
+    68/push 0/imm32/is-deref:false
+    56/push-esi/next
+    68/push 0x11/imm32/alloc-id:fake
+    51/push-ecx/var1
+    68/push 0x11/imm32/alloc-id:fake
+    68/push 0x11/imm32/alloc-id:fake:payload
+    89/<- %esi 4/r32/esp
+$test-compare-reg-with-reg:initialize-stmt:
+    # var stmt/esi: (addr statement)
+    68/push 0/imm32/next
+    68/push 0/imm32/next
+    68/push 0/imm32/outputs
+    68/push 0/imm32/outputs
+    56/push-esi/inouts
+    68/push 0x11/imm32/alloc-id:fake
+    68/push 0/imm32/operation
+    68/push 0/imm32/operation
+    68/push 1/imm32/tag:stmt1
+    89/<- %esi 4/r32/esp
+$test-compare-reg-with-reg:initialize-stmt-operation:
+    # stmt->operation = "compare"
+    8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
+    (copy-array Heap "compare" %eax)
+    # convert
+    c7 0/subop/copy *Curr-block-depth 0/imm32
+    (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
+    (flush _test-output-buffered-file)
+#?     # dump _test-output-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-output-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-output-stream)
+#?     # }}}
+    # check output
+    (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 test-compare-mem-with-reg:
     #   compare var1, var2/eax
     # =>
diff --git a/apps/pack b/apps/pack
index ad15dd42..2b9e77dd 100755
--- a/apps/pack
+++ b/apps/pack
Binary files differdiff --git a/apps/parse-int.mu b/apps/parse-int.mu
new file mode 100644
index 00000000..c9c1d945
--- /dev/null
+++ b/apps/parse-int.mu
@@ -0,0 +1,50 @@
+# parse a decimal int at the commandline
+#
+# To run:
+#   $ ./translate_mu apps/parse-int.mu
+#   $ ./a.elf 123
+#   $ echo $?
+#   123
+
+fn main _args: (addr array (addr array byte)) -> exit-status/ebx: int {
+$main-body: {
+  # if no args, print a message and exit
+  var args/esi: (addr array (addr array byte)) <- copy _args
+  var n/ecx: int <- length args
+  compare n, 1
+  {
+    break-if->
+    print-string "usage: parse-int <integer>\n"
+    exit-status <- copy 1
+    break $main-body
+  }
+  # otherwise parse the first arg as an integer
+  var in/ecx: (addr addr array byte) <- index args, 1
+  var out/eax: int <- parse-int *in
+  exit-status <- copy out
+}
+}
+
+fn parse-int _in: (addr array byte) -> result/eax: int {
+  var in/esi: (addr array byte) <- copy _in
+  var len/edx: int <- length in
+  var i/ecx: int <- copy 0
+  var out/edi: int <- copy 0
+  {
+    compare i, len
+    break-if->=
+    # out *= 10
+    var ten/eax: int <- copy 0xa
+    out <- multiply ten
+    # c = in[i]
+    var tmp/ebx: (addr byte) <- index in, i
+    var c/eax: byte <- copy 0
+    c <- copy-byte *tmp
+    #
+    var digit/eax: int <- to-decimal-digit c
+    out <- add digit
+    i <- increment
+    loop
+  }
+  result <- copy out
+}
diff --git a/apps/sigils b/apps/sigils
index b2ab77cf..29dafc9d 100755
--- a/apps/sigils
+++ b/apps/sigils
Binary files differdiff --git a/apps/survey b/apps/survey
index 0d94f444..9d00da8a 100755
--- a/apps/survey
+++ b/apps/survey
Binary files differdiff --git a/apps/tests b/apps/tests
index 5f431146..8e318bb3 100755
--- a/apps/tests
+++ b/apps/tests
Binary files differ