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.

Table of Contents

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:

 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:

 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));
 }
⚠️ **GitHub.com Fallback** ⚠️