about summary refs log tree commit diff stats
path: root/apps/mu.subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-05-24 13:27:08 -0700
committerKartik Agaram <vc@akkartik.com>2020-05-24 14:48:41 -0700
commit156763463d07072bed54172f45d9083c207470c8 (patch)
tree527a1696fa48aeec57765a0c2573da63998325aa /apps/mu.subx
parentd89af9bdfa690e839d1f26205d95b4110d3ae73f (diff)
downloadmu-156763463d07072bed54172f45d9083c207470c8.tar.gz
6390 - return `length` in elements
Diffstat (limited to 'apps/mu.subx')
-rw-r--r--apps/mu.subx110
1 files changed, 88 insertions, 22 deletions
diff --git a/apps/mu.subx b/apps/mu.subx
index 3d6c9dc2..1d1d60ab 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -2436,14 +2436,15 @@ test-convert-length-of-array:
     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
-    (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/9")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/11")
-    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/12")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/13")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/14")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/15")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/16")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/17")
+    (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
+    (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm32"  "F - test-convert-length-of-array/9")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -2484,14 +2485,15 @@ test-convert-length-of-array-on-stack:
     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
-    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/10")
-    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/11")
-    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/12")
-    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/13")
-    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/14")
-    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/15")
-    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/16")
-    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/17")
+    (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm32"  "F - test-convert-length-of-array-on-stack/10")
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
+    (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -8842,28 +8844,31 @@ translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
     # . save registers
     50/push-eax
     51/push-ecx
+    52/push-edx
+    53/push-ebx
     # ecx = stmt
     8b/-> *(ebp+0xc) 1/r32/ecx
     #
     (emit-indent *(ebp+8) *Curr-block-depth)
     (write-buffered *(ebp+8) "8b/-> *")
-    # var base/eax: (handle var) = inouts[0]
+    # var base/ebx: (addr var) = inouts[0]
     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    89/<- %ebx 0/r32/eax
     # if base is an (addr array ...) in a register
     {
-      81 7/subop/compare *(eax+0x18)) 0/imm32  # Var-register
+      81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
       74/jump-if-= break/disp8
-      (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
+      (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
       (write-buffered *(ebp+8) %eax)
       eb/jump $translate-mu-length-stmt:emit-output/disp8
     }
     # otherwise if base is an (array ...) on the stack
     {
-      81 7/subop/compare *(eax+0x14)) 0/imm32  # Var-offset
+      81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
       74/jump-if-= break/disp8
       (write-buffered *(ebp+8) "(ebp+")
-      (print-int32-buffered *(ebp+8) *(eax+0x14))  # Var-offset
+      (print-int32-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
       (write-buffered *(ebp+8) ")")
     }
 $translate-mu-length-stmt:emit-output:
@@ -8871,12 +8876,40 @@ $translate-mu-length-stmt: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
+    # edx = outputs[0]->register
     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
-    (get Registers %eax 0xc "Registers")  # => eax
+    89/<- %edx 0/r32/eax
+    #
+    (get Registers %edx 0xc "Registers")  # => eax
     (print-int32-buffered *(ebp+8) *eax)
     (write-buffered *(ebp+8) "/r32\n")
+$translate-mu-length-stmt:check-power-of-2:
+    # ecx = size-of(element-type(base))
+    (array-element-type-id %ebx)  # => eax
+    (size-of-type-id %eax)  # => eax
+    89/<- %ecx 0/r32/eax
+    #
+    (power-of-2? %ecx)  # => eax
+    3d/compare-eax-and 0/imm32/false
+    {
+      0f 84/jump-if-= break/disp32
+$translate-mu-length-stmt:is-power-of-2:
+      (emit-indent *(ebp+8) *Curr-block-depth)
+      (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
+      (write-buffered *(ebp+8) %edx)
+      (write-buffered *(ebp+8) Space)
+      (num-shift-rights %ecx)  # => eax
+      (print-int32-buffered *(ebp+8) %eax)
+      (write-buffered *(ebp+8) "/imm32\n")
+      eb/jump $translate-mu-length-stmt:end/disp8
+    }
+    {
+      75/jump-if-!= break/disp8
+$translate-mu-length-stmt:not-power-of-2:
+    }
 $translate-mu-length-stmt:end:
     # . restore registers
+    5b/pop-to-ebx
     59/pop-to-ecx
     58/pop-to-eax
     # . epilogue
@@ -9310,6 +9343,39 @@ $array-element-type-id:end:
     5d/pop-to-ebp
     c3/return
 
+power-of-2?:  # n: int -> result/eax: boolean
+    # precondition: n is positive
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # eax = n
+    8b/-> *(ebp+8) 0/r32/eax
+    # if (n < 0) abort
+    3d/compare-eax-with 0/imm32
+    0f 8c/jump-if-< $power-of-2?:abort/disp32
+    # var tmp/eax: int = n-1
+    48/decrement-eax
+    # var tmp2/eax: int = n & tmp
+    23/and-> *(ebp+8) 0/r32/eax
+    # return (tmp2 == 0)
+    3d/compare-eax-and 0/imm32
+    0f 94/set-byte-if-= %al
+    81 4/subop/and %eax 0xff/imm32
+$power-of-2?:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+$power-of-2?:abort:
+    (write-buffered Stderr "power-of-2?: negative number\n")
+    (flush Stderr)
+    # . syscall(exit, 1)
+    bb/copy-to-ebx  1/imm32
+    b8/copy-to-eax  1/imm32/exit
+    cd/syscall  0x80/imm8
+    # never gets here
+
 num-shift-rights:  # n: int -> result/eax: int
     # precondition: n is a positive power of 2
     # . prologue