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 :(
This commit is contained in:
Kartik Agaram 2019-11-18 01:13:31 -08:00
parent 0ea0ebcf81
commit 442fdabe30
18 changed files with 1221 additions and 1187 deletions

15
085register-names.subx Normal file
View File

@ -0,0 +1,15 @@
== data
Registers: # (table string int)
# a table is a stream
0x40/imm32/write
0/imm32/read
0x40/imm32/length
# data
"eax"/imm32 0/imm32
"ecx"/imm32 1/imm32
"edx"/imm32 2/imm32
"ebx"/imm32 3/imm32
"esp"/imm32 4/imm32
"ebp"/imm32 5/imm32
"esi"/imm32 6/imm32
"edi"/imm32 7/imm32

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
apps/hex

Binary file not shown.

BIN
apps/mu

Binary file not shown.

View File

@ -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

BIN
apps/pack

Binary file not shown.

Binary file not shown.

View File

@ -4638,20 +4638,4 @@ test-next-positive-hex-int-0-prefix:
5d/pop-to-ebp
c3/return
== data
Registers: # (table string int)
# a table is a stream
0x40/imm32/write
0/imm32/read
0x40/imm32/length
# data
"eax"/imm32 0/imm32
"ecx"/imm32 1/imm32
"edx"/imm32 2/imm32
"ebx"/imm32 3/imm32
"esp"/imm32 4/imm32
"ebp"/imm32 5/imm32
"esi"/imm32 6/imm32
"edi"/imm32 7/imm32
# . . vim:nowrap:textwidth=0

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff