Files
fail/simulators/ovp/armmModel/armmDecodeThumb.c

2726 lines
96 KiB
C

/*
* Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com
*
* YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL
* UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS
* TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER
* IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD
* PARTY PATENTS.
*
* THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR
* MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING
* A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE
* FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER.
* YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW
* PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED
* AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE,
* MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM.
*
* Licensed under an Imperas Modfied Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// VMI header files
#include "vmi/vmiCxt.h"
#include "vmi/vmiDecode.h"
#include "vmi/vmiMessage.h"
#include "vmi/vmiRt.h"
// model header files
#include "armAttributeEntriesThumb16.h"
#include "armAttributeEntriesThumb32.h"
#include "armBitMacros.h"
#include "armDecode.h"
#include "armDecodeEntriesThumb16.h"
#include "armDecodeEntriesThumb32.h"
#include "armDecodeThumb.h"
#include "armRegisters.h"
#include "armStructure.h"
#include "armSysRegisters.h"
#include "armVariant.h"
//
// Prefix for messages from this module
//
#define CPU_PREFIX "ARM_DECODE_THUMB"
////////////////////////////////////////////////////////////////////////////////
// THUMB INSTRUCTION TYPES
////////////////////////////////////////////////////////////////////////////////
//
// Decode entries for 32-bit Thumb instructions like LDR
//
#define TT32_SET_LDR(_NAME) \
TT32_##_NAME##_IMM1, \
TT32_##_NAME##_IMM2, \
TT32_##_NAME##_IMM3, \
TT32_##_NAME##_RM, \
TT32_##_NAME##_RM_SHFT_IMM, \
TT32_##_NAME##T_IMM
//
// Decode entries for 32-bit Thumb instructions like PLD
//
#define TT32_SET_PLD(_NAME) \
TT32_##_NAME##_IMM1, \
TT32_##_NAME##_IMM2, \
TT32_##_NAME##_IMM3, \
TT32_##_NAME##_RM, \
TT32_##_NAME##_RM_SHFT_IMM
//
// Decode entries for 32-bit Thumb instructions like ADD
//
#define TT32_SET_ADD(_NAME) \
TT32_##_NAME##_IMM, \
TT32_##_NAME##_RM_SHFT_IMM, \
TT32_##_NAME##_RM_RRX
//
// Instruction types for 32-bit Thumb parallel add/subtract Media instructions
//
#define TT32_SET_PAS(_NAME) \
TT32_S##_NAME, \
TT32_Q##_NAME, \
TT32_SH##_NAME, \
TT32_U##_NAME, \
TT32_UQ##_NAME, \
TT32_UH##_NAME
//
// Instruction types for 32-bit Thumb DSP instructions like SMLA<x><y>
//
#define TT32_SET_SMLA_XY(_NAME) \
TT32_##_NAME##BB, \
TT32_##_NAME##BT, \
TT32_##_NAME##TB, \
TT32_##_NAME##TT
//
// Instruction types for 32-bit Thumb DSP instructions like SMLAW<y>
//
#define TT32_SET_SMLAW_Y(_NAME) \
TT32_##_NAME##B, \
TT32_##_NAME##T
//
// Instruction types for 32-bit Thumb instructions with optional argument exchange
//
#define TT32_SET_MEDIA_X(_NAME) \
TT32_##_NAME, \
TT32_##_NAME##X
//
// Instruction types for 32-bit Thumb instructions with optional result rounding
//
#define TT32_SET_MEDIA_R(_NAME) \
TT32_##_NAME, \
TT32_##_NAME##R
//
// Instruction types for 32-bit Thumb instructions like LDC
//
#define TT32_SET_LDC(_NAME) \
TT32_##_NAME##_IMM, \
TT32_##_NAME##_UNINDEXED
//
// Instruction types for VFP instructions with D and S variants
//
#define TT32_VFP_DS(_NAME) \
TT32_##_NAME##_D, \
TT32_##_NAME##_S
//
// Instruction type enumeration
//
typedef enum armThumbTypeE {
////////////////////////////////////////////////////////////////////////////
// 16-bit instructions
////////////////////////////////////////////////////////////////////////////
// data processing instructions
TT16_ADC,
TT16_ADD1,
TT16_ADD2,
TT16_ADD3,
TT16_ADD4LL,
TT16_ADD4LH,
TT16_ADD4H,
TT16_ADD5,
TT16_ADD6,
TT16_ADD7,
TT16_AND,
TT16_ASR1,
TT16_ASR2,
TT16_BIC,
TT16_EOR,
TT16_LSL1,
TT16_LSL2,
TT16_LSR1,
TT16_LSR2,
TT16_MOV1,
TT16_MOV2,
TT16_MOV3LL,
TT16_MOV3LH,
TT16_MOV3H,
TT16_MUL,
TT16_MVN,
TT16_NEG,
TT16_ORR,
TT16_ROR,
TT16_SBC,
TT16_SUB1,
TT16_SUB2,
TT16_SUB3,
TT16_SUB4,
// compare instructions
TT16_CMN,
TT16_CMP1,
TT16_CMP2,
TT16_CMP3LH,
TT16_CMP3H,
TT16_TST,
// branch instructions
TT16_B1,
TT16_B2,
TT16_BLX2,
TT16_BX,
TT16_SWI,
TT16_BU,
// miscellaneous instructions
TT16_CPS,
TT16_CBNZ,
TT16_CBZ,
TT16_SXTH,
TT16_SXTB,
TT16_UXTH,
TT16_UXTB,
TT16_REV,
TT16_REV16,
TT16_REVSH,
TT16_BKPT,
// load and store instructions
TT16_LDR1,
TT16_LDR2,
TT16_LDR3,
TT16_LDR4,
TT16_LDRB1,
TT16_LDRB2,
TT16_LDRH1,
TT16_LDRH2,
TT16_LDRSB,
TT16_LDRSH,
TT16_STR1,
TT16_STR2,
TT16_STR3,
TT16_STRB1,
TT16_STRB2,
TT16_STRH1,
TT16_STRH2,
// load and store multiple instructions
TT16_LDMIA,
TT16_POP,
TT16_PUSH,
TT16_STMIA,
// if-then and hints
TT16_IT,
TT16_NOP,
TT16_YIELD,
TT16_WFE,
TT16_WFI,
TT16_SEV,
////////////////////////////////////////////////////////////////////////////
// 32-bit instructions
////////////////////////////////////////////////////////////////////////////
// data processing
TT32_SET_ADD (AND),
TT32_SET_ADD (TST),
TT32_SET_ADD (BIC),
TT32_SET_ADD (ORR),
TT32_SET_ADD (MOV),
TT32_SET_ADD (ORN),
TT32_SET_ADD (MVN),
TT32_SET_ADD (EOR),
TT32_SET_ADD (TEQ),
TT32_SET_ADD (ADD),
TT32_SET_ADD (CMN),
TT32_SET_ADD (ADC),
TT32_SET_ADD (SBC),
TT32_SET_ADD (SUB),
TT32_SET_ADD (CMP),
TT32_SET_ADD (RSB),
// pack halfword
TT32_PKHBT,
TT32_PKHTB,
// data processing (plain binary immediate)
TT32_ADD_PI,
TT32_ADD_ADR_PI,
TT32_SUB_PI,
TT32_SUB_ADR_PI,
TT32_MOV_PI,
TT32_MOVT_PI,
TT32_SSAT,
TT32_SSAT16,
TT32_SBFX,
TT32_BFI,
TT32_BFC,
TT32_USAT,
TT32_USAT16,
TT32_UBFX,
// data processing (register)
TT32_LSL,
TT32_LSR,
TT32_ASR,
TT32_ROR,
TT32_SXTAH,
TT32_SXTH,
TT32_UXTAH,
TT32_UXTH,
TT32_SXTAB16,
TT32_SXTB16,
TT32_UXTAB16,
TT32_UXTB16,
TT32_SXTAB,
TT32_SXTB,
TT32_UXTAB,
TT32_UXTB,
// parallel add/subtract instructions
TT32_SET_PAS (ADD16),
TT32_SET_PAS (ASX ),
TT32_SET_PAS (SAX ),
TT32_SET_PAS (SUB16),
TT32_SET_PAS (ADD8 ),
TT32_SET_PAS (SUB8 ),
// miscellaneous operation instructions
TT32_QADD,
TT32_QDADD,
TT32_QSUB,
TT32_QDSUB,
TT32_REV,
TT32_REV16,
TT32_RBIT,
TT32_REVSH,
TT32_SEL,
TT32_CLZ,
// multiply, divide, multiply accumulate and absolute difference instructions
TT32_MLA,
TT32_MUL,
TT32_MLS,
TT32_SDIV,
TT32_UDIV,
TT32_SET_SMLA_XY (SMLA),
TT32_SET_SMLA_XY (SMUL),
TT32_SET_MEDIA_X (SMLAD),
TT32_SET_MEDIA_X (SMUAD),
TT32_SET_SMLAW_Y (SMLAW),
TT32_SET_SMLAW_Y (SMULW),
TT32_SET_MEDIA_X (SMLSD),
TT32_SET_MEDIA_X (SMUSD),
TT32_SET_MEDIA_R (SMMLA),
TT32_SET_MEDIA_R (SMMUL),
TT32_SET_MEDIA_R (SMMLS),
TT32_USAD8,
TT32_USADA8,
TT32_SMLAL,
TT32_SMULL,
TT32_UMAAL,
TT32_UMLAL,
TT32_UMULL,
TT32_SET_SMLA_XY (SMLAL),
TT32_SET_MEDIA_X (SMLALD),
TT32_SET_MEDIA_X (SMLSLD),
// branch and miscellaneous control instructions
TT32_B1,
TT32_B2,
TT32_BL,
TT32_MSR,
TT32_NOP,
TT32_YIELD,
TT32_WFE,
TT32_WFI,
TT32_SEV,
TT32_DBG,
TT32_MRS,
TT32_UNDEF,
TT32_CLREX,
TT32_DSB,
TT32_DMB,
TT32_ISB,
// load and store multiple instructions
TT32_STMDB,
TT32_STMIA,
TT32_LDMDB,
TT32_LDMIA,
TT32_POPM,
TT32_PUSHM,
// dual and exclusive instructions
TT32_LDRD_IMM,
TT32_STRD_IMM,
TT32_LDREX,
TT32_LDREXB,
TT32_LDREXH,
TT32_STREX,
TT32_STREXB,
TT32_STREXH,
TT32_TBB,
TT32_TBH,
// load and store instructions
TT32_SET_LDR (LDR ),
TT32_SET_LDR (LDRH ),
TT32_SET_LDR (LDRB ),
TT32_SET_LDR (LDRSH),
TT32_SET_LDR (LDRSB),
TT32_SET_LDR (STR ),
TT32_SET_LDR (STRH ),
TT32_SET_LDR (STRB ),
TT32_SET_PLD (PLD ),
TT32_SET_PLD (PLI ),
TT32_UHINTH,
TT32_UHINTB,
// coprocessor instructions
TT32_CDP,
TT32_CDP2,
TT32_SET_LDC (LDC ),
TT32_SET_LDC (LDC2),
TT32_MCR,
TT32_MCR2,
TT32_MRC,
TT32_MRC2,
TT32_SET_LDC (STC ),
TT32_SET_LDC (STC2),
TT32_MCRR,
TT32_MCRR2,
TT32_MRRC,
TT32_MRRC2,
// VFP data processing instructions
TT32_VMLA_VFP,
TT32_VMLS_VFP,
TT32_VNMLS_VFP,
TT32_VNMLA_VFP,
TT32_VMUL_VFP,
TT32_VNMUL_VFP,
TT32_VADD_VFP,
TT32_VSUB_VFP,
TT32_VDIV_VFP,
TT32_VFNMA_VFP,
TT32_VFNMS_VFP,
TT32_VFMA_VFP,
TT32_VFMS_VFP,
TT32_VMOVI_VFP,
TT32_VMOVR_VFP,
TT32_VABS_VFP,
TT32_VNEG_VFP,
TT32_VSQRT_VFP,
TT32_VCVTBFH_VFP,
TT32_VCVTTFH_VFP,
TT32_VCVTBHF_VFP,
TT32_VCVTTHF_VFP,
TT32_VCMP_VFP,
TT32_VCMPE_VFP,
TT32_VCMP0_VFP,
TT32_VCMPE0_VFP,
TT32_VCVTFU_VFP,
TT32_VCVTFS_VFP,
TT32_VCVTFXUH_VFP,
TT32_VCVTFXUW_VFP,
TT32_VCVTFXSH_VFP,
TT32_VCVTFXSW_VFP,
TT32_VCVTUF_VFP,
TT32_VCVTRUF_VFP,
TT32_VCVTSF_VFP,
TT32_VCVTRSF_VFP,
TT32_VCVTXFSH_VFP,
TT32_VCVTXFSW_VFP,
TT32_VCVTXFUH_VFP,
TT32_VCVTXFUW_VFP,
// Extension register load/store instructions
TT32_VFP_DS (VSTMIA),
TT32_VFP_DS (VSTMIAW),
TT32_VFP_DS (VSTR),
TT32_VFP_DS (VSTMDBW),
TT32_VFP_DS (VPUSH),
TT32_VFP_DS (VLDMIA),
TT32_VFP_DS (VLDMIAW),
TT32_VFP_DS (VPOP),
TT32_VFP_DS (VLDR),
TT32_VFP_DS (VLDMDBW),
// 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs
TT32_VMRS,
TT32_VMSR,
TT32_VMOVRS,
TT32_VMOVSR,
TT32_VMOVZR,
TT32_VMOVRZ,
// 64-bit transfer instructions between ARM core regs and extension regs
TT32_VMOVRRD,
TT32_VMOVDRR,
TT32_VMOVRRSS,
TT32_VMOVSSRR,
// KEEP LAST
TT_LAST
} armThumbType;
////////////////////////////////////////////////////////////////////////////////
// FIELD EXTRACTION MACROS
////////////////////////////////////////////////////////////////////////////////
#define OP_R0(_I) WIDTH(4,(_I)>> 0)
#define OP_R12(_I) WIDTH(4,(_I)>>12)
#define OP_R16(_I) WIDTH(4,(_I)>>16)
#define OP_F20(_I) WIDTH(1,(_I)>>20)
#define OP_COND_8(_I) WIDTH(4,(_I)>> 8)
#define OP_COND_22(_I) WIDTH(4,(_I)>>22)
#define OP_COND_28(_I) WIDTH(4,(_I)>>28)
#define OP_IT(_I) WIDTH(8,(_I)>> 0)
#define OP_R3_0(_I) WIDTH(3,(_I)>> 0)
#define OP_R3_3(_I) WIDTH(3,(_I)>> 3)
#define OP_R3_6(_I) WIDTH(3,(_I)>> 6)
#define OP_R3_8(_I) WIDTH(3,(_I)>> 8)
#define OP_R4_0(_I) WIDTH(4,(_I)>> 0)
#define OP_R4_8(_I) WIDTH(4,(_I)>> 8)
#define OP_R4_12(_I) WIDTH(4,(_I)>>12)
#define OP_R4_16(_I) WIDTH(4,(_I)>>16)
#define OP_U_1_5(_I) WIDTH(1,(_I)>> 5)
#define OP_U_1_7(_I) WIDTH(1,(_I)>> 7)
#define OP_U_1_19(_I) WIDTH(1,(_I)>>19)
#define OP_U_1_21(_I) WIDTH(1,(_I)>>21)
#define OP_U_2_4(_I) WIDTH(2,(_I)>> 4)
#define OP_U_2_10(_I) WIDTH(2,(_I)>>10)
#define OP_U_2_20(_I) WIDTH(2,(_I)>>20)
#define OP_U_2_21(_I) WIDTH(2,(_I)>>21)
#define OP_U_3_0(_I) WIDTH(3,(_I)>> 0)
#define OP_U_3_6(_I) WIDTH(3,(_I)>> 6)
#define OP_U_4_0(_I) WIDTH(4,(_I)>> 0)
#define OP_U_4_4(_I) WIDTH(4,(_I)>> 4)
#define OP_U_5_0(_I) WIDTH(5,(_I)>> 0)
#define OP_U_5_0_5(_I) (((WIDTH(4,(_I)>>0))<<1)|WIDTH(1,(_I)>>5))
#define OP_U_5_6(_I) WIDTH(5,(_I)>> 6)
#define OP_U_7_0(_I) WIDTH(7,(_I)>> 0)
#define OP_U_7_1(_I) WIDTH(7,(_I)>> 1)
#define OP_U_8_0(_I) WIDTH(8,(_I)>> 0)
#define OP_U_8_16_0(_I) (((WIDTH(4,(_I)>>16))<<4) | WIDTH(4,(_I)>>0))
#define OP_U_9(_I) WIDTH(1,(_I)>> 9)
#define OP_U_12_0(_I) WIDTH(12,(_I)>>0)
#define OP_U_23(_I) WIDTH(1,(_I)>>23)
#define OP_R4_0_H7(_I) (((WIDTH(1,(_I)>>7))<<3)|OP_R3_0(_I))
#define OP_R4_3_H6(_I) (((WIDTH(1,(_I)>>6))<<3)|OP_R3_3(_I))
#define OP_TS8(_I) (((Int32)((_I)<<24))>>23)
#define OP_TS11(_I) (((Int32)((_I)<<21))>>20)
#define OP_TU9_7_3(_I) ((WIDTH(1,(_I)>>9)<<6) | (WIDTH(5,(_I)>>3)<<1))
#define OP_RL_16(_I) WIDTH(8,(_I)>>0)
#define OP_RL_16_LR(_I) (OP_RL_16(_I) | (((_I)&0x100) ? (1<<ARM_REG_LR) : 0))
#define OP_RL_16_PC(_I) (OP_RL_16(_I) | (((_I)&0x100) ? (1<<ARM_REG_PC) : 0))
#define OP_RL_32(_I) WIDTH(16,(_I)>>0)
#define OP_RL_32_SP(_I) (OP_RL_32(_I) & ~(1<<ARM_REG_SP))
#define OP_RL_32_PCSP(_I) (OP_RL_32(_I) & ~((1<<ARM_REG_SP)|(1<<ARM_REG_PC)))
#define OP_IS_4(_I) WIDTH(1,(_I)>> 4)
#define OP_AIF_0(_I) WIDTH(3,(_I)>> 0)
#define OP_MA(_I) WIDTH(1,(_I)>> 8)
#define OP_PI_10(_I) WIDTH(1,(_I)>>10)
#define OP_PI_24(_I) WIDTH(1,(_I)>>24)
#define OP_WB_8(_I) WIDTH(1,(_I)>> 8)
#define OP_WB_21(_I) WIDTH(1,(_I)>>21)
#define OP_CPNUM(_I) WIDTH(4,(_I)>> 8)
#define OP_CPOP1_4_4(_I) WIDTH(4,(_I)>> 4)
#define OP_CPOP1_4_20(_I) WIDTH(4,(_I)>>20)
#define OP_CPOP1_3_21(_I) WIDTH(3,(_I)>>21)
#define OP_CPOP2(_I) WIDTH(3,(_I)>> 5)
#define OP_LL(_I) WIDTH(1,(_I)>>22)
#define OP_V0_5(_I) ((OP_R0(_I) <<1) | WIDTH(1,(_I)>> 5))
#define OP_V16_7(_I) ((OP_R16(_I)<<1) | WIDTH(1,(_I)>> 7))
#define OP_V12_22(_I) ((OP_R12(_I)<<1) | WIDTH(1,(_I)>>22))
#define OP_V5_0(_I) ((WIDTH(1,(_I)>>5) <<4) | OP_R0(_I))
#define OP_V22_12(_I) ((WIDTH(1,(_I)>>22)<<4) | OP_R12(_I))
#define OP_V7_16(_I) ((WIDTH(1,(_I)>>7) <<4) | OP_R16(_I))
#define OP_U(_I) WIDTH(1,(_I)>>23)
#define OP_PI(_I) WIDTH(1,(_I)>>24)
////////////////////////////////////////////////////////////////////////////////
// INSTRUCTION ATTRIBUTE TABLE
////////////////////////////////////////////////////////////////////////////////
//
// This defines whether the instruction sets flags
//
typedef enum setFlagsE {
SF_0, // don't set flags
SF_V, // set flags, show in disassembly using "s" suffix
SF_I, // set flags, not shown in instruction disassembly
SF_20_V, // set flags if field 20 set, show in disassembly
SF_IT, // only when not in if-then block
} setFlags;
//
// This defines whether the instruction sets flags
//
typedef enum condSpecE {
CO_NA, // no condition
CO_8, // condition at 11:8
CO_22, // condition at 25:22
CO_28, // condition at 31:28
} condSpec;
//
// Define the location of register in an instruction
//
typedef enum rSpecE {
R_NA, // no register
R3_0, // 3-bit register specification at 2:0
R3_3, // 3-bit register specification at 5:3
R3_6, // 3-bit register specification at 8:6
R3_8, // 3-bit register specification at 10:8
R4_0, // 4-bit register specification at 3:0
R4_8, // 4-bit register specification at 11:8
R4_12, // 4-bit register specification at 15:12
R4_16, // 4-bit register specification at 19:16
R4_0H7, // 4-bit register specification at 7,2:0
R4_3H6, // 4-bit register specification at 6,5:3
R_PC, // register PC
R_SP, // register SP
R_LR, // register LR
V_0_5, // register at 3:0,5
V_12_22, // register at 15:12,22
V_16_7, // register at 19:16,7
V_5_0, // register at 5,3:0
V_22_12, // register at 22,15:12
V_7_16, // register at 7,19:16
V3_0, // register is 3bits wide at 2:0
} rSpec;
//
// Define the location of a constant in an instruction
//
typedef enum constSpecE {
CS_NA, // instruction has no constant
CS_U_2_4, // 2-bit unsigned constant at 5:4
CS_U_2_4x8, // 2-bit unsigned constant at 5:4*8
CS_U_2_10, // 2-bit unsigned constant at 11:10
CS_U_3_6, // 3-bit unsigned constant at 8:6
CS_U_4_4, // 4-bit unsigned constant at 8:5
CS_U_4_0, // 4-bit unsigned constant at 4:0
CS_U_5_6, // 5-bit unsigned constant at 10:6
CS_U_5_6_SZ, // 5-bit unsigned constant at 10:6, scaled by size
CS_U_5_0_5M16, // 5-bit unsigned constant at 3:0, 5. Subtract from 16 to get value
CS_U_5_0_5M32, // 5-bit unsigned constant at 3:0, 5. Subtract from 32 to get value
CS_U_7_0x4, // 7-bit unsigned constant at 6:0*4
CS_U_8_0, // 8-bit unsigned constant at 7:0
CS_U_8_0_U, // 8-bit unsigned constant at 7:0, negated if U=0
CS_U_8_0_SZ, // 8-bit unsigned constant at 7:0, scaled by size
CS_U_8_0x4_U, // 8-bit unsigned constant at 7:0*4, negated if U=0
CS_U_8_0x4, // 8-bit unsigned constant at 7:0*4
CS_U_12_0, // 12-bit unsigned constant at 11:0
CS_U_12_0_U, // 12-bit unsigned constant at 11:0, negated if U=0
CS_PI5, // 5-bit plain immediate
CS_PI12, // 12-bit plain immediate
CS_PI16, // 16-bit plain immediate
CS_MI // modified immediate
} constSpec;
//
// This defines target address field in the instruction
//
typedef enum targetSpecE {
TC_NA, // no target
TC_S8, // target PC + s8 field (2-byte aligned)
TC_S11, // target PC + s11 field (2-byte aligned)
TC_S20_T2, // target PC + s20 field (2-byte aligned)
TC_S24_T2, // target PC + s24 field (2-byte aligned)
TC_U9_7_3 // target PC + unsigned constant at 9,7:3*2
} targetSpec;
//
// This defines shift in the instruction
//
typedef enum shiftSpecE {
SS_NA, // no shift operation
SS_ASR, // ASR
SS_LSL, // LSL
SS_LSR, // LSR
SS_ROR, // ROR
SS_RRX, // RRX
SS2_4, // shift spec at offset 5:4
SS2_20, // shift spec at offset 21:20
SS2_21, // shift spec at offset 22:21
} shiftSpec;
//
// This defines whether the instruction specifies post-indexed addressing
//
typedef enum postIndexSpecE {
PI_0, // not post-indexed
PI_1, // post-indexed
PI_10, // post-indexed at position 10
PI_24, // post-indexed at position 24
} postIndexSpec;
//
// This defines whether the instruction specifies writeback
//
typedef enum writebackSpecE {
WB_0, // no writeback
WB_1, // writeback
WB_1_NB, // writeback unless base in register list
WB_8, // writeback at position 8
WB_21 // writeback at position 21
} writebackSpec;
//
// This defines coprocessor opcode field in the instruction
//
typedef enum cpOp1SpecE {
COP_NA, // no opcode1 field
COP_4_4, // 4-bit constant at offset 7:4
COP_4_20, // 4-bit constant at offset 23:20
COP_3_21 // 3-bit constant at offset 23:21
} cpOp1Spec;
//
// This defines register list field in the instruction
//
typedef enum rListSpecE {
RL_NA, // no register list
RL_16, // register list in 16-bit Thumb opcode
RL_16_LR, // register list in 16-bit Thumb opcode, possibly including LR
RL_16_PC, // register list in 16-bit Thumb opcode, possibly including PC
RL_32_SP, // register list in 32-bit Thumb opcode, excluding SP
RL_32_PCSP, // register list in 32-bit Thumb opcode, excluding PC & SP
} rListSpec;
//
// This defines increment/decrement specification in the instruction
//
typedef enum incDecSpecE {
ID_NA, // no increment/decrement specification
ID_U_P, // increment/decrement defined by U and P bits
ID_DB, // increment/decrement specification is Decrement Before
ID_IA, // increment/decrement specification is Increment After
ID_U_P_IAI, // increment/decrement defined by U and P bits, IA is implicit in disassembly (UAL only)
ID_U_P_IMP, // increment/decrement defined by U and P bits, IA is always implicit in disassembly
ID_DB_I, // increment/decrement specification is Decrement Before, Implicit in disassembly
ID_IA_I, // increment/decrement specification is Increment After, Implicit in disassembly
} incDecSpec;
//
// This defines interrupt enable/disable fields in the instruction
//
typedef enum imodSpecE {
IS_NA, // no imod spec
IS_4 // imod spec at bit 4
} imodSpec;
//
// This defines interrupt disable bits in the instruction
//
typedef enum aifSpecE {
AIF_NA, // no aif spec
AIF_0 // aif field at 2:0
} aifSpec;
//
// This defines width field in the instruction
//
typedef enum widthSpecE {
WS_NA, // no width specification
WS_WIDTH4, // width in field 3:0
WS_WIDTH4M1, // width in field 3:0+1
WS_WIDTH5, // width in field 4:0
WS_WIDTH5M1, // width in field 4:0+1
WS_MSB // width in field 4:0 - {14:12,7:6} + 1;
} widthSpec;
//
// This defines u field in the instruction
//
typedef enum uSpecE {
US_1, // u=1
US_9, // u in field at position 9
US_23, // u in field at position 23
} uSpec;
//
// This defines mask field in MSR instruction
//
typedef enum maskSpecE {
MSRMASK_NA, // no MSR mask spec
MSRMASK_10 // mask field in bits 11:10
} maskSpec;
//
// Define a SIMD/VFP modified immediate constant type
//
typedef enum sdfpMISpecE {
SDFP_MI_NA, // instruction has no SIMD/VFP modified immediate constant
SDFP_MI_VFP_S, // single precision VFP modified immediate value
} sdfpMISpec;
//
// This defines the SIMD scalar index field in the instruction
//
typedef enum indexSpecE {
IDX_NA, // no index specification
IDX_21, // index is 1 bit wide, in bit 21
IDX_5, // index is 1 bit wide, in bit 5
IDX_7, // index is 1 bit wide, in bit 7
IDX_19, // index is 1 bit wide, in bit 19
} indexSpec;
//
// This defines the number of regs in a VFP register list
//
typedef enum nregSpecE {
NREG_NA, // no alignment specification
NREG_7_1, // Nregs is 7 bits wide in bits 7:1
NREG_8_0, // Nregs is 8 bits wide in bits 7:0
} nregSpec;
//
// Structure defining characteristics of each opcode type
//
typedef struct opAttrsS {
const char *opcode; // opcode name
const char *format; // format string
armInstructionType type; // equivalent ARM instruction
armArchitecture support:16; // variants on which instruction supported
armISARSupport isar : 8; // ISAR instruction support
setFlags f : 4; // does this opcode set flags?
condSpec cond : 4; // condition field specification
rSpec r1 : 8; // does instruction have r1?
rSpec r2 : 8; // does instruction have r2?
rSpec r3 : 8; // does instruction have r3?
rSpec r4 : 8; // does instruction have r4?
constSpec cs : 8; // location of constant
targetSpec ts : 4; // target specification
shiftSpec ss : 4; // shifter specification
Uns8 sz : 4; // load/store size
Uns8 xs : 4; // sign extend?
Uns8 tl : 4; // translate?
postIndexSpec pi : 4; // instruction specifies post-indexed address?
writebackSpec wb : 4; // instruction specifies writeback?
Uns8 ll : 4; // instruction specifies long load?
Uns8 cpNum : 4; // does instruction have coprocessor number?
cpOp1Spec cpOp1 : 4; // does instruction have coprocessor op 1?
Uns8 cpOp2 : 4; // does instruction have coprocessor op 2?
rListSpec rList : 4; // does instruction have register list?
incDecSpec incDec : 4; // does instruction have increment/decrement?
armUnalignedAction ua45 : 4; // action if unaligned (Control.U=0)
armUnalignedAction ua67 : 4; // action if unaligned (Control.U=1)
Bool ea : 1; // exclusive access?
imodSpec imod : 4; // imod field specification
Bool m : 1; // M field present?
aifSpec aif : 4; // A/I/F fields specification
Bool it : 1; // IT specification present?
widthSpec w : 4; // width specification
uSpec u : 4; // U bit specification
maskSpec mask : 4; // mask specification (MSR instruction)
indexSpec index : 4; // VFP scalar index specification?
nregSpec nregs : 4; // number of regs in VFP register list specification?
sdfpMISpec sdfpMI : 4; // SIMD/floating point modified immediate constant?
armSDFPType dt1 : 8; // SIMD/VFP first data type?
armSDFPType dt2 : 8; // SIMD/VFP second data type?
} opAttrs;
typedef const struct opAttrsS *opAttrsCP;
//
// This specifies attributes for each opcode
//
const static opAttrs attrsArray[TT_LAST+1] = {
////////////////////////////////////////////////////////////////////////////
// 16-bit instructions
////////////////////////////////////////////////////////////////////////////
// data processing instructions
ATTR_SET_16_ADC (ADC, ADC_RT, ARM_VT, ARM_ISAR_NA, "adc" ),
ATTR_SET_16_ADD1 (ADD1, ADD_IMM, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD2 (ADD2, ADD_IT, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD3 (ADD3, ADD_RM, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD4 (ADD4LL, ADD4, ARM_VT2, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD4 (ADD4LH, ADD4, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD4 (ADD4H, ADD4, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD5 (ADD5, ADD_ADR, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD6 (ADD6, ADD6, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ADD7 (ADD7, ADD7, ARM_VT, ARM_ISAR_NA, "add" ),
ATTR_SET_16_ASR1 (ASR1, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "asr", SS_ASR),
ATTR_SET_16_ASR2 (ASR2, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "asr", SS_ASR),
ATTR_SET_16_ADC (AND, AND_RT, ARM_VT, ARM_ISAR_NA, "and" ),
ATTR_SET_16_ADC (BIC, BIC_RT, ARM_VT, ARM_ISAR_NA, "bic" ),
ATTR_SET_16_ADC (EOR, EOR_RT, ARM_VT, ARM_ISAR_NA, "eor" ),
ATTR_SET_16_ASR1 (LSL1, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "lsl", SS_LSL),
ATTR_SET_16_ASR2 (LSL2, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "lsl", SS_LSL),
ATTR_SET_16_ASR1 (LSR1, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "lsr", SS_LSR),
ATTR_SET_16_ASR2 (LSR2, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "lsr", SS_LSR),
ATTR_SET_16_ADD2 (MOV1, MOV_IMM, ARM_VT, ARM_ISAR_NA, "mov" ),
ATTR_SET_16_MOV2 (MOV2, MOV_RM_SHFT_IMM, ARM_VT, ARM_ISAR_NA, "mov" ),
ATTR_SET_16_ADD4 (MOV3LL, MOV3, 6|ARM_VT, ARM_ISAR_MOVLL, "mov" ),
ATTR_SET_16_ADD4 (MOV3LH, MOV3, ARM_VT, ARM_ISAR_NA, "mov" ),
ATTR_SET_16_ADD4 (MOV3H, MOV3, ARM_VT, ARM_ISAR_NA, "mov" ),
ATTR_SET_16_ADC (MUL, MUL_RT, ARM_VT, ARM_ISAR_NA, "mul" ),
ATTR_SET_16_ADC (MVN, MVN_RM, ARM_VT, ARM_ISAR_NA, "mvn" ),
ATTR_SET_16_ADC (NEG, NEG_RM, ARM_VT, ARM_ISAR_NA, "neg" ),
ATTR_SET_16_ADC (ORR, ORR_RT, ARM_VT, ARM_ISAR_NA, "orr" ),
ATTR_SET_16_ASR2 (ROR, MOV_RM_SHFT_RST, ARM_VT, ARM_ISAR_NA, "ror", SS_ROR),
ATTR_SET_16_ADC (SBC, SBC_RT, ARM_VT, ARM_ISAR_NA, "sbc" ),
ATTR_SET_16_ADD1 (SUB1, SUB_IMM, ARM_VT, ARM_ISAR_NA, "sub" ),
ATTR_SET_16_ADD2 (SUB2, SUB_IT, ARM_VT, ARM_ISAR_NA, "sub" ),
ATTR_SET_16_ADD3 (SUB3, SUB_RM, ARM_VT, ARM_ISAR_NA, "sub" ),
ATTR_SET_16_ADD7 (SUB4, SUB4, ARM_VT, ARM_ISAR_NA, "sub" ),
// compare instructions
ATTR_SET_16_CMP2 (CMN, CMN_RM, ARM_VT, ARM_ISAR_NA, "cmn"),
ATTR_SET_16_CMP1 (CMP1, CMP_IMM, ARM_VT, ARM_ISAR_NA, "cmp"),
ATTR_SET_16_CMP2 (CMP2, CMP_RM, ARM_VT, ARM_ISAR_NA, "cmp"),
ATTR_SET_16_CMP3 (CMP3LH, CMP_RM, ARM_VT, ARM_ISAR_NA, "cmp"),
ATTR_SET_16_CMP3 (CMP3H, CMP_RM, ARM_VT, ARM_ISAR_NA, "cmp"),
ATTR_SET_16_CMP2 (TST, TST_RM, ARM_VT, ARM_ISAR_NA, "tst"),
// branch instructions
ATTR_SET_16_B1 (B1, B, ARM_VT, ARM_ISAR_NA, "b" ),
ATTR_SET_16_B2 (B2, B, ARM_VT, ARM_ISAR_NA, "b" ),
ATTR_SET_16_BLX2 (BLX2, 5|ARM_VT, ARM_ISAR_BLX, "blx"),
ATTR_SET_16_BLX2 (BX, ARM_VT, ARM_ISAR_BX, "bx" ),
ATTR_SET_16_BKPT (SWI, ARM_VT, ARM_ISAR_SVC, "svc"),
ATTR_SET_16_UNDECODED (BU ),
// miscellaneous instructions
ATTR_SET_16_CPS (CPS, 6|ARM_VT, ARM_ISAR_MRS_M, "cps" ),
ATTR_SET_16_CBNZ (CBNZ, ARM_VT2, ARM_ISAR_CBZ, "cbnz" ),
ATTR_SET_16_CBNZ (CBZ, ARM_VT2, ARM_ISAR_CBZ, "cbz" ),
ATTR_SET_16_SXTH (SXTH, 6|ARM_VT, ARM_ISAR_SXTB, "sxth" ),
ATTR_SET_16_SXTH (SXTB, 6|ARM_VT, ARM_ISAR_SXTB, "sxtb" ),
ATTR_SET_16_SXTH (UXTH, 6|ARM_VT, ARM_ISAR_SXTB, "uxth" ),
ATTR_SET_16_SXTH (UXTB, 6|ARM_VT, ARM_ISAR_SXTB, "uxtb" ),
ATTR_SET_16_SXTH (REV, 6|ARM_VT, ARM_ISAR_REV, "rev" ),
ATTR_SET_16_SXTH (REV16, 6|ARM_VT, ARM_ISAR_REV, "rev16"),
ATTR_SET_16_SXTH (REVSH, 6|ARM_VT, ARM_ISAR_REV, "revsh"),
ATTR_SET_16_BKPT (BKPT, 5|ARM_VT, ARM_ISAR_BKPT, "bkpt" ),
// load and store instructions
ATTR_SET_16_LDR1 (LDR1, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (LDR2, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR3 (LDR3, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR4 (LDR4, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR1 (LDRB1, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (LDRB2, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR1 (LDRH1, LDR_IMM, ARM_VT, ARM_ISAR_NA, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (LDRH2, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (LDRSB, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 1, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (LDRSH, LDR_RM, ARM_VT, ARM_ISAR_NA, "ldr", 2, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR1 (STR1, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (STR2, STR_RM, ARM_VT, ARM_ISAR_NA, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR4 (STR3, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR1 (STRB1, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (STRB2, STR_RM, ARM_VT, ARM_ISAR_NA, "str", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR1 (STRH1, STR_IMM, ARM_VT, ARM_ISAR_NA, "str", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_16_LDR2 (STRH2, STR_RM, ARM_VT, ARM_ISAR_NA, "str", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
// load and store multiple instructions
ATTR_SET_16_LDMIA (LDMIA, LDM1, ARM_VT, ARM_ISAR_NA, "ldm", RL_16, ID_IA, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_16_POP (POP, LDM1, ARM_VT, ARM_ISAR_NA, "pop", RL_16_PC, ID_IA_I, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_16_POP (PUSH, STM1, ARM_VT, ARM_ISAR_NA, "push", RL_16_LR, ID_DB_I, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_16_STMIA (STMIA, STM1, ARM_VT, ARM_ISAR_NA, "stm", RL_16, ID_IA, ARM_UA_ALIGN, ARM_UA_DABORT),
// if-then and hints
ATTR_SET_16_IT (IT, NOP, ARM_VT2, ARM_ISAR_IT, "it" ),
ATTR_SET_16_NOP (NOP, NOP, ARM_VT2, ARM_ISAR_NOP, "nop" ),
ATTR_SET_16_NOP (YIELD, YIELD, ARM_VT2, ARM_ISAR_NOP, "yield"),
ATTR_SET_16_NOP (WFE, WFE, ARM_VT2, ARM_ISAR_NOP, "wfe" ),
ATTR_SET_16_NOP (WFI, WFI, ARM_VT2, ARM_ISAR_NOP, "wfi" ),
ATTR_SET_16_NOP (SEV, SEV, ARM_VT2, ARM_ISAR_NOP, "sev" ),
////////////////////////////////////////////////////////////////////////////
// 32-bit instructions
////////////////////////////////////////////////////////////////////////////
// data processing
ATTR_SET_32_AND (AND, ARM_VT2, ARM_ISAR_NA, "and"),
ATTR_SET_32_TST (TST, ARM_VT2, ARM_ISAR_NA, "tst"),
ATTR_SET_32_AND (BIC, ARM_VT2, ARM_ISAR_NA, "bic"),
ATTR_SET_32_AND (ORR, ARM_VT2, ARM_ISAR_NA, "orr"),
ATTR_SET_32_MOV (MOV, ARM_VT2, ARM_ISAR_NA, "mov"),
ATTR_SET_32_AND (ORN, ARM_VT2, ARM_ISAR_NA, "orn"),
ATTR_SET_32_MOV (MVN, ARM_VT2, ARM_ISAR_NA, "mvn"),
ATTR_SET_32_AND (EOR, ARM_VT2, ARM_ISAR_NA, "eor"),
ATTR_SET_32_TST (TEQ, ARM_VT2, ARM_ISAR_NA, "teq"),
ATTR_SET_32_AND (ADD, ARM_VT2, ARM_ISAR_NA, "add"),
ATTR_SET_32_TST (CMN, ARM_VT2, ARM_ISAR_NA, "cmn"),
ATTR_SET_32_AND (ADC, ARM_VT2, ARM_ISAR_NA, "adc"),
ATTR_SET_32_AND (SBC, ARM_VT2, ARM_ISAR_NA, "sbc"),
ATTR_SET_32_AND (SUB, ARM_VT2, ARM_ISAR_NA, "sub"),
ATTR_SET_32_TST (CMP, ARM_VT2, ARM_ISAR_NA, "cmp"),
ATTR_SET_32_AND (RSB, ARM_VT2, ARM_ISAR_NA, "rsb"),
// pack halfword
ATTR_SET_32_PKHBT (PKHBT, ARM_VT2, ARM_ISAR_PKHBT, "pkhbt"),
ATTR_SET_32_PKHBT (PKHTB, ARM_VT2, ARM_ISAR_PKHBT, "pkhtb"),
// data processing (plain binary immediate)
ATTR_SET_32_ADD_PI (ADD_PI, ADD_IMM, ARM_VT2, ARM_ISAR_MOVT, "addw"),
ATTR_SET_32_ADD_PI (ADD_ADR_PI, ADD_ADR, ARM_VT2, ARM_ISAR_MOVT, "addw"),
ATTR_SET_32_ADD_PI (SUB_PI, SUB_IMM, ARM_VT2, ARM_ISAR_MOVT, "subw"),
ATTR_SET_32_ADD_PI (SUB_ADR_PI, SUB_ADR, ARM_VT2, ARM_ISAR_MOVT, "subw"),
ATTR_SET_32_MOV_PI (MOV_PI, MOVW, ARM_VT2, ARM_ISAR_MOVT, "movw"),
ATTR_SET_32_MOV_PI (MOVT_PI, MOVT, ARM_VT2, ARM_ISAR_MOVT, "movt"),
ATTR_SET_32_SSAT (SSAT, SSAT, ARM_VT2, ARM_ISAR_SSAT, "ssat"),
ATTR_SET_32_SSAT16 (SSAT16, SSAT16, ARM_VT2, ARM_ISAR_PKHBT, "ssat16"),
ATTR_SET_32_SBFX (SBFX, SBFX, ARM_VT2, ARM_ISAR_BFC, "sbfx"),
ATTR_SET_32_BFI (BFI, BFI, ARM_VT2, ARM_ISAR_BFC, "bfi" ),
ATTR_SET_32_BFC (BFC, BFC, ARM_VT2, ARM_ISAR_BFC, "bfc" ),
ATTR_SET_32_USAT (USAT, USAT, ARM_VT2, ARM_ISAR_SSAT, "usat"),
ATTR_SET_32_USAT16 (USAT16, USAT16, ARM_VT2, ARM_ISAR_PKHBT, "usat16"),
ATTR_SET_32_SBFX (UBFX, UBFX, ARM_VT2, ARM_ISAR_BFC, "ubfx"),
// data processing (register)
ATTR_SET_32_LSL (LSL, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "lsl" ),
ATTR_SET_32_LSL (LSR, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "lsr" ),
ATTR_SET_32_LSL (ASR, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "asr" ),
ATTR_SET_32_LSL (ROR, MOV_RM_SHFT_RS, ARM_VT2, ARM_ISAR_NA, "ror" ),
ATTR_SET_32_SXTAH (SXTAH, ARM_VT2, ARM_ISAR_SXTAB, "sxtah" ),
ATTR_SET_32_SXTH (SXTH, ARM_VT2, ARM_ISAR_SXTB, "sxth" ),
ATTR_SET_32_SXTAH (UXTAH, ARM_VT2, ARM_ISAR_SXTAB, "uxtah" ),
ATTR_SET_32_SXTH (UXTH, ARM_VT2, ARM_ISAR_SXTB, "uxth" ),
ATTR_SET_32_SXTAH (SXTAB16, ARM_VT2, ARM_ISAR_SXTB16, "sxtab16"),
ATTR_SET_32_SXTH (SXTB16, ARM_VT2, ARM_ISAR_SXTB16, "sxtb16" ),
ATTR_SET_32_SXTAH (UXTAB16, ARM_VT2, ARM_ISAR_SXTB16, "uxtab16"),
ATTR_SET_32_SXTH (UXTB16, ARM_VT2, ARM_ISAR_SXTB16, "uxtb16" ),
ATTR_SET_32_SXTAH (SXTAB, ARM_VT2, ARM_ISAR_SXTAB, "sxtab" ),
ATTR_SET_32_SXTH (SXTB, ARM_VT2, ARM_ISAR_SXTB, "sxtb" ),
ATTR_SET_32_SXTAH (UXTAB, ARM_VT2, ARM_ISAR_SXTAB, "uxtab" ),
ATTR_SET_32_SXTH (UXTB, ARM_VT2, ARM_ISAR_SXTB, "uxtb" ),
// parallel add/subtract instructions
ATTR_SET_32_PAS (ADD16, ARM_VT2, ARM_ISAR_PKHBT, "add16"),
ATTR_SET_32_PAS (ASX, ARM_VT2, ARM_ISAR_PKHBT, "asx" ),
ATTR_SET_32_PAS (SAX, ARM_VT2, ARM_ISAR_PKHBT, "sax" ),
ATTR_SET_32_PAS (SUB16, ARM_VT2, ARM_ISAR_PKHBT, "sub16"),
ATTR_SET_32_PAS (ADD8, ARM_VT2, ARM_ISAR_PKHBT, "add8" ),
ATTR_SET_32_PAS (SUB8, ARM_VT2, ARM_ISAR_PKHBT, "sub8" ),
// miscellaneous operation instructions
ATTR_SET_32_QADD (QADD, ARM_VT2, ARM_ISAR_QADD, "qadd" ),
ATTR_SET_32_QADD (QDADD, ARM_VT2, ARM_ISAR_QADD, "qdadd"),
ATTR_SET_32_QADD (QSUB, ARM_VT2, ARM_ISAR_QADD, "qsub" ),
ATTR_SET_32_QADD (QDSUB, ARM_VT2, ARM_ISAR_QADD, "qdsub"),
ATTR_SET_32_CLZ (REV, ARM_VT2, ARM_ISAR_REV, "rev" ),
ATTR_SET_32_CLZ (REV16, ARM_VT2, ARM_ISAR_REV, "rev16"),
ATTR_SET_32_CLZ (RBIT, ARM_VT2, ARM_ISAR_RBIT, "rbit" ),
ATTR_SET_32_CLZ (REVSH, ARM_VT2, ARM_ISAR_REV, "revsh"),
ATTR_SET_32_SEL (SEL, ARM_VT2, ARM_ISAR_PKHBT, "sel" ),
ATTR_SET_32_CLZ (CLZ, ARM_VT2, ARM_ISAR_CLZ, "clz" ),
// multiply, multiply accumulate and absolute difference instructions
ATTR_SET_32_MLA (MLA, ARM_VT2, ARM_ISAR_MLA, "mla" ),
ATTR_SET_32_MUL (MUL, ARM_VT2, ARM_ISAR_NA, "mul" ),
ATTR_SET_32_MLA (MLS, ARM_VT2, ARM_ISAR_MLS, "mls" ),
ATTR_SET_32_MUL (SDIV, 7, ARM_ISAR_DIV, "sdiv" ),
ATTR_SET_32_MUL (UDIV, 7, ARM_ISAR_DIV, "udiv" ),
ATTR_SET_32_SMLA_XY (SMLA, ARM_VT2, ARM_ISAR_SMLABB, "smla" ),
ATTR_SET_32_SMUL_XY (SMUL, ARM_VT2, ARM_ISAR_SMLABB, "smul" ),
ATTR_SET_32_SMLAD (SMLAD, ARM_VT2, ARM_ISAR_SMLAD, "smlad" ),
ATTR_SET_32_SMUAD (SMUAD, ARM_VT2, ARM_ISAR_SMLAD, "smuad" ),
ATTR_SET_32_SMLAW (SMLAW, ARM_VT2, ARM_ISAR_SMLABB, "smlaw" ),
ATTR_SET_32_SMULW (SMULW, ARM_VT2, ARM_ISAR_SMLABB, "smulw" ),
ATTR_SET_32_SMLAD (SMLSD, ARM_VT2, ARM_ISAR_SMLAD, "smlsd" ),
ATTR_SET_32_SMUAD (SMUSD, ARM_VT2, ARM_ISAR_SMLAD, "smusd" ),
ATTR_SET_32_SMMLA (SMMLA, ARM_VT2, ARM_ISAR_SMLAD, "smmla" ),
ATTR_SET_32_SMMUL (SMMUL, ARM_VT2, ARM_ISAR_SMLAD, "smmul" ),
ATTR_SET_32_SMMLA (SMMLS, ARM_VT2, ARM_ISAR_SMLAD, "smmls" ),
ATTR_SET_32_MUL (USAD8, ARM_VT2, ARM_ISAR_PKHBT, "usad8" ),
ATTR_SET_32_MLA (USADA8, ARM_VT2, ARM_ISAR_PKHBT, "usada8"),
ATTR_SET_32_SMLAL (SMLAL, ARM_VT2, ARM_ISAR_SMULL, "smlal" ),
ATTR_SET_32_SMLAL (SMULL, ARM_VT2, ARM_ISAR_SMULL, "smull" ),
ATTR_SET_32_SMLAL (UMAAL, ARM_VT2, ARM_ISAR_UMAAL, "umaal" ),
ATTR_SET_32_SMLAL (UMLAL, ARM_VT2, ARM_ISAR_UMULL, "umlal" ),
ATTR_SET_32_SMLAL (UMULL, ARM_VT2, ARM_ISAR_UMULL, "umull" ),
ATTR_SET_32_SMLAL_XY (SMLAL, ARM_VT2, ARM_ISAR_SMLABB, "smlal" ),
ATTR_SET_32_SMLALD (SMLALD, ARM_VT2, ARM_ISAR_SMLAD, "smlald"),
ATTR_SET_32_SMLALD (SMLSLD, ARM_VT2, ARM_ISAR_SMLAD, "smlsld"),
// branch and miscellaneous control instructions
ATTR_SET_32_B1 (B1, B, ARM_VT2, ARM_ISAR_NA, "b" ),
ATTR_SET_32_BL (B2, B, ARM_VT2, ARM_ISAR_NA, "b" ),
ATTR_SET_32_BL (BL, BL, ARM_VT, ARM_ISAR_NA, "bl" ),
ATTR_SET_32_MSR (MSR, 7, ARM_ISAR_MRS_M, "msr" ),
ATTR_SET_32_NOP (NOP, ARM_VT2, ARM_ISAR_NOP, "nop" ),
ATTR_SET_32_NOP (YIELD, ARM_VT2, ARM_ISAR_NOP, "yield"),
ATTR_SET_32_NOP (WFE, ARM_VT2, ARM_ISAR_NOP, "wfe" ),
ATTR_SET_32_NOP (WFI, ARM_VT2, ARM_ISAR_NOP, "wfi" ),
ATTR_SET_32_NOP (SEV, ARM_VT2, ARM_ISAR_NOP, "sev" ),
ATTR_SET_32_DBG (DBG, ARM_VT2, ARM_ISAR_NOP, "dbg" ),
ATTR_SET_32_MRS (MRS, 7, ARM_ISAR_MRS_M, "mrs" ),
ATTR_SET_32_UND (UNDEF, ARM_VT2, ARM_ISAR_NA ),
ATTR_SET_32_NOP (CLREX, 7, ARM_ISAR_CLREX, "clrex"),
ATTR_SET_32_DSB (DSB, 7, ARM_ISAR_DMB, "dsb" ),
ATTR_SET_32_DSB (DMB, 7, ARM_ISAR_DMB, "dmb" ),
ATTR_SET_32_DSB (ISB, 7, ARM_ISAR_DMB, "isb" ),
// load and store multiple instructions
ATTR_SET_32_LDM (STMDB, STM1, ARM_VT2, ARM_ISAR_NA, "stm", ID_DB, RL_32_PCSP, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDM (STMIA, STM1, ARM_VT2, ARM_ISAR_NA, "stm", ID_IA, RL_32_PCSP, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDM (LDMDB, LDM1, ARM_VT2, ARM_ISAR_NA, "ldm", ID_DB, RL_32_SP, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDM (LDMIA, LDM1, ARM_VT2, ARM_ISAR_NA, "ldm", ID_IA, RL_32_SP, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_POPM (POPM, LDM1, ARM_VT2, ARM_ISAR_NA, "pop", ID_IA_I, RL_32_SP, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_POPM (PUSHM, STM1, ARM_VT2, ARM_ISAR_NA, "push", ID_DB_I, RL_32_PCSP, ARM_UA_ALIGN, ARM_UA_DABORT),
// dual and exclusive instructions
ATTR_SET_32_LDRD_IMM (LDRD_IMM, ARM_VT2, ARM_ISAR_LDRD, "ldr", 8, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDRD_IMM (STRD_IMM, ARM_VT2, ARM_ISAR_LDRD, "str", 8, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDREX (LDREX, ARM_VT2, ARM_ISAR_LDREX, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDREXB (LDREXB, 7, ARM_ISAR_CLREX, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_LDREXB (LDREXH, 7, ARM_ISAR_CLREX, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_STREX (STREX, ARM_VT2, ARM_ISAR_LDREX, "str", 4, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_STREXB (STREXB, 7, ARM_ISAR_CLREX, "str", 1, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_STREXB (STREXH, 7, ARM_ISAR_CLREX, "str", 2, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_TBB (TBB, TB, ARM_VT2, ARM_ISAR_TBB, "tb", 1, False, ARM_UA_ALIGN, ARM_UA_DABORT),
ATTR_SET_32_TBB (TBH, TB, ARM_VT2, ARM_ISAR_TBB, "tb", 2, False, ARM_UA_ALIGN, ARM_UA_DABORT),
// load instructions
ATTR_SET_32_LDR (LDR, LDR, ARM_VT2, ARM_ISAR_LDRBT, "ldr", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (LDRH, LDR, ARM_VT2, ARM_ISAR_LDRHT, "ldr", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (LDRB, LDR, ARM_VT2, ARM_ISAR_LDRBT, "ldr", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (LDRSH, LDR, ARM_VT2, ARM_ISAR_LDRHT, "ldr", 2, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (LDRSB, LDR, ARM_VT2, ARM_ISAR_LDRHT, "ldr", 1, True, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (STR, STR, ARM_VT2, ARM_ISAR_LDRBT, "str", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (STRH, STR, ARM_VT2, ARM_ISAR_LDRHT, "str", 2, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_LDR (STRB, STR, ARM_VT2, ARM_ISAR_LDRBT, "str", 1, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_PLD (PLD, PLD, ARM_VT2, ARM_ISAR_PLD, "pld", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_PLD (PLI, PLI, ARM_VT2, ARM_ISAR_PLI, "pli", 4, False, ARM_UA_ALIGN, ARM_UA_UNALIGNED),
ATTR_SET_32_UHINTH (UHINTH, NOP, ARM_VT2, ARM_ISAR_NA, "nop" ),
ATTR_SET_32_UHINTH (UHINTB, NOP, ARM_VT2, ARM_ISAR_NA, "nop" ),
// coprocessor instructions
ATTR_SET_32_CDP (CDP, ARM_VT2, ARM_ISAR_NA, "cdp" ),
ATTR_SET_32_CDP2 (CDP2, ARM_VT2, ARM_ISAR_NA, "cdp2" ),
ATTR_SET_32_LDC (LDC, ARM_VT2, ARM_ISAR_NA, "ldc" ),
ATTR_SET_32_LDC2 (LDC2, ARM_VT2, ARM_ISAR_NA, "ldc2" ),
ATTR_SET_32_MCR (MCR, ARM_VT2, ARM_ISAR_NA, "mcr" ),
ATTR_SET_32_MCR2 (MCR2, ARM_VT2, ARM_ISAR_NA, "mcr2" ),
ATTR_SET_32_MRC (MRC, ARM_VT2, ARM_ISAR_NA, "mrc" ),
ATTR_SET_32_MRC2 (MRC2, ARM_VT2, ARM_ISAR_NA, "mrc2" ),
ATTR_SET_32_LDC (STC, ARM_VT2, ARM_ISAR_NA, "stc" ),
ATTR_SET_32_LDC2 (STC2, ARM_VT2, ARM_ISAR_NA, "stc2" ),
ATTR_SET_32_MCRR (MCRR, ARM_VT2, ARM_ISAR_NA, "mcrr" ),
ATTR_SET_32_MCRR2 (MCRR2, ARM_VT2, ARM_ISAR_NA, "mcrr2"),
ATTR_SET_32_MCRR (MRRC, ARM_VT2, ARM_ISAR_NA, "mrrc" ),
ATTR_SET_32_MCRR2 (MRRC2, ARM_VT2, ARM_ISAR_NA, "mrrc2"),
////////////////////////////////////////////////////////////////////////////
// VFP Instructions (single precision only)
////////////////////////////////////////////////////////////////////////////
// VFP data processing instructions
ATTR_SET_32_VFP_RRR (VMLA_VFP, 7, ARM_ISAR_VFPV2, "vmla"),
ATTR_SET_32_VFP_RRR (VMLS_VFP, 7, ARM_ISAR_VFPV2, "vmls"),
ATTR_SET_32_VFP_RRR (VNMLS_VFP, 7, ARM_ISAR_VFPV2, "vnmls"),
ATTR_SET_32_VFP_RRR (VNMLA_VFP, 7, ARM_ISAR_VFPV2, "vnmla"),
ATTR_SET_32_VFP_RRR (VMUL_VFP, 7, ARM_ISAR_VFPV2, "vmul"),
ATTR_SET_32_VFP_RRR (VNMUL_VFP, 7, ARM_ISAR_VFPV2, "vnmul"),
ATTR_SET_32_VFP_RRR (VADD_VFP, 7, ARM_ISAR_VFPV2, "vadd"),
ATTR_SET_32_VFP_RRR (VSUB_VFP, 7, ARM_ISAR_VFPV2, "vsub"),
ATTR_SET_32_VFP_RRR (VDIV_VFP, 7, ARM_ISAR_VFPDIV, "vdiv"),
ATTR_SET_32_VFP_RRR (VFNMA_VFP, 7, ARM_ISAR_VFPFMAC, "vfnma"),
ATTR_SET_32_VFP_RRR (VFNMS_VFP, 7, ARM_ISAR_VFPFMAC, "vfnms"),
ATTR_SET_32_VFP_RRR (VFMA_VFP, 7, ARM_ISAR_VFPFMAC, "vfma"),
ATTR_SET_32_VFP_RRR (VFMS_VFP, 7, ARM_ISAR_VFPFMAC, "vfms"),
ATTR_SET_32_VFP_RI (VMOVI_VFP, 7, ARM_ISAR_VFPV3, "vmov"),
ATTR_SET_32_VFP_RR (VMOVR_VFP, 7, ARM_ISAR_VFPV2, "vmov"),
ATTR_SET_32_VFP_RR (VABS_VFP, 7, ARM_ISAR_VFPV2, "vabs"),
ATTR_SET_32_VFP_RR (VNEG_VFP, 7, ARM_ISAR_VFPV2, "vneg"),
ATTR_SET_32_VFP_RR (VSQRT_VFP, 7, ARM_ISAR_VFPSQRT, "vsqrt"),
ATTR_SET_32_VFP_RR_S_S2 (VCVTBFH_VFP, 7, ARM_ISAR_VFPHP, "vcvtb", 32, 16),
ATTR_SET_32_VFP_RR_S_S2 (VCVTTFH_VFP, 7, ARM_ISAR_VFPHP, "vcvtt", 32, 16),
ATTR_SET_32_VFP_RR_S_S2 (VCVTBHF_VFP, 7, ARM_ISAR_VFPHP, "vcvtb", 16, 32),
ATTR_SET_32_VFP_RR_S_S2 (VCVTTHF_VFP, 7, ARM_ISAR_VFPHP, "vcvtt", 16, 32),
ATTR_SET_32_VFP_RR (VCMP_VFP, 7, ARM_ISAR_VFPV2, "vcmp"),
ATTR_SET_32_VFP_RR (VCMPE_VFP, 7, ARM_ISAR_VFPV2, "vcmpe"),
ATTR_SET_32_VFP_R0 (VCMP0_VFP, 7, ARM_ISAR_VFPV2, "vcmp"),
ATTR_SET_32_VFP_R0 (VCMPE0_VFP, 7, ARM_ISAR_VFPV2, "vcmpe"),
ATTR_SET_32_VFP_LS_T (VCVTFU_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _U),
ATTR_SET_32_VFP_LS_T (VCVTFS_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _S),
ATTR_SET_32_VFP_RI_T2C (VCVTFXUH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _U16, 16),
ATTR_SET_32_VFP_RI_T2C (VCVTFXUW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _U32, 32),
ATTR_SET_32_VFP_RI_T2C (VCVTFXSH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _S16, 16),
ATTR_SET_32_VFP_RI_T2C (VCVTFXSW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _F32, _S32, 32),
ATTR_SET_32_VFP_NS_T (VCVTRUF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvtr", _U),
ATTR_SET_32_VFP_NS_T (VCVTUF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _U),
ATTR_SET_32_VFP_NS_T (VCVTRSF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvtr", _S),
ATTR_SET_32_VFP_NS_T (VCVTSF_VFP, 7, ARM_ISAR_VFPCVT2, "vcvt", _S),
ATTR_SET_32_VFP_RI_T2C (VCVTXFSH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _S16, _F32, 16),
ATTR_SET_32_VFP_RI_T2C (VCVTXFSW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _S32, _F32, 32),
ATTR_SET_32_VFP_RI_T2C (VCVTXFUH_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _U16, _F32, 16),
ATTR_SET_32_VFP_RI_T2C (VCVTXFUW_VFP, 7, ARM_ISAR_VFPCVT3, "vcvt", _U32, _F32, 32),
// Extension register load/store instructions
ATTR_SET_32_SDFP_LDSTM (VSTMIA, 7, ARM_ISAR_VMRS, "vstm"),
ATTR_SET_32_SDFP_LDSTM (VSTMIAW, 7, ARM_ISAR_VMRS, "vstm"),
ATTR_SET_32_SDFP_LDST (VSTR, 7, ARM_ISAR_VMRS, "vstr"),
ATTR_SET_32_SDFP_LDSTM (VSTMDBW, 7, ARM_ISAR_VMRS, "vstm"),
ATTR_SET_32_SDFP_PUSH (VPUSH, 7, ARM_ISAR_VMRS, "vpush"),
ATTR_SET_32_SDFP_LDSTM (VLDMIA, 7, ARM_ISAR_VMRS, "vldm"),
ATTR_SET_32_SDFP_LDSTM (VLDMIAW, 7, ARM_ISAR_VMRS, "vldm"),
ATTR_SET_32_SDFP_PUSH (VPOP, 7, ARM_ISAR_VMRS, "vpop"),
ATTR_SET_32_SDFP_LDST (VLDR, 7, ARM_ISAR_VMRS, "vldr"),
ATTR_SET_32_SDFP_LDSTM (VLDMDBW, 7, ARM_ISAR_VMRS, "vldm"),
// 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs
ATTR_SET_32_VMRS (VMRS, 7, ARM_ISAR_VMRS, "vmrs"),
ATTR_SET_32_VMSR (VMSR, 7, ARM_ISAR_VMRS, "vmsr"),
ATTR_SET_32_VMOVRS (VMOVRS, 7, ARM_ISAR_VMRS, "vmov"),
ATTR_SET_32_VMOVSR (VMOVSR, 7, ARM_ISAR_VMRS, "vmov"),
ATTR_SET_32_VMOVZR (VMOVZR, 7, ARM_ISAR_VMRS, "vmov"),
ATTR_SET_32_VMOVRZ (VMOVRZ, 7, ARM_ISAR_VMRS, "vmov"),
// 64-bit transfer instructions between ARM core regs and extension regs
ATTR_SET_32_VMOVRRD (VMOVRRD, 7, ARM_ISAR_VMRS, "vmov"),
ATTR_SET_32_VMOVDRR (VMOVDRR, 7, ARM_ISAR_VMRS, "vmov"),
ATTR_SET_32_VMOVRRSS (VMOVRRSS, 7, ARM_ISAR_VMRS, "vmov"),
ATTR_SET_32_VMOVSSRR (VMOVSSRR, 7, ARM_ISAR_VMRS, "vmov"),
////////////////////////////////////////////////////////////////////////////
// terminator
////////////////////////////////////////////////////////////////////////////
// dummy entry for undecoded instruction
[TT_LAST] = {type:ARM_IT_LAST}
};
////////////////////////////////////////////////////////////////////////////////
// GENERIC DECODE TYPES
////////////////////////////////////////////////////////////////////////////////
//
// This type specifies the pattern for a decode table entry
//
typedef struct decodeEntryS {
armThumbType type :16;
Uns32 priority:16;
const char *name;
const char *pattern;
} decodeEntry;
////////////////////////////////////////////////////////////////////////////////
// 16-BIT INSTRUCTION DECODE TABLE
////////////////////////////////////////////////////////////////////////////////
//
// Create the 16-bit Thumb instruction decode table
//
static vmidDecodeTableP createDecodeTableThumb16(void) {
const static decodeEntry entries[] = {
// data processing instructions
DECODE_SET_16_ADC (ADC, "010000|0101"),
DECODE_SET_16_ADD1 (ADD1, "0001110"),
DECODE_SET_16_ADD2 (ADD2, "00110"),
DECODE_SET_16_ADD1 (ADD3, "0001100"),
DECODE_SET_16_ADD4 (ADD4LL, "01000100|0|0"),
DECODE_SET_16_ADD4 (ADD4LH, "01000100|0|1"),
DECODE_SET_16_ADD4 (ADD4H, "01000100|1|."),
DECODE_SET_16_ADD2 (ADD5, "10100"),
DECODE_SET_16_ADD2 (ADD6, "10101"),
DECODE_SET_16_ADD7 (ADD7, "101100000"),
DECODE_SET_16_ADC (AND, "010000|0000"),
DECODE_SET_16_ASR1 (ASR1, "00010"),
DECODE_SET_16_ADC (ASR2, "010000|0100"),
DECODE_SET_16_ADC (BIC, "010000|1110"),
DECODE_SET_16_ADC (EOR, "010000|0001"),
DECODE_SET_16_ASR1 (LSL1, "00000"),
DECODE_SET_16_ADC (LSL2, "010000|0010"),
DECODE_SET_16_ASR1 (LSR1, "00001"),
DECODE_SET_16_ADC (LSR2, "010000|0011"),
DECODE_SET_16_ADD2 (MOV1, "00100"),
DECODE_SET_16_ADC (MOV2, "000000|0000"),
DECODE_SET_16_ADD4 (MOV3LL, "01000110|0|0"),
DECODE_SET_16_ADD4 (MOV3LH, "01000110|0|1"),
DECODE_SET_16_ADD4 (MOV3H, "01000110|1|."),
DECODE_SET_16_ADC (MVN, "010000|1111"),
DECODE_SET_16_ADC (NEG, "010000|1001"),
DECODE_SET_16_ADC (ORR, "010000|1100"),
DECODE_SET_16_ADC (ROR, "010000|0111"),
DECODE_SET_16_ADC (SBC, "010000|0110"),
DECODE_SET_16_ADD1 (SUB1, "0001111"),
DECODE_SET_16_ADD2 (SUB2, "00111"),
DECODE_SET_16_ADD1 (SUB3, "0001101"),
DECODE_SET_16_ADD7 (SUB4, "101100001"),
// multiply instructions
DECODE_SET_16_ADC (MUL, "010000|1101"),
// compare instructions
DECODE_SET_16_ADC (CMN, "010000|1011"),
DECODE_SET_16_ADD2 (CMP1, "00101"),
DECODE_SET_16_ADC (CMP2, "010000|1010"),
DECODE_SET_16_ADD4 (CMP3LH, "01000101|0|1"),
DECODE_SET_16_ADD4 (CMP3H, "01000101|1|."),
DECODE_SET_16_ADC (TST, "010000|1000"),
// branch instructions
DECODE_SET_16_B1 (B1, "...."),
DECODE_SET_16_B2 (B2, "00"),
DECODE_SET_16_BLX2 (BLX2, "010001111"),
DECODE_SET_16_BLX2 (BX, "010001110"),
DECODE_SET_16_SWI (SWI, "1111"),
DECODE_SET_16_SWI (BU, "1110"),
// miscellaneous instructions
DECODE_SET_16_BKPT (CPS, "0110011"),
DECODE_SET_16_BKPT (CBNZ, "10.1..."),
DECODE_SET_16_BKPT (CBZ, "00.1..."),
DECODE_SET_16_BKPT (SXTH, "001000."),
DECODE_SET_16_BKPT (SXTB, "001001."),
DECODE_SET_16_BKPT (UXTH, "001010."),
DECODE_SET_16_BKPT (UXTB, "001011."),
DECODE_SET_16_BKPT (REV, "101000."),
DECODE_SET_16_BKPT (REV16, "101001."),
DECODE_SET_16_BKPT (REVSH, "101011."),
DECODE_SET_16_BKPT (BKPT, "1110..."),
// load and store instructions
DECODE_SET_16_ASR1 (LDR1, "01101"),
DECODE_SET_16_ADD1 (LDR2, "0101100"),
DECODE_SET_16_ADD2 (LDR3, "01001"),
DECODE_SET_16_ADD2 (LDR4, "10011"),
DECODE_SET_16_ASR1 (LDRB1, "01111"),
DECODE_SET_16_ADD1 (LDRB2, "0101110"),
DECODE_SET_16_ASR1 (LDRH1, "10001"),
DECODE_SET_16_ADD1 (LDRH2, "0101101"),
DECODE_SET_16_ADD1 (LDRSB, "0101011"),
DECODE_SET_16_ADD1 (LDRSH, "0101111"),
DECODE_SET_16_ASR1 (STR1, "01100"),
DECODE_SET_16_ADD1 (STR2, "0101000"),
DECODE_SET_16_ADD2 (STR3, "10010"),
DECODE_SET_16_ASR1 (STRB1, "01110"),
DECODE_SET_16_ADD1 (STRB2, "0101010"),
DECODE_SET_16_ASR1 (STRH1, "10000"),
DECODE_SET_16_ADD1 (STRH2, "0101001"),
// load and store multiple instructions
DECODE_SET_16_ADD2 (LDMIA, "11001"),
DECODE_SET_16_POP (POP, "1011110"),
DECODE_SET_16_POP (PUSH, "1011010"),
DECODE_SET_16_ADD2 (STMIA, "11000"),
// if-then and hints
DECODE_SET_16_IT (IT, "....", "...."),
DECODE_SET_16_HINT1 (NOP, "....", "0000"),
DECODE_SET_16_HINT2 (YIELD, "0001", "0000"),
DECODE_SET_16_HINT2 (WFE, "0010", "0000"),
DECODE_SET_16_HINT2 (WFI, "0011", "0000"),
DECODE_SET_16_HINT2 (SEV, "0100", "0000"),
// terminator
{0}
};
// create the table
vmidDecodeTableP table = vmidNewDecodeTable(16, TT_LAST);
const decodeEntry *entry;
// add all entries to the decode table
for(entry=entries; entry->pattern; entry++) {
vmidNewEntryFmtBin(
table,
entry->name,
entry->type,
entry->pattern,
entry->priority
);
}
return table;
}
//
// Create the 32-bit Thumb instruction decode table
//
static vmidDecodeTableP createDecodeTableThumb32(void) {
const static decodeEntry entries[] = {
// data processing
DECODE_SET_32_AND (AND, "0000"),
DECODE_SET_32_TST (TST, "0000"),
DECODE_SET_32_AND (BIC, "0001"),
DECODE_SET_32_AND (ORR, "0010"),
DECODE_SET_32_MOV (MOV, "0010"),
DECODE_SET_32_AND (ORN, "0011"),
DECODE_SET_32_MOV (MVN, "0011"),
DECODE_SET_32_AND (EOR, "0100"),
DECODE_SET_32_TST (TEQ, "0100"),
DECODE_SET_32_AND (ADD, "1000"),
DECODE_SET_32_TST (CMN, "1000"),
DECODE_SET_32_AND (ADC, "1010"),
DECODE_SET_32_AND (SBC, "1011"),
DECODE_SET_32_AND (SUB, "1101"),
DECODE_SET_32_TST (CMP, "1101"),
DECODE_SET_32_AND (RSB, "1110"),
// pack halfword
DECODE_SET_32_PKHBT (PKHBT, "0"),
DECODE_SET_32_PKHBT (PKHTB, "1"),
// data processing (plain binary immediate)
DECODE_SET_32_ADD_PI (ADD_PI, "00000"),
DECODE_SET_32_ADR_PI (ADD_ADR_PI, "00000"),
DECODE_SET_32_ADD_PI (SUB_PI, "01010"),
DECODE_SET_32_ADR_PI (SUB_ADR_PI, "01010"),
DECODE_SET_32_ADD_PI (MOV_PI, "00100"),
DECODE_SET_32_ADD_PI (MOVT_PI, "01100"),
DECODE_SET_32_ADD_PI (SSAT, "100.0"),
DECODE_SET_32_SSAT16 (SSAT16, "10010"),
DECODE_SET_32_ADD_PI (SBFX, "10100"),
DECODE_SET_32_ADD_PI (BFI, "10110"),
DECODE_SET_32_BFC (BFC, "10110"),
DECODE_SET_32_ADD_PI (UBFX, "11100"),
DECODE_SET_32_ADD_PI (USAT, "110.0"),
DECODE_SET_32_SSAT16 (USAT16, "11010"),
// data processing (register)
DECODE_SET_32_LSL (LSL, "000.", "0000", "...."),
DECODE_SET_32_LSL (LSR, "001.", "0000", "...."),
DECODE_SET_32_LSL (ASR, "010.", "0000", "...."),
DECODE_SET_32_LSL (ROR, "011.", "0000", "...."),
DECODE_SET_32_LSL (SXTAH, "0000", "1...", "...."),
DECODE_SET_32_SXTH (SXTH, "0000", "1...", "1111"),
DECODE_SET_32_LSL (UXTAH, "0001", "1...", "...."),
DECODE_SET_32_SXTH (UXTH, "0001", "1...", "1111"),
DECODE_SET_32_LSL (SXTAB16, "0010", "1...", "...."),
DECODE_SET_32_SXTH (SXTB16, "0010", "1...", "1111"),
DECODE_SET_32_LSL (UXTAB16, "0011", "1...", "...."),
DECODE_SET_32_SXTH (UXTB16, "0011", "1...", "1111"),
DECODE_SET_32_LSL (SXTAB, "0100", "1...", "...."),
DECODE_SET_32_SXTH (SXTB, "0100", "1...", "1111"),
DECODE_SET_32_LSL (UXTAB, "0101", "1...", "...."),
DECODE_SET_32_SXTH (UXTB, "0101", "1...", "1111"),
// parallel add/subtract instructions
DECODE_SET_32_PAS (ADD16, "001"),
DECODE_SET_32_PAS (ASX, "010"),
DECODE_SET_32_PAS (SAX, "110"),
DECODE_SET_32_PAS (SUB16, "101"),
DECODE_SET_32_PAS (ADD8, "000"),
DECODE_SET_32_PAS (SUB8, "100"),
// miscellaneous operation instructions
DECODE_SET_32_LSL (QADD, "1000", "1000", "...."),
DECODE_SET_32_LSL (QDADD, "1000", "1001", "...."),
DECODE_SET_32_LSL (QSUB, "1000", "1010", "...."),
DECODE_SET_32_LSL (QDSUB, "1000", "1011", "...."),
DECODE_SET_32_LSL (REV, "1001", "1000", "...."),
DECODE_SET_32_LSL (REV16, "1001", "1001", "...."),
DECODE_SET_32_LSL (RBIT, "1001", "1010", "...."),
DECODE_SET_32_LSL (REVSH, "1001", "1011", "...."),
DECODE_SET_32_LSL (SEL, "1010", "1000", "...."),
DECODE_SET_32_LSL (CLZ, "1011", "1000", "...."),
// multiply, multiply accumulate and absolute difference instructions
DECODE_SET_32_MLA (MLA, "0000", "0000"),
DECODE_SET_32_MUL (MUL, "0000", "0000"),
DECODE_SET_32_MLA (MLS, "0000", "0001"),
DECODE_SET_32_MLA (SDIV, "1001", "1111"),
DECODE_SET_32_MLA (UDIV, "1011", "1111"),
DECODE_SET_32_SMLA_XY (SMLA, "0001", "00" ),
DECODE_SET_32_SMUL_XY (SMUL, "0001", "00" ),
DECODE_SET_32_SMLAD (SMLAD, "0010", "000" ),
DECODE_SET_32_SMUAD (SMUAD, "0010", "000" ),
DECODE_SET_32_SMLAW (SMLAW, "0011", "000" ),
DECODE_SET_32_SMULW (SMULW, "0011", "000" ),
DECODE_SET_32_SMLAD (SMLSD, "0100", "000" ),
DECODE_SET_32_SMUAD (SMUSD, "0100", "000" ),
DECODE_SET_32_SMMLA (SMMLA, "0101", "000" ),
DECODE_SET_32_SMMUL (SMMUL, "0101", "000" ),
DECODE_SET_32_SMMLA (SMMLS, "0110", "000" ),
DECODE_SET_32_MUL (USAD8, "0111", "0000"),
DECODE_SET_32_MLA (USADA8, "0111", "0000"),
DECODE_SET_32_MLA (SMLAL, "1100", "0000"),
DECODE_SET_32_MLA (SMULL, "1000", "0000"),
DECODE_SET_32_MLA (UMAAL, "1110", "0110"),
DECODE_SET_32_MLA (UMLAL, "1110", "0000"),
DECODE_SET_32_MLA (UMULL, "1010", "0000"),
DECODE_SET_32_SMLA_XY (SMLAL, "1100", "10" ),
DECODE_SET_32_SMLAD (SMLALD, "1100", "110" ),
DECODE_SET_32_SMLAD (SMLSLD, "1101", "110" ),
// branch and miscellaneous control instructions
DECODE_SET_32_B1 (B1, "0.0", "."),
DECODE_SET_32_B1 (B2, "0.1", "."),
DECODE_SET_32_B1 (BL, "1.1", "."),
DECODE_SET_32_MSR (MSR, "0.0", "011100."),
DECODE_SET_32_HINT1 (NOP, "0.0", "0111010", "........"),
DECODE_SET_32_HINT2 (YIELD, "0.0", "0111010", "00000001"),
DECODE_SET_32_HINT2 (WFE, "0.0", "0111010", "00000010"),
DECODE_SET_32_HINT2 (WFI, "0.0", "0111010", "00000011"),
DECODE_SET_32_HINT2 (SEV, "0.0", "0111010", "00000100"),
DECODE_SET_32_HINT2 (DBG, "0.0", "0111010", "1111...."),
DECODE_SET_32_MSR (MRS, "0.0", "011111."),
DECODE_SET_32_UNDEF (UNDEF, "0.0", ".111..."),
DECODE_SET_32_CLREX (CLREX, "0010"),
DECODE_SET_32_CLREX (DSB, "0100"),
DECODE_SET_32_CLREX (DMB, "0101"),
DECODE_SET_32_CLREX (ISB, "0110"),
// load and store multiple instructions
DECODE_SET_32_SRS (STMDB, "10", ".0...."),
DECODE_SET_32_SRS (STMIA, "01", ".0...."),
DECODE_SET_32_SRS (LDMDB, "10", ".1...."),
DECODE_SET_32_SRS (LDMIA, "01", ".1...."),
DECODE_SET_32_POPM (POPM, "01", "111101"),
DECODE_SET_32_POPM (PUSHM, "10", "101101"),
// dual and exclusive instructions
DECODE_SET_32_LDRD_IMM (LDRD_IMM, "0.", "11", "...."),
DECODE_SET_32_LDRD_IMM (LDRD_IMM, "1.", ".1", "...."),
DECODE_SET_32_LDRD_IMM (STRD_IMM, "0.", "10", "...."),
DECODE_SET_32_LDRD_IMM (STRD_IMM, "1.", ".0", "...."),
DECODE_SET_32_LDREX (LDREX, "00", "01", "...."),
DECODE_SET_32_LDREX (LDREXB, "01", "01", "0100"),
DECODE_SET_32_LDREX (LDREXH, "01", "01", "0101"),
DECODE_SET_32_LDREX (STREX, "00", "00", "...."),
DECODE_SET_32_LDREX (STREXB, "01", "00", "0100"),
DECODE_SET_32_LDREX (STREXH, "01", "00", "0101"),
DECODE_SET_32_LDREX (TBB, "01", "01", "0000"),
DECODE_SET_32_LDREX (TBH, "01", "01", "0001"),
// load instructions
DECODE_SET_32_LDR (LDR, "0", "10"),
DECODE_SET_32_LDR (LDRH, "0", "01"),
DECODE_SET_32_LDR (LDRB, "0", "00"),
DECODE_SET_32_LDR (LDRSH, "1", "01"),
DECODE_SET_32_LDR (LDRSB, "1", "00"),
DECODE_SET_32_STR (STR, "0", "10"),
DECODE_SET_32_STR (STRH, "0", "01"),
DECODE_SET_32_STR (STRB, "0", "00"),
DECODE_SET_32_PLD (PLD, "0", "00"),
DECODE_SET_32_PLD (PLI, "1", "00"),
DECODE_SET_32_UHINTH (UHINTH, "01"),
DECODE_SET_32_UHINTH (UHINTB, "00"),
// coprocessor instructions
DECODE_SET_32_CDP (CDP ),
DECODE_SET_32_CDP2 (CDP2 ),
DECODE_SET_32_LDC (LDC, "1"),
DECODE_SET_32_LDC2 (LDC2, "1"),
DECODE_SET_32_MCR (MCR, "0"),
DECODE_SET_32_MCR2 (MCR2, "0"),
DECODE_SET_32_MCR (MRC, "1"),
DECODE_SET_32_MCR2 (MRC2, "1"),
DECODE_SET_32_LDC (STC, "0"),
DECODE_SET_32_LDC2 (STC2, "0"),
DECODE_SET_32_MCRR (MCRR, "0"),
DECODE_SET_32_MCRR2 (MCRR2, "0"),
DECODE_SET_32_MCRR (MRRC, "1"),
DECODE_SET_32_MCRR2 (MRRC2, "1"),
// VFP data processing instructions
DECODE_SET_32_VFP_S (VMLA_VFP, "0.00", "....", ".0"),
DECODE_SET_32_VFP_S (VMLS_VFP, "0.00", "....", ".1"),
DECODE_SET_32_VFP_S (VNMLS_VFP, "0.01", "....", ".0"),
DECODE_SET_32_VFP_S (VNMLA_VFP, "0.01", "....", ".1"),
DECODE_SET_32_VFP_S (VMUL_VFP, "0.10", "....", ".0"),
DECODE_SET_32_VFP_S (VNMUL_VFP, "0.10", "....", ".1"),
DECODE_SET_32_VFP_S (VADD_VFP, "0.11", "....", ".0"),
DECODE_SET_32_VFP_S (VSUB_VFP, "0.11", "....", ".1"),
DECODE_SET_32_VFP_S (VDIV_VFP, "1.00", "....", ".0"),
// Note: Arm docs wrong: op=1 is VFNMA, not VFNMS
DECODE_SET_32_VFP_S (VFNMA_VFP, "1.01", "....", ".1"),
DECODE_SET_32_VFP_S (VFNMS_VFP, "1.01", "....", ".0"),
DECODE_SET_32_VFP_S (VFMA_VFP, "1.10", "....", ".0"),
DECODE_SET_32_VFP_S (VFMS_VFP, "1.10", "....", ".1"),
DECODE_SET_32_VFP_S (VMOVI_VFP, "1.11", "....", ".0"),
DECODE_SET_32_VFP_S (VMOVR_VFP, "1.11", "0000", "01"),
DECODE_SET_32_VFP_S (VABS_VFP, "1.11", "0000", "11"),
DECODE_SET_32_VFP_S (VNEG_VFP, "1.11", "0001", "01"),
DECODE_SET_32_VFP_S (VSQRT_VFP, "1.11", "0001", "11"),
DECODE_SET_32_VFP_S (VCVTBFH_VFP, "1.11", "0010", "01"),
DECODE_SET_32_VFP_S (VCVTTFH_VFP, "1.11", "0010", "11"),
DECODE_SET_32_VFP_S (VCVTBHF_VFP, "1.11", "0011", "01"),
DECODE_SET_32_VFP_S (VCVTTHF_VFP, "1.11", "0011", "11"),
DECODE_SET_32_VFP_S (VCMP_VFP, "1.11", "0100", "01"),
DECODE_SET_32_VFP_S (VCMPE_VFP, "1.11", "0100", "11"),
DECODE_SET_32_VFP_S (VCMP0_VFP, "1.11", "0101", "01"),
DECODE_SET_32_VFP_S (VCMPE0_VFP, "1.11", "0101", "11"),
DECODE_SET_32_VFP_S (VCVTFU_VFP, "1.11", "1000", "01"),
DECODE_SET_32_VFP_S (VCVTFS_VFP, "1.11", "1000", "11"),
DECODE_SET_32_VFP_S (VCVTFXSH_VFP, "1.11", "1010", "01"),
DECODE_SET_32_VFP_S (VCVTFXSW_VFP, "1.11", "1010", "11"),
DECODE_SET_32_VFP_S (VCVTFXUH_VFP, "1.11", "1011", "01"),
DECODE_SET_32_VFP_S (VCVTFXUW_VFP, "1.11", "1011", "11"),
DECODE_SET_32_VFP_S (VCVTRUF_VFP, "1.11", "1100", "01"),
DECODE_SET_32_VFP_S (VCVTUF_VFP, "1.11", "1100", "11"),
DECODE_SET_32_VFP_S (VCVTRSF_VFP, "1.11", "1101", "01"),
DECODE_SET_32_VFP_S (VCVTSF_VFP, "1.11", "1101", "11"),
DECODE_SET_32_VFP_S (VCVTXFSH_VFP, "1.11", "1110", "01"),
DECODE_SET_32_VFP_S (VCVTXFSW_VFP, "1.11", "1110", "11"),
DECODE_SET_32_VFP_S (VCVTXFUH_VFP, "1.11", "1111", "01"),
DECODE_SET_32_VFP_S (VCVTXFUW_VFP, "1.11", "1111", "11"),
// Extension register load/store instructions
DECODE_SET_32_SDFP_LDST (VSTMIA, "01.00"),
DECODE_SET_32_SDFP_LDST (VSTMIAW, "01.10"),
DECODE_SET_32_SDFP_LDST (VSTR, "1..00"),
DECODE_SET_32_SDFP_LDST (VSTMDBW, "10.10"),
DECODE_SET_32_SDFP_PUSH_POP (VPUSH, "10.10"),
DECODE_SET_32_SDFP_LDST (VLDMIA, "01.01"),
DECODE_SET_32_SDFP_LDST (VLDMIAW, "01.11"),
DECODE_SET_32_SDFP_PUSH_POP (VPOP, "01.11"),
DECODE_SET_32_SDFP_LDST (VLDR, "1..01"),
DECODE_SET_32_SDFP_LDST (VLDMDBW, "10.11"),
// 8, 16 and 32-bit transfer instructions between ARM core regs and extension regs
DECODE_SET_32_VMRS (VMRS, "1", "0", "111", ".."),
DECODE_SET_32_VMRS (VMSR, "0", "0", "111", ".."),
DECODE_SET_32_VMRS (VMOVRS, "1", "0", "000", ".."),
DECODE_SET_32_VMRS (VMOVSR, "0", "0", "000", ".."),
DECODE_SET_32_VMRS (VMOVRZ, "1", "1", "00.", "00"),
DECODE_SET_32_VMRS (VMOVZR, "0", "1", "00.", "00"),
// 64-bit transfer instructions between ARM core regs and extension regs
DECODE_SET_32_VMOVRRD (VMOVRRD, "1", "1", "00.1"),
DECODE_SET_32_VMOVRRD (VMOVDRR, "0", "1", "00.1"),
DECODE_SET_32_VMOVRRD (VMOVRRSS, "1", "0", "00.1"),
DECODE_SET_32_VMOVRRD (VMOVSSRR, "0", "0", "00.1"),
// terminator
{0}
};
// create the table
vmidDecodeTableP table = vmidNewDecodeTable(32, TT_LAST);
const decodeEntry *entry;
// add all entries to the decode table
for(entry=entries; entry->pattern; entry++) {
vmidNewEntryFmtBin(
table,
entry->name,
entry->type,
entry->pattern,
entry->priority
);
}
return table;
}
//
// Get the 16-bit Thumb instruction decode table
//
static vmidDecodeTableP getDecodeTableThumb16(void) {
static vmidDecodeTableP table;
if(!table) {
table = createDecodeTableThumb16();
}
return table;
}
//
// Get the 32-bit Thumb instruction decode table
//
static vmidDecodeTableP getDecodeTableThumb32(void) {
static vmidDecodeTableP table;
if(!table) {
table = createDecodeTableThumb32();
}
return table;
}
//
// Return effect that the instruction has on the flags (note that this may
// depend on whether the instruction is in an if-then block)
//
static armSetFlags getSetFlagsThumb(armP arm, Uns32 instr, armSetFlags sf) {
armSetFlags result;
switch(sf) {
case SF_0:
result = ARM_SF_0;
break;
case SF_V:
result = ARM_SF_V;
break;
case SF_I:
result = ARM_SF_I;
break;
case SF_20_V:
result = OP_F20(instr) ? ARM_SF_V : ARM_SF_0;
break;
case SF_IT:
if(arm->itStateMT) {
result = ARM_SF_0;
} else if(arm->UAL) {
result = ARM_SF_V;
} else {
result = ARM_SF_I;
}
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Return condition associated with the instruction (note that this may depend
// on whether the instruction is in an if-then block)
//
static armCondition getConditionThumb(armP arm, Uns32 instr, condSpec cond) {
armCondition result = ARM_C_AL;
if(arm->itStateMT) {
result = arm->itStateMT>>4;
} else switch(cond) {
case CO_NA: break;
case CO_8: result = OP_COND_8(instr); break;
case CO_22: result = OP_COND_22(instr); break;
case CO_28: result = OP_COND_28(instr); break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return register index encoded in the Thumb instruction
//
static Uns8 getRegisterThumb(Uns32 instr, rSpec r) {
Uns8 result = 0;
switch(r) {
case R_NA: break;
case R3_0: result = OP_R3_0(instr); break;
case R3_3: result = OP_R3_3(instr); break;
case R3_6: result = OP_R3_6(instr); break;
case R3_8: result = OP_R3_8(instr); break;
case R4_0: result = OP_R4_0(instr); break;
case R4_8: result = OP_R4_8(instr); break;
case R4_12: result = OP_R4_12(instr); break;
case R4_16: result = OP_R4_16(instr); break;
case R4_0H7: result = OP_R4_0_H7(instr); break;
case R4_3H6: result = OP_R4_3_H6(instr); break;
case R_PC: result = ARM_REG_PC; break;
case R_SP: result = ARM_REG_SP; break;
case R_LR: result = ARM_REG_LR; break;
case V_0_5: result = OP_V0_5(instr); break;
case V_16_7: result = OP_V16_7(instr); break;
case V_12_22: result = OP_V12_22(instr); break;
case V_5_0: result = OP_V5_0(instr); break;
case V_22_12: result = OP_V22_12(instr); break;
case V_7_16: result = OP_V7_16(instr); break;
case V3_0: result = OP_U_3_0(instr); break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
///
// Return shift operation encoded in the Thumb instruction
//
static armShiftOp getShiftOpThumb(Uns32 instr, shiftSpec ss) {
Uns32 result = ARM_SO_NA;
const static armShiftOp shiftMap[] = {
ARM_SO_LSL, ARM_SO_LSR, ARM_SO_ASR, ARM_SO_ROR
};
switch(ss) {
case SS_NA:
break;
case SS_ASR:
result = ARM_SO_ASR;
break;
case SS_LSL:
result = ARM_SO_LSL;
break;
case SS_LSR:
result = ARM_SO_LSR;
break;
case SS_ROR:
result = ARM_SO_ROR;
break;
case SS_RRX:
result = ARM_SO_RRX;
break;
case SS2_4:
result = shiftMap[OP_U_2_4(instr)];
break;
case SS2_20:
result = shiftMap[OP_U_2_20(instr)];
break;
case SS2_21:
result = shiftMap[OP_U_2_21(instr)];
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Allow for cases where constant value of zero is interpreted as 32
//
static Uns32 adjustShift(Uns32 result, constSpec c, armShiftOp so) {
if((result==0) && (c!=CS_NA) && ((so==ARM_SO_LSR) || (so==ARM_SO_ASR))) {
result = 32;
}
return result;
}
//
// Return a 5-bit plain immediate constant encoded within the Thumb instruction
//
static Uns32 plainImmediateThumb5(Uns32 instr) {
// bitfield to extract instruction parts
union {
Uns32 instr;
struct {
Uns32 _u1 : 6;
Uns32 imm2 : 2;
Uns32 _u2 : 4;
Uns32 imm3 : 3;
Uns32 _u3 : 17;
} f;
} u1 = {instr};
// compose result
return ((u1.f.imm3)<<2) | u1.f.imm2;
}
//
// Return a 12-bit plain immediate constant encoded within the Thumb instruction
//
static Uns32 plainImmediateThumb12(Uns32 instr) {
// bitfield to extract instruction parts
union {
Uns32 instr;
struct {
Uns32 imm8 : 8;
Uns32 _u1 : 4;
Uns32 imm3 : 3;
Uns32 _u2 : 11;
Uns32 i : 1;
Uns32 _u3 : 5;
} f;
} u1 = {instr};
// compose result
return ((u1.f.i)<<11) | ((u1.f.imm3)<<8) | u1.f.imm8;
}
//
// Return a 16-bit plain immediate constant encoded within the Thumb instruction
//
static Uns32 plainImmediateThumb16(Uns32 instr) {
// bitfield to extract instruction parts
union {
Uns32 instr;
struct {
Uns32 imm8 : 8;
Uns32 _u1 : 4;
Uns32 imm3 : 3;
Uns32 _u2 : 1;
Uns32 imm4 : 4;
Uns32 _u3 : 6;
Uns32 i : 1;
Uns32 _u4 : 5;
} f;
} u1 = {instr};
// compose result
return ((u1.f.imm4)<<12) | ((u1.f.i)<<11) | ((u1.f.imm3)<<8) | u1.f.imm8;
}
//
// Return a modified immediate constant encoded within the Thumb instruction
// and set byref 'crotate' to any constant rotation
//
static Uns32 modifiedImmediateThumb(Uns32 instr, Uns8 *crotate) {
Uns32 result;
// bitfield to extract instruction parts
union {
Uns32 instr;
struct {
Uns32 bcdefgh : 7;
Uns32 a : 1;
Uns32 _u1 : 4;
Uns32 imm3 : 3;
Uns32 _u2 : 11;
Uns32 i : 1;
Uns32 _u3 : 5;
} f;
} u1 = {instr};
// compose code
Uns32 code = ((u1.f.i)<<4) | ((u1.f.imm3)<<1) | u1.f.a;
Uns32 abcdefgh = (u1.f.a<<7) | u1.f.bcdefgh;
// derive result from code
switch(code) {
case 0x00: case 0x01:
result = abcdefgh;
break;
case 0x02: case 0x03:
result = (abcdefgh<<16) | abcdefgh;
break;
case 0x04: case 0x05:
result = (abcdefgh<<24) | (abcdefgh<<8);
break;
case 0x06: case 0x07:
result = (abcdefgh<<24) | (abcdefgh<<16) | (abcdefgh<<8) | abcdefgh;
break;
default: {
Uns32 shift = 32-code;
result = (1<<7) | u1.f.bcdefgh;
result <<= shift;
*crotate = code;
break;
}
}
return result;
}
//
// Negate the argument if U bit of Thumb instruction is zero
//
inline static Uns32 negateIfU(armInstructionInfoP info, Uns32 result) {
return info->u ? result : -result;
}
//
// Return a constant encoded within the Thumb instruction and set byref
// 'crotate' to any constant rotation
//
static Uns32 getConstantThumb(
armP arm,
armInstructionInfoP info,
Uns32 instr,
constSpec c,
armShiftOp so,
Uns8 *crotate
) {
Uns32 result = 0;
// assume constant rotation is zero
*crotate = 0;
switch(c) {
case CS_NA:
break;
case CS_U_2_4:
result = OP_U_2_4(instr);
break;
case CS_U_2_4x8:
result = OP_U_2_4(instr)*8;
break;
case CS_U_2_10:
result = OP_U_2_10(instr);
break;
case CS_U_3_6:
result = OP_U_3_6(instr);
break;
case CS_U_4_4:
result = OP_U_4_4(instr);
break;
case CS_U_4_0:
result = OP_U_4_0(instr);
break;
case CS_U_5_6:
result = OP_U_5_6(instr);
break;
case CS_U_5_6_SZ:
result = OP_U_5_6(instr)*info->sz;
break;
case CS_U_5_0_5M16:
result = OP_U_5_0_5(instr);
result = 16 - (result > 16 ? 0 : result);
break;
case CS_U_5_0_5M32:
result = 32 - OP_U_5_0_5(instr);
break;
case CS_U_7_0x4:
result = OP_U_7_0(instr)*4;
break;
case CS_U_8_0:
result = OP_U_8_0(instr);
break;
case CS_U_8_0_U:
result = negateIfU(info, OP_U_8_0(instr));
break;
case CS_U_8_0_SZ:
result = OP_U_8_0(instr)*info->sz;
break;
case CS_U_8_0x4_U:
result = negateIfU(info, OP_U_8_0(instr)*4);
break;
case CS_U_8_0x4:
result = OP_U_8_0(instr)*4;
break;
case CS_U_12_0:
result = OP_U_12_0(instr);
break;
case CS_U_12_0_U:
result = negateIfU(info, OP_U_12_0(instr));
break;
case CS_PI5:
result = plainImmediateThumb5(instr);
break;
case CS_PI12:
result = plainImmediateThumb12(instr);
break;
case CS_PI16:
result = plainImmediateThumb16(instr);
break;
case CS_MI:
result = modifiedImmediateThumb(instr, crotate);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
// allow for cases where constant value of zero is interpreted as 32
return adjustShift(result, c, so);
}
//
// Return nregs, fixed or encoded within the Thumb instruction
//
static Uns8 getNRegsThumb(Uns32 instr, nregSpec nRegs) {
Uns8 result = 0;
switch(nRegs) {
case NREG_NA:
break;
case NREG_7_1:
result = OP_U_7_1(instr);
break;
case NREG_8_0:
result = OP_U_8_0(instr);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return bit operation width encoded in the ARM instruction
//
static Int8 getWidthThumb(Uns32 instr, widthSpec w) {
Int8 result = 0;
switch(w) {
case WS_NA:
break;
case WS_WIDTH4:
result = OP_U_4_0(instr);
break;
case WS_WIDTH4M1:
result = OP_U_4_0(instr)+1;
break;
case WS_WIDTH5:
result = OP_U_5_0(instr);
break;
case WS_WIDTH5M1:
result = OP_U_5_0(instr)+1;
break;
case WS_MSB:
result = OP_U_5_0(instr)-plainImmediateThumb5(instr)+1;
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Get post-indexed attributes for the Thumb instruction
//
static Bool getPostIndexedThumb(Uns32 instr, postIndexSpec pi) {
Bool result = False;
switch(pi) {
case PI_0:
result = False;
break;
case PI_1:
result = True;
break;
case PI_10:
result = !OP_PI_10(instr);
break;
case PI_24:
result = !OP_PI_24(instr);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Get writeback attributes for the Thumb instruction
//
static Bool getWritebackThumb(
Uns32 instr,
writebackSpec wb,
Uns32 base,
Uns32 rList
) {
Bool result = False;
switch(wb) {
case WB_0:
result = False;
break;
case WB_1:
result = True;
break;
case WB_1_NB:
result = !(rList & (1<<base));
break;
case WB_8:
result = OP_WB_8(instr);
break;
case WB_21:
result = OP_WB_21(instr);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Return target address calculated by adding the current PC and the displacement
//
static Uns32 getTarget(armInstructionInfoP info, Int32 displacement) {
return info->thisPC + displacement;
}
//
// Return a 20-bit target address encoded within the Thumb instruction
//
static Uns32 getTarget20(armInstructionInfoP info, Uns32 instr) {
// bitfield to extract instruction parts
union {
Uns32 instr;
struct {
Uns32 imm11 : 11;
Uns32 j2 : 1;
Uns32 _u1 : 1;
Uns32 j1 : 1;
Uns32 _u2 : 2;
Uns32 imm6 : 6;
Uns32 _u3 : 4;
Uns32 s : 1;
Uns32 _u4 : 5;
} f;
} u1 = {instr};
// bitfield to compose target
union {
Uns32 offset;
struct {
Uns32 zero : 1;
Uns32 imm11 : 11;
Uns32 imm6 : 6;
Uns32 j2 : 1;
Uns32 j1 : 1;
Uns32 s : 12;
} f;
} u2;
// fill target fields;
u2.f.zero = 0;
u2.f.imm11 = u1.f.imm11;
u2.f.imm6 = u1.f.imm6;
u2.f.j2 = u1.f.j2;
u2.f.j1 = u1.f.j1;
u2.f.s = -u1.f.s;
// return target address
return getTarget(info, u2.offset+4);
}
//
// Return a 24-bit target address encoded within the Thumb instruction
//
static Uns32 getTarget24(armInstructionInfoP info, Uns32 instr) {
// bitfield to extract instruction parts
union {
Uns32 instr;
struct {
Uns32 imm11 : 11;
Uns32 j2 : 1;
Uns32 _u1 : 1;
Uns32 j1 : 1;
Uns32 _u2 : 2;
Uns32 imm10 : 10;
Uns32 s : 1;
Uns32 _u3 : 5;
} f;
} u1 = {instr};
// bitfield to compose target
union {
Uns32 offset;
struct {
Uns32 zero : 1;
Uns32 imm11 : 11;
Uns32 imm10 : 10;
Uns32 i2 : 1;
Uns32 i1 : 1;
Uns32 s : 8;
} f;
} u2;
// compose i1 and i2 fields;
Uns32 s = u1.f.s;
Uns32 i1 = !(u1.f.j1 ^ s);
Uns32 i2 = !(u1.f.j2 ^ s);
// fill target fields;
u2.f.zero = 0;
u2.f.imm11 = u1.f.imm11;
u2.f.imm10 = u1.f.imm10;
u2.f.i2 = i2;
u2.f.i1 = i1;
u2.f.s = -s;
// return target address
return getTarget(info, u2.offset+4);
}
//
// Return a target address encoded within the Thumb instruction
//
static Uns32 getTargetThumb(
armInstructionInfoP info,
Uns32 instr,
targetSpec t
) {
Uns32 result = 0;
switch(t) {
case TC_NA:
break;
case TC_S8:
result = getTarget(info, OP_TS8(instr)+4);
break;
case TC_S11:
result = getTarget(info, OP_TS11(instr)+4);
break;
case TC_S20_T2:
result = getTarget20(info, instr);
break;
case TC_S24_T2:
result = getTarget24(info, instr);
break;
case TC_U9_7_3:
result = getTarget(info, OP_TU9_7_3(instr)+4);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Return coprocessor opcode1 encoded within the Thumb instruction
//
static Uns32 getCpOp1Thumb(
armP arm,
armInstructionInfoP info,
Uns32 instr,
cpOp1Spec cpOp1
) {
Uns32 result = 0;
switch(cpOp1) {
case COP_NA: break;
case COP_4_4: result = OP_CPOP1_4_4(instr); break;
case COP_4_20: result = OP_CPOP1_4_20(instr); break;
case COP_3_21: result = OP_CPOP1_3_21(instr); break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return register list encoded within the Thumb instruction
//
static Uns32 getRListThumb(Uns32 instr, rListSpec rList) {
Uns32 result = 0;
switch(rList) {
case RL_NA: break;
case RL_16: result = OP_RL_16(instr); break;
case RL_16_LR: result = OP_RL_16_LR(instr); break;
case RL_16_PC: result = OP_RL_16_PC(instr); break;
case RL_32_SP: result = OP_RL_32_SP(instr); break;
case RL_32_PCSP: result = OP_RL_32_PCSP(instr); break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return increment/decrement action encoded within the Thumb instruction
//
static armIncDec getIncDecThumb(
armInstructionInfoP info,
armP arm,
Uns32 instr,
incDecSpec incDec
) {
armIncDec result = ARM_ID_NA;
switch (incDec) {
case ID_NA: break;
case ID_DB: result = ARM_ID_DB; break;
case ID_IA: result = ARM_ID_IA; break;
case ID_DB_I: result = ARM_ID_DBI; break;
case ID_IA_I: result = ARM_ID_IAI; break;
case ID_U_P:
case ID_U_P_IMP:
case ID_U_P_IAI: {
armIncDec USpec = OP_U (instr) ? ARM_ID_I : ARM_ID_D;
armIncDec PSpec = OP_PI(instr) ? ARM_ID_B : ARM_ID_A;
result = (ARM_ID_P | USpec | PSpec);
if (incDec==ID_U_P_IMP) {
// inc/dec spec is always implicit (VPUSH/VPOP)
result |= ARM_ID_NS;
} else if(arm->UAL && (result==ARM_ID_IA) && (incDec==ID_U_P_IAI)) {
// inc/dec spec is implicit in UAL mode when it is IA
result |= ARM_ID_NS;
}
break;
}
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return indication of whether Thumb instruction enables or disables interrupts
// (CPS)
//
static armFlagAction getFlagActionThumb(
armInstructionInfoP info,
imodSpec imod,
Uns32 instr
) {
armFlagAction result = ARM_FACT_NA;
switch(imod) {
case IS_NA: break;
case IS_4: result = OP_IS_4(instr) ? ARM_FACT_ID : ARM_FACT_IE; break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return interrupt flag list in Thumb instruction
//
static armFlagAffect getFlagAffectThumb(
armInstructionInfoP info,
aifSpec aif,
Uns32 instr
) {
armFlagAffect result = ARM_FAFF_NA;
if((info->fact==ARM_FACT_IE) || (info->fact==ARM_FACT_ID)) {
switch(aif) {
case AIF_0: result = OP_AIF_0(instr); break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
}
return result;
}
//
// Get the value of the U bit in the instruction
//
static Bool getUThumb(Uns32 instr, uSpec u) {
Bool result = False;
switch(u) {
case US_1:
result = True;
break;
case US_9:
result = OP_U_9(instr);
break;
case US_23:
result = OP_U_23(instr);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Return indication of PSR bits specified by the instruction, if any
//
static armPSRBits getPSRBitsThumb(
armInstructionInfoP info,
maskSpec mask,
Uns32 instr
) {
armPSRBits result = ARM_PSRBITS_NA;
switch(mask) {
case MSRMASK_NA: break;
case MSRMASK_10: result = OP_U_2_10(instr); break;
default: VMI_ABORT("%s: unimplemented case", FUNC_NAME); break;
}
return result;
}
//
// Return a modified immediate constant for the given immediate value
// If single is true then form a single precision value,
// otherwise form the high order 32 bits of a double precision value (low order 32 bits are always all 0's)
//
static armSdfpMItype modifiedImmediateVFPthumb(Uns32 imm, Bool single) {
armSdfpMItype result;
if (single) {
// Set the sign bit to be a
result.u32.w0 = (imm & 0x80) ? 0x80000000 : 0;
// Set the exponent sign to be Bbbbbb - where B = Not b
result.u32.w0 |= (imm & 0x40) ? 0x3e000000 : 0x40000000;
// set the mantissa to cdefgh
result.u32.w0 |= (imm & 0x3f) << 19;
// CLear the high order bits just to be safe
result.u32.w1 = 0;
} else {
// Set the sign bit to be a
result.u64 = (imm & 0x80) ? 0x8000000000000000ULL : 0ULL;
// Set the exponent sign to be Bbbbbbbbb - where B = Not b
result.u64 |= (imm & 0x40) ? 0x3fc0000000000000ULL : 0x4000000000000000ULL;
// set the mantissa to cdefgh
result.u64 |= ((Uns64) (imm & 0x3f)) << 48;
}
return result;
}
//
// Decode and return a SIMD/VFP modified immediate constant encoded within the ARM instruction
//
static armSdfpMItype getSdfpMIthumb(
Uns32 instr,
sdfpMISpec s,
armSDFPType dt
) {
armSdfpMItype result;
result.u64 = 0;
switch (s) {
case SDFP_MI_NA:
break;
case SDFP_MI_VFP_S:
VMI_ASSERT(dt == ARM_SDFPT_F32, "VFP Modified immediate constant type does not match dt");
result = modifiedImmediateVFPthumb(OP_U_8_16_0(instr), True);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
//
// Return the VFP scalar index encoded in the Thumb instruction
//
static Int8 getIndexThumb(Uns32 instr, indexSpec index) {
Int8 result = 0;
switch(index) {
case IDX_NA:
break;
case IDX_21:
result = OP_U_1_21(instr);
break;
case IDX_5:
result = OP_U_1_5(instr);
break;
case IDX_7:
result = OP_U_1_7(instr);
break;
case IDX_19:
result = OP_U_1_19(instr);
break;
default:
VMI_ABORT("%s: unimplemented case", FUNC_NAME);
break;
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
// PUBLIC INTERFACE
////////////////////////////////////////////////////////////////////////////////
//
// Bitmasks for identification of 32-bit Thumb instructions
//
#define THUMB32_MASK 0xf800
#define THUMB32_BL_H01 0xe800
#define THUMB32_BL_H10 0xf000
#define THUMB32_BL_H11 0xf800
//
// Return size in bytes of Thumb instruction at the passed address
//
Uns32 armGetThumbInstructionSize(armP arm, Uns32 thisPC) {
Uns16 instr1 = vmicxtFetch2Byte((vmiProcessorP)arm, thisPC);
Uns16 hw1 = instr1 & THUMB32_MASK;
Bool isBL_H01 = (hw1==THUMB32_BL_H01);
Bool isBL_H10 = (hw1==THUMB32_BL_H10);
Bool isBL_H11 = (hw1==THUMB32_BL_H11);
return (isBL_H01 || isBL_H10 || isBL_H11) ? 4 : 2;
}
//
// Decode the Thumb instruction at the passed address. The 'info' structure is
// filled with details of the instruction.
//
void armDecodeThumb(armP arm, Uns32 thisPC, armInstructionInfoP info) {
vmiProcessorP processor = (vmiProcessorP)arm;
Uns32 bytes = armGetThumbInstructionSize(arm, thisPC);
Uns32 instr = vmicxtFetch2Byte(processor, thisPC);
armThumbType type;
// fetch instruction and decode it based on size
if(bytes==2) {
type = vmidDecode(getDecodeTableThumb16(), instr);
} else {
instr = (instr<<16) | vmicxtFetch2Byte(processor, thisPC+2);
type = vmidDecode(getDecodeTableThumb32(), instr);
}
// save instruction
info->instruction = instr;
// get instruction attributes based on type
opAttrsCP attrs = &attrsArray[type];
// get the equivalent main series type
info->type = attrs->type;
// specify the name and format for the opcode
info->opcode = attrs->opcode;
info->format = attrs->format;
// specify required architecture for the instruction
info->support = attrs->support;
info->isar = attrs->isar;
// save instruction bytes
info->bytes = bytes;
// get any flags set in the instruction
info->f = getSetFlagsThumb(arm, instr, attrs->f);
// indicate whether the instruction is conditional
info->cond = getConditionThumb(arm, instr, attrs->cond);
// get registers used by this instruction
info->r1 = getRegisterThumb(instr, attrs->r1);
info->r2 = getRegisterThumb(instr, attrs->r2);
info->r3 = getRegisterThumb(instr, attrs->r3);
info->r4 = getRegisterThumb(instr, attrs->r4);
// get shiftop for the instruction
info->so = getShiftOpThumb(instr, attrs->ss);
// get load/store size, sign extension, translate and exclusive access
// settings
info->sz = attrs->sz;
info->w = getWidthThumb(instr, attrs->w);
info->xs = attrs->xs;
info->tl = attrs->tl;
info->ea = attrs->ea;
// does the opcode have a long load field?
info->ll = attrs->ll ? OP_LL(instr) : 0;
// get U bit (must be valid *before* getConstantThumb which uses it)
info->u = getUThumb(instr, attrs->u);
// get any constant value and constant rotate associated with the instruction
info->c = getConstantThumb(
arm, info, instr, attrs->cs, info->so, &info->crotate
);
// get any constant target address associated with the instruction
info->t = getTargetThumb(info, instr, attrs->ts);
// get any coprocessor fields associated with the instruction
info->cpNum = attrs->cpNum ? OP_CPNUM(instr) : 0;
info->cpOp1 = getCpOp1Thumb(arm, info, instr, attrs->cpOp1);
info->cpOp2 = attrs->cpOp2 ? OP_CPOP2(instr) : 0;
// get any _bits specification for MSR instructions
info->psrbits = getPSRBitsThumb(info, attrs->mask, instr);
// get any register list and increment/decrement specification
info->rList = getRListThumb(instr, attrs->rList);
info->incDec = getIncDecThumb(info, arm, instr, attrs->incDec);
// get post-indexed and writeback attributes for the instruction
info->pi = getPostIndexedThumb(instr, attrs->pi);
info->wb = info->pi || getWritebackThumb(instr, attrs->wb, info->r1, info->rList);
// specify action on unaligned access
info->ua = attrs->ua67;
// get flag and mode effect fields (CPS instruction)
info->ma = attrs->m ? OP_MA(instr) : 0;
info->fact = getFlagActionThumb(info, attrs->imod, instr);
info->faff = getFlagAffectThumb(info, attrs->aif, instr);
// get if-then specification
info->it = attrs->it ? OP_IT(instr) : 0;
// Get VFP specifications
info->index = getIndexThumb(instr, attrs->index);
info->nregs = getNRegsThumb(instr, attrs->nregs);
// get any SIMD modified immediate constant value (64 bits long)
info->sdfpMI = getSdfpMIthumb (instr, attrs->sdfpMI, attrs->dt1);
// get floating point type specification
info->dt1 = attrs->dt1;
info->dt2 = attrs->dt2;
}