UML Floating Point Opcodes
Below is a detailed description of all the UML floating point opcodes. For general information about the UML, please see UML Architecture.
FLOAD
Usage:
FSLOAD dest,base,index FDLOAD dest,base,index
Codegen Shorthand:
UML_FSLOAD(block, PTYPE(dest), base, PTYPE(index)); UML_FDLOAD(block, PTYPE(dest), base, PTYPE(index));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- base — a memory pointer to the base of the table to read from
- index — a 32-bit integer register, memory location, map variable, or immediate
Flags: undefined
Description: The FSLOAD opcode performs a table-lookup memory read to a 32-bit destination; the FDLOAD opcode does the same to a 64-bit destination.
Unlike a standard memory location parameter (which must reside in the near cache), the base parameter may point anywhere in memory. Furthermore, the index parameter is truly an index and not a byte offset; thus the final address read will be base + (size x index).
Note that it is a defined property of the UML architecture that data passing through floating point registers is not interpreted or modified until arithmetic operations are performed; thus, an FLOAD followed by an FSTORE of the same size is guaranteed to write back the identical data that was read, regardless of whether the data loaded represents a valid IEEE floating point number.
Also note that the index parameter is always a fixed 32-bit size, regardless of the opcode size.
Example:
static const float lookup_table[] = { 0.1, 0.2, 0.4, 0.8 }; void generate_lookup_index_i2_to_f0(drcuml_block *block) { UML_FSLOAD(block, FREG(0), lookup_table, IREG(2)); }
FSTORE
Usage:
FSSTORE base,index,source FDSTORE base,index,source
Codegen Shorthand:
UML_FSSTORE(block, base, PTYPE(index), PTYPE(source)); UML_FDSTORE(block, base, PTYPE(index), PTYPE(source));
Parameters:
- base — a memory pointer to the base of the table to store to
- index — a 32-bit integer register, memory location, map variable, or immediate
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSSTORE opcode performs a table-lookup memory write from a 32-bit source; the FDSTORE opcode does the same from a 64-bit source.
Unlike a standard memory location parameter (which must reside in the near cache), the base parameter may point anywhere in memory. Furthermore, the index parameter is truly an index and not a byte offset; thus the final address read will be base + (size x index).
Note that it is a defined property of the UML architecture that data passing through floating point registers is not interpreted or modified until arithmetic operations are performed; thus, an FLOAD followed by an FSTORE of the same size is guaranteed to write back the identical data that was read, regardless of whether the data loaded represents a valid IEEE floating point number.
Also note that the index parameter is always a fixed 32-bit size, regardless of the opcode size.
Example:
static double register_aray[32]; void generate_store_f1_to_register_array_index_i9(drcuml_block *block) { UML_FDSTORE(block, register_array, IREG(9), FREG(1)); }
FREAD
Usage:
FSREAD dest,address,space FDREAD dest,address,space
Codegen Shorthand:
UML_FSREAD(block, PTYPE(dest), PTYPE(address), PROGRAM | DATA | IO); UML_FDREAD(block, PTYPE(dest), PTYPE(address), PROGRAM | DATA | IO);
Parameters:
- dest — a 32/64-bit floating point register or memory location
- address — a 32-bit integer register, memory location, map variable, or immediate
- space — the address space of the memory to access
Flags: undefined
Description: The FSREAD opcode performs a read from the emulated CPU's memory system to a 32-bit destination; the FDREAD opcode does the same to a 64-bit destination.
Note that it is a defined property of the UML architecture that data passing through floating point registers is not interpreted or modified until arithmetic operations are performed; thus, an FREAD followed by an FWRITE of the same size is guaranteed to write back the identical data that was read, regardless of whether the data loaded represents a valid IEEE floating point number.
Also note that the address parameter is always a fixed 32-bit size, regardless of the opcode size.
Example:
void generate_load_double_from_program_space_address_i0(drcuml_block *block) { UML_FDLOAD(block, FREG(0), IREG(0), PROGRAM); }
FWRITE
Usage:
FSWRITE address,source,space FDWRITE address,source,space
Codegen Shorthand:
UML_FSWRITE(block, PTYPE(address), PTYPE(source), PROGRAM | DATA | IO); UML_FDWRITE(block, PTYPE(address), PTYPE(source), PROGRAM | DATA | IO);
Parameters:
- address — a 32-bit integer register, memory location, map variable, or immediate
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- space — the address space of the memory to access
Flags: undefined
Description: The FSWRITE opcode performs a write to the emulated CPU's memory system from a 32-bit source; the FDWRITE opcode does the same from a 64-bit source.
Note that it is a defined property of the UML architecture that data passing through floating point registers is not interpreted or modified until arithmetic operations are performed; thus, an FREAD followed by an FWRITE of the same size is guaranteed to write back the identical data that was read, regardless of whether the data loaded represents a valid IEEE floating point number.
Also note that the address parameter is always a fixed 32-bit size, regardless of the opcode size.
Example:
void generate_write_float_from_memory(drcuml_block *block, float *memory) { UML_FSWRITE(block, IREG(0), MEM(memory), PROGRAM); }
FMOV
Usage:
FSMOV dest,source[,condition] FDMOV dest,source[,condition]
Codegen Shorthand:
UML_FSMOV(block, PTYPE(dest), PTYPE(source)); UML_FSMOVc(block, condition, PTYPE(dest), PTYPE(source)); UML_FDMOV(block, PTYPE(dest), PTYPE(source)); UML_FDMOVc(block, condition, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
- condition — an optional condition which is used to determine whether or not to perform the move
Flags: unaffected
Description: The FSMOV opcode transfers a 32-bit value from the source operand to the dest operand; the FDMOV opcode does the same with 64-bit values. An optional condition can be provided which makes the move operation dependent on the condition being true. Note that the flags are defined to remain unaffected here; FMOV is one of the very few opcodes that can be reliably used between a flag-changing opcode and a flag-consuming opcode.
Note that it is a defined property of the UML architecture that data passing through floating point registers is not interpreted or modified until arithmetic operations are performed; thus, an FMOV from memory to register and back is guaranteed to write back the same bits regardless of whether the data in question represents a valid IEEE floating point number.
Example:
void generate_swap_two_values(drcuml_block *block, double *val1, double *val2) { UML_FDMOV(block, FREG(0), MEM(val1)); UML_FDMOV(block, MEM(val1), MEM(val2)); UML_FDMOV(block, MEM(val2), FREG(0)); }
FTOINT
Usage:
FSTOINT dest,source,size,round FDTOINT dest,source,size,round
Codegen Shorthand:
UML_FSTOINT(block, PTYPE(dest), PTYPE(source), DWORD | QWORD, TRUNC | ROUND | CEIL | FLOOR | DEFAULT); UML_FDTOINT(block, PTYPE(dest), PTYPE(source), DWORD | QWORD, TRUNC | ROUND | CEIL | FLOOR | DEFAULT);
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit floating point register or memory location
- size — the size of the destination operand; can be 4 or 8
- round — one of five rounding modes to use during conversion:
- DRCUML_FMOD_TRUNC (0) means truncate, or round toward zero
- DRCUML_FMOD_ROUND (1) means round to nearest
- DRCUML_FMOD_CEIL (2) means round toward positive infinity
- DRCUML_FMOD_FLOOR (3) means round toward negative infinity
- DRCUML_FMOD_DEFAULT (4) means round using the mode specified by the most recent SETFMOD instruction
Flags: undefined
Description: The FSTOINT opcode converts a 32-bit source operand to either a 32-bit or 64-bit integer and stores it in the dest operand; the FDTOINT opcode performs the same operation with a 64-bit source operand.
Example:
void generate_convert_float_to_int64_with_truncation(drcuml_block *block) { UML_FSTOINT(block, IREG(0), FREG(0), QWORD, TRUNC); }
FFRINT
Usage:
FSFRINT dest,source,size FDFRINT dest,source,size
Codegen Shorthand:
UML_FSFRINT(block, PTYPE(dest), PTYPE(source), DWORD | QWORD); UML_FDFRINT(block, PTYPE(dest), PTYPE(source), DWORD | QWORD);
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- size — the size of the source operand; can be 4 or 8
Flags: undefined
Description: The FSFRINT opcode converts a 32-bit or 64-bit source integer operand to a 32-bit floating point value and stores it in the dest operand; the FDFRINT opcode performs the same operation to a 64-bit dest operand.
Example:
void generate_load_1_into_f2(drcuml_block *block) { UML_FDFRINT(block, FREG(2), IMM(1)); }
FFRFLT
Usage:
FSFRFLT dest,source,size FDFRFLT dest,source,size
Codegen Shorthand:
UML_FSFRFLT(block, PTYPE(dest), PTYPE(source), QWORD); UML_FDFRFLT(block, PTYPE(dest), PTYPE(source), DWORD);
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
- size — the size of the source operand; can be 4 or 8
Flags: undefined
Description: The FSFRFLT opcode converts a 64-bit source floating point operand to a 32-bit floating point value and stores it in the dest operand; the FDFRFLT opcode converts a 32-bit source floating point operand to a 64-bit floating point value and stores it in the dest operand
The rounding mode used by this opcode is implied by the most recent SETFMOD operation.
Example:
void generate_convert_float_to_double(drcuml_block *block) { UML_FDFRFLT(block, FREG(0), FREG(2)); }
FRNDS
Usage:
FDRNDS dest,source,size
Codegen Shorthand:
UML_FDRNDS(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FDRNDS opcode rounds a 64-bit source floating point operand to single-precision and stores the resulting 64-bit floating point value to the dest operand.
The rounding mode used by this opcode is implied by the most recent SETFMOD operation.
Example:
void generate_reduce_to_single_precision(drcuml_block *block) { UML_FDRNDS(block, FREG(0), FREG(0)); }
FADD
Usage:
FSADD dest,source1,source2 FDADD dest,source1,source2
Codegen Shorthand:
UML_FSADD(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_FDADD(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source1 — a 32/64-bit floating point register or memory location
- source2 — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSADD opcode performs addition between the 32-bit source1 and source2 operands and stores the result in dest; the FDADD opcode performs the same operation using 64-bit operands.
Example:
void generate_add_one_float(drcuml_block *block) { UML_FSFRINT(block, FREG(1), IMM(1)); UML_FSADD(block, FREG(0), FREG(0), FREG(1)); }
FSUB
Usage:
FSSUB dest,source1,source2 FDSUB dest,source1,source2
Codegen Shorthand:
UML_FSSUB(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_FDSUB(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source1 — a 32/64-bit floating point register or memory location
- source2 — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSSUB opcode subtracts the 32-bit source2 operand from the source1 operand and stores the result in dest; the FDSUB opcode performs the same operation using 64-bit operands.
Example:
void generate_negate_f0_double(drcuml_block *block) { UML_FDFRINT(block, FREG(1), IMM(0)); UML_FDSUB(block, FREG(0), FREG(1), FREG(0)); }
FCMP
Usage:
FSCMP source1,source2 FDCMP source1,source2
Codegen Shorthand:
UML_FSCMP(block, PTYPE(source1), PTYPE(source2)); UML_FDCMP(block, PTYPE(source1), PTYPE(source2));
Parameters:
- source1 — a 32/64-bit floating point register or memory location
- source2 — a 32/64-bit floating point register or memory location
Flags:
- C — set if source1 is less than source2
- V — undefined
- Z — set if source1 is equal to source2
- S — undefined
- U — set if either source1 or source2 is a NaN
Description: The FSCMP opcode compares two 32-bit floating point values and sets the flags accordingly; the FDCMP does the same operation with 64-bit floating point values.
Example:
void generate_branch_if_invalid_fp_value_in_i0(drcuml_block *block, drcuml_codelabel target) { UML_FDCMP(block, FREG(0), FREG(0)); UML_JMPc(block, IF_U, target); }
FMUL
Usage:
FSMUL dest,source1,source2 FDMUL dest,source1,source2
Codegen Shorthand:
UML_FSMUL(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_FDMUL(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source1 — a 32/64-bit floating point register or memory location
- source2 — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSMUL opcode multiplies two 32-bit source operands and stores the result in dest; the FDMUL opcode performs the same operation using 64-bit operands.
Example:
void generate_compute_f0_squared(drcuml_block *block) { UML_FDMUL(block, FREG(0), FREG(0), FREG(0)); }
FDIV
Usage:
FSDIV dest,source1,source2 FDDIV dest,source1,source2
Codegen Shorthand:
UML_FSDIV(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_FDDIV(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source1 — a 32/64-bit floating point register or memory location
- source2 — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSDIV opcode divides the 32-bit source1 operand by the 32-bit source2 operand and stores the result in dest; the FDDIV opcode performs the same operation using 64-bit operands.
Example:
void generate_divide_f5_by_constant_in_memory(drcuml_block *block, const float *divisor) { UML_FSDIV(block, FREG(5), FREG(5), MEM(divisor)); }
FNEG
Usage:
FSNEG dest,source FDNEG dest,source
Codegen Shorthand:
UML_FSNEG(block, PTYPE(dest), PTYPE(source)); UML_FDNEG(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSNEG opcode computes the negative of the 32-bit source operand and stores the result in dest; the FDNEG opcode performs the same operation for a 64-bit operand.
Example:
void generate_fnmadd(drcuml_block *block) { /* compute f0 = -(f2 * f3 + f1) */ UML_FSMUL(block, FREG(0), FREG(2), FREG(3)); UML_FSADD(block, FREG(0), FREG(0), FREG(1)); UML_FSNEG(block, FREG(0), FREG(0)); }
FABS
Usage:
FSABS dest,source FDABS dest,source
Codegen Shorthand:
UML_FSABS(block, PTYPE(dest), PTYPE(source)); UML_FDABS(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSABS opcode computes the absolute volume of the 32-bit source operand and stores the result in dest; the FDABS opcode performs the same operation for a 64-bit operand.
Example:
void generate_compute_absolute_delta_f1_and_f2(drcuml_block *block) { UML_FDSUB(block, FREG(0), FREG(1), FREG(2)); UML_FDABS(block, FREG(0), FREG(0)); }
FSQRT
Usage:
FSSQRT dest,source FDSQRT dest,source
Codegen Shorthand:
UML_FSSQRT(block, PTYPE(dest), PTYPE(source)); UML_FDSQRT(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSSQRT opcode computes the square root of the 32-bit source operand and stores the result in dest; the FDSQRT opcode performs the same operation for a 64-bit operand.
Example:
void generate_compute_hypoteneuse(drcuml_block *block) { /* lengths in f1,f2 */ UML_FDMUL(block, FREG(1), FREG(1), FREG(1)); UML_FDMUL(block, FREG(2), FREG(2), FREG(2)); UML_FDADD(block, FREG(0), FREG(1), FREG(2)); UML_FDSQRT(block, FREG(0), FREG(0)); }
FRECIP
Usage:
FSRECIP dest,source FDRECIP dest,source
Codegen Shorthand:
UML_FSRECIP(block, PTYPE(dest), PTYPE(source)); UML_FDRECIP(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSRECIP opcode computes an approximate reciprocal of the 32-bit source operand and stores the result in dest; the FDRECIP opcode performs the same operation for a 64-bit operand.
Note that it is currently undefined what the minimum accuracy of this reciprocal approximation must be.
Example:
void generate_compute_fast_corrected_uv(drcuml_block *block) { /* f1=u, f2=v, f0=z */ UML_FSRECIP(block, FREG(0), FREG(0)); UML_FSMUL(block, FREG(1), FREG(1), FREG(0)); UML_FSMUL(block, FREG(2), FREG(2), FREG(0)); }
FRSQRT
Usage:
FSRSQRT dest,source FDRSQRT dest,source
Codegen Shorthand:
UML_FSRSQRT(block, PTYPE(dest), PTYPE(source)); UML_FDRSQRT(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit floating point register or memory location
- source — a 32/64-bit floating point register or memory location
Flags: undefined
Description: The FSRSQRT opcode computes an approximate reciprocal square root of the 32-bit source operand and stores the result in dest; the FDRECIP opcode performs the same operation for a 64-bit operand.
Note that it is currently undefined what the minimum accuracy of this reciprocal square root approximation must be.
Example:
void generate_fast_approximate_vector_length(drcuml_block *block) { /* f1=x, f2=y, f3=z */ UML_FSMUL(block, FREG(1), FREG(1), FREG(1)); UML_FSMUL(block, FREG(2), FREG(2), FREG(2)); UML_FSMUL(block, FREG(3), FREG(3), FREG(3)); UML_FSADD(block, FREG(0), FREG(1), FREG(2)); UML_FSADD(block, FREG(0), FREG(0), FREG(3)); UML_FSRSQRT(block, FREG(1), FREG(0)); UML_FSMUL(block, FREG(0), FREG(0), FREG(1)); }