UML Floating Point Opcodes

From MAMEDEV Wiki

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));
}