7146
This commit is contained in:
parent
8c44afcccc
commit
3f30e4c6e6
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>~/Attic/Repos/mu/mu_instructions.html</title>
|
||||
<title>Mu's instructions and their table-driven translation</title>
|
||||
<meta name="Generator" content="Vim/8.1">
|
||||
<meta name="plugin-version" content="vim8.1_v1">
|
||||
<meta name="syntax" content="none">
|
||||
|
@ -150,6 +150,92 @@ compare *var/reg, n => <span class="Constant">"81 7/subop/
|
|||
var/reg <span class="SpecialChar"><-</span> multiply var2 => <span class="Constant">"0f af/multiply *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> multiply *var2/reg2 => <span class="Constant">"0f af/multiply *"</span> reg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
|
||||
<span class="muComment"># Floating-point operations</span>
|
||||
|
||||
All the instructions so far use Intel's general-purpose integer registers.
|
||||
However, some of them translate to different SubX if their arguments are in
|
||||
floating-point registers.
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> add var2/xreg2 => <span class="Constant">"f3 0f 58/add %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> add var2 => <span class="Constant">"f3 0f 58/add *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> add *var2/reg2 => <span class="Constant">"f3 0f 58/add *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> subtract var2/xreg2 => <span class="Constant">"f3 0f 5c/subtract %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> subtract var2 => <span class="Constant">"f3 0f 5c/subtract *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> subtract *var2/reg2 => <span class="Constant">"f3 0f 5c/subtract *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> multiply var2/xreg2 => <span class="Constant">"f3 0f 59/multiply %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> multiply var2 => <span class="Constant">"f3 0f 59/multiply *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> multiply *var2/reg2 => <span class="Constant">"f3 0f 59/multiply *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> divide var2/xreg2 => <span class="Constant">"f3 0f 5e/divide %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> divide var2 => <span class="Constant">"f3 0f 5e/divide *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> divide *var2/reg2 => <span class="Constant">"f3 0f 5e/divide *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
There are also some exclusively floating-point instructions:
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> reciprocal var2/xreg2 => <span class="Constant">"f3 0f 53/reciprocal %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> reciprocal var2 => <span class="Constant">"f3 0f 53/reciprocal *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> reciprocal *var2/reg2 => <span class="Constant">"f3 0f 53/reciprocal *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> square-root var2/xreg2 => <span class="Constant">"f3 0f 51/square-root %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> square-root var2 => <span class="Constant">"f3 0f 51/square-root *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> square-root *var2/reg2 => <span class="Constant">"f3 0f 51/square-root *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> inverse-square-root var2/xreg2 => <span class="Constant">"f3 0f 52/inverse-square-root %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> inverse-square-root var2 => <span class="Constant">"f3 0f 52/inverse-square-root *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> inverse-square-root *var2/reg2 => <span class="Constant">"f3 0f 52/inverse-square-root *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> min var2/xreg2 => <span class="Constant">"f3 0f 5d/min %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> min var2 => <span class="Constant">"f3 0f 5d/min *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> min *var2/reg2 => <span class="Constant">"f3 0f 5d/min *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> max var2/xreg2 => <span class="Constant">"f3 0f 5f/max %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> max var2 => <span class="Constant">"f3 0f 5f/max *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> max *var2/reg2 => <span class="Constant">"f3 0f 5f/max *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
Remember, when these instructions use indirect mode, they still use an integer
|
||||
register. Floating-point registers can't hold addresses.
|
||||
|
||||
Most instructions operate exclusively on integer or floating-point operands.
|
||||
The only exceptions are the instructions for converting between integers and
|
||||
floating-point numbers.
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> convert var2/reg2 => <span class="Constant">"f3 0f 2a/convert-to-float %"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> convert var2 => <span class="Constant">"f3 0f 2a/convert-to-float *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> convert *var2/reg2 => <span class="Constant">"f3 0f 2a/convert-to-float *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
Converting floats to ints performs rounding by default. (We don't mess with the
|
||||
MXCSR control register.)
|
||||
|
||||
var/reg <span class="SpecialChar"><-</span> convert var2/xreg2 => <span class="Constant">"f3 0f 2d/convert-to-int %"</span> xreg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> convert var2 => <span class="Constant">"f3 0f 2d/convert-to-int *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> convert *var2/reg2 => <span class="Constant">"f3 0f 2d/convert-to-int *"</span> reg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
|
||||
There's a separate instruction for truncating the fractional part.
|
||||
|
||||
var/reg <span class="SpecialChar"><-</span> truncate var2/xreg2 => <span class="Constant">"f3 0f 2c/truncate-to-int %"</span> xreg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> truncate var2 => <span class="Constant">"f3 0f 2c/truncate-to-int *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> truncate *var2/reg2 => <span class="Constant">"f3 0f 2c/truncate-to-int *"</span> reg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
|
||||
There are no instructions accepting floating-point literals. To obtain integer
|
||||
literals in floating-point registers, copy them to general-purpose registers
|
||||
and then convert them to floating-point.
|
||||
|
||||
One pattern you may have noticed above is that the floating-point instructions
|
||||
above always write to registers. The only exceptions are `copy` instructions,
|
||||
which can write to memory locations.
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> copy var2/xreg2 => <span class="Constant">"f3 0f 11/<- %"</span> xreg <span class="Constant">" "</span> xreg2 <span class="Constant">"/x32"</span>
|
||||
copy-to var1, var2/xreg => <span class="Constant">"f3 0f 11/<- *(ebp+"</span> var1.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> copy var2 => <span class="Constant">"f3 0f 10/-> *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> copy *var2/reg2 => <span class="Constant">"f3 0f 10/-> *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
Comparisons must always start with a register:
|
||||
|
||||
compare var1/xreg1, var2/xreg2 => <span class="Constant">"0f 2f/compare %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
compare var1/xreg1, var2 => <span class="Constant">"0f 2f/compare *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
|
||||
<span class="PreProc">break</span> => <span class="Constant">"e9/jump break/disp32"</span>
|
||||
<span class="PreProc">break</span> label => <span class="Constant">"e9/jump "</span> label <span class="Constant">":break/disp32"</span>
|
||||
<span class="PreProc">loop</span> => <span class="Constant">"e9/jump loop/disp32"</span>
|
||||
|
@ -296,92 +382,6 @@ read-from-stream s: (addr stream T), out: (addr T)
|
|||
write-to-stream s: (addr stream T), in: (addr T)
|
||||
=> <span class="Constant">"(write-to-stream "</span> s <span class="Constant">" "</span> in <span class="Constant">" "</span> size-of(T) <span class="Constant">")"</span>
|
||||
|
||||
<span class="muComment"># Floating-point operations</span>
|
||||
|
||||
All the instructions so far use Intel's general-purpose integer registers.
|
||||
However, some of them translate to different SubX if their arguments are in
|
||||
floating-point registers.
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> add var2/xreg2 => <span class="Constant">"f3 0f 58/add %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> add var2 => <span class="Constant">"f3 0f 58/add *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> add *var2/reg2 => <span class="Constant">"f3 0f 58/add *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> subtract var2/xreg2 => <span class="Constant">"f3 0f 5c/subtract %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> subtract var2 => <span class="Constant">"f3 0f 5c/subtract *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> subtract *var2/reg2 => <span class="Constant">"f3 0f 5c/subtract *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> multiply var2/xreg2 => <span class="Constant">"f3 0f 59/multiply %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> multiply var2 => <span class="Constant">"f3 0f 59/multiply *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> multiply *var2/reg2 => <span class="Constant">"f3 0f 59/multiply *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> divide var2/xreg2 => <span class="Constant">"f3 0f 5e/divide %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> divide var2 => <span class="Constant">"f3 0f 5e/divide *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> divide *var2/reg2 => <span class="Constant">"f3 0f 5e/divide *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
There are also some exclusively floating-point instructions:
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> reciprocal var2/xreg2 => <span class="Constant">"f3 0f 53/reciprocal %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> reciprocal var2 => <span class="Constant">"f3 0f 53/reciprocal *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> reciprocal *var2/reg2 => <span class="Constant">"f3 0f 53/reciprocal *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> square-root var2/xreg2 => <span class="Constant">"f3 0f 51/square-root %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> square-root var2 => <span class="Constant">"f3 0f 51/square-root *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> square-root *var2/reg2 => <span class="Constant">"f3 0f 51/square-root *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> inverse-square-root var2/xreg2 => <span class="Constant">"f3 0f 52/inverse-square-root %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> inverse-square-root var2 => <span class="Constant">"f3 0f 52/inverse-square-root *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> inverse-square-root *var2/reg2 => <span class="Constant">"f3 0f 52/inverse-square-root *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> min var2/xreg2 => <span class="Constant">"f3 0f 5d/min %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> min var2 => <span class="Constant">"f3 0f 5d/min *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> min *var2/reg2 => <span class="Constant">"f3 0f 5d/min *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> max var2/xreg2 => <span class="Constant">"f3 0f 5f/max %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> max var2 => <span class="Constant">"f3 0f 5f/max *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> max *var2/reg2 => <span class="Constant">"f3 0f 5f/max *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
Remember, when these instructions use indirect mode, they still use an integer
|
||||
register. Floating-point registers can't hold addresses.
|
||||
|
||||
Most instructions operate exclusively on integer or floating-point operands.
|
||||
The only exceptions are the instructions for converting between integers and
|
||||
floating-point numbers.
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> convert var2/reg2 => <span class="Constant">"f3 0f 2a/convert-to-float %"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> convert var2 => <span class="Constant">"f3 0f 2a/convert-to-float *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> convert *var2/reg2 => <span class="Constant">"f3 0f 2a/convert-to-float *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
Converting floats to ints performs rounding by default. (We don't mess with the
|
||||
MXCSR control register.)
|
||||
|
||||
var/reg <span class="SpecialChar"><-</span> convert var2/xreg2 => <span class="Constant">"f3 0f 2d/convert-to-int %"</span> xreg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> convert var2 => <span class="Constant">"f3 0f 2d/convert-to-int *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> convert *var2/reg2 => <span class="Constant">"f3 0f 2d/convert-to-int *"</span> reg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
|
||||
There's a separate instruction for truncating the fractional part.
|
||||
|
||||
var/reg <span class="SpecialChar"><-</span> truncate var2/xreg2 => <span class="Constant">"f3 0f 2c/truncate-to-int %"</span> xreg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> truncate var2 => <span class="Constant">"f3 0f 2c/truncate-to-int *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> reg <span class="Constant">"/r32"</span>
|
||||
var/reg <span class="SpecialChar"><-</span> truncate *var2/reg2 => <span class="Constant">"f3 0f 2c/truncate-to-int *"</span> reg2 <span class="Constant">" "</span> reg <span class="Constant">"/r32"</span>
|
||||
|
||||
There are no instructions accepting floating-point literals. To obtain integer
|
||||
literals in floating-point registers, copy them to general-purpose registers
|
||||
and then convert them to floating-point.
|
||||
|
||||
One pattern you may have noticed above is that the floating-point instructions
|
||||
above always write to registers. The only exceptions are `copy` instructions,
|
||||
which can write to memory locations.
|
||||
|
||||
var/xreg <span class="SpecialChar"><-</span> copy var2/xreg2 => <span class="Constant">"f3 0f 11/<- %"</span> xreg <span class="Constant">" "</span> xreg2 <span class="Constant">"/x32"</span>
|
||||
copy-to var1, var2/xreg => <span class="Constant">"f3 0f 11/<- *(ebp+"</span> var1.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> copy var2 => <span class="Constant">"f3 0f 10/-> *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg <span class="Constant">"/x32"</span>
|
||||
var/xreg <span class="SpecialChar"><-</span> copy *var2/reg2 => <span class="Constant">"f3 0f 10/-> *"</span> reg2 <span class="Constant">" "</span> xreg <span class="Constant">"/x32"</span>
|
||||
|
||||
Comparisons must always start with a register:
|
||||
|
||||
compare var1/xreg1, var2/xreg2 => <span class="Constant">"0f 2f/compare %"</span> xreg2 <span class="Constant">" "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
compare var1/xreg1, var2 => <span class="Constant">"0f 2f/compare *(ebp+"</span> var2.stack-offset <span class="Constant">") "</span> xreg1 <span class="Constant">"/x32"</span>
|
||||
|
||||
vim:ft=mu:nowrap:textwidth=<span class="Constant">0</span>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
172
mu_instructions
172
mu_instructions
|
@ -126,6 +126,92 @@ compare *var/reg, n => "81 7/subop/compare *" reg " " n "/imm32"
|
|||
var/reg <- multiply var2 => "0f af/multiply *(ebp+" var2.stack-offset ") " reg "/r32"
|
||||
var/reg <- multiply *var2/reg2 => "0f af/multiply *" reg2 " " reg "/r32"
|
||||
|
||||
# Floating-point operations
|
||||
|
||||
All the instructions so far use Intel's general-purpose integer registers.
|
||||
However, some of them translate to different SubX if their arguments are in
|
||||
floating-point registers.
|
||||
|
||||
var/xreg <- add var2/xreg2 => "f3 0f 58/add %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- add var2 => "f3 0f 58/add *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- add *var2/reg2 => "f3 0f 58/add *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- subtract var2/xreg2 => "f3 0f 5c/subtract %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- subtract var2 => "f3 0f 5c/subtract *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- subtract *var2/reg2 => "f3 0f 5c/subtract *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- multiply var2/xreg2 => "f3 0f 59/multiply %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- multiply var2 => "f3 0f 59/multiply *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- multiply *var2/reg2 => "f3 0f 59/multiply *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- divide var2/xreg2 => "f3 0f 5e/divide %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- divide var2 => "f3 0f 5e/divide *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- divide *var2/reg2 => "f3 0f 5e/divide *" reg2 " " xreg "/x32"
|
||||
|
||||
There are also some exclusively floating-point instructions:
|
||||
|
||||
var/xreg <- reciprocal var2/xreg2 => "f3 0f 53/reciprocal %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- reciprocal var2 => "f3 0f 53/reciprocal *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- reciprocal *var2/reg2 => "f3 0f 53/reciprocal *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- square-root var2/xreg2 => "f3 0f 51/square-root %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- square-root var2 => "f3 0f 51/square-root *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- square-root *var2/reg2 => "f3 0f 51/square-root *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- inverse-square-root var2/xreg2 => "f3 0f 52/inverse-square-root %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- inverse-square-root var2 => "f3 0f 52/inverse-square-root *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- inverse-square-root *var2/reg2 => "f3 0f 52/inverse-square-root *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- min var2/xreg2 => "f3 0f 5d/min %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- min var2 => "f3 0f 5d/min *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- min *var2/reg2 => "f3 0f 5d/min *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- max var2/xreg2 => "f3 0f 5f/max %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- max var2 => "f3 0f 5f/max *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- max *var2/reg2 => "f3 0f 5f/max *" reg2 " " xreg "/x32"
|
||||
|
||||
Remember, when these instructions use indirect mode, they still use an integer
|
||||
register. Floating-point registers can't hold addresses.
|
||||
|
||||
Most instructions operate exclusively on integer or floating-point operands.
|
||||
The only exceptions are the instructions for converting between integers and
|
||||
floating-point numbers.
|
||||
|
||||
var/xreg <- convert var2/reg2 => "f3 0f 2a/convert-to-float %" reg2 " " xreg "/x32"
|
||||
var/xreg <- convert var2 => "f3 0f 2a/convert-to-float *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- convert *var2/reg2 => "f3 0f 2a/convert-to-float *" reg2 " " xreg "/x32"
|
||||
|
||||
Converting floats to ints performs rounding by default. (We don't mess with the
|
||||
MXCSR control register.)
|
||||
|
||||
var/reg <- convert var2/xreg2 => "f3 0f 2d/convert-to-int %" xreg2 " " reg "/r32"
|
||||
var/reg <- convert var2 => "f3 0f 2d/convert-to-int *(ebp+" var2.stack-offset ") " reg "/r32"
|
||||
var/reg <- convert *var2/reg2 => "f3 0f 2d/convert-to-int *" reg2 " " reg "/r32"
|
||||
|
||||
There's a separate instruction for truncating the fractional part.
|
||||
|
||||
var/reg <- truncate var2/xreg2 => "f3 0f 2c/truncate-to-int %" xreg2 " " reg "/r32"
|
||||
var/reg <- truncate var2 => "f3 0f 2c/truncate-to-int *(ebp+" var2.stack-offset ") " reg "/r32"
|
||||
var/reg <- truncate *var2/reg2 => "f3 0f 2c/truncate-to-int *" reg2 " " reg "/r32"
|
||||
|
||||
There are no instructions accepting floating-point literals. To obtain integer
|
||||
literals in floating-point registers, copy them to general-purpose registers
|
||||
and then convert them to floating-point.
|
||||
|
||||
One pattern you may have noticed above is that the floating-point instructions
|
||||
above always write to registers. The only exceptions are `copy` instructions,
|
||||
which can write to memory locations.
|
||||
|
||||
var/xreg <- copy var2/xreg2 => "f3 0f 11/<- %" xreg " " xreg2 "/x32"
|
||||
copy-to var1, var2/xreg => "f3 0f 11/<- *(ebp+" var1.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- copy var2 => "f3 0f 10/-> *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- copy *var2/reg2 => "f3 0f 10/-> *" reg2 " " xreg "/x32"
|
||||
|
||||
Comparisons must always start with a register:
|
||||
|
||||
compare var1/xreg1, var2/xreg2 => "0f 2f/compare %" xreg2 " " xreg1 "/x32"
|
||||
compare var1/xreg1, var2 => "0f 2f/compare *(ebp+" var2.stack-offset ") " xreg1 "/x32"
|
||||
|
||||
break => "e9/jump break/disp32"
|
||||
break label => "e9/jump " label ":break/disp32"
|
||||
loop => "e9/jump loop/disp32"
|
||||
|
@ -272,90 +358,4 @@ read-from-stream s: (addr stream T), out: (addr T)
|
|||
write-to-stream s: (addr stream T), in: (addr T)
|
||||
=> "(write-to-stream " s " " in " " size-of(T) ")"
|
||||
|
||||
# Floating-point operations
|
||||
|
||||
All the instructions so far use Intel's general-purpose integer registers.
|
||||
However, some of them translate to different SubX if their arguments are in
|
||||
floating-point registers.
|
||||
|
||||
var/xreg <- add var2/xreg2 => "f3 0f 58/add %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- add var2 => "f3 0f 58/add *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- add *var2/reg2 => "f3 0f 58/add *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- subtract var2/xreg2 => "f3 0f 5c/subtract %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- subtract var2 => "f3 0f 5c/subtract *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- subtract *var2/reg2 => "f3 0f 5c/subtract *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- multiply var2/xreg2 => "f3 0f 59/multiply %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- multiply var2 => "f3 0f 59/multiply *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- multiply *var2/reg2 => "f3 0f 59/multiply *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- divide var2/xreg2 => "f3 0f 5e/divide %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- divide var2 => "f3 0f 5e/divide *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- divide *var2/reg2 => "f3 0f 5e/divide *" reg2 " " xreg "/x32"
|
||||
|
||||
There are also some exclusively floating-point instructions:
|
||||
|
||||
var/xreg <- reciprocal var2/xreg2 => "f3 0f 53/reciprocal %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- reciprocal var2 => "f3 0f 53/reciprocal *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- reciprocal *var2/reg2 => "f3 0f 53/reciprocal *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- square-root var2/xreg2 => "f3 0f 51/square-root %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- square-root var2 => "f3 0f 51/square-root *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- square-root *var2/reg2 => "f3 0f 51/square-root *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- inverse-square-root var2/xreg2 => "f3 0f 52/inverse-square-root %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- inverse-square-root var2 => "f3 0f 52/inverse-square-root *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- inverse-square-root *var2/reg2 => "f3 0f 52/inverse-square-root *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- min var2/xreg2 => "f3 0f 5d/min %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- min var2 => "f3 0f 5d/min *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- min *var2/reg2 => "f3 0f 5d/min *" reg2 " " xreg "/x32"
|
||||
|
||||
var/xreg <- max var2/xreg2 => "f3 0f 5f/max %" xreg2 " " xreg1 "/x32"
|
||||
var/xreg <- max var2 => "f3 0f 5f/max *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- max *var2/reg2 => "f3 0f 5f/max *" reg2 " " xreg "/x32"
|
||||
|
||||
Remember, when these instructions use indirect mode, they still use an integer
|
||||
register. Floating-point registers can't hold addresses.
|
||||
|
||||
Most instructions operate exclusively on integer or floating-point operands.
|
||||
The only exceptions are the instructions for converting between integers and
|
||||
floating-point numbers.
|
||||
|
||||
var/xreg <- convert var2/reg2 => "f3 0f 2a/convert-to-float %" reg2 " " xreg "/x32"
|
||||
var/xreg <- convert var2 => "f3 0f 2a/convert-to-float *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- convert *var2/reg2 => "f3 0f 2a/convert-to-float *" reg2 " " xreg "/x32"
|
||||
|
||||
Converting floats to ints performs rounding by default. (We don't mess with the
|
||||
MXCSR control register.)
|
||||
|
||||
var/reg <- convert var2/xreg2 => "f3 0f 2d/convert-to-int %" xreg2 " " reg "/r32"
|
||||
var/reg <- convert var2 => "f3 0f 2d/convert-to-int *(ebp+" var2.stack-offset ") " reg "/r32"
|
||||
var/reg <- convert *var2/reg2 => "f3 0f 2d/convert-to-int *" reg2 " " reg "/r32"
|
||||
|
||||
There's a separate instruction for truncating the fractional part.
|
||||
|
||||
var/reg <- truncate var2/xreg2 => "f3 0f 2c/truncate-to-int %" xreg2 " " reg "/r32"
|
||||
var/reg <- truncate var2 => "f3 0f 2c/truncate-to-int *(ebp+" var2.stack-offset ") " reg "/r32"
|
||||
var/reg <- truncate *var2/reg2 => "f3 0f 2c/truncate-to-int *" reg2 " " reg "/r32"
|
||||
|
||||
There are no instructions accepting floating-point literals. To obtain integer
|
||||
literals in floating-point registers, copy them to general-purpose registers
|
||||
and then convert them to floating-point.
|
||||
|
||||
One pattern you may have noticed above is that the floating-point instructions
|
||||
above always write to registers. The only exceptions are `copy` instructions,
|
||||
which can write to memory locations.
|
||||
|
||||
var/xreg <- copy var2/xreg2 => "f3 0f 11/<- %" xreg " " xreg2 "/x32"
|
||||
copy-to var1, var2/xreg => "f3 0f 11/<- *(ebp+" var1.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- copy var2 => "f3 0f 10/-> *(ebp+" var2.stack-offset ") " xreg "/x32"
|
||||
var/xreg <- copy *var2/reg2 => "f3 0f 10/-> *" reg2 " " xreg "/x32"
|
||||
|
||||
Comparisons must always start with a register:
|
||||
|
||||
compare var1/xreg1, var2/xreg2 => "0f 2f/compare %" xreg2 " " xreg1 "/x32"
|
||||
compare var1/xreg1, var2 => "0f 2f/compare *(ebp+" var2.stack-offset ") " xreg1 "/x32"
|
||||
|
||||
vim:ft=mu:nowrap:textwidth=0
|
||||
|
|
Loading…
Reference in New Issue