about summary refs log tree commit diff stats
path: root/apps/mu.subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-11-18 01:13:31 -0800
committerKartik Agaram <vc@akkartik.com>2019-11-18 01:15:29 -0800
commit442fdabe305fa35bf1649a072b9a7b3b87cd50e9 (patch)
tree1e9319ac010e605ff43c60c1fd53bd95f9671ae5 /apps/mu.subx
parent0ea0ebcf81afc722f731b22a1e1d5d7819830efd (diff)
downloadmu-442fdabe305fa35bf1649a072b9a7b3b87cd50e9.tar.gz
5752
Support binary operations with reg/mem and reg operands.

Everything is passing. However, the self-hosting translator now generates
some discrepancies compared to the C++ translator :(
Diffstat (limited to 'apps/mu.subx')
-rw-r--r--apps/mu.subx174
1 files changed, 97 insertions, 77 deletions
diff --git a/apps/mu.subx b/apps/mu.subx
index 1f8542ea..2f64affd 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -953,16 +953,26 @@ Primitives:
     1/imm32/rm32-is-first-inout
     0/imm32/no-r32
     0/imm32/no-imm32
-    _Primitive-inc-reg/imm32
+    _Primitive-inc-reg/imm32/next
 _Primitive-inc-reg:
     # var/reg <- increment => ff 0/subop/increment %__
     "increment"/imm32/name
     0/imm32/no-inouts
-    Single-var-in-some-register/imm32/outputs
+    Single-int-var-in-some-register/imm32/outputs
     "ff 0/subop/increment"/imm32/subx-name
     3/imm32/rm32-is-first-output
     0/imm32/no-r32
     0/imm32/no-imm32
+    _Primitive-add-reg-to-reg/imm32/next
+_Primitive-add-reg-to-reg:
+    # var1/reg <- add var2/reg => 01 var1/rm32 var2/r32
+    "add"/imm32/name
+    Single-int-var-in-some-register/imm32/inouts
+    Single-int-var-in-some-register/imm32/outputs
+    "01"/imm32/subx-name
+    3/imm32/rm32-is-first-output
+    1/imm32/r32-is-first-inout
+    0/imm32/no-imm32
     0/imm32/next
 
 Single-int-var-on-stack:
@@ -976,7 +986,7 @@ Int-var-on-stack:
     1/imm32/some-stack-offset
     0/imm32/no-register
 
-Single-var-in-some-register:
+Single-int-var-in-some-register:
     Int-var-in-some-register/imm32
     0/imm32/next
 
@@ -1001,8 +1011,8 @@ emit-subx-primitive:  # out : (address buffered-file), stmt : (address statement
     (write-buffered *(ebp+8) *(ecx+0xc))  # Primitive-subx-name
     # emit rm32 if necessary
     (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc))  # out, Primitive-subx-rm32, stmt
-#?     # emit r32 if necessary
-#?     (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc))  # out, Primitive-subx-r32, stmt
+    # emit r32 if necessary
+    (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc))  # out, Primitive-subx-r32, stmt
 #?     # emit imm32 if necessary
 #?     (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc))  # out, Primitive-subx-imm32, stmt
 $emit-subx-primitive:end:
@@ -1101,10 +1111,15 @@ emit-subx-r32:  # out : (address buffered-file), l : arg-location, stmt : (addre
     # . save registers
     50/push-eax
     51/push-ecx
-    # location/ecx : enum = primitive->subx-r32
     # if (location == 0) return
-    # var/ecx : var = get-operand(stmt, primitive->subx-rm32)
-    # emit-subx-call-operand(out, var)
+    81 7/subop/compare *(ebp+0xc) 0/imm32
+    0f 84/jump-if-equal $emit-subx-r32:end/disp32
+    #
+    (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # stmt, l => var/eax
+    (maybe-get Registers *(eax+0x10) 8)  # Var-register => eax : (address register-index)
+    (write-buffered *(ebp+8) Space)
+    (print-int32-buffered *(ebp+8) *eax)
+    (write-buffered *(ebp+8) "/r32")
 $emit-subx-r32:end:
     # . restore registers
     59/pop-to-ecx
@@ -1121,8 +1136,12 @@ emit-subx-imm32:  # out : (address buffered-file), l : arg-location, stmt : (add
     # . save registers
     50/push-eax
     51/push-ecx
-    # var/ecx : var = get-operand(stmt, primitive->subx-rm32)
-    # emit-subx-call-operand(out, var)
+    # if (location == 0) return
+    81 7/subop/compare *(ebp+0xc) 0/imm32
+    74/jump-if-equal $emit-subx-imm32:end/disp8
+    #
+    (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # stmt, l => var/eax
+    (emit-subx-call-operand *(ebp+8) %eax)  # out, var
 $emit-subx-imm32:end:
     # . restore registers
     59/pop-to-ecx
@@ -1394,7 +1413,7 @@ $mu-stmt-matches-primitive?:check-outputs:
       }
       # if (curr != curr2) return false
       {
-        (output-operand-matches-primitive? *esi *edi)  # => eax
+        (operand-matches-primitive? *esi *edi)  # => eax
         3d/compare-eax-and 0/imm32
         75/jump-if-not-equal break/disp8
         b8/copy-to-eax 0/imm32
@@ -1419,48 +1438,7 @@ $mu-stmt-matches-primitive?:end:
     5d/pop-to-ebp
     c3/return
 
-operand-matches-primitive?:  # var1 : (address var), var2 : (address var) => result/eax : boolean
-    # . prologue
-    55/push-ebp
-    89/<- %ebp 4/r32/esp
-    # . save registers
-    56/push-esi
-    57/push-edi
-    # esi = var1
-    8b/-> *(ebp+8) 6/r32/esi
-    # edi = var2
-    8b/-> *(ebp+0xc) 7/r32/edi
-    # if (var1->type != var2->type) return false
-    # if (var1->register != var1->register) return false
-    {
-      # if addresses are equal, don't return here
-      8b/-> *(esi+0x10) 0/r32/eax
-      39/compare *(edi+0x10) 0/r32/eax
-      74/jump-if-equal break/disp8
-      # if either address is 0, return false
-      3d/compare-eax-and 0/imm32
-      74/jump-if-equal  $operand-matches-primitive?:end/disp8  # eax goes from meaning var1->register to result
-      81 7/subop/compare *(edi+0x10) 0/imm32
-      74/jump-if-equal  $operand-matches-primitive?:end/disp8  # eax goes from meaning var1->register to result
-      # if string contents don't match, return false
-      (string-equal? *(esi+0x10) *(edi+0x10))  # Var-register Var-register
-      3d/compare-eax-and 0/imm32
-      b8/copy-to-eax 0/imm32/false
-      74/jump-if-equal $operand-matches-primitive?:end/disp8
-    }
-    # return true
-    b8/copy-to-eax 1/imm32/true
-$operand-matches-primitive?:end:
-    # . restore registers
-    5f/pop-to-edi
-    5e/pop-to-esi
-    # . epilogue
-    89/<- %esp 5/r32/ebp
-    5d/pop-to-ebp
-    c3/return
-
-# like operand-matches-primitive? but also handles "*" register in primitive
-output-operand-matches-primitive?:  # var : (address var), primout-var : (address var) => result/eax : boolean
+operand-matches-primitive?:  # var : (address var), primout-var : (address var) => result/eax : boolean
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -1472,6 +1450,7 @@ output-operand-matches-primitive?:  # var : (address var), primout-var : (addres
     # edi = primout-var
     8b/-> *(ebp+0xc) 7/r32/edi
     # if (var->type != primout-var->type) return false
+    # TODO
     # return false if var->register doesn't match primout-var->register
     {
       # if addresses are equal, don't return here
@@ -1496,7 +1475,7 @@ output-operand-matches-primitive?:  # var : (address var), primout-var : (addres
     }
     # return true
     b8/copy-to-eax 1/imm32/true
-$output-operand-matches-primitive?:end:
+$operand-matches-primitive?:end:
     # . restore registers
     5f/pop-to-edi
     5e/pop-to-esi
@@ -1576,9 +1555,7 @@ $aa-primitive-in-ebx:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x48/imm32
+    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -1661,9 +1638,7 @@ test-emit-subx-statement-primitive-register:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x48/imm32
+    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -1759,9 +1734,7 @@ test-emit-subx-statement-select-primitive:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x48/imm32
+    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -1857,15 +1830,13 @@ test-emit-subx-statement-select-primitive-2:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x48/imm32
+    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
     c3/return
 
-test-emit-subx-statement-select-primitive-using-global-primitives:
+test-increment-register:
     # Select the right primitive between overloads.
     #   foo <- increment
     # =>
@@ -1918,15 +1889,13 @@ test-emit-subx-statement-select-primitive-using-global-primitives:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x48/imm32
+    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-register")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
     c3/return
 
-test-emit-subx-statement-select-primitive-using-global-primitives-2:
+test-increment-var:
     # Select the right primitive between overloads.
     #   foo <- increment
     # =>
@@ -1979,9 +1948,62 @@ test-emit-subx-statement-select-primitive-using-global-primitives-2:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x48/imm32
+    (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-increment-var")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+test-add-reg-to-reg:
+    #   var1/reg <- add var2/reg
+    # =>
+    #   01 %var1 var2
+    #
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-output-stream)
+    (clear-stream _test-output-buffered-file->buffer)
+    # var-var1/ecx : var in eax
+    68/push "eax"/imm32/register
+    68/push 0/imm32/no-stack-offset
+    68/push 1/imm32/block-depth
+    68/push 1/imm32/type-int
+    68/push "var1"/imm32
+    89/<- %ecx 4/r32/esp
+    # var-var2/edx : var in ecx
+    68/push "ecx"/imm32/register
+    68/push 0/imm32/no-stack-offset
+    68/push 1/imm32/block-depth
+    68/push 1/imm32/type-int
+    68/push "var2"/imm32
+    89/<- %edx 4/r32/esp
+    # inouts/esi : (list var2)
+    68/push 0/imm32/next
+    52/push-edx/var-var2
+    89/<- %esi 4/r32/esp
+    # outputs/edi : (list var1)
+    68/push 0/imm32/next
+    51/push-ecx/var-var1
+    89/<- %edi 4/r32/esp
+    # stmt/esi : statement
+    68/push 0/imm32/next
+    57/push-edi/outputs
+    56/push-esi/inouts
+    68/push "add"/imm32/operation
+    89/<- %esi 4/r32/esp
+    # convert
+    (emit-subx-statement _test-output-buffered-file %esi 0 Primitives 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 "01 %eax 0x00000001/r32" "F - test-add-reg-to-reg")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -2053,9 +2075,7 @@ test-emit-subx-statement-function-call:
 #?     (rewind-stream _test-output-stream)
 #?     # }}}
     # check output
-    (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call/0")
-    # . reclaim locals
-    81 0/subop/add %esp 0x3c/imm32
+    (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp