UML Integer Opcodes: Difference between revisions
No edit summary |
No edit summary |
||
(12 intermediate revisions by 3 users not shown) | |||
Line 4: | Line 4: | ||
'''Usage:''' | '''Usage:''' | ||
LOAD ''dest'',''base'',''index'',''size'' | LOAD ''dest'',''base'',''index'',''size'',''scale'' | ||
DLOAD ''dest'',''base'',''index'',''size'' | DLOAD ''dest'',''base'',''index'',''size'',''scale'' | ||
'''Codegen Shorthand:''' | '''Codegen Shorthand:''' | ||
UML_LOAD(block, PTYPE(''dest''), ''base'', PTYPE(''index''), BYTE | WORD | DWORD); | UML_LOAD(block, PTYPE(''dest''), ''base'', PTYPE(''index''), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); | ||
UML_DLOAD(block, PTYPE(''dest''), ''base'', PTYPE(''index''), BYTE | WORD | DWORD | QWORD); | UML_DLOAD(block, PTYPE(''dest''), ''base'', PTYPE(''index''), SIZE_ ## (BYTE | WORD | DWORD | QWORD), SCALE_ ## (x1 | x2 | x4 | x8)); | ||
'''Parameters:''' | '''Parameters:''' | ||
Line 16: | Line 16: | ||
* ''index'' — a 32/64-bit integer register, memory location, map variable, or immediate | * ''index'' — a 32/64-bit integer register, memory location, map variable, or immediate | ||
* ''size'' — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form) | * ''size'' — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form) | ||
* ''scale'' — the scale factor to apply to the index; can be 1, 2, 4, or 8 | |||
'''Flags:''' undefined | '''Flags:''' undefined | ||
Line 21: | Line 22: | ||
'''Description:''' The '''LOAD''' opcode performs a table-lookup memory read to a 32-bit destination; the '''DLOAD''' opcode does the same to a 64-bit destination. If the ''size'' specified is smaller than the destination, the result is zero-extended before being stored. | '''Description:''' The '''LOAD''' opcode performs a table-lookup memory read to a 32-bit destination; the '''DLOAD''' opcode does the same to a 64-bit destination. If the ''size'' specified is smaller than the destination, the result is zero-extended before being stored. | ||
Unlike a standard memory location parameter (which must reside in the near cache), the ''base'' parameter may point anywhere in memory. | Unlike a standard memory location parameter (which must reside in the near cache), the ''base'' parameter may point anywhere in memory. The ''index'' parameter is scaled by the ''scale'' parameter prior to being added to the base. | ||
'''Example:''' | '''Example:''' | ||
Line 28: | Line 29: | ||
void generate_lookup_index_i2_to_i0(drcuml_block *block) | void generate_lookup_index_i2_to_i0(drcuml_block *block) | ||
{ | { | ||
UML_LOAD(block, | UML_LOAD(block, ireg(0), lookup_table, ireg(2), SIZE_WORD, SCALE_x2); | ||
} | } | ||
Line 34: | Line 35: | ||
'''Usage:''' | '''Usage:''' | ||
LOADS ''dest'',''base'',''index'',''size'' | LOADS ''dest'',''base'',''index'',''size'',''scale'' | ||
DLOADS ''dest'',''base'',''index'',''size'' | DLOADS ''dest'',''base'',''index'',''size'',''scale'' | ||
'''Codegen Shorthand:''' | '''Codegen Shorthand:''' | ||
UML_LOADS(block, PTYPE(''dest''), ''base'', PTYPE(''index''), BYTE | WORD | DWORD); | UML_LOADS(block, PTYPE(''dest''), ''base'', PTYPE(''index''), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); | ||
UML_DLOADS(block, PTYPE(''dest''), ''base'', PTYPE(''index''), BYTE | WORD | DWORD | | UML_DLOADS(block, PTYPE(''dest''), ''base'', PTYPE(''index''), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); | ||
'''Parameters:''' | '''Parameters:''' | ||
Line 46: | Line 47: | ||
* ''index'' — a 32/64-bit integer register, memory location, map variable, or immediate | * ''index'' — a 32/64-bit integer register, memory location, map variable, or immediate | ||
* ''size'' — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form) | * ''size'' — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form) | ||
* ''scale'' — the scale factor to apply to the index; can be 1, 2, 4, or 8 | |||
'''Flags:''' undefined | '''Flags:''' undefined | ||
'''Description:''' The '''LOADS''' opcode performs a table-lookup memory read to a 32-bit destination; the '''DLOADS''' | '''Description:''' The '''LOADS''' opcode performs a table-lookup memory read to a 32-bit destination; the '''DLOADS''' opcode does the same to a 64-bit destination. If the ''size'' specified is smaller than the destination, the result is sign-extended before being stored. | ||
Unlike a standard memory location parameter (which must reside in the near cache), the ''base'' parameter may point anywhere in memory. | Unlike a standard memory location parameter (which must reside in the near cache), the ''base'' parameter may point anywhere in memory. The ''index'' parameter is scaled by the ''scale'' parameter prior to being added to the base. | ||
'''Example:''' | '''Example:''' | ||
Line 58: | Line 60: | ||
void generate_read_byte_from_array_index_i2(drcuml_block *block) | void generate_read_byte_from_array_index_i2(drcuml_block *block) | ||
{ | { | ||
UML_LOADS(block, | UML_LOADS(block, ireg(0), my_signed_byte_array, ireg(2), SIZE_BYTE, SCALE_x1); | ||
} | } | ||
Line 64: | Line 66: | ||
'''Usage:''' | '''Usage:''' | ||
STORE ''base'',''index'',''source'',''size'' | STORE ''base'',''index'',''source'',''size'',''scale'' | ||
DSTORE ''base'',''index'',''source'',''size'' | DSTORE ''base'',''index'',''source'',''size'',''scale'' | ||
'''Codegen Shorthand:''' | '''Codegen Shorthand:''' | ||
UML_STORE(block, ''base'', PTYPE(''index''), PTYPE(''source''), BYTE | WORD | DWORD); | UML_STORE(block, ''base'', PTYPE(''index''), PTYPE(''source''), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); | ||
UML_DSTORE(block, ''base'', PTYPE(''index''), PTYPE(''source''), BYTE | WORD | DWORD | | UML_DSTORE(block, ''base'', PTYPE(''index''), PTYPE(''source''),SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); | ||
'''Parameters:''' | '''Parameters:''' | ||
Line 76: | Line 78: | ||
* ''source'' — a 32/64-bit integer register, memory location, map variable, or immediate | * ''source'' — a 32/64-bit integer register, memory location, map variable, or immediate | ||
* ''size'' — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form) | * ''size'' — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form) | ||
* ''scale'' — the scale factor to apply to the index; can be 1, 2, 4, or 8 | |||
'''Flags:''' undefined | '''Flags:''' undefined | ||
Line 81: | Line 84: | ||
'''Description:''' The '''STORE''' opcode performs a table-lookup memory write from a 32-bit source; the '''DSTORE''' opcode does the same from a 64-bit source. Note that because the low 32 bits are the same regardless of whether the source is 32-bit or 64-bit, STORE and DSTORE are identical when ''size'' is 1, 2, or 4. | '''Description:''' The '''STORE''' opcode performs a table-lookup memory write from a 32-bit source; the '''DSTORE''' opcode does the same from a 64-bit source. Note that because the low 32 bits are the same regardless of whether the source is 32-bit or 64-bit, STORE and DSTORE are identical when ''size'' is 1, 2, or 4. | ||
Unlike a standard memory location parameter (which must reside in the near cache), the ''base'' parameter may point anywhere in memory. | Unlike a standard memory location parameter (which must reside in the near cache), the ''base'' parameter may point anywhere in memory. The ''index'' parameter is scaled by the ''scale'' parameter prior to being added to the base. | ||
'''Example:''' | '''Example:''' | ||
Line 88: | Line 91: | ||
void generate_store_i0_to_register_array_index_i9(drcuml_block *block) | void generate_store_i0_to_register_array_index_i9(drcuml_block *block) | ||
{ | { | ||
UML_STORE(block, register_array, | UML_STORE(block, register_array, ireg(9), ireg(0), SIZE_DWORD, SCALE_x4); | ||
} | } | ||
Line 119: | Line 122: | ||
void generate_load_qword_from_program_space_address_i0(drcuml_block *block) | void generate_load_qword_from_program_space_address_i0(drcuml_block *block) | ||
{ | { | ||
UML_DLOAD(block, | UML_DLOAD(block, ireg(0), ireg(0), PROGRAM_QWORD); | ||
} | } | ||
Line 150: | Line 153: | ||
void generate_load_signed_word_from_data_space_address_i0(drcuml_block *block) | void generate_load_signed_word_from_data_space_address_i0(drcuml_block *block) | ||
{ | { | ||
UML_LOADS(block, | UML_LOADS(block, ireg(0), ireg(0), DATA_WORD); | ||
} | } | ||
Line 182: | Line 185: | ||
/* big-endian */ | /* big-endian */ | ||
if (upper) | if (upper) | ||
UML_LOADM(block, | UML_LOADM(block, ireg(0), ireg(0), 0xffff0000, PROGRAM_DWORD); | ||
else | else | ||
UML_LOADM(block, | UML_LOADM(block, ireg(0), ireg(0), 0x0000ffff, PROGRAM_DWORD); | ||
} | } | ||
Line 215: | Line 218: | ||
void generate_write_memory_to_byte(drcuml_block *block, UINT32 *memory) | void generate_write_memory_to_byte(drcuml_block *block, UINT32 *memory) | ||
{ | { | ||
UML_WRITE(block, | UML_WRITE(block, ireg(0), mem(memory), PROGRAM_BYTE); | ||
} | } | ||
Line 245: | Line 248: | ||
void generate_write_store_masked_byte(drcuml_block *block, UINT8 byte, UINT32 mask) | void generate_write_store_masked_byte(drcuml_block *block, UINT8 byte, UINT32 mask) | ||
{ | { | ||
UML_WRITEM(block, | UML_WRITEM(block, ireg(0), byte, mask, PROGRAM_DWORD); | ||
} | } | ||
Line 269: | Line 272: | ||
* U — undefined | * U — undefined | ||
'''Description:''' The '''CARRY''' opcode is used to seed the live carry flag prior to performing an '''ADDC''' or '''SUBC''' operation. The value of the carry flag is set based on the value of the specified ''bitnum'' of the ''source'' operand; all other flags are undefined. For the 32-bit form, only the low 5 bits of ''bitnum'' are considered; for the 64-bit form, only the low 6 bits of ''bitnum'' are considered. | '''Description:''' The '''CARRY''' opcode is used to seed the live carry flag prior to performing an '''ADDC''' or '''SUBC''' operation. The value of the carry flag is set based on the value of the specified ''bitnum'' of the ''source'' operand; all other flags are undefined. For the 32-bit form, only the low 5 bits of ''bitnum'' are considered; for the 64-bit form, only the low 6 bits of ''bitnum'' are considered. NOTE: the opcode immediately after a CARRY opcode must use the carry flag. | ||
'''Example:''' | '''Example:''' | ||
Line 277: | Line 280: | ||
void generate_add_with_carry(drcuml_block *block) | void generate_add_with_carry(drcuml_block *block) | ||
{ | { | ||
UML_CARRY(block, | UML_CARRY(block, mem(&flagsregister), CARRYBIT); | ||
UML_ADDC(block, | UML_ADDC(block, ireg(0), ireg(1), ireg(2)); | ||
} | } | ||
Line 302: | Line 305: | ||
void generate_set_i0_if_i1_equals_0(drcuml_block *block) | void generate_set_i0_if_i1_equals_0(drcuml_block *block) | ||
{ | { | ||
UML_CMP(block, | UML_CMP(block, ireg(1), 0); | ||
UML_SET(block, | UML_SET(block, COND_E, ireg(0)); | ||
} | } | ||
Line 330: | Line 333: | ||
void generate_swap_two_values(drcuml_block *block, UINT64 *val1, UINT64 *val2) | void generate_swap_two_values(drcuml_block *block, UINT64 *val1, UINT64 *val2) | ||
{ | { | ||
UML_DMOV(block, | UML_DMOV(block, ireg(0), mem(val1)); | ||
UML_DMOV(block, | UML_DMOV(block, mem(val1), mem(val2)); | ||
UML_DMOV(block, | UML_DMOV(block, mem(val2), ireg(0)); | ||
} | } | ||
Line 348: | Line 351: | ||
* ''dest'' — a 32/64-bit integer register or memory location | * ''dest'' — a 32/64-bit integer register or memory location | ||
* ''source'' — a 32/64-bit integer register, memory location, map variable, or immediate | * ''source'' — a 32/64-bit integer register, memory location, map variable, or immediate | ||
* ''size'' — the | * ''size'' — the width to sign-extend to; can be 1 or 2 (or 4 for the 64-bit form) | ||
'''Flags:''' | '''Flags:''' | ||
Line 357: | Line 360: | ||
* U — undefined | * U — undefined | ||
'''Description:''' The '''SEXT''' opcode | '''Description:''' The '''SEXT''' opcode take a 32-bit ''source'' operand, sign-extends the lower 8 or 16 bits to 32 bits, and stores it into the 32-bit ''dest'' operand; the '''DSEXT''' opcode takes a 64-bit ''source'' operand, sign-extends the lower 8, 16, or 32 bits to 64 bits, and stores it into the 64-bit ''dest'' operand. | ||
Note that there is no equivalent '''ZEXT''' opcode; to zero-extend, just perform the equivalent '''AND''' or '''DAND'''. | |||
Also note that if you specify a memory parameter for ''source'', a full 32-bit value is read and truncated down to 8 or 16 bits. This means that you cannot reliably specify a 16-bit memory location for ''source'', as it will produce different results on big-endian systems versus little-endian systems. | |||
'''Example:''' | '''Example:''' | ||
void generate_add_16bit_i0_to_32bit_i1(drcuml_block *block) | void generate_add_16bit_i0_to_32bit_i1(drcuml_block *block) | ||
{ | { | ||
UML_SEXT(block, | UML_SEXT(block, ireg(2), ireg(0)); | ||
UML_ADD(block, | UML_ADD(block, ireg(1), ireg(1), ireg(2)); | ||
} | } | ||
Line 395: | Line 402: | ||
{ | { | ||
/* extract from i0; high byte goes to i1, low byte goes to i4 */ | /* extract from i0; high byte goes to i1, low byte goes to i4 */ | ||
UML_ROLAND(block, | UML_ROLAND(block, ireg(1), ireg(0), 8, 0xff); | ||
UML_ROLAND(block, | UML_ROLAND(block, ireg(2), ireg(0), 16, 0xff); | ||
UML_ROLAND(block, | UML_ROLAND(block, ireg(3), ireg(0), 24, 0xff); | ||
UML_ROLAND(block, | UML_ROLAND(block, ireg(4), ireg(0), 0, 0xff); | ||
} | } | ||
Line 430: | Line 437: | ||
{ | { | ||
/* copy a bit from srcbitnum to dstbitnum within the i0 register */ | /* copy a bit from srcbitnum to dstbitnum within the i0 register */ | ||
UML_DROLINS(block, | UML_DROLINS(block, ireg(0), ireg(0), (dstbitnum - srcbitnum) & 63, u64(1) << dstbitnum); | ||
} | } | ||
Line 460: | Line 467: | ||
void generate_get_cycles_plus_10_in_i0(drcuml_block *block, UINT32 *cycles) | void generate_get_cycles_plus_10_in_i0(drcuml_block *block, UINT32 *cycles) | ||
{ | { | ||
UML_ADD(block, | UML_ADD(block, ireg(0), mem(cycles), 10); | ||
} | } | ||
Line 490: | Line 497: | ||
void generate_add_with_carry(drcuml_block *block) | void generate_add_with_carry(drcuml_block *block) | ||
{ | { | ||
UML_CARRY(block, | UML_CARRY(block, mem(flags), 0); | ||
UML_ADDC(block, | UML_ADDC(block, ireg(0), ireg(1), ireg(2)); | ||
} | } | ||
Line 521: | Line 528: | ||
void generate_subtract_accumlated_cycles(drcuml_block *block, UINT32 *cycles) | void generate_subtract_accumlated_cycles(drcuml_block *block, UINT32 *cycles) | ||
{ | { | ||
UML_SUB(block, | UML_SUB(block, mem(cycles), mem(cycles), MVAR(10)); | ||
} | } | ||
Line 551: | Line 558: | ||
void generate_sub_with_borrow(drcuml_block *block) | void generate_sub_with_borrow(drcuml_block *block) | ||
{ | { | ||
UML_CARRY(block, | UML_CARRY(block, mem(flags), 0); | ||
UML_SUBB(block, | UML_SUBB(block, ireg(0), ireg(1), ireg(2)); | ||
} | } | ||
Line 581: | Line 588: | ||
void generate_branch_if_under_16_unsigned(drcuml_block *block, UINT32 *param, drcuml_codelabel target) | void generate_branch_if_under_16_unsigned(drcuml_block *block, UINT32 *param, drcuml_codelabel target) | ||
{ | { | ||
UML_CMP(block, | UML_CMP(block, mem(param), 16); | ||
UML_JMPc(block, | UML_JMPc(block, COND_B, target); | ||
} | } | ||
Line 616: | Line 623: | ||
{ | { | ||
/* lower result in i0, upper result in i1 */ | /* lower result in i0, upper result in i1 */ | ||
UML_DMULU(block, | UML_DMULU(block, ireg(0), ireg(1), mem(src1), mem(src2)); | ||
} | } | ||
Line 650: | Line 657: | ||
{ | { | ||
/* lower result in i0, upper result in i1 */ | /* lower result in i0, upper result in i1 */ | ||
UML_MULS(block, | UML_MULS(block, ireg(0), ireg(0), ireg(0), 20); | ||
} | } | ||
Line 683: | Line 690: | ||
void generate_64x32_unsigned_divide(drcuml_block *block, UINT64 *dividend, UINT32 *divisor) | void generate_64x32_unsigned_divide(drcuml_block *block, UINT64 *dividend, UINT32 *divisor) | ||
{ | { | ||
UML_DSEXT(block, | UML_DSEXT(block, ireg(0), mem(divisor), DWORD); | ||
UML_DDIVU(block, | UML_DDIVU(block, ireg(0), ireg(0), mem(dividend), ireg(0)); | ||
} | } | ||
Line 718: | Line 725: | ||
{ | { | ||
/* result in i0; we use i2 for scratch space since we cannot avoid computing the quotient */ | /* result in i0; we use i2 for scratch space since we cannot avoid computing the quotient */ | ||
UML_DIVS(block, | UML_DIVS(block, ireg(2), ireg(0), ireg(0), ireg(1)); | ||
} | } | ||
Line 748: | Line 755: | ||
void generate_keep_low_16_bits(drcuml_block *block, UINT32 *param) | void generate_keep_low_16_bits(drcuml_block *block, UINT32 *param) | ||
{ | { | ||
UML_AND(block, | UML_AND(block, mem(param), mem(param), 0xffff); | ||
} | } | ||
Line 777: | Line 784: | ||
void generate_branch_if_set(drcuml_block *block, int bitnum, drcuml_codelabel target) | void generate_branch_if_set(drcuml_block *block, int bitnum, drcuml_codelabel target) | ||
{ | { | ||
UML_TEST(block, | UML_TEST(block, ireg(0), 1 << bitnum); | ||
UML_JMPc(block, | UML_JMPc(block, COND_NZ, target); | ||
} | } | ||
Line 808: | Line 815: | ||
void generate_set_bit_in_i1(drcuml_block *block, int whichbit) | void generate_set_bit_in_i1(drcuml_block *block, int whichbit) | ||
{ | { | ||
UML_OR(block, | UML_OR(block, ireg(1), ireg(1), 1 << whichbit); | ||
} | } | ||
Line 838: | Line 845: | ||
void generate_invert_all_bits_in_i0(drcuml_block *block) | void generate_invert_all_bits_in_i0(drcuml_block *block) | ||
{ | { | ||
UML_DXOR(block, | UML_DXOR(block, ireg(0), ~u64(0)); | ||
} | } | ||
Line 869: | Line 876: | ||
void generate_left_justify_bits_in_i0(drcuml_block *block) | void generate_left_justify_bits_in_i0(drcuml_block *block) | ||
{ | { | ||
UML_LZCNT(block, | UML_LZCNT(block, ireg(1), ireg(0)); | ||
UML_SHL(block, | UML_SHL(block, ireg(0), ireg(0), ireg(1)); | ||
} | } | ||
Line 899: | Line 906: | ||
void generate_byte_swap_16bit_value_in_i0(drcuml_block *block) | void generate_byte_swap_16bit_value_in_i0(drcuml_block *block) | ||
{ | { | ||
UML_BSWAP(block, | UML_BSWAP(block, ireg(0), ireg(0)); | ||
UML_SHR(block, | UML_SHR(block, ireg(0), ireg(0), 16); | ||
} | } | ||
Line 932: | Line 939: | ||
void generate_multiply_i0_by_16(drcuml_block *block) | void generate_multiply_i0_by_16(drcuml_block *block) | ||
{ | { | ||
UML_SHL(block, | UML_SHL(block, ireg(0), ireg(0), 4); | ||
} | } | ||
Line 964: | Line 971: | ||
void generate_unsigned_divide_i0_by_128(drcuml_block *block) | void generate_unsigned_divide_i0_by_128(drcuml_block *block) | ||
{ | { | ||
UML_SHR(block, | UML_SHR(block, ireg(0), ireg(0), 7); | ||
} | } | ||
Line 996: | Line 1,003: | ||
void generate_get_sign_extension_of_i0_in_i1(drcuml_block *block) | void generate_get_sign_extension_of_i0_in_i1(drcuml_block *block) | ||
{ | { | ||
UML_SAR(block, | UML_SAR(block, ireg(1), ireg(0), 31); | ||
} | } | ||
Line 1,028: | Line 1,035: | ||
void generate_swap_words_in_i0(drcuml_block *block) | void generate_swap_words_in_i0(drcuml_block *block) | ||
{ | { | ||
UML_ROL(block, | UML_ROL(block, ireg(0), ireg(0), 16); | ||
} | } | ||
Line 1,060: | Line 1,067: | ||
void generate_swap_dwords_in_i1(drcuml_block *block) | void generate_swap_dwords_in_i1(drcuml_block *block) | ||
{ | { | ||
UML_DROR(block, | UML_DROR(block, ireg(1), ireg(1), 32); | ||
} | } | ||
Line 1,092: | Line 1,099: | ||
void generate_rotate_128bit_value_in_i0_i1(drcuml_block *block) | void generate_rotate_128bit_value_in_i0_i1(drcuml_block *block) | ||
{ | { | ||
UML_CARRY(block, | UML_CARRY(block, ireg(0), 63); | ||
UML_DROLC(block, | UML_DROLC(block, ireg(1), ireg(1), 1); | ||
UML_DROLC(block, | UML_DROLC(block, ireg(0), ireg(0), 1); | ||
} | } | ||
== | == RORC == | ||
'''Usage:''' | '''Usage:''' | ||
Line 1,126: | Line 1,133: | ||
void generate_rotate_64bit_value_in_i0_i1(drcuml_block *block) | void generate_rotate_64bit_value_in_i0_i1(drcuml_block *block) | ||
{ | { | ||
UML_CARRY(block, | UML_CARRY(block, ireg(1), 0); | ||
UML_RORC(block, | UML_RORC(block, ireg(0), ireg(0), 1); | ||
UML_RORC(block, | UML_RORC(block, ireg(1), ireg(1), 1); | ||
} | } |
Latest revision as of 06:22, 23 March 2018
Below is a detailed description of all the UML integer opcodes. For general information about the UML, please see UML Architecture.
LOAD
Usage:
LOAD dest,base,index,size,scale DLOAD dest,base,index,size,scale
Codegen Shorthand:
UML_LOAD(block, PTYPE(dest), base, PTYPE(index), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); UML_DLOAD(block, PTYPE(dest), base, PTYPE(index), SIZE_ ## (BYTE | WORD | DWORD | QWORD), SCALE_ ## (x1 | x2 | x4 | x8));
Parameters:
- dest — a 32/64-bit integer register or memory location
- base — a memory pointer to the base of the table to read from
- index — a 32/64-bit integer register, memory location, map variable, or immediate
- size — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form)
- scale — the scale factor to apply to the index; can be 1, 2, 4, or 8
Flags: undefined
Description: The LOAD opcode performs a table-lookup memory read to a 32-bit destination; the DLOAD opcode does the same to a 64-bit destination. If the size specified is smaller than the destination, the result is zero-extended before being stored.
Unlike a standard memory location parameter (which must reside in the near cache), the base parameter may point anywhere in memory. The index parameter is scaled by the scale parameter prior to being added to the base.
Example:
static const UINT16 lookup_table[] = { 0, 1, 4, 5, 9, 10 }; void generate_lookup_index_i2_to_i0(drcuml_block *block) { UML_LOAD(block, ireg(0), lookup_table, ireg(2), SIZE_WORD, SCALE_x2); }
LOADS
Usage:
LOADS dest,base,index,size,scale DLOADS dest,base,index,size,scale
Codegen Shorthand:
UML_LOADS(block, PTYPE(dest), base, PTYPE(index), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); UML_DLOADS(block, PTYPE(dest), base, PTYPE(index), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8));
Parameters:
- dest — a 32/64-bit integer register or memory location
- base — a memory pointer to the base of the table to read from
- index — a 32/64-bit integer register, memory location, map variable, or immediate
- size — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form)
- scale — the scale factor to apply to the index; can be 1, 2, 4, or 8
Flags: undefined
Description: The LOADS opcode performs a table-lookup memory read to a 32-bit destination; the DLOADS opcode does the same to a 64-bit destination. If the size specified is smaller than the destination, the result is sign-extended before being stored.
Unlike a standard memory location parameter (which must reside in the near cache), the base parameter may point anywhere in memory. The index parameter is scaled by the scale parameter prior to being added to the base.
Example:
static const INT8 my_signed_byte_array[100]; void generate_read_byte_from_array_index_i2(drcuml_block *block) { UML_LOADS(block, ireg(0), my_signed_byte_array, ireg(2), SIZE_BYTE, SCALE_x1); }
STORE
Usage:
STORE base,index,source,size,scale DSTORE base,index,source,size,scale
Codegen Shorthand:
UML_STORE(block, base, PTYPE(index), PTYPE(source), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8)); UML_DSTORE(block, base, PTYPE(index), PTYPE(source),SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8));
Parameters:
- base — a memory pointer to the base of the table to store to
- index — a 32/64-bit integer register, memory location, map variable, or immediate
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- size — the size of the memory to access; can be 1, 2, or 4 (or 8 for the 64-bit form)
- scale — the scale factor to apply to the index; can be 1, 2, 4, or 8
Flags: undefined
Description: The STORE opcode performs a table-lookup memory write from a 32-bit source; the DSTORE opcode does the same from a 64-bit source. Note that because the low 32 bits are the same regardless of whether the source is 32-bit or 64-bit, STORE and DSTORE are identical when size is 1, 2, or 4.
Unlike a standard memory location parameter (which must reside in the near cache), the base parameter may point anywhere in memory. The index parameter is scaled by the scale parameter prior to being added to the base.
Example:
static const INT32 register_aray[32]; void generate_store_i0_to_register_array_index_i9(drcuml_block *block) { UML_STORE(block, register_array, ireg(9), ireg(0), SIZE_DWORD, SCALE_x4); }
READ
Usage:
READ dest,address,space-size DREAD dest,address,space-size
Codegen Shorthand:
UML_READ(block, PTYPE(dest), PTYPE(address), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD)); UML_DREAD(block, PTYPE(dest), PTYPE(address), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD | QWORD));
Parameters:
- dest — a 32/64-bit integer register or memory location
- address — a 32-bit integer register, memory location, map variable, or immediate
- space-size — the address space and size of the memory to access; can be one of these values:
- PROGRAM_BYTE/DATA_BYTE/IO_BYTE — a 1-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_WORD/DATA_WORD/IO_WORD — a 2-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_DWORD/DATA_DWORD/IO_DWORD — a 4-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_QWORD/DATA_QWORD/IO_QWORD — an 8-byte value from the PROGRAM/DATA/IO address space
Flags: undefined
Description: The READ opcode performs a read from the emulated CPU's memory system to a 32-bit destination; the DREAD opcode does the same to a 64-bit destination. If the number of bytes specified by the space-size parameter is smaller than the destination, the result is zero-extended before being stored.
Note that even in its 64-bit form, the DREAD opcode still takes a fixed 32-bit size parameter for the address.
Example:
void generate_load_qword_from_program_space_address_i0(drcuml_block *block) { UML_DLOAD(block, ireg(0), ireg(0), PROGRAM_QWORD); }
READS
Usage:
READS dest,address,space-size DREADS dest,address,space-size
Codegen Shorthand:
UML_READS(block, PTYPE(dest), PTYPE(address), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD)); UML_DREADS(block, PTYPE(dest), PTYPE(address), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD | QWORD));
Parameters:
- dest — a 32/64-bit integer register or memory location
- address — a 32-bit integer register, memory location, map variable, or immediate
- space-size — the address space and size of the memory to access; can be one of these values:
- PROGRAM_BYTE/DATA_BYTE/IO_BYTE — a 1-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_WORD/DATA_WORD/IO_WORD — a 2-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_DWORD/DATA_DWORD/IO_DWORD — a 4-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_QWORD/DATA_QWORD/IO_QWORD — an 8-byte value from the PROGRAM/DATA/IO address space
Flags: undefined
Description: The READS opcode performs a read from the emulated CPU's memory system to a 32-bit destination; the DREADS opcode does the same to a 64-bit destination. If the number of bytes specified by the space-size parameter is smaller than the destination, the result is sign-extended before being stored.
Note that even in its 64-bit form, the DREADS opcode still takes a fixed 32-bit size parameter for the address.
Example:
void generate_load_signed_word_from_data_space_address_i0(drcuml_block *block) { UML_LOADS(block, ireg(0), ireg(0), DATA_WORD); }
READM
Usage:
READM dest,address,mask,space-size DREADM dest,address,mask,space-size
Codegen Shorthand:
UML_READ(block, PTYPE(dest), PTYPE(address), PTYPE(mask), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD)); UML_DREAD(block, PTYPE(dest), PTYPE(address), PTYPE(mask), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD | QWORD));
Parameters:
- dest — a 32/64-bit integer register or memory location
- address — a 32-bit integer register, memory location, map variable, or immediate
- mask — a 32/64-bit integer register, memory location, map variable, or immediate
- space-size — the address space and size of the memory to access; can be one of these values:
- PROGRAM_BYTE/DATA_BYTE/IO_BYTE — a 1-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_WORD/DATA_WORD/IO_WORD — a 2-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_DWORD/DATA_DWORD/IO_DWORD — a 4-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_QWORD/DATA_QWORD/IO_QWORD — an 8-byte value from the PROGRAM/DATA/IO address space
Flags: undefined
Description: The READM opcode performs a masked read from the emulated CPU's memory system to a 32-bit destination; the DREADM opcode does the same to a 64-bit destination. These opcodes are similar to the READ and DREAD opcodes described above, with the exception that the additional parameter mask specifies which bytes within the larger access should be referenced. As with READ and DREAD, these opcodes zero-extend the result if it is smaller than the destination size.
Example:
void generate_load_upper_or_lower_word_from_i0(drcuml_block *block, int upper) { /* big-endian */ if (upper) UML_LOADM(block, ireg(0), ireg(0), 0xffff0000, PROGRAM_DWORD); else UML_LOADM(block, ireg(0), ireg(0), 0x0000ffff, PROGRAM_DWORD); }
WRITE
Usage:
WRITE address,source,space-size DWRITE address,source,space-size
Codegen Shorthand:
UML_WRITE(block, PTYPE(address), PTYPE(source), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD)); UML_DWRITE(block, PTYPE(address), PTYPE(source), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD | QWORD));
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-size — the address space and size of the memory to access; can be one of these values:
- PROGRAM_BYTE/DATA_BYTE/IO_BYTE — a 1-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_WORD/DATA_WORD/IO_WORD — a 2-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_DWORD/DATA_DWORD/IO_DWORD — a 4-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_QWORD/DATA_QWORD/IO_QWORD — an 8-byte value from the PROGRAM/DATA/IO address space
Flags: undefined
Description: The WRITE opcode performss a write to the emulated CPU's memory system from a 32-bit source; the DWRITE opcode does the same from a 64-bit source. Note that because the low 32 bits are the same regardless of whether the source is 32-bit or 64-bit, WRITE and DWRITE are identical when size is 1, 2, or 4.
Note that even in its 64-bit form, the DWRITE opcode still takes a fixed 32-bit size parameter for the address.
Example:
void generate_write_memory_to_byte(drcuml_block *block, UINT32 *memory) { UML_WRITE(block, ireg(0), mem(memory), PROGRAM_BYTE); }
WRITEM
Usage:
WRITEM address,source,mask,space-size DWRITEM address,source,mask,space-size
Codegen Shorthand:
UML_WRITEM(block, PTYPE(address), PTYPE(source), PTYPE(mask), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD)); UML_DWRITEM(block, PTYPE(address), PTYPE(source), PTYPE(mask), (PROGRAM_ | DATA_ | IO_) ## (BYTE | WORD | DWORD | QWORD));
Parameters:
- space — an immediate describing which address space to read from
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- mask — a 32/64-bit integer register, memory location, map variable, or immediate
- space-size — the address space and size of the memory to access; can be one of these values:
- PROGRAM_BYTE/DATA_BYTE/IO_BYTE — a 1-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_WORD/DATA_WORD/IO_WORD — a 2-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_DWORD/DATA_DWORD/IO_DWORD — a 4-byte value from the PROGRAM/DATA/IO address space
- PROGRAM_QWORD/DATA_QWORD/IO_QWORD — an 8-byte value from the PROGRAM/DATA/IO address space
Flags: undefined
Description: The WRITEM opcode performs a masked write to the emulated CPU's memory system from a 32-bit source; the DWRITEM opcode does the same from a 64-bit source. These opcodes are similar to the WRITE and DWRITE opcodes described above, with the exception that the additional parameter mask specifies which bytes within the larger access should be written.
Example:
void generate_write_store_masked_byte(drcuml_block *block, UINT8 byte, UINT32 mask) { UML_WRITEM(block, ireg(0), byte, mask, PROGRAM_DWORD); }
CARRY
Usage:
CARRY source,bitnum DCARRY source,bitnum
Codegen Shorthand:
UML_CARRY(block, PTYPE(source), PTYPE(bitnum)); UML_DCARRY(block, PTYPE(source), PTYPE(bitnum));
Parameters:
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- bitnum — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set to the value of the specified bitnum of the source operand
- V — undefined
- Z — undefined
- S — undefined
- U — undefined
Description: The CARRY opcode is used to seed the live carry flag prior to performing an ADDC or SUBC operation. The value of the carry flag is set based on the value of the specified bitnum of the source operand; all other flags are undefined. For the 32-bit form, only the low 5 bits of bitnum are considered; for the 64-bit form, only the low 6 bits of bitnum are considered. NOTE: the opcode immediately after a CARRY opcode must use the carry flag.
Example:
#define CARRYBIT 10 #define CARRYMASK (1 << CARRYBIT) void generate_add_with_carry(drcuml_block *block) { UML_CARRY(block, mem(&flagsregister), CARRYBIT); UML_ADDC(block, ireg(0), ireg(1), ireg(2)); }
SET
Usage:
SET dest,condition DSET dest,condition
Codegen Shorthand:
UML_SET(block, condition, PTYPE(dest)); UML_DSET(block, condition, PTYPE(dest));
Parameters:
- dest — a 32/64-bit integer register or memory location
- condition — the condition whose value determines the result of the SET operation
Flags: undefined
Description: The SET opcode tests the provided condition and sets the dest operand to 1 if the condition is true or 0 if it is false; the DSET opcode does the same with a 64-bit operand.
Example:
void generate_set_i0_if_i1_equals_0(drcuml_block *block) { UML_CMP(block, ireg(1), 0); UML_SET(block, COND_E, ireg(0)); }
MOV
Usage:
MOV dest,source[,condition] DMOV dest,source[,condition]
Codegen Shorthand:
UML_MOV(block, PTYPE(dest), PTYPE(source)); UML_MOVc(block, condition, PTYPE(dest), PTYPE(source)); UML_DMOV(block, PTYPE(dest), PTYPE(source)); UML_DMOVc(block, condition, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- condition — an optional condition which is used to determine whether or not to perform the move
Flags: unaffected
Description: The MOV opcode transfers a 32-bit value from the source operand to the dest operand; the DMOV 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; MOV is one of the very few opcodes that can be reliably used between a flag-changing opcode and a flag-consuming opcode.
Example:
void generate_swap_two_values(drcuml_block *block, UINT64 *val1, UINT64 *val2) { UML_DMOV(block, ireg(0), mem(val1)); UML_DMOV(block, mem(val1), mem(val2)); UML_DMOV(block, mem(val2), ireg(0)); }
SEXT
Usage:
SEXT dest,source,size DSEXT dest,source,size
Codegen Shorthand:
UML_SEXT(block, PTYPE(dest), PTYPE(source), BYTE | WORD); UML_DSEXT(block, PTYPE(dest), PTYPE(source), BYTE | WORD | DWORD);
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- size — the width to sign-extend to; can be 1 or 2 (or 4 for the 64-bit form)
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The SEXT opcode take a 32-bit source operand, sign-extends the lower 8 or 16 bits to 32 bits, and stores it into the 32-bit dest operand; the DSEXT opcode takes a 64-bit source operand, sign-extends the lower 8, 16, or 32 bits to 64 bits, and stores it into the 64-bit dest operand.
Note that there is no equivalent ZEXT opcode; to zero-extend, just perform the equivalent AND or DAND.
Also note that if you specify a memory parameter for source, a full 32-bit value is read and truncated down to 8 or 16 bits. This means that you cannot reliably specify a 16-bit memory location for source, as it will produce different results on big-endian systems versus little-endian systems.
Example:
void generate_add_16bit_i0_to_32bit_i1(drcuml_block *block) { UML_SEXT(block, ireg(2), ireg(0)); UML_ADD(block, ireg(1), ireg(1), ireg(2)); }
ROLAND
Usage:
ROLAND dest,source,rotate,mask DROLAND dest,source,rotate,mask
Codegen Shorthand:
UML_ROLAND(block, PTYPE(dest), PTYPE(source), PTYPE(rotate), PTYPE(mask)); UML_DROLAND(block, PTYPE(dest), PTYPE(source), PTYPE(rotate), PTYPE(mask));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- rotate — a 32/64-bit integer register, memory location, map variable, or immediate
- mask — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ROLAND opcode rotates the 32-bit source operand left by the number of bits specified in rotate and then ANDs the result with mask; the DROLAND opcode performs the same operation on 64-bit operands. For the 32-bit form, only the low 5 bits of rotate are considered; for the 64-bit form, only the low 6 bits of rotate are considered.
Example:
void generate_extract_bytes(drcuml_block *block) { /* extract from i0; high byte goes to i1, low byte goes to i4 */ UML_ROLAND(block, ireg(1), ireg(0), 8, 0xff); UML_ROLAND(block, ireg(2), ireg(0), 16, 0xff); UML_ROLAND(block, ireg(3), ireg(0), 24, 0xff); UML_ROLAND(block, ireg(4), ireg(0), 0, 0xff); }
ROLINS
Usage:
ROLINS dest,source,rotate,mask DROLINS dest,source,rotate,mask
Codegen Shorthand:
UML_ROLINS(block, PTYPE(dest), PTYPE(source), PTYPE(rotate), PTYPE(mask)); UML_DROLINS(block, PTYPE(dest), PTYPE(source), PTYPE(rotate), PTYPE(mask));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- rotate — a 32/64-bit integer register, memory location, map variable, or immediate
- mask — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ROLINS opcode rotates the 32-bit source operand left by the number of bits specified in rotate and then inserts a subset of bits into dest under control of the mask; the DROLINS opcode performs the same operation on 64-bit operands. For the 32-bit form, only the low 5 bits of rotate are considered; for the 64-bit form, only the low 6 bits of rotate are considered.
Example:
void generate_copy_bit(drcuml_block *block, int srcbitnum, dstbitnum) { /* copy a bit from srcbitnum to dstbitnum within the i0 register */ UML_DROLINS(block, ireg(0), ireg(0), (dstbitnum - srcbitnum) & 63, u64(1) << dstbitnum); }
ADD
Usage:
ADD dest,source1,source2 DADD dest,source1,source2
Codegen Shorthand:
UML_ADD(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DADD(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the addition results in an unsigned overflow
- V — set if the addition results in a signed overflow
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ADD opcode performs addition between the 32-bit source1 and source2 operands and stores the result in dest; the DADD opcode performs the same operation using 64-bit operands.
Example:
void generate_get_cycles_plus_10_in_i0(drcuml_block *block, UINT32 *cycles) { UML_ADD(block, ireg(0), mem(cycles), 10); }
ADDC
Usage:
ADDC dest,source1,source2 DADDC dest,source1,source2
Codegen Shorthand:
UML_ADDC(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DADDC(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the addition results in an unsigned overflow
- V — set if the addition results in a signed overflow
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ADDC opcode performs a three-way addition between the 32-bit source1 and source2 operands and the carry flag (0 or 1) and stores the result in dest; the DADDC opcode performs the same operation using 64-bit operands.
Example:
void generate_add_with_carry(drcuml_block *block) { UML_CARRY(block, mem(flags), 0); UML_ADDC(block, ireg(0), ireg(1), ireg(2)); }
SUB
Usage:
SUB dest,source1,source2 DSUB dest,source1,source2
Codegen Shorthand:
UML_SUB(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DSUB(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the subtraction results in an unsigned overflow
- V — set if the subtraction results in a signed overflow
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The SUB opcode subtracts the 32-bit source2 operand from the source1 operand and stores the result in dest; the DSUB opcode performs the same operation using 64-bit operands.
Example:
void generate_subtract_accumlated_cycles(drcuml_block *block, UINT32 *cycles) { UML_SUB(block, mem(cycles), mem(cycles), MVAR(10)); }
SUBB
Usage:
SUBB dest,source1,source2 DSUBB dest,source1,source2
Codegen Shorthand:
UML_SUBB(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DSUBB(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the subtraction results in an unsigned overflow
- V — set if the subtraction results in a signed overflow
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The SUBB opcode subtracts the 32-bit source2 operand and the carry flag (0 or 1) from the source1 operand and stores the result in dest; the DSUBB opcode performs the same operation using 64-bit operands.
Example:
void generate_sub_with_borrow(drcuml_block *block) { UML_CARRY(block, mem(flags), 0); UML_SUBB(block, ireg(0), ireg(1), ireg(2)); }
CMP
Usage:
CMP source1,source2 DCMP 'source1,source2
Codegen Shorthand:
UML_CMP(block, PTYPE(source1), PTYPE(source2)); UML_DCMP(block, PTYPE(source1), PTYPE(source2));
Parameters:
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the compare results in an unsigned overflow
- V — set if the compare results in a signed overflow
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The CMP opcode subtracts the 32-bit source2 operand from the source1 operand and throws away the result, keeping only the flags; the DCMP opcode performs the same operation using 64-bit operands.
Example:
void generate_branch_if_under_16_unsigned(drcuml_block *block, UINT32 *param, drcuml_codelabel target) { UML_CMP(block, mem(param), 16); UML_JMPc(block, COND_B, target); }
MULU
Usage:
MULU dest1,dest2,source1,source2 DMULU dest1,dest2,source1,source2
Codegen Shorthand:
UML_MULU(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2)); UML_DMULU(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2));
Parameters:
- dest1 — a 32/64-bit integer register or memory location
- dest2 — a 32/64-bit integer register or memory location; can be the same as dest1
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — set if the upper half of the resulting value is not 0
- Z — set if the resulting value is 0 (only lower half considered if dest1 == dest2)
- S — set if the high bit of resulting value is set (only lower half considered if dest1 == dest2)
- U — undefined
Description: The MULU opcode performs a 32-bit unsigned multiply between the source1 and source2 parameters and stores the lower half of the result in dest1 and the upper half in dest2; the DMULU opcode performs the same operation using 64-bit operands.
Note that dest1 can be set equal to dest2; in this case, only the lower half of the final result is stored to the operand specified. The S and Z flags are also set differently, being based only on the lower half value (normally they are set based on the full double-width result).
Example:
void generate_64x64_wide_multiply(drcuml_block *block, UINT64 *src1, UINT64 *src2) { /* lower result in i0, upper result in i1 */ UML_DMULU(block, ireg(0), ireg(1), mem(src1), mem(src2)); }
MULS
Usage:
MULS dest1,dest2,source1,source2 DMULS dest1,dest2,source1,source2
Codegen Shorthand:
UML_MULS(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2)); UML_DMULS(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2));
Parameters:
- dest1 — a 32/64-bit integer register or memory location
- dest2 — a 32/64-bit integer register or memory location; can be the same as dest1
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — set if the upper half of the resulting value is not the sign extension of the lower half
- Z — set if the resulting value is 0 (only lower half considered if dest1 == dest2)
- S — set if the high bit of resulting value is set (only lower half considered if dest1 == dest2)
- U — undefined
Description: The MULS opcode performs a 32-bit signed multiply between the source1 and source2 parameters and stores the lower half of the result in dest1 and the upper half in dest2; the DMULS opcode performs the same operation using 64-bit operands.
As with MULU, dest1 can be set equal to dest2; in this case, only the lower half of the final result is stored to the operand specified. The S and Z flags are also set differently, being based only on the lower half value (normally they are set based on the full double-width result).
Example:
void generate_multiply_i0_by_20_and_assume_no_overflow(drcuml_block *block) { /* lower result in i0, upper result in i1 */ UML_MULS(block, ireg(0), ireg(0), ireg(0), 20); }
DIVU
Usage:
DIVU dest1,dest2,source1,source2 DDIVU dest1,dest2,source1,source2
Codegen Shorthand:
UML_DIVU(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2)); UML_DDIVU(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2));
Parameters:
- dest1 — a 32/64-bit integer register or memory location
- dest2 — a 32/64-bit integer register or memory location; can be the same as dest1
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — set if the source2 parameter was 0
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The DIVU opcode performs a 32-bit unsigned divide of source1 by source2 and stores the quotient in dest1 and the remainder in dest2; the DDIVU opcode performs the same operation using 64-bit operands.
Note that dest1 can be set equal to dest2; in this case, only the quotient is stored to the operand specified. The remainder does not need to computed.
Example:
void generate_64x32_unsigned_divide(drcuml_block *block, UINT64 *dividend, UINT32 *divisor) { UML_DSEXT(block, ireg(0), mem(divisor), DWORD); UML_DDIVU(block, ireg(0), ireg(0), mem(dividend), ireg(0)); }
DIVS
Usage:
DIVS dest1,dest2,source1,source2 DDIVS dest1,dest2,source1,source2
Codegen Shorthand:
UML_DIVS(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2)); UML_DDIVS(block, PTYPE(dest1), PTYPE(dest2), PTYPE(source1), PTYPE(source2));
Parameters:
- dest1 — a 32/64-bit integer register or memory location
- dest2 — a 32/64-bit integer register or memory location; can be the same as dest1
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — set if the source2 parameter was 0
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The DIVS opcode performs a 32-bit signed divide of source1 by source2 and stores the quotient in dest1 and the remainder in dest2; the DDIVS opcode performs the same operation using 64-bit operands.
Note that dest1 can be set equal to dest2; in this case, only the quotient is stored to the operand specified. The remainder does not need to computed.
Example:
void generate_compute_remainder_of_i0_over_i1(drcuml_block *block) { /* result in i0; we use i2 for scratch space since we cannot avoid computing the quotient */ UML_DIVS(block, ireg(2), ireg(0), ireg(0), ireg(1)); }
AND
Usage:
AND dest,source1,source2 DAND dest,source1,source2
Codegen Shorthand:
UML_AND(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DAND(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The AND opcode performs a logical AND between the 32-bit source1 and source2 operands and stores the result in dest; the DAND opcode performs the same operation using 64-bit operands.
Example:
void generate_keep_low_16_bits(drcuml_block *block, UINT32 *param) { UML_AND(block, mem(param), mem(param), 0xffff); }
TEST
Usage:
TEST source1,source2 DTEST source1,source2
Codegen Shorthand:
UML_TEST(block, PTYPE(source1), PTYPE(source2)); UML_DTEST(block, PTYPE(source1), PTYPE(source2));
Parameters:
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The TEST opcode performs a logical AND between the 32-bit source1 and source2 operands and throws away the result, keeping only the flags; the DTEST opcode performs the same operation using 64-bit operands.
Example:
void generate_branch_if_set(drcuml_block *block, int bitnum, drcuml_codelabel target) { UML_TEST(block, ireg(0), 1 << bitnum); UML_JMPc(block, COND_NZ, target); }
OR
Usage:
OR dest,source1,source2 DOR dest,source1,source2
Codegen Shorthand:
UML_OR(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DOR(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The OR opcode performs a logical OR between the 32-bit source1 and source2 operands and stores the result in dest; the DOR opcode performs the same operation using 64-bit operands.
Example:
void generate_set_bit_in_i1(drcuml_block *block, int whichbit) { UML_OR(block, ireg(1), ireg(1), 1 << whichbit); }
XOR
Usage:
XOR dest,source1,source2 DXOR dest,source1,source2
Codegen Shorthand:
UML_XOR(block, PTYPE(dest), PTYPE(source1), PTYPE(source2)); UML_DXOR(block, PTYPE(dest), PTYPE(source1), PTYPE(source2));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source1 — a 32/64-bit integer register, memory location, map variable, or immediate
- source2 — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The XOR opcode performs a logical XOR between the 32-bit source1 and source2 operands and stores the result in dest; the DXOR opcode performs the same operation using 64-bit operands.
Example:
void generate_invert_all_bits_in_i0(drcuml_block *block) { UML_DXOR(block, ireg(0), ~u64(0)); }
LZCNT
Usage:
LZCNT dest,source DLZCNT dest,source
Codegen Shorthand:
UML_LZCNT(block, PTYPE(dest), PTYPE(source')); UML_DLZCNT(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — undefined
- U — undefined
Description: The LZCNT opcode counts the number of consecutive high order 0 bits in a 32-bit source operand and stores the result to dest; the DLZCNT opcode performs the same operation using 64-bit operands.
If the source value is 0, the result is either 32 (LZCNT) or 64 (DLZCNT).
Example:
void generate_left_justify_bits_in_i0(drcuml_block *block) { UML_LZCNT(block, ireg(1), ireg(0)); UML_SHL(block, ireg(0), ireg(0), ireg(1)); }
BSWAP
Usage:
BSWAP dest,source DBSWAP dest,source
Codegen Shorthand:
UML_BSWAP(block, PTYPE(dest), PTYPE(source)); UML_BSWAP(block, PTYPE(dest), PTYPE(source));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — undefined
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The BSWAP opcode reverses the byte order of the 32-bit source operand and stores the result in dest; the DBSWAP opcode performs the same operation using 64-bit operands.
Example:
void generate_byte_swap_16bit_value_in_i0(drcuml_block *block) { UML_BSWAP(block, ireg(0), ireg(0)); UML_SHR(block, ireg(0), ireg(0), 16); }
SHL
Usage:
SHL dest,source,shift DSHL dest,source,shift
Codegen Shorthand:
UML_SHL(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DSHL(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit shifted out of the source is a 1
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The SHL opcode shifts the source operand left by the number of bits specified by shift and stores the result to dest; the DSHL opcode performs the same operation using 64-bit operands. For each bit shifted, a 0 bit is inserted into the least significant bit.
Note that only the low bits of the shift operand are considered. For SHL, only the low 5 bits are used for the shift amount; for DSHL, only the low 6 bits are used.
Example:
void generate_multiply_i0_by_16(drcuml_block *block) { UML_SHL(block, ireg(0), ireg(0), 4); }
SHR
Usage:
SHR dest,source,shift DSHR dest,source,shift
Codegen Shorthand:
UML_SHR(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DSHR(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit shifted out of the source is a 1
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The SHR opcode shifts the source operand right by the number of bits specified by shift and stores the result to dest; the DSHR opcode performs the same operation using 64-bit operands. For each bit shifted, a 0 bit is inserted into the most significant bit.
Note that only the low bits of the shift operand are considered. For SHR, only the low 5 bits are used for the shift amount; for DSHR, only the low 6 bits are used.
Example:
void generate_unsigned_divide_i0_by_128(drcuml_block *block) { UML_SHR(block, ireg(0), ireg(0), 7); }
SAR
Usage:
SAR dest,source,shift DSAR dest,source,shift
Codegen Shorthand:
UML_SAR(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DSAR(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit shifted out of the source is a 1
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The SAR opcode arithmetically shifts the source operand right by the number of bits specified by shift and stores the result to dest; theDSHR opcode performs the same operation using 64-bit operands. For each bit shifted, a copy of the previous most significant bit is inserted as the new most significant bit.
Note that only the low bits of the shift operand are considered. For SHR, only the low 5 bits are used for the shift amount; for DSHR, only the low 6 bits are used.
Example:
void generate_get_sign_extension_of_i0_in_i1(drcuml_block *block) { UML_SAR(block, ireg(1), ireg(0), 31); }
ROL
Usage:
ROL dest,source,shift DROL dest,source,shift
Codegen Shorthand:
UML_ROL(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DROL(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit rotated out of the source is a 1; equal to the new LSB
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ROL opcode rotates the source operand left by the number of bits specified by shift and stores the result to dest; the DROL opcode performs the same operation using 64-bit operands. Each bit shifted out of the most-significant location is inserted as the new least-significant bit.
Note that only the low bits of the shift operand are considered. For ROL, only the low 5 bits are used for the shift amount; for DROL, only the low 6 bits are used.
Example:
void generate_swap_words_in_i0(drcuml_block *block) { UML_ROL(block, ireg(0), ireg(0), 16); }
ROR
Usage:
ROR dest,source,shift DROR dest,source,shift
Codegen Shorthand:
UML_ROR(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DROR(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit rotated out of the source is a 1; equal to the new MSB
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ROR opcode rotates the source operand right by the number of bits specified by shift and stores the result to dest; the DROR opcode performs the same operation using 64-bit operands. Each bit shifted out of the least-significant location is inserted as the new most-significant bit.
Note that only the low bits of the shift operand are considered. For ROR, only the low 5 bits are used for the shift amount; for DROR, only the low 6 bits are used.
Example:
void generate_swap_dwords_in_i1(drcuml_block *block) { UML_DROR(block, ireg(1), ireg(1), 32); }
ROLC
Usage:
ROLC dest,source,shift DROLC dest,source,shift
Codegen Shorthand:
UML_ROLC(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DROLC(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit rotated out of the source is a 1
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The ROLC opcode rotates the 33-bit contatenation of the source operand and the carry flag left by the number of bits specified by shift and stores the result to dest; the DROL opcode performs the same operation using 64-bit operands (with an effective 65-bit source). Each bit shifted out of the most-significant location is stored in the carry; the previous value of the carry is inserted as the new least-significant bit.
Note that only the low bits of the shift operand are considered. For ROL, only the low 5 bits are used for the shift amount; for DROL, only the low 6 bits are used.
Example:
void generate_rotate_128bit_value_in_i0_i1(drcuml_block *block) { UML_CARRY(block, ireg(0), 63); UML_DROLC(block, ireg(1), ireg(1), 1); UML_DROLC(block, ireg(0), ireg(0), 1); }
RORC
Usage:
RORC dest,source,shift DRORC dest,source,shift
Codegen Shorthand:
UML_RORC(block, PTYPE(dest), PTYPE(source), PTYPE(shift)); UML_DRORC(block, PTYPE(dest), PTYPE(source), PTYPE(shift));
Parameters:
- dest — a 32/64-bit integer register or memory location
- source — a 32/64-bit integer register, memory location, map variable, or immediate
- shift — a 32/64-bit integer register, memory location, map variable, or immediate
Flags:
- C — set if the final bit rotated out of the source is a 1
- V — undefined
- Z — set if the resulting value is 0
- S — set if the high bit of the resulting value is set
- U — undefined
Description: The RORC opcode rotates the 33-bit contatenation of the source operand and the carry flag right by the number of bits specified by shift and stores the result to dest; the DROR opcode performs the same operation using 64-bit operands (with an effective 65-bit source). Each bit shifted out of the least-significant location is stored in the carry; the previous value of the carry is inserted as the new most-significant bit.
Note that only the low bits of the shift operand are considered. For ROL, only the low 5 bits are used for the shift amount; for DROL, only the low 6 bits are used.
Example:
void generate_rotate_64bit_value_in_i0_i1(drcuml_block *block) { UML_CARRY(block, ireg(1), 0); UML_RORC(block, ireg(0), ireg(0), 1); UML_RORC(block, ireg(1), ireg(1), 1); }