UML Integer Opcodes: Difference between revisions

From MAMEDEV Wiki
No edit summary
 
(7 intermediate revisions by 2 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. Furthermore, the ''index'' parameter is truly an index and not a byte offset; thus the final address read will be ''base'' + (''size'' x ''index'').
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, IREG(0), lookup_table, IREG(2), WORD);
     UML_LOAD(block, ireg(0), lookup_table, ireg(2), SIZE_WORD, SCALE_x2);
  }
  }


Line 34: Line 35:


'''Usage:'''  
'''Usage:'''  
  LOADS  ''dest'',''base'',''index'',''size_scale''
  LOADS  ''dest'',''base'',''index'',''size'',''scale''
  DLOADS  ''dest'',''base'',''index'',''size_scale''
  DLOADS  ''dest'',''base'',''index'',''size'',''scale''


'''Codegen Shorthand:'''
'''Codegen Shorthand:'''
  UML_LOADS(block, PTYPE(''dest''), ''base'', PTYPE(''index''), (BYTE_ | WORD_ | DWORD_) ## (x1 | x2 | x4 | x8));
  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_ | QWORD_) ## (x1 | x2 | x4 | x8)););
  UML_DLOADS(block, PTYPE(''dest''), ''base'', PTYPE(''index''), SIZE_ ## (BYTE | WORD | DWORD), SCALE_ ## (x1 | x2 | x4 | x8));


'''Parameters:'''
'''Parameters:'''
Line 45: Line 46:
* ''base'' — a memory pointer to the base of the table to read from
* ''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
* ''index'' — a 32/64-bit integer register, memory location, map variable, or immediate
* ''size_scale'' — the size of the memory to access, combined with the scale factor to apply to the index; the size portion can be 1, 2, or 4 (or 8 for the 64-bit form), while the scale factor can be 1, 2, 4, or 8
* ''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 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, IREG(0), my_signed_byte_array, IREG(2), BYTE_x1);
     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 | QWORD);
  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. Furthermore, the ''index'' parameter is truly an index and not a byte offset; thus the final address read will be ''base'' + (''size'' x ''index'').
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, IREG(9), IREG(0), DWORD);
     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, IREG(0), IREG(0), PROGRAM_QWORD);
     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, IREG(0), IREG(0), DATA_WORD);
     UML_LOADS(block, ireg(0), ireg(0), DATA_WORD);
  }
  }


Line 182: Line 185:
     /* big-endian */
     /* big-endian */
     if (upper)
     if (upper)
         UML_LOADM(block, IREG(0), IREG(0), IMM(0xffff0000), PROGRAM_DWORD);
         UML_LOADM(block, ireg(0), ireg(0), 0xffff0000, PROGRAM_DWORD);
     else
     else
         UML_LOADM(block, IREG(0), IREG(0), IMM(0x0000ffff), PROGRAM_DWORD);
         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, IREG(0), MEM(memory), PROGRAM_BYTE);
     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, IREG(0), IMM(byte), IMM(mask), PROGRAM_DWORD);
     UML_WRITEM(block, ireg(0), byte, mask, PROGRAM_DWORD);
  }
  }


Line 277: Line 280:
  void generate_add_with_carry(drcuml_block *block)
  void generate_add_with_carry(drcuml_block *block)
  {
  {
     UML_CARRY(block, MEM(&flagsregister), IMM(CARRYBIT));
     UML_CARRY(block, mem(&flagsregister), CARRYBIT);
     UML_ADDC(block, IREG(0), IREG(1), IREG(2));
     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, IREG(1), IMM(0));
     UML_CMP(block, ireg(1), 0);
     UML_SET(block, IF_E, IREG(0));
     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, IREG(0), MEM(val1));
     UML_DMOV(block, ireg(0), mem(val1));
     UML_DMOV(block, MEM(val1), MEM(val2));
     UML_DMOV(block, mem(val1), mem(val2));
     UML_DMOV(block, MEM(val2), IREG(0));
     UML_DMOV(block, mem(val2), ireg(0));
  }
  }


Line 366: Line 369:
  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, IREG(2), IREG(0));
     UML_SEXT(block, ireg(2), ireg(0));
     UML_ADD(block, IREG(1), IREG(1), IREG(2));
     UML_ADD(block, ireg(1), ireg(1), ireg(2));
  }
  }


Line 399: 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, IREG(1), IREG(0), IMM(8), IMM(0xff));
     UML_ROLAND(block, ireg(1), ireg(0), 8, 0xff);
     UML_ROLAND(block, IREG(2), IREG(0), IMM(16), IMM(0xff));
     UML_ROLAND(block, ireg(2), ireg(0), 16, 0xff);
     UML_ROLAND(block, IREG(3), IREG(0), IMM(24), IMM(0xff));
     UML_ROLAND(block, ireg(3), ireg(0), 24, 0xff);
     UML_ROLAND(block, IREG(4), IREG(0), IMM(0), IMM(0xff));
     UML_ROLAND(block, ireg(4), ireg(0), 0, 0xff);
  }
  }


Line 434: 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, IREG(0), IREG(0), IMM((dstbitnum - srcbitnum) & 63), IMM(U64(1) << dstbitnum));
     UML_DROLINS(block, ireg(0), ireg(0), (dstbitnum - srcbitnum) & 63, u64(1) << dstbitnum);
  }
  }


Line 464: 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, IREG(0), MEM(cycles), IMM(10));
     UML_ADD(block, ireg(0), mem(cycles), 10);
  }
  }


Line 494: Line 497:
  void generate_add_with_carry(drcuml_block *block)
  void generate_add_with_carry(drcuml_block *block)
  {
  {
     UML_CARRY(block, MEM(flags), IMM(0));
     UML_CARRY(block, mem(flags), 0);
     UML_ADDC(block, IREG(0), IREG(1), IREG(2));
     UML_ADDC(block, ireg(0), ireg(1), ireg(2));
  }
  }


Line 525: 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, MEM(cycles), MEM(cycles), MVAR(10));
     UML_SUB(block, mem(cycles), mem(cycles), MVAR(10));
  }
  }


Line 555: Line 558:
  void generate_sub_with_borrow(drcuml_block *block)
  void generate_sub_with_borrow(drcuml_block *block)
  {
  {
     UML_CARRY(block, MEM(flags), IMM(0));
     UML_CARRY(block, mem(flags), 0);
     UML_SUBB(block, IREG(0), IREG(1), IREG(2));
     UML_SUBB(block, ireg(0), ireg(1), ireg(2));
  }
  }


Line 585: 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, MEM(param), IMM(16));
     UML_CMP(block, mem(param), 16);
     UML_JMPc(block, IF_B, target);
     UML_JMPc(block, COND_B, target);
  }
  }


Line 620: Line 623:
  {
  {
     /* lower result in i0, upper result in i1 */
     /* lower result in i0, upper result in i1 */
     UML_DMULU(block, IREG(0), IREG(1), MEM(src1), MEM(src2));
     UML_DMULU(block, ireg(0), ireg(1), mem(src1), mem(src2));
  }
  }


Line 654: Line 657:
  {
  {
     /* lower result in i0, upper result in i1 */
     /* lower result in i0, upper result in i1 */
     UML_MULS(block, IREG(0), IREG(0), IREG(0), IMM(20));
     UML_MULS(block, ireg(0), ireg(0), ireg(0), 20);
  }
  }


Line 687: 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, IREG(0), MEM(divisor), DWORD);
     UML_DSEXT(block, ireg(0), mem(divisor), DWORD);
     UML_DDIVU(block, IREG(0), IREG(0), MEM(dividend), IREG(0));
     UML_DDIVU(block, ireg(0), ireg(0), mem(dividend), ireg(0));
  }
  }


Line 722: 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, IREG(2), IREG(0), IREG(0), IREG(1));
     UML_DIVS(block, ireg(2), ireg(0), ireg(0), ireg(1));
  }
  }


Line 752: 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, MEM(param), MEM(param), IMM(0xffff));
     UML_AND(block, mem(param), mem(param), 0xffff);
  }
  }


Line 781: 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, IREG(0), IMM(1 << bitnum));
     UML_TEST(block, ireg(0), 1 << bitnum);
     UML_JMPc(block, IF_NZ, target);
     UML_JMPc(block, COND_NZ, target);
  }
  }


Line 812: 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, IREG(1), IREG(1), IMM(1 << Whichbit));
     UML_OR(block, ireg(1), ireg(1), 1 << whichbit);
  }
  }


Line 842: 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, IREG(0), IMM(~U64(0)));
     UML_DXOR(block, ireg(0), ~u64(0));
  }
  }


Line 873: 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, IREG(1), IREG(0));
     UML_LZCNT(block, ireg(1), ireg(0));
     UML_SHL(block, IREG(0), IREG(0), IREG(1));
     UML_SHL(block, ireg(0), ireg(0), ireg(1));
  }
  }


Line 903: 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, IREG(0), IREG(0));
     UML_BSWAP(block, ireg(0), ireg(0));
     UML_SHR(block, IREG(0), IREG(0), IMM(16));
     UML_SHR(block, ireg(0), ireg(0), 16);
  }
  }


Line 936: Line 939:
  void generate_multiply_i0_by_16(drcuml_block *block)
  void generate_multiply_i0_by_16(drcuml_block *block)
  {
  {
     UML_SHL(block, IREG(0), IREG(0), IMM(4));
     UML_SHL(block, ireg(0), ireg(0), 4);
  }
  }


Line 968: 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, IREG(0), IREG(0), IMM(7));
     UML_SHR(block, ireg(0), ireg(0), 7);
  }
  }


Line 1,000: 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, IREG(1), IREG(0), IMM(31));
     UML_SAR(block, ireg(1), ireg(0), 31);
  }
  }


Line 1,032: Line 1,035:
  void generate_swap_words_in_i0(drcuml_block *block)
  void generate_swap_words_in_i0(drcuml_block *block)
  {
  {
     UML_ROL(block, IREG(0), IREG(0), IMM(16));
     UML_ROL(block, ireg(0), ireg(0), 16);
  }
  }


Line 1,064: Line 1,067:
  void generate_swap_dwords_in_i1(drcuml_block *block)
  void generate_swap_dwords_in_i1(drcuml_block *block)
  {
  {
     UML_DROR(block, IREG(1), IREG(1), IMM(32));
     UML_DROR(block, ireg(1), ireg(1), 32);
  }
  }


Line 1,096: 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, IREG(0), IMM(63));
     UML_CARRY(block, ireg(0), 63);
     UML_DROLC(block, IREG(1), IREG(1), IMM(1));
     UML_DROLC(block, ireg(1), ireg(1), 1);
     UML_DROLC(block, IREG(0), IREG(0), IMM(1));
     UML_DROLC(block, ireg(0), ireg(0), 1);
  }
  }


Line 1,130: 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, IREG(1), IMM(0));
     UML_CARRY(block, ireg(1), 0);
     UML_RORC(block, IREG(0), IREG(0), IMM(1));
     UML_RORC(block, ireg(0), ireg(0), 1);
     UML_RORC(block, IREG(1), IREG(1), IMM(1));
     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);
}