From 3f30e4c6e6598eb281331626f0f021005ba608f3 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 31 Oct 2020 19:50:41 -0700 Subject: 7146 --- mu_instructions | 172 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 86 insertions(+), 86 deletions(-) (limited to 'mu_instructions') diff --git a/mu_instructions b/mu_instructions index f93bb685..8879c878 100644 --- a/mu_instructions +++ b/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 -- cgit 1.4.1-2-gfad0