/*++

Copyright (c) 2014 Minoca Corp. All Rights Reserved

Module Name:

    thmdis.h

Abstract:

    This header contains internal definitions for the Thumb-2 disassembler.

Author:

    Evan Green 27-Apr-2014

--*/

//
// ------------------------------------------------------------------- Includes
//

//
// --------------------------------------------------------------------- Macros
//

//
// This macro aligns the given program counter down to a four byte boundary.
//

#define THUMB_ALIGN_4(_ProgramCounter) ((_ProgramCounter) & ~0x3)

//
// This macro returns the number of elements in the given table.
//

#define THUMB_TABLE_SIZE(_Table) (sizeof(_Table) / sizeof((_Table)[0]))

//
// This macro calls the thumb decode with table function, using the table
// size macro to compute the size of the table.
//

#define THUMB_DECODE_WITH_TABLE(_Context, _Table) \
    DbgpThumbDecodeWithTable(_Context, _Table, THUMB_TABLE_SIZE(_Table))

//
// ---------------------------------------------------------------- Definitions
//

//
// Thumb 16-bit definitions
//

#define THUMB16_INSTRUCTION_LENGTH 2
#define THUMB16_MOVS_MASK 0x3E00
#define THUMB16_MOVS_VALUE 0x0000

#define THUMB16_MOVS_RD_SHIFT 0
#define THUMB16_MOVS_RM_SHIFT 3

#define THUMB_MOVS_MNEMONIC "movs"

#define THUMB16_SHIFT_IMMEDIATE_OP_SHIFT 11
#define THUMB16_SHIFT_IMMEDIATE_OP_MASK 0x3
#define THUMB16_SHIFT_IMMEDIATE_RD_SHIFT 0
#define THUMB16_SHIFT_IMMEDIATE_RM_SHIFT 3
#define THUMB16_SHIFT_IMMEDIATE5_SHIFT 6

#define THUMB_REGISTER8_MASK 0x7
#define THUMB_REGISTER16_MASK 0xF

#define THUMB_IMMEDIATE2_MASK 0x3
#define THUMB_IMMEDIATE3_MASK 0x7
#define THUMB_IMMEDIATE4_MASK 0xF
#define THUMB_IMMEDIATE5_MASK 0x1F
#define THUMB_IMMEDIATE6_MASK 0x3F
#define THUMB_IMMEDIATE7_MASK 0x7F
#define THUMB_IMMEDIATE8_MASK 0xFF
#define THUMB_IMMEDIATE10_MASK 0x3FF
#define THUMB_IMMEDIATE11_MASK 0x7FF
#define THUMB_IMMEDIATE12_MASK 0xFFF

#define THUMB16_ADD_SUBTRACT_REGISTER_RD_SHIFT 0
#define THUMB16_ADD_SUBTRACT_REGISTER_RN_SHIFT 3
#define THUMB16_ADD_SUBTRACT_REGISTER_RM_SHIFT 6
#define THUMB16_SUBTRACT (1 << 9)

#define THUMB_ADDS_MNEMONIC "adds"
#define THUMB_SUBS_MNEMONIC "subs"

#define THUMB16_ADD_SUBTRACT_IMMEDIATE3_RD_SHIFT 0
#define THUMB16_ADD_SUBTRACT_IMMEDIATE3_RN_SHIFT 3
#define THUMB16_ADD_SUBTRACT_IMMEDIATE3_SHIFT 6

#define THUMB16_MOVE_COMPARE_IMMEDIATE_SHIFT 0
#define THUMB16_MOVE_COMPARE_IMMEDIATE_REGISTER_SHIFT 8
#define THUMB16_MOVE_COMPARE_IMMEDIATE_OP_SHIFT 11
#define THUMB16_MOVE_COMPARE_IMMEDIATE_OP_MASK 0x3
#define THUMB_CMP_MNEMONIC "cmp"

#define THUMB16_DATA_PROCESSING_OP_SHIFT 6
#define THUMB16_DATA_PROCESSING_OP_MASK 0xF
#define THUMB16_DATA_PROCESSING_RSB 0x9
#define THUMB16_DATA_PROCESSING_MUL 0xD
#define THUMB16_DATA_PROCESSING_RD_SHIFT 0
#define THUMB16_DATA_PROCESSING_RM_SHIFT 3

#define THUMB16_SPECIAL_DATA_OP_SHIFT 8
#define THUMB16_SPECIAL_DATA_OP_MASK 0x3
#define THUMB16_SPECIAL_DATA_OP_BRANCH 0x3
#define THUMB16_SPECIAL_DATA_BRANCH_LINK (1 << 7)
#define THUMB16_SPECIAL_DATA_RD_SHIFT 0
#define THUMB16_SPECIAL_DATA_RM_SHIFT 3
#define THUMB16_SPECIAL_DATA_RD_HIGH (1 << 7)

#define THUMB_BX_MNEMONIC "bx"
#define THUMB_BLX_MNEMONIC "blx"

#define THUMB_LDR_MNEMONIC "ldr"
#define THUMB16_LDR_RT_SHIFT 8
#define THUMB16_LDR_IMMEDIATE8_SHIFT 0

#define THUMB16_LOAD_STORE_REGISTER_OP_SHIFT 9
#define THUMB16_LOAD_STORE_REGISTER_OP_MASK 0x7

#define THUMB16_LOAD_STORE_REGISTER_RT_SHIFT 0
#define THUMB16_LOAD_STORE_REGISTER_RN_SHIFT 3
#define THUMB16_LOAD_STORE_REGISTER_RM_SHIFT 6

#define THUMB16_LOAD_STORE_IMMEDIATE_RT_SHIFT 0
#define THUMB16_LOAD_STORE_IMMEDIATE_RN_SHIFT 3
#define THUMB16_LOAD_STORE_IMMEDIATE5_SHIFT 6
#define THUMB16_LOAD_STORE_IMMEDIATE_OP_SHIFT 13
#define THUMB16_LOAD_STORE_IMMEDIATE_OP_MASK 0x7
#define THUMB16_LOAD_STORE_IMMEDIATE_OP_HALF_WORD 0x4
#define THUMB16_LOAD_STORE_BYTE (1 << 12)

#define THUMB16_LOAD_BIT (1 << 11)

#define THUMB_LDRH_MNEMONIC "ldrh"
#define THUMB_STRH_MNEMONIC "strh"
#define THUMB_LDRB_MNEMONIC "ldrb"
#define THUMB_STRB_MNEMONIC "strb"
#define THUMB_LDR_MNEMONIC "ldr"
#define THUMB_STR_MNEMONIC "str"

#define THUMB16_LOAD_STORE_SP_RELATIVE_IMMEDIATE8_SHIFT 0
#define THUMB16_LOAD_STORE_SP_RELATIVE_RT_SHIFT 8

#define THUMB16_ADR_IMMEDIATE8_SHIFT 0
#define THUMB16_ADR_RD_SHIFT 8
#define THUMB16_ADR_SP (1 << 11)

#define THUMB_ADR_MNEMONIC "adr"
#define THUMB_ADR_W_MNEMONIC "adr.w"
#define THUMB_ADD_MNEMONIC "add"

#define THUMB16_LOAD_STORE_MULTIPLE_RN_SHIFT 8
#define THUMB_REGISTER8_LIST 0xFF
#define THUMB_REGISTER16_LIST 0xFFFF

#define THUMB_LDM_MNEMONIC "ldm"
#define THUMB_STM_MNEMONIC "stm"

#define THUMB16_BRANCH_SVC_OP_SHIFT 8
#define THUMB16_BRANCH_SVC_OP_MASK 0xF
#define THUMB16_BRANCH_SVC_OP_UDF 0xE
#define THUMB16_BRANCH_SVC_OP_SVC 0xF

#define THUMB_UDF_MNEMONIC "udf"
#define THUMB_SVC_MNEMONIC "svc"
#define THUMB_B_MNEMONIC "b"

#define THUMB16_ADJUST_STACK_POINTER_SUBTRACT (1 << 7)
#define THUMB_SUB_MNEMONIC "sub"

#define THUMB16_COMPARE_BRANCH_NOT_ZERO (1 << 11)
#define THUMB16_COMPARE_BRANCH_ZERO_RN_SHIFT 0
#define THUMB16_COMPARE_BRANCH_ZERO_IMMEDIATE5_SHIFT 3
#define THUMB16_COMPARE_BRANCH_ZERO_IMMEDIATE6 (1 << 9)

#define THUMB_CBZ_MNEMONIC "cbz"
#define THUMB_CBNZ_MNEMONIC "cbnz"

#define THUMB16_SIGN_ZERO_EXTEND_OP_SHIFT 6
#define THUMB16_SIGN_ZERO_EXTEND_OP_MASK 0x3
#define THUMB16_SIGN_ZERO_EXTEND_RD_SHIFT 0
#define THUMB16_SIGN_ZERO_EXTEND_RM_SHIFT 3

#define THUMB_PUSH_MNEMONIC "push"
#define THUMB_POP_MNEMONIC "pop"
#define THUMB16_PUSH_POP_LINK_OR_PC (1 << 8)

#define THUMB16_SET_ENDIAN_BIG (1 << 9)
#define THUMB16_LITTLE_ENDIAN_MNEMONIC "little"
#define THUMB16_BIG_ENDIAN_MNEMONIC "big"
#define THUMB_SETEND_MNEMONIC "setend"

#define THUMB_CPS_DISABLE_MNEMONIC "cpsid"
#define THUMB_CPS_ENABLE_MNEMONIC "cpsie"

#define THUMB16_CPS_DISABLE (1 << 4)
#define THUMB16_CPS_FLAG_F (1 << 0)
#define THUMB16_CPS_FLAG_I (1 << 1)
#define THUMB16_CPS_FLAG_A (1 << 2)

#define THUMB16_REVERSE_BYTES_OP_SHIFT 6
#define THUMB16_REVERSE_BYTES_OP_MASK 0x3
#define THUMB16_REVERSE_BYTES_RD_SHIFT 0
#define THUMB16_REVERSE_BYTES_RN_SHIFT 3

#define THUMB16_BREAKPOINT_IMMEDIATE8_SHIFT 0
#define THUMB_BKPT_MNEMONIC "bkpt"

#define THUMB16_IF_THEN_CONDITION_SHIFT 4
#define THUMB16_IF_THEN_CONDITION_MASK 0xF
#define THUMB16_IF_THEN_MASK 0xF

#define THUMB16_HINTS_OP_SHIFT 4
#define THUMB16_HINTS_OP_MASK 0xF

#define THUMB_IT_MNEMONIC "it"

//
// Thumb 32-bit definitions
//

#define THUMB32_INSTRUCTION_LENGTH 4
#define THUMB32_DATA_SET_FLAGS (1 << 20)

#define THUMB32_LOAD_STORE_MULTIPLE_OP_SHIFT 23
#define THUMB32_LOAD_STORE_MULTIPLE_OP_MASK 0x3
#define THUMB32_LOAD_STORE_RETURN_STATE_OP 0
#define THUMB32_LOAD_STORE_MULTIPLE_OP 1
#define THUMB32_LOAD_STORE_MULTIPLE_OP2 2
#define THUMB32_LOAD_STORE_RETURN_STATE_OP2 3
#define THUMB32_LOAD_BIT (1 << 20)
#define THUMB32_LOAD_STORE_MULTIPLE_WRITE_BACK_BIT (1 << 21)
#define THUMB32_LOAD_STORE_MULTIPLE_RN_SHIFT 16
#define THUMB32_LOAD_STORE_MODE_MASK 0x1F
#define THUMB32_LOAD_STORE_INCREMENT 0x00800000
#define THUMB_SRS_MNEMONIC "srs"
#define THUMB_RFE_MNEMONIC "rfe"

#define THUMB_DB_SUFFIX "db"
#define THUMB_IA_SUFFIX "ia"

#define THUMB32_EXCLUSIVE_RN_SHIFT 16
#define THUMB32_EXCLUSIVE_RT_SHIFT 12
#define THUMB32_EXCLUSIVE_RD_SHIFT 8
#define THUMB32_EXCLUSIVE_IMMEDIATE8_SHIFT 0

#define THUMB_LDREX_MNEMONIC "ldrex"
#define THUMB_STREX_MNEMONIC "strex"

#define THUMB32_DUAL_RN_SHIFT 16
#define THUMB32_DUAL_RT_SHIFT 12
#define THUMB32_DUAL_RT2_SHIFT 8

#define THUMB_LDRD_MNEMONIC "ldrd"
#define THUMB_STRD_MNEMONIC "strd"

#define THUMB32_PREINDEX_BIT (1 << 24)
#define THUMB32_WRITE_BACK_BIT (1 << 23)

#define THUMB32_EXCLUSIVE_FUNKY_RD_SHIFT 0
#define THUMB32_EXCLUSIVE_FUNKY_OP_SHIFT 4
#define THUMB32_EXCLUSIVE_FUNKY_OP_MASK 0xF
#define THUMB32_EXCLUSIVE_FUNKY_RT2_SHIFT 8
#define THUMB32_EXCLUSIVE_FUNKY_RT_SHIFT 12
#define THUMB32_EXCLUSIVE_FUNKY_RN_SHIFT 16

#define THUMB32_EXCLUSIVE_FUNKY_OP_BYTE 0x4
#define THUMB32_EXCLUSIVE_FUNKY_OP_HALF_WORD 0x5
#define THUMB32_EXCLUSIVE_FUNKY_OP_DUAL 0x7

#define THUMB_LDREXB_MNEMONIC "ldrexb"
#define THUMB_LDREXH_MNEMONIC "ldrexh"
#define THUMB_LDREXD_MNEMONIC "ldrexd"
#define THUMB_STREXB_MNEMONIC "strexb"
#define THUMB_STREXH_MNEMONIC "strexh"
#define THUMB_STREXD_MNEMONIC "strexd"

#define THUMB32_DATA_SHIFTED_REGISTER_RM_SHIFT 0
#define THUMB32_DATA_SHIFTED_REGISTER_TYPE_SHIFT 2
#define THUMB32_DATA_SHIFTED_REGISTER_TYPE_MASK 0x3
#define THUMB32_DATA_SHIFTED_REGISTER_IMMEDIATE2_SHIFT 6
#define THUMB32_DATA_SHIFTED_REGISTER_IMMEDIATE2_MASK 0x3
#define THUMB32_DATA_SHIFTED_REGISTER_RD_SHIFT 8
#define THUMB32_DATA_SHIFTED_REGISTER_IMMEDIATE3_SHIFT 12
#define THUMB32_DATA_SHIFTED_REGISTER_IMMEDIATE3_MASK 0x7
#define THUMB32_DATA_SHIFTED_REGISTER_RN_SHIFT 16
#define THUMB32_DATA_SHIFTED_REGISTER_OP_SHIFT 21
#define THUMB32_DATA_SHIFTED_REGISTER_OP_MASK 0xF
#define THUMB32_DATA_AND 0x0
#define THUMB32_DATA_BIC 0x1
#define THUMB32_DATA_ORR 0x2
#define THUMB32_DATA_ORN 0x3
#define THUMB32_DATA_EOR 0x4
#define THUMB32_DATA_PKH 0x6
#define THUMB32_DATA_ADD 0x8
#define THUMB32_DATA_ADC 0xA
#define THUMB32_DATA_SBC 0xB
#define THUMB32_DATA_SUB 0xD
#define THUMB32_DATA_RSB 0xE
#define THUMB32_PACK_HALF_WORD_TB (1 << 5)

#define THUMB_TST_W_MNEMONIC "tst.w"
#define THUMB_TEQ_W_MNEMONIC "teq.w"
#define THUMB_PKHBT_MNEMONIC "pkhbt"
#define THUMB_PKHTB_MNEMONIC "pkhtb"
#define THUMB_CMN_W_MNEMONIC "cmn.w"
#define THUMB_CMP_W_MNEMONIC "cmp.w"
#define THUMB_CMN_MNEMONIC "cmn"

#define THUMB_SHIFT_TYPE_LSL_STRING "lsl"
#define THUMB_SHIFT_TYPE_LSR_STRING "lsr"
#define THUMB_SHIFT_TYPE_ASR_STRING "asr"
#define THUMB_SHIFT_TYPE_ROR_STRING "ror"
#define THUMB_SHIFT_TYPE_RRX_STRING "rrx"

#define THUMB32_TABLE_BRANCH_RM_SHIFT 0
#define THUMB32_TABLE_BRANCH_RN_SHIFT 16
#define THUMB32_TABLE_BRANCH_HALF_WORD (1 << 4)

#define THUMB_TBB_MNEMONIC "tbb"
#define THUMB_TBH_MNEMONIC "tbh"

#define THUMB32_DATA_MODIFIED_IMMEDIATE_IMMEDIATE8_SHIFT 0
#define THUMB32_DATA_MODIFIED_IMMEDIATE_RD_SHIFT 8
#define THUMB32_DATA_MODIFIED_IMMEDIATE_IMMEDIATE3_SHIFT 12
#define THUMB32_DATA_MODIFIED_IMMEDIATE_RN_SHIFT 16
#define THUMB32_DATA_MODIFIED_IMMEDIATE_OP_SHIFT 21
#define THUMB32_DATA_MODIFIED_IMMEDIATE_OP_MASK 0xF
#define THUMB32_DATA_MODIFIED_IMMEDIATE_IMMEDIATE12 (1 << 26)

#define THUMB32_DATA_PLAIN_IMMEDIATE_SAT_IMMEDIATE_SHIFT 0
#define THUMB32_DATA_PLAIN_IMMEDIATE_SAT_IMMEDIATE4_MASK 0xF
#define THUMB32_DATA_PLAIN_IMMEDIATE_SAT_IMMEDIATE5_MASK 0x1F
#define THUMB32_DATA_PLAIN_IMMEDIATE_MSB_SHIFT 0
#define THUMB32_DATA_PLAIN_IMMEDIATE_MSB_MASK 0x1F
#define THUMB32_DATA_PLAIN_IMMEDIATE_WIDTH_MINUS_1_SHIFT 0
#define THUMB32_DATA_PLAIN_IMMEDIATE_WIDTH_MINUS_1_MASK 0x1F
#define THUMB32_DATA_PLAIN_IMMEDIATE_MSB_MASK 0x1F
#define THUMB32_DATA_PLAIN_IMMEDIATE_RD_SHIFT 8
#define THUMB32_DATA_PLAIN_IMMEDIATE_IMMEDIATE2_SHIFT 6
#define THUMB32_DATA_PLAIN_IMMEDIATE_IMMEDIATE3_SHIFT 12
#define THUMB32_DATA_PLAIN_IMMEDIATE_IMMEDIATE4_SHIFT 16
#define THUMB32_DATA_PLAIN_IMMEDIATE_RN_SHIFT 16
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_SHIFT 20
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_MASK 0x1F
#define THUMB32_DATA_PLAIN_IMMEDIATE_SHIFT_RIGHT (1 << 21)
#define THUMB32_DATA_PLAIN_IMMEDIATE_UNSIGNED (1 << 23)

#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_ADD 0x00
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_MOV 0x04
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_SUB 0x0A
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_MOVT 0x0C
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_SSAT 0x10
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_SSAT16 0x12
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_SBFX 0x14
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_BFIC 0x16
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_USAT 0x18
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_USAT16 0x1A
#define THUMB32_DATA_PLAIN_IMMEDIATE_OP_UBFX 0x1C

#define THUMB_MOVT_MNEMONIC   "movt"
#define THUMB_MOVW_MNEMONIC   "movw"
#define THUMB_BFI_MNEMONIC    "bfi"
#define THUMB_BFC_MNEMONIC    "bfc"
#define THUMB_UBFX_MNEMONIC   "ubfx"
#define THUMB_SBFX_MNEMONIC   "sbfx"
#define THUMB_SSAT_MNEMONIC   "ssat"
#define THUMB_SSAT16_MNEMONIC "ssat16"
#define THUMB_USAT_MNEMONIC   "usat"
#define THUMB_USAT16_MNEMONIC "usat16"

#define THUMB32_MSR_RN_SHIFT 16
#define THUMB32_MSR_WRITE_G (1 << 10)
#define THUMB32_MSR_WRITE_FLAGS (1 << 11)
#define THUMB32_MSR_MODE_SHIFT 8
#define THUMB32_MSR_MODE_MASK 0xF
#define THUMB32_MSR_MODE4 (1 << 4)
#define THUMB32_MSR_BANKED_REGISTER (1 << 5)
#define THUMB32_MSR_SPSR (1 << 20)
#define THUMB32_MSR_MASK_SHIFT 8
#define THUMB32_MSR_MASK_MASK 0xF
#define THUMB32_MSR_MASK_C 0x1
#define THUMB32_MSR_MASK_X 0x2
#define THUMB32_MSR_MASK_S 0x4
#define THUMB32_MSR_MASK_F 0x8

#define THUMB_MSR_MNEMONIC "msr"
#define THUMB_CPSR_STRING "cpsr"
#define THUMB_SPSR_STRING "spsr"

#define THUMB32_CPS_MASK 0x00000700
#define THUMB32_CPS_VALUE 0x00000000
#define THUMB32_CPS_MODE_MASK 0x0000001F
#define THUMB32_CPS_DISABLE (1 << 9)
#define THUMB32_CPS_FLAG_F (1 << 5)
#define THUMB32_CPS_FLAG_I (1 << 6)
#define THUMB32_CPS_FLAG_A (1 << 7)
#define THUMB32_CPS_CHANGE_MODE (1 << 8)
#define THUMB_CPS_DISABLE_W_MNEMONIC "cpsid.w"
#define THUMB_CPS_ENABLE_W_MNEMONIC "cpsie.w"
#define THUMB32_HINT_MASK 0x000000FF
#define THUMB32_HINT_DBG_MASK 0xF0
#define THUMB32_HINT_DBG_VALUE 0xF0
#define THUMB_DBG_MNEMONIC "dbg"
#define THUMB32_DBG_OPTION_MASK 0xF
#define THUMB32_HINT_OP_COUNT 5

#define THUMB32_MISCELLANEOUS_CONTROL_OP_SHIFT 4
#define THUMB32_MISCELLANEOUS_CONTROL_OP_MASK 0xF
#define THUMB32_MISCELLANEOUS_CONTROL_OP_ENTERX 0x0
#define THUMB32_MISCELLANEOUS_CONTROL_OP_LEAVEX 0x1
#define THUMB32_MISCELLANEOUS_CONTROL_OP_CLREX 0x2
#define THUMB32_MISCELLANEOUS_CONTROL_OP_DSB 0x4
#define THUMB32_MISCELLANEOUS_CONTROL_OP_DMB 0x5
#define THUMB32_MISCELLANEOUS_CONTROL_OP_ISB 0x6
#define THUMB_ENTERX_MNEMONIC "enterx"
#define THUMB_LEAVEX_MNEMONIC "leavex"
#define THUMB_CLREX_MNEMONIC "clrex"
#define THUMB_DSB_MNEMONIC "dsb"
#define THUMB_DMB_MNEMONIC "dmb"
#define THUMB_ISB_MNEMONIC "isb"
#define THUMB32_BARRIER_MODE_MASK 0xF

#define THUMB32_BXJ_RM_SHIFT 16
#define THUMB_BXJ_MNEMONIC "bxj"
#define THUMB_ERET_MNEMONIC "eret"

#define THUMB32_MRS_RD_SHIFT 8
#define THUMB_MRS_MNEMONIC "mrs"
#define THUMB32_MRS_BANKED_REGISTER (1 << 5)
#define THUMB32_MRS_MODE_SHIFT 16
#define THUMB32_MRS_MODE_MASK 0xF
#define THUMB32_MRS_MODE4 (1 << 4)
#define THUMB32_MRS_SPSR (1 << 20)

#define THUMB32_HVC_IMMEDIATE12_MASK 0x00000FFF
#define THUMB32_HVC_IMMEDIATE4_SHIFT 4
#define THUMB32_HVC_IMMEDIATE4_MASK 0x0000F000
#define THUMB_HVC_MNEMONIC "hvc"

#define THUMB32_SMC_IMMEDIATE4_SHIFT 16
#define THUMB32_SMC_IMMEDIATE4_MASK 0xF
#define THUMB_SMC_MNEMONIC "smc"

#define THUMB32_B_IMMEDIATE11_SHIFT 0
#define THUMB32_B_IMMEDIATE11_MASK 0x00007FF
#define THUMB32_B_CONDITION_SHIFT 22
#define THUMB32_B_CONDITION_MASK 0xF
#define THUMB32_B_UNCONDITIONAL_MASK 0x03800000
#define THUMB32_B_UNCONDITIONAL_VALUE 0x03800000
#define THUMB32_B_S_BIT (1 << 26)
#define THUMB32_B_J1_BIT (1 << 13)
#define THUMB32_B_J2_BIT (1 << 11)
#define THUMB32_B_IMMEDIATE6_SHIFT 16
#define THUMB32_B_IMMEDIATE10_SHIFT 16

#define THUMB_B_W_MNEMONIC_FORMAT "b%s.w"

#define THUMB_UDF_W_MNEMONIC "udf.w"
#define THUMB32_UDF_IMMEDIATE4_SHIFT 16

#define THUMB_BL_MNEMONIC "bl"
#define THUMB32_BL_IMMEDIATE11_SHIFT 0
#define THUMB32_BL_IMMEDIATE10_SHIFT 16
#define THUMB32_BL_X_BIT (1 << 12)
#define THUMB32_BL_THUMB_BIT (1 << 0)

#define THUMB32_LOAD_STORE_IMMEDIATE_RT_SHIFT 12
#define THUMB32_LOAD_STORE_IMMEDIATE_RN_SHIFT 16
#define THUMB32_LOAD_STORE_IMMEDIATE_LARGE (1 << 23)
#define THUMB32_LOAD_SET_FLAGS (1 << 24)
#define THUMB32_LOAD_STORE_OP_SHIFT 21
#define THUMB32_LOAD_STORE_OP_MASK 0x3
#define THUMB32_LOAD_STORE_IMMEDIATE_PREINDEX (1 << 10)
#define THUMB32_LOAD_STORE_IMMEDIATE_ADD (1 << 9)
#define THUMB32_LOAD_STORE_IMMEDIATE_WRITE_BACK (1 << 8)
#define THUMB32_LOAD_STORE_REGISTER_RM_SHIFT 0
#define THUMB32_LOAD_STORE_REGISTER_RT_SHIFT 12
#define THUMB32_LOAD_STORE_REGISTER_RN_SHIFT 16
#define THUMB32_LOAD_STORE_REGISTER_IMMEDIATE2_SHIFT 4

#define THUMB32_LOAD_STORE_REGISTER_MASK 0x00000FC0
#define THUMB32_LOAD_STORE_REGISTER_VALUE 0x00000000

#define THUMB32_DATA_PROCESSING_REGISTER_RM_SHIFT 0
#define THUMB32_DATA_PROCESSING_REGISTER_RD_SHIFT 8
#define THUMB32_DATA_PROCESSING_REGISTER_RN_SHIFT 16
#define THUMB32_DATA_PROCESSING_REGISTER_SHIFT_MASK 0x008000F0
#define THUMB32_DATA_PROCESSING_REGISTER_SHIFT_VALUE 0x00000000
#define THUMB32_DATA_PROCESSING_REGISTER_OP1_SHIFT 20
#define THUMB32_DATA_PROCESSING_REGISTER_OP1_MASK 0xF
#define THUMB32_DATA_PROCESSING_REGISTER_OP1_EXTEND 0x8
#define THUMB32_DATA_PROCESSING_REGISTER_OP1_EXTEND_COUNT 6
#define THUMB32_DATA_PROCESSING_REGISTER_ROTATE_SHIFT 4
#define THUMB32_DATA_PROCESSING_REGISTER_ROTATE_MASK 0x3
#define THUMB32_DATA_PROCESSING_REGISTER_UNSIGNED (1 << 6)
#define THUMB32_DATA_PROCESSING_REGISTER_PARALLEL 0x00000080
#define THUMB32_DATA_PROCESSING_PARALLEL_OP1_SHIFT 20
#define THUMB32_DATA_PROCESSING_PARALLEL_OP1_MASK 0x7
#define THUMB32_DATA_PROCESSING_PARALLEL_OP2_SHIFT 4
#define THUMB32_DATA_PROCESSING_PARALLEL_OP2_MASK 0x3
#define THUMB32_DATA_PROCESSING_PARALLEL_OP_COUNT 24
#define THUMB32_DATA_PROCESSING_MISCELLANEOUS_OP1_SHIFT 20
#define THUMB32_DATA_PROCESSING_MISCELLANEOUS_OP1_MASK 0x3
#define THUMB32_DATA_PROCESSING_MISCELLANEOUS_OP2_SHIFT 4
#define THUMB32_DATA_PROCESSING_MISCELLANEOUS_OP2_MASK 0x3

#define THUMB32_MULTIPLY_RM_SHIFT 0
#define THUMB32_MULTIPLY_RD_SHIFT 8
#define THUMB32_MULTIPLY_RA_SHIFT 12
#define THUMB32_MULTIPLY_RN_SHIFT 16
#define THUMB32_MULTIPLY_OP1_SHIFT 20
#define THUMB32_MULTIPLY_OP1_MASK 0x7
#define THUMB32_MULTIPLY_OP2_SHIFT 4
#define THUMB32_MULTIPLY_OP2_MASK 0x3
#define THUMB32_MULTIPLY_RM_TOP (1 << 4)
#define THUMB32_MULTIPLY_RN_TOP (1 << 5)

#define THUMB32_MULTIPLY_OP1_MLS 0x0
#define THUMB32_MULTIPLY_OP2_MLS 0x1
#define THUMB32_MULTIPLY_OP1_HALF_HALF 0x1
#define THUMB32_MULTIPLY_OP1_WORD_HALF 0x3
#define THUMB32_MULTIPLY_OP1_SMAD 0x2
#define THUMB32_MULTIPLY_OP1_SMSD 0x4
#define THUMB32_MULTIPLY_OP1_SMML 0x5
#define THUMB32_MULTIPLY_DUAL_CROSS (1 << 4)
#define THUMB32_MULTIPLY_ROUND (1 << 4)

#define THUMB_MLS_MNEMONIC "mls"
#define THUMB_MULTIPLY_CROSS_MNEMONIC "x"
#define THUMB_MULTIPLY_ROUND_MNEMONIC "r"

#define THUMB32_LONG_MULTIPLY_RM_SHIFT 0
#define THUMB32_LONG_MULTIPLY_RD_HIGH_SHIFT 8
#define THUMB32_LONG_MULTIPLY_RD_LOW_SHIFT 12
#define THUMB32_LONG_MULTIPLY_RN_SHIFT 16
#define THUMB32_LONG_MULTIPLY_OP1_SHIFT 20
#define THUMB32_LONG_MULTIPLY_OP1_MASK 0x7
#define THUMB32_LONG_MULTIPLY_OP2_SHIFT 4
#define THUMB32_LONG_MULTIPLY_OP2_MASK 0xF

#define THUMB32_LONG_MULTIPLY_OP1_SMLA 0x4
#define THUMB32_LONG_MULTIPLY_OP1_SMLSLD 0x5
#define THUMB32_LONG_MULTIPLY_OP2_SMLA_HALF_MASK 0xC
#define THUMB32_LONG_MULTIPLY_OP2_SMLA_HALF_VALUE 0x8
#define THUMB32_LONG_MULTIPLY_OP2_SMLALD_MASK 0xE
#define THUMB32_LONG_MULTIPLY_OP2_SMLALD_VALUE 0xC
#define THUMB_SMLALD_MNEMONIC "smlald"

#define THUMB_SHIFT_TYPE_LSL 0x0
#define THUMB_SHIFT_TYPE_LSR 0x1
#define THUMB_SHIFT_TYPE_ASR 0x2
#define THUMB_SHIFT_TYPE_ROR 0x3

#define THUMB32_MODIFIED_IMMEDIATE_OP_MASK (0x3 << 10)
#define THUMB32_MODIFIED_IMMEDIATE_OP_NO_ROTATE 0x0
#define THUMB32_MODIFIED_IMMEDIATE_CONSTANT_MASK 0x07F
#define THUMB32_MODIFIED_IMMEDIATE_EXTRA_ONE (1 << 7)
#define THUMB32_MODIFIED_IMMEDIATE_ROTATE_SHIFT 7
#define THUMB32_MODIFIED_IMMEDIATE_ROTATE_MASK 0x1F

#define THUMB32_SIMD_DATA_PROCESSING_UNSIGNED (1 << 28)

//
// ------------------------------------------------------ Data Type Definitions
//

typedef
VOID
(*PTHUMB_DISASSEMBLE_ROUTINE) (
    PARM_DISASSEMBLY Context
    );

/*++

Routine Description:

    This routine disassembles a subset of the Thumb instruction set.

Arguments:

    Context - Supplies a pointer to the disassembly context.

Return Value:

    None.

--*/

/*++

Structure Description:

    This structure defines a tuple of the instruction value for a certain mask
    and the function used to decode that subset of the instruction set.

Members:

    Mask - Stores the mask of the instruction to check against.

    Value - Stores the value of the instruction the mask should match.

    Shift - Stores the value to shift both the mask and the value by.

    Disassemble - Stores a pointer to a routine used to decode instructions
        that match the value.

--*/

typedef struct _THUMB_DECODE_BRANCH {
    ULONG Mask;
    ULONG Value;
    ULONG Shift;
    PTHUMB_DISASSEMBLE_ROUTINE Disassemble;
} THUMB_DECODE_BRANCH, *PTHUMB_DECODE_BRANCH;

//
// -------------------------------------------------------------------- Globals
//

//
// -------------------------------------------------------- Function Prototypes
//

VOID
DbgpThumbDecode (
    PARM_DISASSEMBLY Context
    );

/*++

Routine Description:

    This routine decodes the Thumb-2 instruction set.

Arguments:

    Context - Supplies a pointer to the disassembly context.

Return Value:

    None.

--*/

VOID
DbgpThumb32Decode (
    PARM_DISASSEMBLY Context
    );

/*++

Routine Description:

    This routine decodes the 32-bit portion of the Thumb-2 instruction set.

Arguments:

    Context - Supplies a pointer to the disassembly context.

Return Value:

    None.

--*/

BOOL
DbgpThumbDecodeWithTable (
    PARM_DISASSEMBLY Context,
    PTHUMB_DECODE_BRANCH Table,
    ULONG TableSize
    );

/*++

Routine Description:

    This routine checks the masks and values specified by the given table, and
    calls the appropriate disassembly routine.

Arguments:

    Context - Supplies a pointer to the disassembly context.

    Table - Supplies a pointer to the decode branch table.

    TableSize - Supplies the number of elements in the table.

Return Value:

    TRUE if a match was found.

--*/

