diff options
-rw-r--r-- | html/mu_instructions.html | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/html/mu_instructions.html b/html/mu_instructions.html index ff5a2fe3..14b2c931 100644 --- a/html/mu_instructions.html +++ b/html/mu_instructions.html @@ -7,14 +7,15 @@ <meta name="plugin-version" content="vim8.1_v1"> <meta name="syntax" content="none"> <meta name="settings" content="use_css,no_foldcolumn,expand_tabs,prevent_copy="> -<meta name="colorscheme" content="minimal-light"> +<meta name="colorscheme" content="minimal-dark"> <style type="text/css"> <!-- -pre { font-family: monospace; color: #000000; background-color: #c6c6c6; } -body { font-family: monospace; color: #000000; background-color: #c6c6c6; } +pre { font-family: monospace; color: #000000; background-color: #a8a8a8; } +body { font-family: monospace; color: #000000; background-color: #a8a8a8; } * { font-size: 1em; } .PreProc { color: #c000c0; } .muComment { color: #005faf; } +.Delimiter { color: #c000c0; } .Constant { color: #008787; } .Special { color: #ff6060; } --> @@ -317,6 +318,31 @@ Similar float variants like `<span class="PreProc">break-if-float<`</span> ar `addr` equivalents. The x86 instruction set stupidly has floating-point operations only update a subset of flags. +Four sets of conditional jumps are useful for detecting overflow. + +<span class="PreProc">break-if-carry</span> => <span class="Constant">"0f 82/jump-if-carry break/disp32"</span> +<span class="PreProc">break-if-carry</span> label => <span class="Constant">"0f 82/jump-if-carry "</span> label <span class="Constant">"/disp32"</span> +<span class="PreProc">loop-if-carry</span> => <span class="Constant">"0f 82/jump-if-carry break/disp32"</span> +<span class="PreProc">loop-if-carry</span> label => <span class="Constant">"0f 82/jump-if-carry "</span> label <span class="Constant">"/disp32"</span> + +<span class="PreProc">break-if-not-carry</span> => <span class="Constant">"0f 83/jump-if-not-carry break/disp32"</span> +<span class="PreProc">break-if-not-carry</span> label => <span class="Constant">"0f 83/jump-if-not-carry "</span> label <span class="Constant">"/disp32"</span> +<span class="PreProc">loop-if-not-carry</span> => <span class="Constant">"0f 83/jump-if-not-carry break/disp32"</span> +<span class="PreProc">loop-if-not-carry</span> label => <span class="Constant">"0f 83/jump-if-not-carry "</span> label <span class="Constant">"/disp32"</span> + +<span class="PreProc">break-if-overflow</span> => <span class="Constant">"0f 80/jump-if-overflow break/disp32"</span> +<span class="PreProc">break-if-overflow</span> label => <span class="Constant">"0f 80/jump-if-overflow "</span> label <span class="Constant">":break/disp32"</span> +<span class="PreProc">loop-if-overflow</span> => <span class="Constant">"0f 80/jump-if-overflow loop/disp32"</span> +<span class="PreProc">loop-if-overflow</span> label => <span class="Constant">"0f 80/jump-if-overflow "</span> label <span class="Constant">":loop/disp32"</span> + +<span class="PreProc">break-if-not-overflow</span> => <span class="Constant">"0f 81/jump-if-not-overflow break/disp32"</span> +<span class="PreProc">break-if-not-overflow</span> label => <span class="Constant">"0f 81/jump-if-not-overflow "</span> label <span class="Constant">":break/disp32"</span> +<span class="PreProc">loop-if-not-overflow</span> => <span class="Constant">"0f 81/jump-if-not-overflow loop/disp32"</span> +<span class="PreProc">loop-if-not-overflow</span> label => <span class="Constant">"0f 81/jump-if-not-overflow "</span> label <span class="Constant">":loop/disp32"</span> + +All this relies on a convention that every `<span class="Delimiter">{}</span>` block is delimited by labels +ending in `:<span class="PreProc">loop</span>` and `:<span class="PreProc">break</span>`. + <span class="muComment">## Returns</span> The `<span class="PreProc">return</span>` instruction cleans up variable declarations just like an unconditional @@ -342,13 +368,17 @@ var/reg: (addr T) <span class="Special"><-</span> address var2: T var/reg: (addr T) <span class="Special"><-</span> index arr/rega: (addr array T), idx/regi: int | if size-of(T) is <span class="Constant">1</span>, <span class="Constant">2</span>, <span class="Constant">4</span> or <span class="Constant">8</span> - => <span class="Constant">"(__check-mu-array-bounds *"</span> rega <span class="Constant">" %"</span> regi <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span> + => <span class="Constant">"81 7/subop/compare %"</span> rega <span class="Constant">" 0/imm32"</span> + <span class="Constant">"0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"</span> + <span class="Constant">"(__check-mu-array-bounds *"</span> rega <span class="Constant">" %"</span> regi <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span> <span class="Constant">"8d/copy-address *("</span> rega <span class="Constant">"+"</span> regi <span class="Constant">"<<"</span> log2(size-of(T)) <span class="Constant">"+4) "</span> reg <span class="Constant">"/r32"</span> var/reg: (addr T) <span class="Special"><-</span> index arr: (array T len), idx/regi: int => <span class="Constant">"(__check-mu-array-bounds *(ebp+"</span> arr.stack-offset <span class="Constant">") %"</span> regi <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span> <span class="Constant">"8d/copy-address *(ebp+"</span> regi <span class="Constant">"<<"</span> log2(size-of(T)) <span class="Constant">"+"</span> (arr.stack-offset + <span class="Constant">4</span>) <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span> var/reg: (addr T) <span class="Special"><-</span> index arr/rega: (addr array T), n - => <span class="Constant">"(__check-mu-array-bounds *"</span> rega <span class="Constant">" "</span> n <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span> + => <span class="Constant">"81 7/subop/compare %"</span> rega <span class="Constant">" 0/imm32"</span> + <span class="Constant">"0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"</span> + <span class="Constant">"(__check-mu-array-bounds *"</span> rega <span class="Constant">" "</span> n <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span> <span class="Constant">"8d/copy-address *("</span> rega <span class="Constant">"+"</span> (n*size-of(T)+<span class="Constant">4</span>) <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span> var/reg: (addr T) <span class="Special"><-</span> index arr: (array T len), n => <span class="Constant">"(__check-mu-array-bounds *(ebp+"</span> arr.stack-offset <span class="Constant">") "</span> n <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span> @@ -359,7 +389,9 @@ var/reg: (offset T) <span class="Special"><-</span> compute-offset arr: (addr var/reg: (offset T) <span class="Special"><-</span> compute-offset arr: (addr array T), idx: int <span class="muComment"># arr can be in reg or mem</span> => <span class="Constant">"69/multiply *(ebp+"</span> idx.stack-offset <span class="Constant">") "</span> size-of(T) <span class="Constant">"/imm32 "</span> reg <span class="Constant">"/r32"</span> var/reg: (addr T) <span class="Special"><-</span> index arr/rega: (addr array T), o/rego: (offset T) - => <span class="Constant">"(__check-mu-array-bounds %"</span> rega <span class="Constant">" %"</span> rego <span class="Constant">" 1 \"" function-name "</span>\<span class="Constant">")"</span> + => <span class="Constant">"81 7/subop/compare %"</span> rega <span class="Constant">" 0/imm32"</span> + <span class="Constant">"0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"</span> + <span class="Constant">"(__check-mu-array-bounds %"</span> rega <span class="Constant">" %"</span> rego <span class="Constant">" 1 \"" function-name "</span>\<span class="Constant">")"</span> <span class="Constant">"8d/copy-address *("</span> rega <span class="Constant">"+"</span> rego <span class="Constant">"+4) "</span> reg <span class="Constant">"/r32"</span> Computing the length of an array is complex. @@ -398,10 +430,14 @@ If a record (product) <span class="PreProc">type</span> T was defined to have el types T_a, T_b, T_c, ..., then accessing one of those elements f of <span class="PreProc">type</span> T_f: var/reg: (addr T_f) <span class="Special"><-</span> get var2/reg2: (addr T), f - => <span class="Constant">"8d/copy-address *("</span> reg2 <span class="Constant">"+"</span> offset(f) <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span> + => <span class="Constant">"81 7/subop/compare %"</span> reg2 <span class="Constant">" 0/imm32"</span> + <span class="Constant">"0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"</span> + <span class="Constant">"8d/copy-address *("</span> reg2 <span class="Constant">"+"</span> offset(f) <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span> var/reg: (addr T_f) <span class="Special"><-</span> get var2: T, f => <span class="Constant">"8d/copy-address *(ebp+"</span> var2.stack-offset <span class="Constant">"+"</span> offset(f) <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span> +When the base is an address we perform a null check. + <span class="muComment"># Allocating memory</span> allocate in: (addr handle T) |