6915 - a new family of Mu branch instructions

The realization of commit 6916 means that we should be using jump-if-addr*
after comparing floats. Which is super ugly. Let's create aliases to them
called jump-if-float*.
This commit is contained in:
Kartik Agaram 2020-09-30 23:46:43 -07:00
parent bc3ebe820b
commit 8d32a9aab9
3 changed files with 432 additions and 2 deletions

View File

@ -3177,6 +3177,65 @@ test-convert-function-with-branches-in-block:
5d/pop-to-ebp
c3/return
test-convert-function-with-branches-in-block-2:
# . 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 x: int {\n")
(write _test-input-stream " {\n")
(write _test-input-stream " break-if->=\n")
(write _test-input-stream " loop-if-float<\n")
(write _test-input-stream " increment x\n")
(write _test-input-stream " loop\n")
(write _test-input-stream " }\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-function-with-branches-in-block/0")
(check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1")
(check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2")
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3")
(check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4")
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5")
(check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6")
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7")
(check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/8")
(check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-in-block/9")
(check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-in-block/10")
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/11")
(check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/12")
(check-next-stream-line-equal _test-output-stream " 0f 83/jump-if-addr>= break/disp32" "F - test-convert-function-with-branches-in-block/13")
(check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:loop/disp32" "F - test-convert-function-with-branches-in-block/14")
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/15")
(check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/16")
(check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/17")
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/18")
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/19")
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/20")
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/21")
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/22")
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/23")
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/24")
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/25")
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
test-convert-function-with-branches-in-named-block:
# . prologue
55/push-ebp
@ -15616,9 +15675,9 @@ $emit-reverse-break:end:
# Table from Mu branch instructions to the reverse SubX opcodes for them.
Reverse-branch: # (table (handle array byte) (handle array byte))
# a table is a stream
0x140/imm32/write
0x1c0/imm32/write
0/imm32/read
0x140/imm32/size
0x1c0/imm32/size
# data
0x11/imm32/alloc-id _string-break-if-=/imm32 0x11/imm32/alloc-id _string_0f_85_jump_label/imm32
0x11/imm32/alloc-id _string-loop-if-=/imm32 0x11/imm32/alloc-id _string_0f_85_jump_label/imm32
@ -15640,6 +15699,14 @@ Reverse-branch: # (table (handle array byte) (handle array byte))
0x11/imm32/alloc-id _string-loop-if-addr<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32
0x11/imm32/alloc-id _string-break-if-addr>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32
0x11/imm32/alloc-id _string-loop-if-addr>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32
0x11/imm32/alloc-id _string-break-if-float</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32
0x11/imm32/alloc-id _string-loop-if-float</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32
0x11/imm32/alloc-id _string-break-if-float>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32
0x11/imm32/alloc-id _string-loop-if-float>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32
0x11/imm32/alloc-id _string-break-if-float<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32
0x11/imm32/alloc-id _string-loop-if-float<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32
0x11/imm32/alloc-id _string-break-if-float>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32
0x11/imm32/alloc-id _string-loop-if-float>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32
== code
@ -20933,6 +21000,311 @@ _Primitive-loop-named: # (payload primitive)
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float</imm32/next
# - branches based on floating-point comparisons
_Primitive-break-if-float<: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float</imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_82_jump_break/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float>=/imm32/next
_Primitive-break-if-float>=: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float>=/imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_83_jump_break/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float<=/imm32/next
_Primitive-break-if-float<=: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float<=/imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_86_jump_break/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float>/imm32/next
_Primitive-break-if-float>: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float>/imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_87_jump_break/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float</imm32/next
_Primitive-loop-if-float<: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float</imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_82_jump_loop/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float>=/imm32/next
_Primitive-loop-if-float>=: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float>=/imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_83_jump_loop/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float<=/imm32/next
_Primitive-loop-if-float<=: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float<=/imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_86_jump_loop/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float>/imm32/next
_Primitive-loop-if-float>: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float>/imm32/name
0/imm32/no-inouts
0/imm32/no-inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_87_jump_loop/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
0/imm32/no-disp32
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float<-named/imm32/next
_Primitive-break-if-float<-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float</imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_82_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float>=-named/imm32/next
_Primitive-break-if-float>=-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float>=/imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_83_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float<=-named/imm32/next
_Primitive-break-if-float<=-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float<=/imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_86_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-break-if-float>-named/imm32/next
_Primitive-break-if-float>-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-break-if-float>/imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_87_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float<-named/imm32/next
_Primitive-loop-if-float<-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float</imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_82_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float>=-named/imm32/next
_Primitive-loop-if-float>=-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float>=/imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_83_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float<=-named/imm32/next
_Primitive-loop-if-float<=-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float<=/imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_86_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0x11/imm32/alloc-id:fake
_Primitive-loop-if-float>-named/imm32/next
_Primitive-loop-if-float>-named: # (payload primitive)
0x11/imm32/alloc-id:fake:payload
0x11/imm32/alloc-id:fake
_string-loop-if-float>/imm32/name
0x11/imm32/alloc-id:fake
Single-lit-var/imm32/inouts
0/imm32/no-outputs
0/imm32/no-outputs
0x11/imm32/alloc-id:fake
_string_0f_87_jump_label/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
0/imm32/no-imm8
1/imm32/disp32-is-first-inout
0/imm32/no-xm32
0/imm32/no-x32
0/imm32/next
0/imm32/next
@ -21017,6 +21389,26 @@ _string-break-if-addr>=: # (payload array byte)
# "break-if-addr>="
0xf/imm32/size
0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
_string-break-if-float<: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "break-if-float<"
0xf/imm32/size
0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
_string-break-if-float<=: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "break-if-float<="
0x10/imm32/size
0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
_string-break-if-float>: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "break-if-float>"
0xf/imm32/size
0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
_string-break-if-float>=: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "break-if-float>="
0x10/imm32/size
0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
_string-compare: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "compare"
@ -21107,6 +21499,26 @@ _string-loop-if-addr>=: # (payload array byte)
# "loop-if-addr>="
0xe/imm32/size
0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
_string-loop-if-float<: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "loop-if-float<"
0xe/imm32/size
0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
_string-loop-if-float<=: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "loop-if-float<="
0xf/imm32/size
0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
_string-loop-if-float>: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "loop-if-float>"
0xe/imm32/size
0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
_string-loop-if-float>=: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "loop-if-float>="
0xf/imm32/size
0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
_string-multiply: # (payload array byte)
0x11/imm32/alloc-id:fake:payload
# "multiply"
@ -22748,6 +23160,9 @@ $mu-stmt-matches-primitive?:check-name:
89/<- %esi 0/r32/eax
# . var edi: (addr array byte) = lookup(primitive->name)
(lookup *edx *(edx+4)) # Primitive-name Primitive-name => eax
#? (write-buffered Stderr %eax)
#? (write-buffered Stderr Newline)
#? (flush Stderr)
89/<- %edi 0/r32/eax
(string-equal? %esi %edi) # => eax
3d/compare-eax-and 0/imm32/false

9
mu.md
View File

@ -371,6 +371,15 @@ break-if-addr<=
break-if-addr<= label
break-if-addr>=
break-if-addr>= label
break-if-float<
break-if-float< label
break-if-float>
break-if-float> label
break-if-float<=
break-if-float<= label
break-if-float>=
break-if-float>= label
```
Similarly, conditional loops:

View File

@ -177,6 +177,12 @@ break-if-addr>= label => "0f 83/jump-if-addr>= " label ":break/disp3
loop-if-addr>= => "0f 83/jump-if-addr>= loop/disp32"
loop-if-addr>= label => "0f 83/jump-if-addr>= " label ":loop/disp32"
Similar float variants like `break-if-loop<` are aliases for the corresponding
`addr` equivalents. The x86 instruction set stupidly has floating-point
operations only update a subset of flags.
---
In the following instructions types are provided for clarity even if they must
be provided in an earlier 'var' declaration.