about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xlinux/mubin611784 -> 614607 bytes
-rw-r--r--linux/mu.subx135
-rw-r--r--mu_instructions2
3 files changed, 132 insertions, 5 deletions
diff --git a/linux/mu b/linux/mu
index 0f9798a7..fdeacea0 100755
--- a/linux/mu
+++ b/linux/mu
Binary files differdiff --git a/linux/mu.subx b/linux/mu.subx
index 0a6d6fdb..879b751e 100644
--- a/linux/mu.subx
+++ b/linux/mu.subx
@@ -6760,6 +6760,53 @@ test-convert-index-into-array-using-offset:
     5d/pop-to-ebp
     c3/return
 
+test-convert-compute-offset-using-literal-index:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (clear-stream $_test-input-buffered-file->buffer)
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+    #
+    (write _test-input-stream "fn foo {\n")
+    (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
+    (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, 3\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file 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 "foo:"                                        "F - test-convert-compute-offset-using-literal-index/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-compute-offset-using-literal-index/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-compute-offset-using-literal-index/2")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-compute-offset-using-literal-index/3")
+    (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-compute-offset-using-literal-index/4")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-compute-offset-using-literal-index/5")
+    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-compute-offset-using-literal-index/6")
+    (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-compute-offset-using-literal-index/7")
+    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-compute-offset-using-literal-index/8")
+    (check-next-stream-line-equal _test-output-stream "    c7/copy %ecx 0x0000000c/imm32"           "F - test-convert-compute-offset-using-literal-index/9")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-compute-offset-using-literal-index/10")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-compute-offset-using-literal-index/11")
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-compute-offset-using-literal-index/12")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-compute-offset-using-literal-index/13")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-compute-offset-using-literal-index/14")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-compute-offset-using-literal-index/15")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-compute-offset-using-literal-index/16")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-compute-offset-using-literal-index/17")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 test-convert-index-into-array-of-bytes-using-offset:
     # . prologue
     55/push-ebp
@@ -29846,7 +29893,7 @@ $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
       # var idx-value/edx: int = parse-hex-int(index->name)
       (lookup *edx *(edx+4))  # Var-name Var-name => eax
-      (parse-hex-int %eax)  # Var-name => eax
+      (parse-hex-int %eax)  # => eax
       89/<- %edx 0/r32/eax
       # offset = idx-value * array-element-size(base)
       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
@@ -29889,6 +29936,35 @@ translate-mu-compute-offset-stmt:  # out: (addr buffered-file), stmt: (addr stmt
     89/<- %ebp 4/r32/esp
     # . save registers
     50/push-eax
+    # var index-type/eax: (addr type-tree) = stmt->inouts->next->value->type
+    8b/-> *(ebp+0xc) 0/r32/eax
+    (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
+    (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
+    (simple-mu-type? %eax 0)  # literal => eax
+    3d/compare-eax-and 0/imm32/false
+    {
+      74/jump-if-= break/disp8
+      # special-case: index is a literal
+      (translate-mu-compute-offset-stmt-with-literal-index *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
+      eb/jump $translate-mu-compute-offset-stmt:end/disp8
+    }
+    (translate-mu-compute-offset-stmt-with-register-index *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
+$translate-mu-compute-offset-stmt:end:
+    # . restore registers
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+translate-mu-compute-offset-stmt-with-register-index:  # out: (addr buffered-file), stmt-with-register-index: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
     51/push-ecx
     52/push-edx
     53/push-ebx
@@ -29900,11 +29976,11 @@ translate-mu-compute-offset-stmt:  # out: (addr buffered-file), stmt: (addr stmt
     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
     89/<- %ebx 0/r32/eax
-$translate-mu-compute-offset-stmt:emit-index:
+$translate-mu-compute-offset-stmt-with-register-index:emit-index:
     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
     (emit-subx-var-as-rm32 *(ebp+8) %eax)
     (write-buffered *(ebp+8) Space)
-$translate-mu-compute-offset-stmt:emit-elem-size:
+$translate-mu-compute-offset-stmt-with-register-index:emit-elem-size:
     # var base/ebx: (addr var)
     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
     89/<- %ebx 0/r32/eax
@@ -29912,7 +29988,7 @@ $translate-mu-compute-offset-stmt:emit-elem-size:
     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
     (write-int32-hex-buffered *(ebp+8) %eax)
     (write-buffered *(ebp+8) "/imm32 ")
-$translate-mu-compute-offset-stmt:emit-output:
+$translate-mu-compute-offset-stmt-with-register-index:emit-output:
     # outputs[0] "/r32"
     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
@@ -29920,7 +29996,56 @@ $translate-mu-compute-offset-stmt:emit-output:
     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
     (write-int32-hex-buffered *(ebp+8) *eax)
     (write-buffered *(ebp+8) "/r32\n")
-$translate-mu-compute-offset-stmt:end:
+$translate-mu-compute-offset-stmt-with-register-index:end:
+    # . restore registers
+    5b/pop-to-ebx
+    5a/pop-to-edx
+    59/pop-to-ecx
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+translate-mu-compute-offset-stmt-with-literal-index:  # out: (addr buffered-file), stmt-with-literal-index: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    51/push-ecx
+    52/push-edx
+    53/push-ebx
+    #
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "c7/copy %")
+    # ecx = stmt
+    8b/-> *(ebp+0xc) 1/r32/ecx
+$translate-mu-compute-offset-stmt-with-literal-index:emit-output:
+    # emit outputs[0]->register
+    (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
+    (write-buffered *(ebp+8) %eax)
+    (write-buffered *(ebp+8) Space)
+$translate-mu-compute-offset-stmt-with-literal-index:emit-offset:
+    # var first-inout/ebx: (addr stmt-var) = stmt->inouts
+    (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
+    89/<- %ebx 0/r32/eax
+    # var index/edx: int = int(first-inout->next->value)
+    (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (parse-hex-int %eax)  # => eax
+    89/<- %edx 0/r32/eax
+    # var base/ebx: (addr var) = first-inout->value
+    (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
+    # emit index * sizeof(base element type)
+    (array-element-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
+    0f af/multiply %edx 0/r32/eax
+    (write-int32-hex-buffered *(ebp+8) %eax)
+    (write-buffered *(ebp+8) "/imm32\n")
+$translate-mu-compute-offset-stmt-with-literal-index:end:
     # . restore registers
     5b/pop-to-ebx
     5a/pop-to-edx
diff --git a/mu_instructions b/mu_instructions
index 2dca40c4..4898f9a1 100644
--- a/mu_instructions
+++ b/mu_instructions
@@ -367,6 +367,8 @@ var/reg: (offset T) <- compute-offset arr: (addr array T), idx/regi: int  # arr
   => "69/multiply %" regi " " size-of(T) "/imm32 " reg "/r32"
 var/reg: (offset T) <- compute-offset arr: (addr array T), idx: int       # arr can be in reg or mem
   => "69/multiply *(ebp+" idx.stack-offset ") " size-of(T) "/imm32 " reg "/r32"
+var/reg: (offset T) <- compute-offset arr: (addr array T), n              # arr can be in reg or mem
+  => "c7 0/subop/copy %" reg " " n*size-of(T) "/imm32"
 var/reg: (addr T) <- index arr/rega: (addr array T), o/rego: (offset T)
   => "81 7/subop/compare %" rega " 0/imm32"
      "0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"