UML Floating Point Opcodes - JoakimLarsson/mame GitHub Wiki
Below is a detailed description of all the UML floating point opcodes. For general information about the UML, please see UML Architecture.
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
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:
void generate_lookup_index_i2_to_f0(drcuml_block *block) { UML_FSLOAD(block, FREG(0), lookup_table, IREG(2)); }
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
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:
void generate_store_f1_to_register_array_index_i9(drcuml_block *block) { UML_FDSTORE(block, register_array, IREG(9), FREG(1)); }
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
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); }
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
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); }
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
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)); }
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
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); }
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
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)); }
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
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)); }
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
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)); }
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
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)); }
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
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)); }
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
- 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
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); }
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
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)); }
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
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)); }
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
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)); }
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
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)); }
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
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)); }
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
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)); }
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
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)); }