From 8d32a9aab9915d78e63d316fcb74fa1afa404798 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 30 Sep 2020 23:46:43 -0700 Subject: [PATCH] 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*. --- apps/mu.subx | 419 +++++++++++++++++++++++++++++++++++++++++++++++- mu.md | 9 ++ mu_instructions | 6 + 3 files changed, 432 insertions(+), 2 deletions(-) diff --git a/apps/mu.subx b/apps/mu.subx index 7d5a8881..590fa595 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -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_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 +_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_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=-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=-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 diff --git a/mu.md b/mu.md index 9ed2f693..a3271631 100644 --- a/mu.md +++ b/mu.md @@ -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: diff --git a/mu_instructions b/mu_instructions index 2013c764..27fe295c 100644 --- a/mu_instructions +++ b/mu_instructions @@ -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.