diff options
Diffstat (limited to 'src/core')
31 files changed, 3590 insertions, 2852 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e9b04098b..0773339a9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -5,6 +5,7 @@ set(SRCS arm/dyncom/arm_dyncom_dec.cpp arm/dyncom/arm_dyncom_interpreter.cpp arm/dyncom/arm_dyncom_thumb.cpp + arm/dyncom/arm_dyncom_trans.cpp arm/skyeye_common/armstate.cpp arm/skyeye_common/armsupp.cpp arm/skyeye_common/vfp/vfp.cpp @@ -26,9 +27,11 @@ set(SRCS hle/config_mem.cpp hle/hle.cpp hle/applets/applet.cpp + hle/applets/erreula.cpp hle/applets/mii_selector.cpp hle/applets/swkbd.cpp hle/kernel/address_arbiter.cpp + hle/kernel/client_port.cpp hle/kernel/event.cpp hle/kernel/kernel.cpp hle/kernel/memory.cpp @@ -36,6 +39,7 @@ set(SRCS hle/kernel/process.cpp hle/kernel/resource_limit.cpp hle/kernel/semaphore.cpp + hle/kernel/server_port.cpp hle/kernel/session.cpp hle/kernel/shared_memory.cpp hle/kernel/thread.cpp @@ -140,6 +144,7 @@ set(HEADERS arm/dyncom/arm_dyncom_interpreter.h arm/dyncom/arm_dyncom_run.h arm/dyncom/arm_dyncom_thumb.h + arm/dyncom/arm_dyncom_trans.h arm/skyeye_common/arm_regformat.h arm/skyeye_common/armstate.h arm/skyeye_common/armsupp.h @@ -164,9 +169,11 @@ set(HEADERS hle/function_wrappers.h hle/hle.h hle/applets/applet.h + hle/applets/erreula.h hle/applets/mii_selector.h hle/applets/swkbd.h hle/kernel/address_arbiter.h + hle/kernel/client_port.h hle/kernel/event.h hle/kernel/kernel.h hle/kernel/memory.h @@ -174,6 +181,7 @@ set(HEADERS hle/kernel/process.h hle/kernel/resource_limit.h hle/kernel/semaphore.h + hle/kernel/server_port.h hle/kernel/session.h hle/kernel/shared_memory.h hle/kernel/thread.h diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index cfc67287f..01d5d478e 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -17,6 +17,7 @@ #include "core/arm/dyncom/arm_dyncom_dec.h" #include "core/arm/dyncom/arm_dyncom_interpreter.h" #include "core/arm/dyncom/arm_dyncom_thumb.h" +#include "core/arm/dyncom/arm_dyncom_trans.h" #include "core/arm/dyncom/arm_dyncom_run.h" #include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armsupp.h" @@ -24,18 +25,6 @@ #include "core/gdbstub/gdbstub.h" -enum { - COND = (1 << 0), - NON_BRANCH = (1 << 1), - DIRECT_BRANCH = (1 << 2), - INDIRECT_BRANCH = (1 << 3), - CALL = (1 << 4), - RET = (1 << 5), - END_OF_PAGE = (1 << 6), - THUMB = (1 << 7), - SINGLE_STEP = (1 << 8) -}; - #define RM BITS(sht_oper, 0, 3) #define RS BITS(sht_oper, 8, 11) @@ -46,8 +35,6 @@ enum { #define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) #define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) -typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); - static bool CondPassed(const ARMul_State* cpu, unsigned int cond) { const bool n_flag = cpu->NFlag != 0; const bool z_flag = cpu->ZFlag != 0; @@ -245,12 +232,6 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh return shifter_operand; } -typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr); - -struct ldst_inst { - unsigned int inst; - get_addr_fp_t get_addr; -}; #define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) #define LnSWoUB(s) glue(LnSWoUB, s) @@ -668,479 +649,7 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u virt_addr = addr; } -struct arm_inst { - unsigned int idx; - unsigned int cond; - int br; - char component[0]; -}; - -struct generic_arm_inst { - u32 Ra; - u32 Rm; - u32 Rn; - u32 Rd; - u8 op1; - u8 op2; -}; - -struct adc_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct add_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct orr_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct and_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct eor_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct bbl_inst { - unsigned int L; - int signed_immed_24; - unsigned int next_addr; - unsigned int jmp_addr; -}; - -struct bx_inst { - unsigned int Rm; -}; - -struct blx_inst { - union { - s32 signed_immed_24; - u32 Rm; - } val; - unsigned int inst; -}; - -struct clz_inst { - unsigned int Rm; - unsigned int Rd; -}; - -struct cps_inst { - unsigned int imod0; - unsigned int imod1; - unsigned int mmod; - unsigned int A, I, F; - unsigned int mode; -}; - -struct clrex_inst { -}; - -struct cpy_inst { - unsigned int Rm; - unsigned int Rd; -}; - -struct bic_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct sub_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct tst_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct cmn_inst { - unsigned int I; - unsigned int Rn; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct teq_inst { - unsigned int I; - unsigned int Rn; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct stm_inst { - unsigned int inst; -}; - -struct bkpt_inst { - u32 imm; -}; - -struct stc_inst { -}; - -struct ldc_inst { -}; - -struct swi_inst { - unsigned int num; -}; - -struct cmp_inst { - unsigned int I; - unsigned int Rn; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct mov_inst { - unsigned int I; - unsigned int S; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct mvn_inst { - unsigned int I; - unsigned int S; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct rev_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int op1; - unsigned int op2; -}; - -struct rsb_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct rsc_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct sbc_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct mul_inst { - unsigned int S; - unsigned int Rd; - unsigned int Rs; - unsigned int Rm; -}; - -struct smul_inst { - unsigned int Rd; - unsigned int Rs; - unsigned int Rm; - unsigned int x; - unsigned int y; -}; - -struct umull_inst { - unsigned int S; - unsigned int RdHi; - unsigned int RdLo; - unsigned int Rs; - unsigned int Rm; -}; - -struct smlad_inst { - unsigned int m; - unsigned int Rm; - unsigned int Rd; - unsigned int Ra; - unsigned int Rn; - unsigned int op1; - unsigned int op2; -}; - -struct smla_inst { - unsigned int x; - unsigned int y; - unsigned int Rm; - unsigned int Rd; - unsigned int Rs; - unsigned int Rn; -}; - -struct smlalxy_inst { - unsigned int x; - unsigned int y; - unsigned int RdLo; - unsigned int RdHi; - unsigned int Rm; - unsigned int Rn; -}; - -struct ssat_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int imm5; - unsigned int sat_imm; - unsigned int shift_type; -}; - -struct umaal_inst { - unsigned int Rn; - unsigned int Rm; - unsigned int RdHi; - unsigned int RdLo; -}; - -struct umlal_inst { - unsigned int S; - unsigned int Rm; - unsigned int Rs; - unsigned int RdHi; - unsigned int RdLo; -}; - -struct smlal_inst { - unsigned int S; - unsigned int Rm; - unsigned int Rs; - unsigned int RdHi; - unsigned int RdLo; -}; - -struct smlald_inst { - unsigned int RdLo; - unsigned int RdHi; - unsigned int Rm; - unsigned int Rn; - unsigned int swap; - unsigned int op1; - unsigned int op2; -}; - -struct mla_inst { - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int Rs; - unsigned int Rm; -}; - -struct mrc_inst { - unsigned int opcode_1; - unsigned int opcode_2; - unsigned int cp_num; - unsigned int crn; - unsigned int crm; - unsigned int Rd; - unsigned int inst; -}; - -struct mcr_inst { - unsigned int opcode_1; - unsigned int opcode_2; - unsigned int cp_num; - unsigned int crn; - unsigned int crm; - unsigned int Rd; - unsigned int inst; -}; - -struct mcrr_inst { - unsigned int opcode_1; - unsigned int cp_num; - unsigned int crm; - unsigned int rt; - unsigned int rt2; -}; - -struct mrs_inst { - unsigned int R; - unsigned int Rd; -}; - -struct msr_inst { - unsigned int field_mask; - unsigned int R; - unsigned int inst; -}; - -struct pld_inst { -}; - -struct sxtb_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct sxtab_inst { - unsigned int Rd; - unsigned int Rn; - unsigned int Rm; - unsigned rotate; -}; - -struct sxtah_inst { - unsigned int Rd; - unsigned int Rn; - unsigned int Rm; - unsigned int rotate; -}; - -struct sxth_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct uxtab_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int rotate; - unsigned int Rm; -}; - -struct uxtah_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int rotate; - unsigned int Rm; -}; - -struct uxth_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct cdp_inst { - unsigned int opcode_1; - unsigned int CRn; - unsigned int CRd; - unsigned int cp_num; - unsigned int opcode_2; - unsigned int CRm; - unsigned int inst; -}; - -struct uxtb_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct swp_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int Rm; -}; - -struct setend_inst { - unsigned int set_bigend; -}; - -struct b_2_thumb { - unsigned int imm; -}; -struct b_cond_thumb { - unsigned int imm; - unsigned int cond; -}; - -struct bl_1_thumb { - unsigned int imm; -}; -struct bl_2_thumb { - unsigned int imm; -}; -struct blx_1_thumb { - unsigned int imm; - unsigned int instr; -}; - -struct pkh_inst { - unsigned int Rm; - unsigned int Rn; - unsigned int Rd; - unsigned char imm; -}; - -typedef arm_inst * ARM_INST_PTR; - -#define CACHE_BUFFER_SIZE (64 * 1024 * 2000) -static char inst_buf[CACHE_BUFFER_SIZE]; -static int top = 0; -static inline void *AllocBuffer(unsigned int size) { - int start = top; - top += size; - if (top > CACHE_BUFFER_SIZE) { - LOG_ERROR(Core_ARM11, "inst_buf is full"); - CITRA_IGNORE_EXIT(-1); - } - return (void *)&inst_buf[start]; -} - -static shtop_fp_t get_shtop(unsigned int inst) { +shtop_fp_t GetShifterOp(unsigned int inst) { if (BIT(inst, 25)) { return DPO(Immediate); } else if (BITS(inst, 4, 11) == 0) { @@ -1165,7 +674,7 @@ static shtop_fp_t get_shtop(unsigned int inst) { return nullptr; } -static get_addr_fp_t get_calc_addr_op(unsigned int inst) { +get_addr_fp_t GetAddressingOp(unsigned int inst) { if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) { return LnSWoUB(ImmediateOffset); } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) { @@ -1208,2201 +717,21 @@ static get_addr_fp_t get_calc_addr_op(unsigned int inst) { return nullptr; } -#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) - -static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); - adc_inst *inst_cream = (adc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); - add_inst *inst_cream = (add_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); - and_inst *inst_cream = (and_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) -{ - #define POSBRANCH ((inst & 0x7fffff) << 2) - #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2) - - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); - bbl_inst *inst_cream = (bbl_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = DIRECT_BRANCH; - - if (BIT(inst, 24)) - inst_base->br = CALL; - if (BITS(inst, 28, 31) <= 0xe) - inst_base->br |= COND; - - inst_cream->L = BIT(inst, 24); - inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); - bic_inst *inst_cream = (bic_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst)); - bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); - blx_inst *inst_cream = (blx_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = INDIRECT_BRANCH; - - inst_cream->inst = inst; - if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { - inst_cream->val.Rm = BITS(inst, 0, 3); - } else { - inst_cream->val.signed_immed_24 = BITS(inst, 0, 23); - } - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); - bx_inst *inst_cream = (bx_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = INDIRECT_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(bx)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); - cdp_inst *inst_cream = (cdp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->CRm = BITS(inst, 0, 3); - inst_cream->CRd = BITS(inst, 12, 15); - inst_cream->CRn = BITS(inst, 16, 19); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->opcode_2 = BITS(inst, 5, 7); - inst_cream->opcode_1 = BITS(inst, 20, 23); - inst_cream->inst = inst; - - LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst)); - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); - clz_inst *inst_cream = (clz_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); - cmn_inst *inst_cream = (cmn_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); - cmp_inst *inst_cream = (cmp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); - cps_inst *inst_cream = (cps_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->imod0 = BIT(inst, 18); - inst_cream->imod1 = BIT(inst, 19); - inst_cream->mmod = BIT(inst, 17); - inst_cream->A = BIT(inst, 8); - inst_cream->I = BIT(inst, 7); - inst_cream->F = BIT(inst, 6); - inst_cream->mode = BITS(inst, 0, 4); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); - mov_inst *inst_cream = (mov_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) { - inst_base->br = INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); - eor_inst *inst_cream = (eor_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst)); - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - if (BIT(inst, 15)) { - inst_base->br = INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); - sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - if (BITS(inst, 12, 15) == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - if (BITS(inst, 12, 15) == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); - uxth_inst *inst_cream = (uxth_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); - uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - if (BITS(inst, 25, 27) == 2) { - inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); - } else if (BITS(inst, 25, 27) == 3) { - inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); - } else { - DEBUG_MSG; - } - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = (BITS(inst, 12, 15) == 15) ? INDIRECT_BRANCH : NON_BRANCH; // Branch if dest is R15 - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ldrex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ldrex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ldrex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; +// Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements +get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) { if (BITS(inst, 25, 27) == 2) { - inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); - } else if (BITS(inst, 25, 27) == 3) { - inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); - } else { - // Reaching this would indicate the thumb version - // of this instruction, however the 3DS CPU doesn't - // support this variant (the 3DS CPU is only ARMv6K, - // while this variant is added in ARMv6T2). - // So it's sufficient for citra to not implement this. - DEBUG_MSG; - } - - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); - mcr_inst *inst_cream = (mcr_inst *)inst_base->component; - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->crn = BITS(inst, 16, 19); - inst_cream->crm = BITS(inst, 0, 3); - inst_cream->opcode_1 = BITS(inst, 21, 23); - inst_cream->opcode_2 = BITS(inst, 5, 7); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->inst = inst; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); - mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->crm = BITS(inst, 0, 3); - inst_cream->opcode_1 = BITS(inst, 4, 7); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->rt = BITS(inst, 12, 15); - inst_cream->rt2 = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); - mla_inst *inst_cream = (mla_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 12, 15); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); - mov_inst *inst_cream = (mov_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) { - inst_base->br = INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); - mrc_inst *inst_cream = (mrc_inst *)inst_base->component; - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->crn = BITS(inst, 16, 19); - inst_cream->crm = BITS(inst, 0, 3); - inst_cream->opcode_1 = BITS(inst, 21, 23); - inst_cream->opcode_2 = BITS(inst, 5, 7); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->inst = inst; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(mcrr)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); - mrs_inst *inst_cream = (mrs_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->R = BIT(inst, 22); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); - msr_inst *inst_cream = (msr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->field_mask = BITS(inst, 16, 19); - inst_cream->R = BIT(inst, 22); - inst_cream->inst = inst; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); - mul_inst *inst_cream = (mul_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rd = BITS(inst, 16, 19); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); - mvn_inst *inst_cream = (mvn_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) { - inst_base->br = INDIRECT_BRANCH; - } - return inst_base; - -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); - orr_inst *inst_cream = (orr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} - -// NOP introduced in ARMv6K. -static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst)); - pkh_inst *inst_cream = (pkh_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->imm = BITS(inst, 7, 11); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(pkhbt)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->op1 = BITS(inst, 21, 22); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); - rev_inst* const inst_cream = (rev_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(rev)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(rev)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = AL; - inst_base->idx = index; - inst_base->br = INDIRECT_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); - rsb_inst *inst_cream = (rsb_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); - rsc_inst *inst_cream = (rsc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); - sbc_inst *inst_cream = (sbc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); - setend_inst* const inst_cream = (setend_inst*)inst_base->component; - - inst_base->cond = AL; - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->set_bigend = BIT(inst, 9); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); - smla_inst *inst_cream = (smla_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->x = BIT(inst, 5); - inst_cream->y = BIT(inst, 6); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rn = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->m = BIT(inst, 5); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Ra = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlad)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlad)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlad)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); - umlal_inst *inst_cream = (umlal_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst)); - smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->x = BIT(inst, 5); - inst_cream->y = BIT(inst, 6); - inst_cream->RdLo = BITS(inst, 12, 15); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->Rn = BITS(inst, 0, 4); - inst_cream->Rm = BITS(inst, 8, 11); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Ra = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->m = BIT(inst, 6); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); - smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->RdLo = BITS(inst, 12, 15); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->swap = BIT(inst, 5); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlald)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->m = BIT(inst, 5); - inst_cream->Ra = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smmla)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smmla)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); - smul_inst *inst_cream = (smul_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - inst_cream->x = BIT(inst, 5); - inst_cream->y = BIT(inst, 6); - - return inst_base; - -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); - umull_inst *inst_cream = (umull_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst *inst_cream = (smlad_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->m = BIT(inst, 6); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = AL; - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->imm5 = BITS(inst, 7, 11); - inst_cream->sat_imm = BITS(inst, 16, 20); - inst_cream->shift_type = BIT(inst, 6); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->sat_imm = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst)); - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); - sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); - uxth_inst *inst_cream = (uxth_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); - uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - - if (BITS(inst, 25, 27) == 2) { - inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); - } else if (BITS(inst, 25, 27) == 3) { - inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); - } else { - DEBUG_MSG; - } - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(strex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(strex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(strex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->inst = inst; - if (BITS(inst, 25, 27) == 2) { - inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + return LnSWoUB(ImmediatePostIndexed); } else if (BITS(inst, 25, 27) == 3) { - inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); - } else { - // Reaching this would indicate the thumb version - // of this instruction, however the 3DS CPU doesn't - // support this variant (the 3DS CPU is only ARMv6K, - // while this variant is added in ARMv6T2). - // So it's sufficient for citra to not implement this. - DEBUG_MSG; + return LnSWoUB(ScaledRegisterPostIndexed); } - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); - sub_inst *inst_cream = (sub_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); - swi_inst *inst_cream = (swi_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->num = BITS(inst, 0, 23); - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); - swp_inst *inst_cream = (swp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); - swp_inst *inst_cream = (swp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); - sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); - sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sxtab16)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); - sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); - teq_inst *inst_cream = (teq_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); - tst_inst *inst_cream = (tst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = get_shtop(inst); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); - umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->RdLo = BITS(inst, 12, 15); - inst_cream->RdHi = BITS(inst, 16, 19); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); - umlal_inst *inst_cream = (umlal_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); - umull_inst *inst_cream = (umull_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); - b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; - - inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); - - inst_base->idx = index; - inst_base->br = DIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); - b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component; - - inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); - inst_cream->cond = ((tinst >> 8) & 0xf); - inst_base->idx = index; - inst_base->br = DIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); - bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; - - inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); - - inst_base->idx = index; - inst_base->br = NON_BRANCH; - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); - bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component; - - inst_cream->imm = (tinst & 0x07FF) << 1; - - inst_base->idx = index; - inst_base->br = DIRECT_BRANCH; - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); - blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; - - inst_cream->imm = (tinst & 0x07FF) << 1; - inst_cream->instr = tinst; - - inst_base->idx = index; - inst_base->br = DIRECT_BRANCH; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 24); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Ra = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(usada8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ssat)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ssat16)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); - uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uxtab16)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; - - return inst_base; + // Reaching this would indicate the thumb version + // of this instruction, however the 3DS CPU doesn't + // support this variant (the 3DS CPU is only ARMv6K, + // while this variant is added in ARMv6T2). + // So it's sufficient for citra to not implement this. + return nullptr; } -// Floating point VFPv3 structures and instructions - -#define VFP_INTERPRETER_STRUCT -#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" -#undef VFP_INTERPRETER_STRUCT - -#define VFP_INTERPRETER_TRANS -#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" -#undef VFP_INTERPRETER_TRANS - -typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int); - -const transop_fp_t arm_instruction_trans[] = { - INTERPRETER_TRANSLATE(vmla), - INTERPRETER_TRANSLATE(vmls), - INTERPRETER_TRANSLATE(vnmla), - INTERPRETER_TRANSLATE(vnmls), - INTERPRETER_TRANSLATE(vnmul), - INTERPRETER_TRANSLATE(vmul), - INTERPRETER_TRANSLATE(vadd), - INTERPRETER_TRANSLATE(vsub), - INTERPRETER_TRANSLATE(vdiv), - INTERPRETER_TRANSLATE(vmovi), - INTERPRETER_TRANSLATE(vmovr), - INTERPRETER_TRANSLATE(vabs), - INTERPRETER_TRANSLATE(vneg), - INTERPRETER_TRANSLATE(vsqrt), - INTERPRETER_TRANSLATE(vcmp), - INTERPRETER_TRANSLATE(vcmp2), - INTERPRETER_TRANSLATE(vcvtbds), - INTERPRETER_TRANSLATE(vcvtbff), - INTERPRETER_TRANSLATE(vcvtbfi), - INTERPRETER_TRANSLATE(vmovbrs), - INTERPRETER_TRANSLATE(vmsr), - INTERPRETER_TRANSLATE(vmovbrc), - INTERPRETER_TRANSLATE(vmrs), - INTERPRETER_TRANSLATE(vmovbcr), - INTERPRETER_TRANSLATE(vmovbrrss), - INTERPRETER_TRANSLATE(vmovbrrd), - INTERPRETER_TRANSLATE(vstr), - INTERPRETER_TRANSLATE(vpush), - INTERPRETER_TRANSLATE(vstm), - INTERPRETER_TRANSLATE(vpop), - INTERPRETER_TRANSLATE(vldr), - INTERPRETER_TRANSLATE(vldm), - - INTERPRETER_TRANSLATE(srs), - INTERPRETER_TRANSLATE(rfe), - INTERPRETER_TRANSLATE(bkpt), - INTERPRETER_TRANSLATE(blx), - INTERPRETER_TRANSLATE(cps), - INTERPRETER_TRANSLATE(pld), - INTERPRETER_TRANSLATE(setend), - INTERPRETER_TRANSLATE(clrex), - INTERPRETER_TRANSLATE(rev16), - INTERPRETER_TRANSLATE(usad8), - INTERPRETER_TRANSLATE(sxtb), - INTERPRETER_TRANSLATE(uxtb), - INTERPRETER_TRANSLATE(sxth), - INTERPRETER_TRANSLATE(sxtb16), - INTERPRETER_TRANSLATE(uxth), - INTERPRETER_TRANSLATE(uxtb16), - INTERPRETER_TRANSLATE(cpy), - INTERPRETER_TRANSLATE(uxtab), - INTERPRETER_TRANSLATE(ssub8), - INTERPRETER_TRANSLATE(shsub8), - INTERPRETER_TRANSLATE(ssubaddx), - INTERPRETER_TRANSLATE(strex), - INTERPRETER_TRANSLATE(strexb), - INTERPRETER_TRANSLATE(swp), - INTERPRETER_TRANSLATE(swpb), - INTERPRETER_TRANSLATE(ssub16), - INTERPRETER_TRANSLATE(ssat16), - INTERPRETER_TRANSLATE(shsubaddx), - INTERPRETER_TRANSLATE(qsubaddx), - INTERPRETER_TRANSLATE(shaddsubx), - INTERPRETER_TRANSLATE(shadd8), - INTERPRETER_TRANSLATE(shadd16), - INTERPRETER_TRANSLATE(sel), - INTERPRETER_TRANSLATE(saddsubx), - INTERPRETER_TRANSLATE(sadd8), - INTERPRETER_TRANSLATE(sadd16), - INTERPRETER_TRANSLATE(shsub16), - INTERPRETER_TRANSLATE(umaal), - INTERPRETER_TRANSLATE(uxtab16), - INTERPRETER_TRANSLATE(usubaddx), - INTERPRETER_TRANSLATE(usub8), - INTERPRETER_TRANSLATE(usub16), - INTERPRETER_TRANSLATE(usat16), - INTERPRETER_TRANSLATE(usada8), - INTERPRETER_TRANSLATE(uqsubaddx), - INTERPRETER_TRANSLATE(uqsub8), - INTERPRETER_TRANSLATE(uqsub16), - INTERPRETER_TRANSLATE(uqaddsubx), - INTERPRETER_TRANSLATE(uqadd8), - INTERPRETER_TRANSLATE(uqadd16), - INTERPRETER_TRANSLATE(sxtab), - INTERPRETER_TRANSLATE(uhsubaddx), - INTERPRETER_TRANSLATE(uhsub8), - INTERPRETER_TRANSLATE(uhsub16), - INTERPRETER_TRANSLATE(uhaddsubx), - INTERPRETER_TRANSLATE(uhadd8), - INTERPRETER_TRANSLATE(uhadd16), - INTERPRETER_TRANSLATE(uaddsubx), - INTERPRETER_TRANSLATE(uadd8), - INTERPRETER_TRANSLATE(uadd16), - INTERPRETER_TRANSLATE(sxtah), - INTERPRETER_TRANSLATE(sxtab16), - INTERPRETER_TRANSLATE(qadd8), - INTERPRETER_TRANSLATE(bxj), - INTERPRETER_TRANSLATE(clz), - INTERPRETER_TRANSLATE(uxtah), - INTERPRETER_TRANSLATE(bx), - INTERPRETER_TRANSLATE(rev), - INTERPRETER_TRANSLATE(blx), - INTERPRETER_TRANSLATE(revsh), - INTERPRETER_TRANSLATE(qadd), - INTERPRETER_TRANSLATE(qadd16), - INTERPRETER_TRANSLATE(qaddsubx), - INTERPRETER_TRANSLATE(ldrex), - INTERPRETER_TRANSLATE(qdadd), - INTERPRETER_TRANSLATE(qdsub), - INTERPRETER_TRANSLATE(qsub), - INTERPRETER_TRANSLATE(ldrexb), - INTERPRETER_TRANSLATE(qsub8), - INTERPRETER_TRANSLATE(qsub16), - INTERPRETER_TRANSLATE(smuad), - INTERPRETER_TRANSLATE(smmul), - INTERPRETER_TRANSLATE(smusd), - INTERPRETER_TRANSLATE(smlsd), - INTERPRETER_TRANSLATE(smlsld), - INTERPRETER_TRANSLATE(smmla), - INTERPRETER_TRANSLATE(smmls), - INTERPRETER_TRANSLATE(smlald), - INTERPRETER_TRANSLATE(smlad), - INTERPRETER_TRANSLATE(smlaw), - INTERPRETER_TRANSLATE(smulw), - INTERPRETER_TRANSLATE(pkhtb), - INTERPRETER_TRANSLATE(pkhbt), - INTERPRETER_TRANSLATE(smul), - INTERPRETER_TRANSLATE(smlalxy), - INTERPRETER_TRANSLATE(smla), - INTERPRETER_TRANSLATE(mcrr), - INTERPRETER_TRANSLATE(mrrc), - INTERPRETER_TRANSLATE(cmp), - INTERPRETER_TRANSLATE(tst), - INTERPRETER_TRANSLATE(teq), - INTERPRETER_TRANSLATE(cmn), - INTERPRETER_TRANSLATE(smull), - INTERPRETER_TRANSLATE(umull), - INTERPRETER_TRANSLATE(umlal), - INTERPRETER_TRANSLATE(smlal), - INTERPRETER_TRANSLATE(mul), - INTERPRETER_TRANSLATE(mla), - INTERPRETER_TRANSLATE(ssat), - INTERPRETER_TRANSLATE(usat), - INTERPRETER_TRANSLATE(mrs), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(and), - INTERPRETER_TRANSLATE(bic), - INTERPRETER_TRANSLATE(ldm), - INTERPRETER_TRANSLATE(eor), - INTERPRETER_TRANSLATE(add), - INTERPRETER_TRANSLATE(rsb), - INTERPRETER_TRANSLATE(rsc), - INTERPRETER_TRANSLATE(sbc), - INTERPRETER_TRANSLATE(adc), - INTERPRETER_TRANSLATE(sub), - INTERPRETER_TRANSLATE(orr), - INTERPRETER_TRANSLATE(mvn), - INTERPRETER_TRANSLATE(mov), - INTERPRETER_TRANSLATE(stm), - INTERPRETER_TRANSLATE(ldm), - INTERPRETER_TRANSLATE(ldrsh), - INTERPRETER_TRANSLATE(stm), - INTERPRETER_TRANSLATE(ldm), - INTERPRETER_TRANSLATE(ldrsb), - INTERPRETER_TRANSLATE(strd), - INTERPRETER_TRANSLATE(ldrh), - INTERPRETER_TRANSLATE(strh), - INTERPRETER_TRANSLATE(ldrd), - INTERPRETER_TRANSLATE(strt), - INTERPRETER_TRANSLATE(strbt), - INTERPRETER_TRANSLATE(ldrbt), - INTERPRETER_TRANSLATE(ldrt), - INTERPRETER_TRANSLATE(mrc), - INTERPRETER_TRANSLATE(mcr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(ldrb), - INTERPRETER_TRANSLATE(strb), - INTERPRETER_TRANSLATE(ldr), - INTERPRETER_TRANSLATE(ldrcond), - INTERPRETER_TRANSLATE(str), - INTERPRETER_TRANSLATE(cdp), - INTERPRETER_TRANSLATE(stc), - INTERPRETER_TRANSLATE(ldc), - INTERPRETER_TRANSLATE(ldrexd), - INTERPRETER_TRANSLATE(strexd), - INTERPRETER_TRANSLATE(ldrexh), - INTERPRETER_TRANSLATE(strexh), - INTERPRETER_TRANSLATE(nop), - INTERPRETER_TRANSLATE(yield), - INTERPRETER_TRANSLATE(wfe), - INTERPRETER_TRANSLATE(wfi), - INTERPRETER_TRANSLATE(sev), - INTERPRETER_TRANSLATE(swi), - INTERPRETER_TRANSLATE(bbl), - - // All the thumb instructions should be placed the end of table - INTERPRETER_TRANSLATE(b_2_thumb), - INTERPRETER_TRANSLATE(b_cond_thumb), - INTERPRETER_TRANSLATE(bl_1_thumb), - INTERPRETER_TRANSLATE(bl_2_thumb), - INTERPRETER_TRANSLATE(blx_1_thumb) -}; - enum { FETCH_SUCCESS, FETCH_FAILURE @@ -3413,7 +742,7 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); if (ret == ThumbDecodeStatus::BRANCH) { int inst_index; - int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); + int table_length = arm_instruction_trans_len; u32 tinstr = GetThumbInstruction(inst, addr); switch ((tinstr & 0xF800) >> 11) { @@ -3499,14 +828,14 @@ static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) // Go on next, until terminal instruction // Save start addr of basicblock in CreamCache ARM_INST_PTR inst_base = nullptr; - int ret = NON_BRANCH; + TransExtData ret = TransExtData::NON_BRANCH; int size = 0; // instruction size of basic block - bb_start = top; + bb_start = trans_cache_buf_top; u32 phys_addr = addr; u32 pc_start = cpu->Reg[15]; - while (ret == NON_BRANCH) { + while (ret == TransExtData::NON_BRANCH) { unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base); size++; @@ -3514,7 +843,7 @@ static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) phys_addr += inst_size; if ((phys_addr & 0xfff) == 0) { - inst_base->br = END_OF_PAGE; + inst_base->br = TransExtData::END_OF_PAGE; } ret = inst_base->br; }; @@ -3528,15 +857,15 @@ static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) MICROPROFILE_SCOPE(DynCom_Decode); ARM_INST_PTR inst_base = nullptr; - bb_start = top; + bb_start = trans_cache_buf_top; u32 phys_addr = addr; u32 pc_start = cpu->Reg[15]; InterpreterTranslateInstruction(cpu, phys_addr, inst_base); - if (inst_base->br == NON_BRANCH) { - inst_base->br = SINGLE_STEP; + if (inst_base->br == TransExtData::NON_BRANCH) { + inst_base->br = TransExtData::SINGLE_STEP; } cpu->instruction_cache[pc_start] = bb_start; @@ -3581,8 +910,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24) #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand) - #define FETCH_INST if (inst_base->br != NON_BRANCH) goto DISPATCH; \ - inst_base = (arm_inst *)&inst_buf[ptr] + #define FETCH_INST if (inst_base->br != TransExtData::NON_BRANCH) goto DISPATCH; \ + inst_base = (arm_inst *)&trans_cache_buf[ptr] #define INC_PC(l) ptr += sizeof(arm_inst) + l #define INC_PC_STUB ptr += sizeof(arm_inst) @@ -3905,7 +1234,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); } - inst_base = (arm_inst *)&inst_buf[ptr]; + inst_base = (arm_inst *)&trans_cache_buf[ptr]; GOTO_NEXT_INST; } ADC_INST: diff --git a/src/core/arm/dyncom/arm_dyncom_trans.cpp b/src/core/arm/dyncom/arm_dyncom_trans.cpp new file mode 100644 index 000000000..00b42c246 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp @@ -0,0 +1,2178 @@ +#include <cstdlib> + +#include "common/assert.h" +#include "common/common_types.h" + +#include "core/arm/dyncom/arm_dyncom_interpreter.h" +#include "core/arm/dyncom/arm_dyncom_trans.h" +#include "core/arm/skyeye_common/armstate.h" +#include "core/arm/skyeye_common/armsupp.h" +#include "core/arm/skyeye_common/vfp/vfp.h" + +char trans_cache_buf[TRANS_CACHE_SIZE]; +size_t trans_cache_buf_top = 0; + +static void* AllocBuffer(size_t size) { + size_t start = trans_cache_buf_top; + trans_cache_buf_top += size; + ASSERT_MSG(trans_cache_buf_top <= TRANS_CACHE_SIZE, "Translation cache is full!"); + return static_cast<void*>(&trans_cache_buf[start]); +} + +#define glue(x, y) x ## y +#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) + +shtop_fp_t GetShifterOp(unsigned int inst); +get_addr_fp_t GetAddressingOp(unsigned int inst); +get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst); + +static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); + adc_inst *inst_cream = (adc_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); + add_inst *inst_cream = (add_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); + and_inst *inst_cream = (and_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) +{ + #define POSBRANCH ((inst & 0x7fffff) << 2) + #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2) + + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); + bbl_inst *inst_cream = (bbl_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::DIRECT_BRANCH; + + if (BIT(inst, 24)) + inst_base->br = TransExtData::CALL; + + inst_cream->L = BIT(inst, 24); + inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); + bic_inst *inst_cream = (bic_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst)); + bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); + blx_inst *inst_cream = (blx_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::INDIRECT_BRANCH; + + inst_cream->inst = inst; + if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { + inst_cream->val.Rm = BITS(inst, 0, 3); + } else { + inst_cream->val.signed_immed_24 = BITS(inst, 0, 23); + } + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); + bx_inst *inst_cream = (bx_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::INDIRECT_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(bx)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); + cdp_inst *inst_cream = (cdp_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->CRm = BITS(inst, 0, 3); + inst_cream->CRd = BITS(inst, 12, 15); + inst_cream->CRn = BITS(inst, 16, 19); + inst_cream->cp_num = BITS(inst, 8, 11); + inst_cream->opcode_2 = BITS(inst, 5, 7); + inst_cream->opcode_1 = BITS(inst, 20, 23); + inst_cream->inst = inst; + + LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst)); + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); + clz_inst *inst_cream = (clz_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); + cmn_inst *inst_cream = (cmn_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); + cmp_inst *inst_cream = (cmp_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); + cps_inst *inst_cream = (cps_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->imod0 = BIT(inst, 18); + inst_cream->imod1 = BIT(inst, 19); + inst_cream->mmod = BIT(inst, 17); + inst_cream->A = BIT(inst, 8); + inst_cream->I = BIT(inst, 7); + inst_cream->F = BIT(inst, 6); + inst_cream->mode = BITS(inst, 0, 4); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); + mov_inst *inst_cream = (mov_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) { + inst_base->br = TransExtData::INDIRECT_BRANCH; + } + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); + eor_inst *inst_cream = (eor_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst)); + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + if (BIT(inst, 15)) { + inst_base->br = TransExtData::INDIRECT_BRANCH; + } + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); + sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->rotate = BITS(inst, 10, 11); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + if (BITS(inst, 12, 15) == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + if (BITS(inst, 12, 15) == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); + uxth_inst *inst_cream = (uxth_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); + uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) +{ + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH : TransExtData::NON_BRANCH; // Branch if dest is R15 + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(ldrex)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(ldrex)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(ldrex)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) +{ + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = TransExtData::INDIRECT_BRANCH; + } + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); + mcr_inst *inst_cream = (mcr_inst *)inst_base->component; + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->crn = BITS(inst, 16, 19); + inst_cream->crm = BITS(inst, 0, 3); + inst_cream->opcode_1 = BITS(inst, 21, 23); + inst_cream->opcode_2 = BITS(inst, 5, 7); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->cp_num = BITS(inst, 8, 11); + inst_cream->inst = inst; + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); + mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->crm = BITS(inst, 0, 3); + inst_cream->opcode_1 = BITS(inst, 4, 7); + inst_cream->cp_num = BITS(inst, 8, 11); + inst_cream->rt = BITS(inst, 12, 15); + inst_cream->rt2 = BITS(inst, 16, 19); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); + mla_inst *inst_cream = (mla_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 12, 15); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); + mov_inst *inst_cream = (mov_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) { + inst_base->br = TransExtData::INDIRECT_BRANCH; + } + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); + mrc_inst *inst_cream = (mrc_inst *)inst_base->component; + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->crn = BITS(inst, 16, 19); + inst_cream->crm = BITS(inst, 0, 3); + inst_cream->opcode_1 = BITS(inst, 21, 23); + inst_cream->opcode_2 = BITS(inst, 5, 7); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->cp_num = BITS(inst, 8, 11); + inst_cream->inst = inst; + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(mcrr)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); + mrs_inst *inst_cream = (mrs_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->R = BIT(inst, 22); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); + msr_inst *inst_cream = (msr_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->field_mask = BITS(inst, 16, 19); + inst_cream->R = BIT(inst, 22); + inst_cream->inst = inst; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); + mul_inst *inst_cream = (mul_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->S = BIT(inst, 20); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->Rd = BITS(inst, 16, 19); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); + mvn_inst *inst_cream = (mvn_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) { + inst_base->br = TransExtData::INDIRECT_BRANCH; + } + return inst_base; + +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); + orr_inst *inst_cream = (orr_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} + +// NOP introduced in ARMv6K. +static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst)); + pkh_inst *inst_cream = (pkh_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->imm = BITS(inst, 7, 11); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(pkhbt)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->op1 = BITS(inst, 21, 22); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd8)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); + rev_inst* const inst_cream = (rev_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 22); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(rev)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(rev)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; + + inst_base->cond = AL; + inst_base->idx = index; + inst_base->br = TransExtData::INDIRECT_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); + rsb_inst *inst_cream = (rsb_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); + rsc_inst *inst_cream = (rsc_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(sadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(sadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(sadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(sadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(sadd8)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); + sbc_inst *inst_cream = (sbc_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 22); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); + setend_inst* const inst_cream = (setend_inst*)inst_base->component; + + inst_base->cond = AL; + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->set_bigend = BIT(inst, 9); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(shadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(shadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(shadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(shadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(shadd8)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); + smla_inst *inst_cream = (smla_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->x = BIT(inst, 5); + inst_cream->y = BIT(inst, 6); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->Rn = BITS(inst, 12, 15); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); + smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->m = BIT(inst, 5); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->Ra = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 22); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(smlad)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(smlad)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(smlad)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); + umlal_inst *inst_cream = (umlal_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->S = BIT(inst, 20); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->RdHi = BITS(inst, 16, 19); + inst_cream->RdLo = BITS(inst, 12, 15); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst)); + smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->x = BIT(inst, 5); + inst_cream->y = BIT(inst, 6); + inst_cream->RdLo = BITS(inst, 12, 15); + inst_cream->RdHi = BITS(inst, 16, 19); + inst_cream->Rn = BITS(inst, 0, 4); + inst_cream->Rm = BITS(inst, 8, 11); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); + smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Ra = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->m = BIT(inst, 6); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); + smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->RdLo = BITS(inst, 12, 15); + inst_cream->RdHi = BITS(inst, 16, 19); + inst_cream->swap = BIT(inst, 5); + inst_cream->op1 = BITS(inst, 20, 22); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(smlald)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); + smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->m = BIT(inst, 5); + inst_cream->Ra = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->op1 = BITS(inst, 20, 22); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(smmla)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(smmla)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); + smul_inst *inst_cream = (smul_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->Rm = BITS(inst, 0, 3); + + inst_cream->x = BIT(inst, 5); + inst_cream->y = BIT(inst, 6); + + return inst_base; + +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); + umull_inst *inst_cream = (umull_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->S = BIT(inst, 20); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->RdHi = BITS(inst, 16, 19); + inst_cream->RdLo = BITS(inst, 12, 15); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); + smlad_inst *inst_cream = (smlad_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->m = BIT(inst, 6); + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 16, 19); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; + + inst_base->cond = AL; + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); + ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->imm5 = BITS(inst, 7, 11); + inst_cream->sat_imm = BITS(inst, 16, 20); + inst_cream->shift_type = BIT(inst, 6); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); + ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->sat_imm = BITS(inst, 16, 19); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst)); + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); + sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->rotate = BITS(inst, 10, 11); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); + uxth_inst *inst_cream = (uxth_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); + uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) +{ + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(strex)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(strex)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(strex)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) +{ + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); + sub_inst *inst_cream = (sub_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + if (inst_cream->Rd == 15) + inst_base->br = TransExtData::INDIRECT_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); + swi_inst *inst_cream = (swi_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->num = BITS(inst, 0, 23); + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); + swp_inst *inst_cream = (swp_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); + swp_inst *inst_cream = (swp_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); + sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); + sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(sxtab16)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); + sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); + teq_inst *inst_cream = (teq_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); + tst_inst *inst_cream = (tst_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->I = BIT(inst, 25); + inst_cream->S = BIT(inst, 20); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = GetShifterOp(inst); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uadd8)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uhadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uhadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uhadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uhadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uhadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); + umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->RdLo = BITS(inst, 12, 15); + inst_cream->RdHi = BITS(inst, 16, 19); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); + umlal_inst *inst_cream = (umlal_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->S = BIT(inst, 20); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->RdHi = BITS(inst, 16, 19); + inst_cream->RdLo = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); + umull_inst *inst_cream = (umull_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->S = BIT(inst, 20); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rs = BITS(inst, 8, 11); + inst_cream->RdHi = BITS(inst, 16, 19); + inst_cream->RdLo = BITS(inst, 12, 15); + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); + b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; + + inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); + + inst_base->idx = index; + inst_base->br = TransExtData::DIRECT_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); + b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component; + + inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); + inst_cream->cond = ((tinst >> 8) & 0xf); + inst_base->idx = index; + inst_base->br = TransExtData::DIRECT_BRANCH; + + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); + bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; + + inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); + + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); + bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component; + + inst_cream->imm = (tinst & 0x07FF) << 1; + + inst_base->idx = index; + inst_base->br = TransExtData::DIRECT_BRANCH; + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); + blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; + + inst_cream->imm = (tinst & 0x07FF) << 1; + inst_cream->instr = tinst; + + inst_base->idx = index; + inst_base->br = TransExtData::DIRECT_BRANCH; + return inst_base; +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uqadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uqadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uqadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uqadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uqadd8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->op1 = BITS(inst, 20, 24); + inst_cream->op2 = BITS(inst, 5, 7); + inst_cream->Rd = BITS(inst, 16, 19); + inst_cream->Rm = BITS(inst, 8, 11); + inst_cream->Rn = BITS(inst, 0, 3); + inst_cream->Ra = BITS(inst, 12, 15); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(usada8)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(ssat)(inst, index); +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(ssat16)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); + uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(uxtab16)(inst, index); +} + +static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} +static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = TransExtData::NON_BRANCH; + + return inst_base; +} + +// Floating point VFPv3 instructions +#define VFP_INTERPRETER_TRANS +#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" +#undef VFP_INTERPRETER_TRANS + +const transop_fp_t arm_instruction_trans[] = { + INTERPRETER_TRANSLATE(vmla), + INTERPRETER_TRANSLATE(vmls), + INTERPRETER_TRANSLATE(vnmla), + INTERPRETER_TRANSLATE(vnmls), + INTERPRETER_TRANSLATE(vnmul), + INTERPRETER_TRANSLATE(vmul), + INTERPRETER_TRANSLATE(vadd), + INTERPRETER_TRANSLATE(vsub), + INTERPRETER_TRANSLATE(vdiv), + INTERPRETER_TRANSLATE(vmovi), + INTERPRETER_TRANSLATE(vmovr), + INTERPRETER_TRANSLATE(vabs), + INTERPRETER_TRANSLATE(vneg), + INTERPRETER_TRANSLATE(vsqrt), + INTERPRETER_TRANSLATE(vcmp), + INTERPRETER_TRANSLATE(vcmp2), + INTERPRETER_TRANSLATE(vcvtbds), + INTERPRETER_TRANSLATE(vcvtbff), + INTERPRETER_TRANSLATE(vcvtbfi), + INTERPRETER_TRANSLATE(vmovbrs), + INTERPRETER_TRANSLATE(vmsr), + INTERPRETER_TRANSLATE(vmovbrc), + INTERPRETER_TRANSLATE(vmrs), + INTERPRETER_TRANSLATE(vmovbcr), + INTERPRETER_TRANSLATE(vmovbrrss), + INTERPRETER_TRANSLATE(vmovbrrd), + INTERPRETER_TRANSLATE(vstr), + INTERPRETER_TRANSLATE(vpush), + INTERPRETER_TRANSLATE(vstm), + INTERPRETER_TRANSLATE(vpop), + INTERPRETER_TRANSLATE(vldr), + INTERPRETER_TRANSLATE(vldm), + + INTERPRETER_TRANSLATE(srs), + INTERPRETER_TRANSLATE(rfe), + INTERPRETER_TRANSLATE(bkpt), + INTERPRETER_TRANSLATE(blx), + INTERPRETER_TRANSLATE(cps), + INTERPRETER_TRANSLATE(pld), + INTERPRETER_TRANSLATE(setend), + INTERPRETER_TRANSLATE(clrex), + INTERPRETER_TRANSLATE(rev16), + INTERPRETER_TRANSLATE(usad8), + INTERPRETER_TRANSLATE(sxtb), + INTERPRETER_TRANSLATE(uxtb), + INTERPRETER_TRANSLATE(sxth), + INTERPRETER_TRANSLATE(sxtb16), + INTERPRETER_TRANSLATE(uxth), + INTERPRETER_TRANSLATE(uxtb16), + INTERPRETER_TRANSLATE(cpy), + INTERPRETER_TRANSLATE(uxtab), + INTERPRETER_TRANSLATE(ssub8), + INTERPRETER_TRANSLATE(shsub8), + INTERPRETER_TRANSLATE(ssubaddx), + INTERPRETER_TRANSLATE(strex), + INTERPRETER_TRANSLATE(strexb), + INTERPRETER_TRANSLATE(swp), + INTERPRETER_TRANSLATE(swpb), + INTERPRETER_TRANSLATE(ssub16), + INTERPRETER_TRANSLATE(ssat16), + INTERPRETER_TRANSLATE(shsubaddx), + INTERPRETER_TRANSLATE(qsubaddx), + INTERPRETER_TRANSLATE(shaddsubx), + INTERPRETER_TRANSLATE(shadd8), + INTERPRETER_TRANSLATE(shadd16), + INTERPRETER_TRANSLATE(sel), + INTERPRETER_TRANSLATE(saddsubx), + INTERPRETER_TRANSLATE(sadd8), + INTERPRETER_TRANSLATE(sadd16), + INTERPRETER_TRANSLATE(shsub16), + INTERPRETER_TRANSLATE(umaal), + INTERPRETER_TRANSLATE(uxtab16), + INTERPRETER_TRANSLATE(usubaddx), + INTERPRETER_TRANSLATE(usub8), + INTERPRETER_TRANSLATE(usub16), + INTERPRETER_TRANSLATE(usat16), + INTERPRETER_TRANSLATE(usada8), + INTERPRETER_TRANSLATE(uqsubaddx), + INTERPRETER_TRANSLATE(uqsub8), + INTERPRETER_TRANSLATE(uqsub16), + INTERPRETER_TRANSLATE(uqaddsubx), + INTERPRETER_TRANSLATE(uqadd8), + INTERPRETER_TRANSLATE(uqadd16), + INTERPRETER_TRANSLATE(sxtab), + INTERPRETER_TRANSLATE(uhsubaddx), + INTERPRETER_TRANSLATE(uhsub8), + INTERPRETER_TRANSLATE(uhsub16), + INTERPRETER_TRANSLATE(uhaddsubx), + INTERPRETER_TRANSLATE(uhadd8), + INTERPRETER_TRANSLATE(uhadd16), + INTERPRETER_TRANSLATE(uaddsubx), + INTERPRETER_TRANSLATE(uadd8), + INTERPRETER_TRANSLATE(uadd16), + INTERPRETER_TRANSLATE(sxtah), + INTERPRETER_TRANSLATE(sxtab16), + INTERPRETER_TRANSLATE(qadd8), + INTERPRETER_TRANSLATE(bxj), + INTERPRETER_TRANSLATE(clz), + INTERPRETER_TRANSLATE(uxtah), + INTERPRETER_TRANSLATE(bx), + INTERPRETER_TRANSLATE(rev), + INTERPRETER_TRANSLATE(blx), + INTERPRETER_TRANSLATE(revsh), + INTERPRETER_TRANSLATE(qadd), + INTERPRETER_TRANSLATE(qadd16), + INTERPRETER_TRANSLATE(qaddsubx), + INTERPRETER_TRANSLATE(ldrex), + INTERPRETER_TRANSLATE(qdadd), + INTERPRETER_TRANSLATE(qdsub), + INTERPRETER_TRANSLATE(qsub), + INTERPRETER_TRANSLATE(ldrexb), + INTERPRETER_TRANSLATE(qsub8), + INTERPRETER_TRANSLATE(qsub16), + INTERPRETER_TRANSLATE(smuad), + INTERPRETER_TRANSLATE(smmul), + INTERPRETER_TRANSLATE(smusd), + INTERPRETER_TRANSLATE(smlsd), + INTERPRETER_TRANSLATE(smlsld), + INTERPRETER_TRANSLATE(smmla), + INTERPRETER_TRANSLATE(smmls), + INTERPRETER_TRANSLATE(smlald), + INTERPRETER_TRANSLATE(smlad), + INTERPRETER_TRANSLATE(smlaw), + INTERPRETER_TRANSLATE(smulw), + INTERPRETER_TRANSLATE(pkhtb), + INTERPRETER_TRANSLATE(pkhbt), + INTERPRETER_TRANSLATE(smul), + INTERPRETER_TRANSLATE(smlalxy), + INTERPRETER_TRANSLATE(smla), + INTERPRETER_TRANSLATE(mcrr), + INTERPRETER_TRANSLATE(mrrc), + INTERPRETER_TRANSLATE(cmp), + INTERPRETER_TRANSLATE(tst), + INTERPRETER_TRANSLATE(teq), + INTERPRETER_TRANSLATE(cmn), + INTERPRETER_TRANSLATE(smull), + INTERPRETER_TRANSLATE(umull), + INTERPRETER_TRANSLATE(umlal), + INTERPRETER_TRANSLATE(smlal), + INTERPRETER_TRANSLATE(mul), + INTERPRETER_TRANSLATE(mla), + INTERPRETER_TRANSLATE(ssat), + INTERPRETER_TRANSLATE(usat), + INTERPRETER_TRANSLATE(mrs), + INTERPRETER_TRANSLATE(msr), + INTERPRETER_TRANSLATE(and), + INTERPRETER_TRANSLATE(bic), + INTERPRETER_TRANSLATE(ldm), + INTERPRETER_TRANSLATE(eor), + INTERPRETER_TRANSLATE(add), + INTERPRETER_TRANSLATE(rsb), + INTERPRETER_TRANSLATE(rsc), + INTERPRETER_TRANSLATE(sbc), + INTERPRETER_TRANSLATE(adc), + INTERPRETER_TRANSLATE(sub), + INTERPRETER_TRANSLATE(orr), + INTERPRETER_TRANSLATE(mvn), + INTERPRETER_TRANSLATE(mov), + INTERPRETER_TRANSLATE(stm), + INTERPRETER_TRANSLATE(ldm), + INTERPRETER_TRANSLATE(ldrsh), + INTERPRETER_TRANSLATE(stm), + INTERPRETER_TRANSLATE(ldm), + INTERPRETER_TRANSLATE(ldrsb), + INTERPRETER_TRANSLATE(strd), + INTERPRETER_TRANSLATE(ldrh), + INTERPRETER_TRANSLATE(strh), + INTERPRETER_TRANSLATE(ldrd), + INTERPRETER_TRANSLATE(strt), + INTERPRETER_TRANSLATE(strbt), + INTERPRETER_TRANSLATE(ldrbt), + INTERPRETER_TRANSLATE(ldrt), + INTERPRETER_TRANSLATE(mrc), + INTERPRETER_TRANSLATE(mcr), + INTERPRETER_TRANSLATE(msr), + INTERPRETER_TRANSLATE(msr), + INTERPRETER_TRANSLATE(msr), + INTERPRETER_TRANSLATE(msr), + INTERPRETER_TRANSLATE(msr), + INTERPRETER_TRANSLATE(ldrb), + INTERPRETER_TRANSLATE(strb), + INTERPRETER_TRANSLATE(ldr), + INTERPRETER_TRANSLATE(ldrcond), + INTERPRETER_TRANSLATE(str), + INTERPRETER_TRANSLATE(cdp), + INTERPRETER_TRANSLATE(stc), + INTERPRETER_TRANSLATE(ldc), + INTERPRETER_TRANSLATE(ldrexd), + INTERPRETER_TRANSLATE(strexd), + INTERPRETER_TRANSLATE(ldrexh), + INTERPRETER_TRANSLATE(strexh), + INTERPRETER_TRANSLATE(nop), + INTERPRETER_TRANSLATE(yield), + INTERPRETER_TRANSLATE(wfe), + INTERPRETER_TRANSLATE(wfi), + INTERPRETER_TRANSLATE(sev), + INTERPRETER_TRANSLATE(swi), + INTERPRETER_TRANSLATE(bbl), + + // All the thumb instructions should be placed the end of table + INTERPRETER_TRANSLATE(b_2_thumb), + INTERPRETER_TRANSLATE(b_cond_thumb), + INTERPRETER_TRANSLATE(bl_1_thumb), + INTERPRETER_TRANSLATE(bl_2_thumb), + INTERPRETER_TRANSLATE(blx_1_thumb) +}; + +const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); diff --git a/src/core/arm/dyncom/arm_dyncom_trans.h b/src/core/arm/dyncom/arm_dyncom_trans.h new file mode 100644 index 000000000..7af71f4e3 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_trans.h @@ -0,0 +1,493 @@ +struct ARMul_State; +typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); + +enum class TransExtData { + COND = (1 << 0), + NON_BRANCH = (1 << 1), + DIRECT_BRANCH = (1 << 2), + INDIRECT_BRANCH = (1 << 3), + CALL = (1 << 4), + RET = (1 << 5), + END_OF_PAGE = (1 << 6), + THUMB = (1 << 7), + SINGLE_STEP = (1 << 8) +}; + +struct arm_inst { + unsigned int idx; + unsigned int cond; + TransExtData br; + char component[0]; +}; + +struct generic_arm_inst { + u32 Ra; + u32 Rm; + u32 Rn; + u32 Rd; + u8 op1; + u8 op2; +}; + +struct adc_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct add_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct orr_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct and_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct eor_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct bbl_inst { + unsigned int L; + int signed_immed_24; + unsigned int next_addr; + unsigned int jmp_addr; +}; + +struct bx_inst { + unsigned int Rm; +}; + +struct blx_inst { + union { + s32 signed_immed_24; + u32 Rm; + } val; + unsigned int inst; +}; + +struct clz_inst { + unsigned int Rm; + unsigned int Rd; +}; + +struct cps_inst { + unsigned int imod0; + unsigned int imod1; + unsigned int mmod; + unsigned int A, I, F; + unsigned int mode; +}; + +struct clrex_inst { +}; + +struct cpy_inst { + unsigned int Rm; + unsigned int Rd; +}; + +struct bic_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct sub_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct tst_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct cmn_inst { + unsigned int I; + unsigned int Rn; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct teq_inst { + unsigned int I; + unsigned int Rn; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct stm_inst { + unsigned int inst; +}; + +struct bkpt_inst { + u32 imm; +}; + +struct stc_inst { +}; + +struct ldc_inst { +}; + +struct swi_inst { + unsigned int num; +}; + +struct cmp_inst { + unsigned int I; + unsigned int Rn; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct mov_inst { + unsigned int I; + unsigned int S; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct mvn_inst { + unsigned int I; + unsigned int S; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct rev_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int op1; + unsigned int op2; +}; + +struct rsb_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct rsc_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct sbc_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +}; + +struct mul_inst { + unsigned int S; + unsigned int Rd; + unsigned int Rs; + unsigned int Rm; +}; + +struct smul_inst { + unsigned int Rd; + unsigned int Rs; + unsigned int Rm; + unsigned int x; + unsigned int y; +}; + +struct umull_inst { + unsigned int S; + unsigned int RdHi; + unsigned int RdLo; + unsigned int Rs; + unsigned int Rm; +}; + +struct smlad_inst { + unsigned int m; + unsigned int Rm; + unsigned int Rd; + unsigned int Ra; + unsigned int Rn; + unsigned int op1; + unsigned int op2; +}; + +struct smla_inst { + unsigned int x; + unsigned int y; + unsigned int Rm; + unsigned int Rd; + unsigned int Rs; + unsigned int Rn; +}; + +struct smlalxy_inst { + unsigned int x; + unsigned int y; + unsigned int RdLo; + unsigned int RdHi; + unsigned int Rm; + unsigned int Rn; +}; + +struct ssat_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int imm5; + unsigned int sat_imm; + unsigned int shift_type; +}; + +struct umaal_inst { + unsigned int Rn; + unsigned int Rm; + unsigned int RdHi; + unsigned int RdLo; +}; + +struct umlal_inst { + unsigned int S; + unsigned int Rm; + unsigned int Rs; + unsigned int RdHi; + unsigned int RdLo; +}; + +struct smlal_inst { + unsigned int S; + unsigned int Rm; + unsigned int Rs; + unsigned int RdHi; + unsigned int RdLo; +}; + +struct smlald_inst { + unsigned int RdLo; + unsigned int RdHi; + unsigned int Rm; + unsigned int Rn; + unsigned int swap; + unsigned int op1; + unsigned int op2; +}; + +struct mla_inst { + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int Rs; + unsigned int Rm; +}; + +struct mrc_inst { + unsigned int opcode_1; + unsigned int opcode_2; + unsigned int cp_num; + unsigned int crn; + unsigned int crm; + unsigned int Rd; + unsigned int inst; +}; + +struct mcr_inst { + unsigned int opcode_1; + unsigned int opcode_2; + unsigned int cp_num; + unsigned int crn; + unsigned int crm; + unsigned int Rd; + unsigned int inst; +}; + +struct mcrr_inst { + unsigned int opcode_1; + unsigned int cp_num; + unsigned int crm; + unsigned int rt; + unsigned int rt2; +}; + +struct mrs_inst { + unsigned int R; + unsigned int Rd; +}; + +struct msr_inst { + unsigned int field_mask; + unsigned int R; + unsigned int inst; +}; + +struct pld_inst { +}; + +struct sxtb_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +}; + +struct sxtab_inst { + unsigned int Rd; + unsigned int Rn; + unsigned int Rm; + unsigned rotate; +}; + +struct sxtah_inst { + unsigned int Rd; + unsigned int Rn; + unsigned int Rm; + unsigned int rotate; +}; + +struct sxth_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +}; + +struct uxtab_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int rotate; + unsigned int Rm; +}; + +struct uxtah_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int rotate; + unsigned int Rm; +}; + +struct uxth_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +}; + +struct cdp_inst { + unsigned int opcode_1; + unsigned int CRn; + unsigned int CRd; + unsigned int cp_num; + unsigned int opcode_2; + unsigned int CRm; + unsigned int inst; +}; + +struct uxtb_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +}; + +struct swp_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int Rm; +}; + +struct setend_inst { + unsigned int set_bigend; +}; + +struct b_2_thumb { + unsigned int imm; +}; +struct b_cond_thumb { + unsigned int imm; + unsigned int cond; +}; + +struct bl_1_thumb { + unsigned int imm; +}; +struct bl_2_thumb { + unsigned int imm; +}; +struct blx_1_thumb { + unsigned int imm; + unsigned int instr; +}; + +struct pkh_inst { + unsigned int Rm; + unsigned int Rn; + unsigned int Rd; + unsigned char imm; +}; + +// Floating point VFPv3 structures +#define VFP_INTERPRETER_STRUCT +#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" +#undef VFP_INTERPRETER_STRUCT + +typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr); + +struct ldst_inst { + unsigned int inst; + get_addr_fp_t get_addr; +}; + +typedef arm_inst* ARM_INST_PTR; +typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int); + +extern const transop_fp_t arm_instruction_trans[]; +extern const size_t arm_instruction_trans_len; + +#define TRANS_CACHE_SIZE (64 * 1024 * 2000) +extern char trans_cache_buf[TRANS_CACHE_SIZE]; +extern size_t trans_cache_buf_top; diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 4f9083515..1a98d0114 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp @@ -26,7 +26,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -75,7 +75,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -124,7 +124,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -174,7 +174,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -223,7 +223,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -272,7 +272,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -321,7 +321,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -370,7 +370,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -419,7 +419,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -470,7 +470,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); @@ -518,7 +518,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); @@ -560,7 +560,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -610,7 +610,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -659,7 +659,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -708,7 +708,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -757,7 +757,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -806,7 +806,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -857,7 +857,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -906,7 +906,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->dp_operation = BIT(inst, 8); inst_cream->instr = inst; @@ -962,7 +962,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->to_arm = BIT(inst, 20) == 1; inst_cream->t = BITS(inst, 12, 15); @@ -1006,7 +1006,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->reg = BITS(inst, 16, 19); inst_cream->Rt = BITS(inst, 12, 15); @@ -1069,7 +1069,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; inst_cream->t = BITS(inst, 12, 15); @@ -1115,7 +1115,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->reg = BITS(inst, 16, 19); inst_cream->Rt = BITS(inst, 12, 15); @@ -1200,7 +1200,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; inst_cream->t = BITS(inst, 12, 15); @@ -1253,7 +1253,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int inde inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->to_arm = BIT(inst, 20) == 1; inst_cream->t = BITS(inst, 12, 15); @@ -1301,7 +1301,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->to_arm = BIT(inst, 20) == 1; inst_cream->t = BITS(inst, 12, 15); @@ -1354,7 +1354,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->add = BIT(inst, 23); @@ -1420,7 +1420,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); @@ -1495,7 +1495,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->add = BIT(inst, 23); @@ -1580,7 +1580,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15)<<1)|BIT(inst, 22) : BITS(inst, 12, 15)|(BIT(inst, 22)<<4)); @@ -1653,7 +1653,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->add = BIT(inst, 23); @@ -1722,7 +1722,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) inst_base->cond = BITS(inst, 28, 31); inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->br = TransExtData::NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->add = BIT(inst, 23); diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 820b19e1a..28d403158 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -646,7 +646,7 @@ static void ReadMemory() { u8* data = Memory::GetPointer(addr); if (!data) { - return SendReply("E0"); + return SendReply("E00"); } MemToGdbHex(reply, data, len); diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index 90e134437..ccf35fa07 100644 --- a/src/core/hle/applets/applet.cpp +++ b/src/core/hle/applets/applet.cpp @@ -12,6 +12,7 @@ #include "core/core_timing.h" #include "core/hle/applets/applet.h" +#include "core/hle/applets/erreula.h" #include "core/hle/applets/mii_selector.h" #include "core/hle/applets/swkbd.h" #include "core/hle/result.h" @@ -52,6 +53,10 @@ ResultCode Applet::Create(Service::APT::AppletId id) { case Service::APT::AppletId::Ed2: applets[id] = std::make_shared<MiiSelector>(id); break; + case Service::APT::AppletId::Error: + case Service::APT::AppletId::Error2: + applets[id] = std::make_shared<ErrEula>(id); + break; default: LOG_ERROR(Service_APT, "Could not create applet %u", id); // TODO(Subv): Find the right error code diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp new file mode 100644 index 000000000..92a4b2323 --- /dev/null +++ b/src/core/hle/applets/erreula.cpp @@ -0,0 +1,72 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/string_util.h" + +#include "core/hle/applets/erreula.h" +#include "core/hle/service/apt/apt.h" + +namespace HLE { +namespace Applets { + +ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& parameter) { + if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) { + LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); + UNIMPLEMENTED(); + // TODO(Subv): Find the right error code + return ResultCode(-1); + } + + // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. + // Create the SharedMemory that will hold the framebuffer data + Service::APT::CaptureBufferInfo capture_info; + ASSERT(sizeof(capture_info) == parameter.buffer.size()); + + memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); + + // TODO: allocated memory never released + using Kernel::MemoryPermission; + // Allocate a heap block of the required size for this applet. + heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); + // Create a SharedMemory that directly points to this heap block. + framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), + MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, + "ErrEula Memory"); + + // Send the response message with the newly created SharedMemory + Service::APT::MessageParameter result; + result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); + result.buffer.clear(); + result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); + result.sender_id = static_cast<u32>(id); + result.object = framebuffer_memory; + + Service::APT::SendParameter(result); + return RESULT_SUCCESS; +} + +ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { + started = true; + + // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. + // TODO(Subv): Reverse the parameter format for the ErrEula applet + + // Let the application know that we're closing + Service::APT::MessageParameter message; + message.buffer.resize(parameter.buffer.size()); + std::fill(message.buffer.begin(), message.buffer.end(), 0); + message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); + message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); + message.sender_id = static_cast<u32>(id); + Service::APT::SendParameter(message); + + started = false; + return RESULT_SUCCESS; +} + +void ErrEula::Update() { +} + +} // namespace Applets +} // namespace HLE diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h new file mode 100644 index 000000000..9fe72ae07 --- /dev/null +++ b/src/core/hle/applets/erreula.h @@ -0,0 +1,31 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/applets/applet.h" +#include "core/hle/kernel/shared_memory.h" + +namespace HLE { +namespace Applets { + +class ErrEula final : public Applet { +public: + explicit ErrEula(Service::APT::AppletId id): Applet(id) { } + + ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; + ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; + void Update() override; + bool IsRunning() const override { return started; } + + /// This SharedMemory will be created when we receive the LibAppJustStarted message. + /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo + Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; +private: + /// Whether this applet is currently running instead of the host application or not. + bool started = false; +}; + +} // namespace Applets +} // namespace HLE diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index bf7f875b6..8839ce482 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -194,6 +194,16 @@ template<ResultCode func(Handle, u32)> void Wrap() { FuncReturn(func(PARAM(0), PARAM(1)).raw); } +template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() { + Handle param_1 = 0; + Handle param_2 = 0; + u32 retval = func(¶m_1, ¶m_2, reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)).raw; + // The first out parameter is moved into R2 and the second is moved into R1. + Core::g_app_core->SetReg(1, param_2); + Core::g_app_core->SetReg(2, param_1); + FuncReturn(retval); +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Function wrappers that return type u32 diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp new file mode 100644 index 000000000..444ce8d45 --- /dev/null +++ b/src/core/hle/kernel/client_port.cpp @@ -0,0 +1,16 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" + +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/server_port.h" + +namespace Kernel { + +ClientPort::ClientPort() {} +ClientPort::~ClientPort() {} + +} // namespace diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h new file mode 100644 index 000000000..480b6ddae --- /dev/null +++ b/src/core/hle/kernel/client_port.h @@ -0,0 +1,36 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <string> + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +class ServerPort; + +class ClientPort : public Object { +public: + friend class ServerPort; + std::string GetTypeName() const override { return "ClientPort"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::ClientPort; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. + u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have + u32 active_sessions; ///< Number of currently open sessions to this port + std::string name; ///< Name of client port (optional) + +protected: + ClientPort(); + ~ClientPort() override; +}; + +} // namespace diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 4d4276f7a..27ba3f912 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -35,7 +35,7 @@ enum KernelHandle : Handle { enum class HandleType : u32 { Unknown = 0, - Port = 1, + Session = 2, Event = 3, Mutex = 4, @@ -48,6 +48,8 @@ enum class HandleType : u32 { Timer = 11, ResourceLimit = 12, CodeSet = 13, + ClientPort = 14, + ServerPort = 15, }; enum { @@ -72,6 +74,7 @@ public: bool IsWaitable() const { switch (GetHandleType()) { case HandleType::Session: + case HandleType::ServerPort: case HandleType::Event: case HandleType::Mutex: case HandleType::Thread: @@ -80,13 +83,13 @@ public: return true; case HandleType::Unknown: - case HandleType::Port: case HandleType::SharedMemory: case HandleType::Redirection: case HandleType::Process: case HandleType::AddressArbiter: case HandleType::ResourceLimit: case HandleType::CodeSet: + case HandleType::ClientPort: return false; } } diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp new file mode 100644 index 000000000..fcc684a20 --- /dev/null +++ b/src/core/hle/kernel/server_port.cpp @@ -0,0 +1,41 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <tuple> + +#include "common/assert.h" + +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/server_port.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +ServerPort::ServerPort() {} +ServerPort::~ServerPort() {} + +bool ServerPort::ShouldWait() { + // If there are no pending sessions, we wait until a new one is added. + return pending_sessions.size() == 0; +} + +void ServerPort::Acquire() { + ASSERT_MSG(!ShouldWait(), "object unavailable!"); +} + +std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { + SharedPtr<ServerPort> server_port(new ServerPort); + SharedPtr<ClientPort> client_port(new ClientPort); + + server_port->name = name + "_Server"; + client_port->name = name + "_Client"; + client_port->server_port = server_port; + client_port->max_sessions = max_sessions; + client_port->active_sessions = 0; + + return std::make_tuple(std::move(server_port), std::move(client_port)); +} + +} // namespace diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h new file mode 100644 index 000000000..e9c972ce6 --- /dev/null +++ b/src/core/hle/kernel/server_port.h @@ -0,0 +1,46 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include <tuple> + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +class ClientPort; + +class ServerPort final : public WaitObject { +public: + /** + * Creates a pair of ServerPort and an associated ClientPort. + * @param max_sessions Maximum number of sessions to the port + * @param name Optional name of the ports + * @return The created port tuple + */ + static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); + + std::string GetTypeName() const override { return "ServerPort"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::ServerPort; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + std::string name; ///< Name of port (optional) + + std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port + + bool ShouldWait() override; + void Acquire() override; + +private: + ServerPort(); + ~ServerPort() override; +}; + +} // namespace diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 6ddaf970e..26b086f87 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -32,6 +32,10 @@ constexpr u32 CallingPidDesc() { return 0x20; } +constexpr u32 TransferHandleDesc() { + return 0x20; +} + constexpr u32 StaticBufferDesc(u32 size, unsigned int buffer_id) { return 0x2 | (size << 14) | ((buffer_id & 0xF) << 10); } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 3f6bec5fa..9dea995f4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -182,6 +182,48 @@ static void PriorityBoostStarvedThreads() { } /** + * Gets the registers for timeout parameter of the next WaitSynchronization call. + * @param thread a pointer to the thread that is ready to call WaitSynchronization + * @returns a tuple of two register pointers to low and high part of the timeout parameter + */ +static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* thread) { + bool thumb_mode = (thread->context.cpsr & TBIT) != 0; + u16 thumb_inst = Memory::Read16(thread->context.pc & 0xFFFFFFFE); + u32 inst = Memory::Read32(thread->context.pc & 0xFFFFFFFC) & 0x0FFFFFFF; + + if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { + // svc #0x24 (WaitSynchronization1) + return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); + } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { + // svc #0x25 (WaitSynchronizationN) + return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); + } + + UNREACHABLE(); +} + +/** + * Updates the WaitSynchronization timeout paramter according to the difference + * between ticks of the last WaitSynchronization call and the incoming one. + * @param timeout_low a pointer to the register for the low part of the timeout parameter + * @param timeout_high a pointer to the register for the high part of the timeout parameter + * @param last_tick tick of the last WaitSynchronization call + */ +static void UpdateTimeoutParameter(u32* timeout_low, u32* timeout_high, u64 last_tick) { + s64 timeout = ((s64)*timeout_high << 32) | *timeout_low; + + if (timeout != -1) { + timeout -= cyclesToUs(CoreTiming::GetTicks() - last_tick) * 1000; // in nanoseconds + + if (timeout < 0) + timeout = 0; + + *timeout_low = timeout & 0xFFFFFFFF; + *timeout_high = timeout >> 32; + } +} + +/** * Switches the CPU's active thread context to that of the specified thread * @param new_thread The thread to switch to */ @@ -219,6 +261,13 @@ static void SwitchContext(Thread* new_thread) { // SVC instruction is 2 bytes for THUMB, 4 bytes for ARM new_thread->context.pc -= thumb_mode ? 2 : 4; + + // Get the register for timeout parameter + u32* timeout_low, *timeout_high; + std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); + + // Update the timeout parameter + UpdateTimeoutParameter(timeout_low, timeout_high, new_thread->last_running_ticks); } // Clean up the thread's wait_objects, they'll be restored if needed during @@ -542,8 +591,12 @@ void Reschedule() { HLE::DoneRescheduling(); - // Don't bother switching to the same thread - if (next == cur) + // Don't bother switching to the same thread. + // But if the thread was waiting on objects, we still need to switch it + // to perform PC modification, change state to RUNNING, etc. + // This occurs in the case when an object the thread is waiting on immediately wakes up + // the current thread before Reschedule() is called. + if (next == cur && (next == nullptr || next->waitsynch_waited == false)) return; if (cur && next) { diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 57dedcb22..268a8dad2 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -20,6 +20,7 @@ enum class ErrorDescription : u32 { WrongPermission = 46, OS_InvalidBufferDescriptor = 48, WrongAddress = 53, + FS_ArchiveNotMounted = 101, FS_NotFound = 120, FS_AlreadyExists = 190, FS_InvalidOpenFlags = 230, @@ -135,15 +136,28 @@ enum class ErrorModule : u32 { MCU = 72, NS = 73, News = 74, - RO_1 = 75, + RO = 75, GD = 76, CardSPI = 77, EC = 78, - RO_2 = 79, - WebBrowser = 80, - Test = 81, - ENC = 82, - PIA = 83, + WebBrowser = 79, + Test = 80, + ENC = 81, + PIA = 82, + ACT = 83, + VCTL = 84, + OLV = 85, + NEIA = 86, + NPNS = 87, + + AVD = 90, + L2B = 91, + MVD = 92, + NFC = 93, + UART = 94, + SPM = 95, + QTM = 96, + NFP = 97, Application = 254, InvalidResult = 255 diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 76b3a3807..53cee4867 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -66,6 +66,8 @@ enum class AppletId : u32 { InstructionManual = 0x115, Notifications = 0x116, Miiverse = 0x117, + MiiversePost = 0x118, + AmiiboSettings = 0x119, SoftwareKeyboard1 = 0x201, Ed1 = 0x202, PnoteApp = 0x204, @@ -78,6 +80,12 @@ enum class AppletId : u32 { AnyLibraryApplet = 0x400, SoftwareKeyboard2 = 0x401, Ed2 = 0x402, + PnoteApp2 = 0x404, + SnoteApp2 = 0x405, + Error2 = 0x406, + Mint2 = 0x407, + Extrapad2 = 0x408, + Memolib2 = 0x409, }; enum class StartupArgumentType : u32 { diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index e067db645..a5dc47322 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -40,6 +40,20 @@ struct SaveFileConfig { }; static_assert(sizeof(SaveFileConfig) == 0x455C, "SaveFileConfig header must be exactly 0x455C bytes"); +enum ConfigBlockID { + StereoCameraSettingsBlockID = 0x00050005, + SoundOutputModeBlockID = 0x00070001, + ConsoleUniqueIDBlockID = 0x00090001, + UsernameBlockID = 0x000A0000, + BirthdayBlockID = 0x000A0001, + LanguageBlockID = 0x000A0002, + CountryInfoBlockID = 0x000B0000, + CountryNameBlockID = 0x000B0001, + StateNameBlockID = 0x000B0002, + EULAVersionBlockID = 0x000D0000, + ConsoleModelBlockID = 0x000F0004, +}; + struct UsernameBlock { char16_t username[10]; ///< Exactly 20 bytes long, padded with zeros at the end if necessary u32 zero; @@ -73,8 +87,7 @@ static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; static const UsernameBlock CONSOLE_USERNAME_BLOCK = { u"CITRA", 0, 0 }; static const BirthdayBlock PROFILE_BIRTHDAY = { 3, 25 }; // March 25th, 2014 -/// TODO(Subv): Find out what this actually is -static const u8 SOUND_OUTPUT_MODE = 2; +static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND; static const u8 UNITED_STATES_COUNTRY_ID = 49; /// TODO(Subv): Find what the other bytes are static const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; @@ -224,6 +237,22 @@ void GetConfigInfoBlk8(Service::Interface* self) { Memory::WriteBlock(data_pointer, data.data(), data.size()); } +void SetConfigInfoBlk4(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 block_id = cmd_buff[1]; + u32 size = cmd_buff[2]; + VAddr data_pointer = cmd_buff[4]; + + if (!Memory::IsValidVirtualAddress(data_pointer)) { + cmd_buff[1] = -1; // TODO(Subv): Find the right error code + return; + } + + std::vector<u8> data(size); + Memory::ReadBlock(data_pointer, data.data(), data.size()); + cmd_buff[1] = Service::CFG::SetConfigInfoBlock(block_id, size, 0x4, data.data()).raw; +} + void UpdateConfigNANDSavegame(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = Service::CFG::UpdateConfigNANDSavegame().raw; @@ -234,13 +263,13 @@ void FormatConfig(Service::Interface* self) { cmd_buff[1] = Service::CFG::FormatConfig().raw; } -ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { +static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) { // Read the header SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); auto itr = std::find_if(std::begin(config->block_entries), std::end(config->block_entries), [&](const SaveConfigBlockEntry& entry) { - return entry.block_id == block_id && (entry.flags & flag); + return entry.block_id == block_id; }); if (itr == std::end(config->block_entries)) { @@ -248,17 +277,38 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { return ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); } + if ((itr->flags & flag) == 0) { + LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id, size); + return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + } + if (itr->size != size) { LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size, block_id, flag); return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); } + void* pointer; + // The data is located in the block header itself if the size is less than 4 bytes if (itr->size <= 4) - memcpy(output, &itr->offset_or_data, itr->size); + pointer = &itr->offset_or_data; else - memcpy(output, &cfg_config_file_buffer[itr->offset_or_data], itr->size); + pointer = &cfg_config_file_buffer[itr->offset_or_data]; + + return MakeResult<void*>(pointer); +} + +ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) { + void* pointer; + CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag)); + memcpy(output, pointer, size); + return RESULT_SUCCESS; +} +ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) { + void* pointer; + CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag)); + memcpy(pointer, input, size); return RESULT_SUCCESS; } @@ -336,25 +386,25 @@ ResultCode FormatConfig() { res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x00050005, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); + res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x00070001, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); + res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x00090001, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); + res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x000A0000, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); + res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x000A0001, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); + res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x000A0002, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); + res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x000B0000, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); + res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); if (!res.IsSuccess()) return res; u16_le country_name_buffer[16][0x40] = {}; @@ -363,10 +413,10 @@ ResultCode FormatConfig() { std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]); } // 0x000B0001 - Localized names for the profile Country - res = CreateConfigInfoBlk(0x000B0001, sizeof(country_name_buffer), 0xE, country_name_buffer); + res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); if (!res.IsSuccess()) return res; // 0x000B0002 - Localized names for the profile State/Province - res = CreateConfigInfoBlk(0x000B0002, sizeof(country_name_buffer), 0xE, country_name_buffer); + res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); if (!res.IsSuccess()) return res; // 0x000B0003 - Unknown, related to country/address (zip code?) @@ -382,10 +432,10 @@ ResultCode FormatConfig() { if (!res.IsSuccess()) return res; // 0x000D0000 - Accepted EULA version - res = CreateConfigInfoBlk(0x000D0000, 0x4, 0xE, zero_buffer); + res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(0x000F0004, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); + res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); if (!res.IsSuccess()) return res; // 0x00170000 - Unknown @@ -399,11 +449,7 @@ ResultCode FormatConfig() { return RESULT_SUCCESS; } -void Init() { - AddService(new CFG_I_Interface); - AddService(new CFG_S_Interface); - AddService(new CFG_U_Interface); - +ResultCode LoadConfigNANDSaveFile() { // Open the SystemSaveData archive 0x00010017 FileSys::Path archive_path(cfg_system_savedata_id); auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); @@ -431,14 +477,75 @@ void Init() { if (config_result.Succeeded()) { auto config = config_result.MoveFrom(); config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); - return; + return RESULT_SUCCESS; } - FormatConfig(); + return FormatConfig(); +} + +void Init() { + AddService(new CFG_I_Interface); + AddService(new CFG_S_Interface); + AddService(new CFG_U_Interface); + + LoadConfigNANDSaveFile(); } void Shutdown() { } +void SetUsername(const std::u16string& name) { + ASSERT(name.size() <= 10); + UsernameBlock block{}; + name.copy(block.username, name.size()); + SetConfigInfoBlock(UsernameBlockID, sizeof(block), 4, &block); +} + +std::u16string GetUsername() { + UsernameBlock block; + GetConfigInfoBlock(UsernameBlockID, sizeof(block), 8, &block); + + // the username string in the block isn't null-terminated, + // so we need to find the end manually. + std::u16string username(block.username, ARRAY_SIZE(block.username)); + const size_t pos = username.find(u'\0'); + if (pos != std::u16string::npos) + username.erase(pos); + return username; +} + +void SetBirthday(u8 month, u8 day) { + BirthdayBlock block = { month, day }; + SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); +} + +std::tuple<u8, u8> GetBirthday() { + BirthdayBlock block; + GetConfigInfoBlock(BirthdayBlockID, sizeof(block), 8, &block); + return std::make_tuple(block.month, block.day); +} + +void SetSystemLanguage(SystemLanguage language) { + u8 block = language; + SetConfigInfoBlock(LanguageBlockID, sizeof(block), 4, &block); +} + +SystemLanguage GetSystemLanguage() { + u8 block; + GetConfigInfoBlock(LanguageBlockID, sizeof(block), 8, &block); + return static_cast<SystemLanguage>(block); +} + +void SetSoundOutputMode(SoundOutputMode mode) { + u8 block = mode; + SetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 4, &block); +} + +SoundOutputMode GetSoundOutputMode() { + u8 block; + GetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 8, &block); + return static_cast<SoundOutputMode>(block); +} + } // namespace CFG } // namespace Service diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index c01806836..18f60f4ca 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <string> #include "common/common_types.h" @@ -35,7 +36,14 @@ enum SystemLanguage { LANGUAGE_KO = 7, LANGUAGE_NL = 8, LANGUAGE_PT = 9, - LANGUAGE_RU = 10 + LANGUAGE_RU = 10, + LANGUAGE_TW = 11 +}; + +enum SoundOutputMode { + SOUND_MONO = 0, + SOUND_STEREO = 1, + SOUND_SURROUND = 2 }; /// Block header in the config savedata file @@ -178,6 +186,22 @@ void GetConfigInfoBlk2(Service::Interface* self); void GetConfigInfoBlk8(Service::Interface* self); /** + * CFG::SetConfigInfoBlk4 service function + * Inputs: + * 0 : 0x04020082 / 0x08020082 + * 1 : Block ID + * 2 : Size + * 3 : Descriptor for the output buffer + * 4 : Output buffer pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Note: + * The parameters order is different from GetConfigInfoBlk2/8's, + * where Block ID and Size are switched. + */ +void SetConfigInfoBlk4(Service::Interface* self); + +/** * CFG::UpdateConfigNANDSavegame service function * Inputs: * 0 : 0x04030000 / 0x08030000 @@ -205,7 +229,19 @@ void FormatConfig(Service::Interface* self); * @param output A pointer where we will write the read data * @returns ResultCode indicating the result of the operation, 0 on success */ -ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output); +ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output); + +/** + * Reads data from input and writes to a block with the specified id and flag + * in the Config savegame buffer. + * The input size must match exactly the size of the target block + * @param block_id The id of the block we want to write + * @param size The size of the block we want to write + * @param flag The target block must have this flag set + * @param input A pointer where we will read data and write to Config savegame buffer + * @returns ResultCode indicating the result of the operation, 0 on success + */ +ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); /** * Creates a block with the specified id and writes the input data to the cfg savegame buffer in memory. @@ -236,11 +272,70 @@ ResultCode UpdateConfigNANDSavegame(); */ ResultCode FormatConfig(); +/** + * Open the config savegame file and load it to the memory buffer + * @returns ResultCode indicating the result of the operation, 0 on success + */ +ResultCode LoadConfigNANDSaveFile(); + /// Initialize the config service void Init(); /// Shutdown the config service void Shutdown(); +// Utilities for frontend to set config data. +// Note: before calling these functions, LoadConfigNANDSaveFile should be called, +// and UpdateConfigNANDSavegame should be called after making changes to config data. + +/** + * Sets the username in config savegame. + * @param name the username to set. The maximum size is 10 in char16_t. + */ +void SetUsername(const std::u16string& name); + +/** + * Gets the username from config savegame. + * @returns the username + */ +std::u16string GetUsername(); + +/** + * Sets the profile birthday in config savegame. + * @param month the month of birthday. + * @param day the day of the birthday. + */ +void SetBirthday(u8 month, u8 day); + +/** + * Gets the profile birthday from the config savegame. + * @returns a tuple of (month, day) of birthday + */ +std::tuple<u8, u8> GetBirthday(); + +/** + * Sets the system language in config savegame. + * @param language the system language to set. + */ +void SetSystemLanguage(SystemLanguage language); + +/** + * Gets the system language from config savegame. + * @returns the system language + */ +SystemLanguage GetSystemLanguage(); + +/** + * Sets the sound output mode in config savegame. + * @param mode the sound output mode to set + */ +void SetSoundOutputMode(SoundOutputMode mode); + +/** + * Gets the sound output mode from config savegame. + * @returns the sound output mode + */ +SoundOutputMode GetSoundOutputMode(); + } // namespace CFG } // namespace Service diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index b18060f6d..8b0db785f 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp @@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, // cfg:i {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, - {0x04020082, nullptr, "SetConfigInfoBlk4"}, + {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, @@ -31,7 +31,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x04080042, nullptr, "SecureInfoGetSerialNo"}, {0x04090000, nullptr, "UpdateConfigBlk00040003"}, {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, - {0x08020082, nullptr, "SetConfigInfoBlk4"}, + {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, {0x080400C2, nullptr, "CreateConfigInfoBlk"}, {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index e001f7687..12b458783 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp @@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, // cfg:s {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, - {0x04020082, nullptr, "SetConfigInfoBlk4"}, + {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 81b9abe4c..4c7aaa7f2 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -58,6 +58,10 @@ namespace FS { const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); +/// Returned when a function is passed an invalid archive handle. +const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Status); // 0xC8804465 + // Command to access archive file enum class FileCommand : u32 { Dummy1 = 0x000100C6, @@ -255,7 +259,7 @@ using FileSys::ArchiveFactory; /** * Map of registered archives, identified by id code. Once an archive is registered here, it is - * never removed until the FS service is shut down. + * never removed until UnregisterArchiveTypes is called. */ static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map; @@ -292,7 +296,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi ResultCode CloseArchive(ArchiveHandle handle) { if (handle_map.erase(handle) == 0) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; else return RESULT_SUCCESS; } @@ -314,7 +318,7 @@ ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_han const FileSys::Path& path, const FileSys::Mode mode) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; auto backend = archive->OpenFile(path, mode); if (backend.Failed()) @@ -327,7 +331,7 @@ ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_han ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; return archive->DeleteFile(path); } @@ -337,7 +341,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil ArchiveBackend* src_archive = GetArchive(src_archive_handle); ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; if (src_archive == dest_archive) { if (src_archive->RenameFile(src_path, dest_path)) @@ -356,7 +360,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; if (archive->DeleteDirectory(path)) return RESULT_SUCCESS; @@ -367,7 +371,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; return archive->CreateFile(path, file_size); } @@ -375,7 +379,7 @@ ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; if (archive->CreateDirectory(path)) return RESULT_SUCCESS; @@ -388,7 +392,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons ArchiveBackend* src_archive = GetArchive(src_archive_handle); ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; if (src_archive == dest_archive) { if (src_archive->RenameDirectory(src_path, dest_path)) @@ -408,7 +412,7 @@ ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle a const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); if (backend == nullptr) { @@ -423,7 +427,7 @@ ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle a ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_HANDLE; + return ERR_INVALID_ARCHIVE_HANDLE; return MakeResult<u64>(archive->GetFreeBytes()); } @@ -516,12 +520,7 @@ ResultCode CreateSystemSaveData(u32 high, u32 low) { return RESULT_SUCCESS; } -/// Initialize archives -void ArchiveInit() { - next_handle = 1; - - AddService(new FS::Interface); - +void RegisterArchiveTypes() { // TODO(Subv): Add the other archive types (see here for the known types: // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). @@ -558,10 +557,23 @@ void ArchiveInit() { RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); } +void UnregisterArchiveTypes() { + id_code_map.clear(); +} + +/// Initialize archives +void ArchiveInit() { + next_handle = 1; + + AddService(new FS::Interface); + + RegisterArchiveTypes(); +} + /// Shutdown archives void ArchiveShutdown() { handle_map.clear(); - id_code_map.clear(); + UnregisterArchiveTypes(); } } // namespace FS diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 006606740..f7a50a3a7 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -235,5 +235,11 @@ void ArchiveInit(); /// Shutdown archives void ArchiveShutdown(); +/// Register all archive types +void RegisterArchiveTypes(); + +/// Unregister all archive types +void UnregisterArchiveTypes(); + } // namespace FS } // namespace Service diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 7df7da5a4..937868747 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -645,20 +645,19 @@ static void DeleteSystemSaveData(Service::Interface* self) { * FS_User::CreateSystemSaveData service function. * Inputs: * 0 : 0x08560240 - * 1 : High word of the SystemSaveData id to create - * 2 : Low word of the SystemSaveData id to create - * 3 : Unknown - * 4 : Unknown - * 5 : Unknown - * 6 : Unknown - * 7 : Unknown - * 8 : Unknown - * 9 : Unknown (Memory address) + * 1 : u8 MediaType of the system save data + * 2 : SystemSaveData id to create + * 3 : Total size + * 4 : Block size + * 5 : Number of directories + * 6 : Number of files + * 7 : Directory bucket count + * 8 : File bucket count + * 9 : u8 Whether to duplicate data or not * Outputs: * 1 : Result of function, 0 on success, otherwise error code */ static void CreateSystemSaveData(Service::Interface* self) { - // TODO(Subv): Figure out the other parameters. u32* cmd_buff = Kernel::GetCommandBuffer(); u32 savedata_high = cmd_buff[1]; u32 savedata_low = cmd_buff[2]; @@ -672,6 +671,38 @@ static void CreateSystemSaveData(Service::Interface* self) { } /** + * FS_User::CreateLegacySystemSaveData service function. + * This function appears to be obsolete and seems to have been replaced by + * command 0x08560240 (CreateSystemSaveData). + * + * Inputs: + * 0 : 0x08100200 + * 1 : SystemSaveData id to create + * 2 : Total size + * 3 : Block size + * 4 : Number of directories + * 5 : Number of files + * 6 : Directory bucket count + * 7 : File bucket count + * 8 : u8 Duplicate data + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void CreateLegacySystemSaveData(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 savedata_id = cmd_buff[1]; + + LOG_WARNING(Service_FS, "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X " + "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " + "cmd_buff[9]=%08X", savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], + cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); + + cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0); + // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND) + cmd_buff[1] = CreateSystemSaveData(0, savedata_id).raw; +} + +/** * FS_User::InitializeWithSdkVersion service function. * Inputs: * 0 : 0x08610042 @@ -820,7 +851,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x080D0144, nullptr, "ControlArchive"}, {0x080E0080, CloseArchive, "CloseArchive"}, {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"}, - {0x08100200, nullptr, "CreateSystemSaveData"}, + {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"}, {0x08110040, nullptr, "DeleteSystemSaveData"}, {0x08120080, GetFreeBytes, "GetFreeBytes"}, {0x08130000, nullptr, "GetCardType"}, diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index d216cecb4..cdec11388 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <cmath> + #include "common/logging/log.h" #include "common/emu_window.h" @@ -19,8 +21,6 @@ namespace Service { namespace HID { -static const int MAX_CIRCLEPAD_POS = 0x9C; ///< Max value for a circle pad position - // Handle to shared memory region designated to HID_User service static Kernel::SharedPtr<Kernel::SharedMemory> shared_mem; @@ -39,38 +39,48 @@ static u32 next_gyroscope_index; static int enable_accelerometer_count = 0; // positive means enabled static int enable_gyroscope_count = 0; // positive means enabled -const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = {{ - Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, - Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, - Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, - Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, - Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT, - Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT -}}; - - -// TODO(peachum): -// Add a method for setting analog input from joystick device for the circle Pad. -// -// This method should: -// * Be called after both PadButton<Press, Release>(). -// * Be called before PadUpdateComplete() -// * Set current PadEntry.circle_pad_<axis> using analog data -// * Set PadData.raw_circle_pad_data -// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_x >= 41 -// * Set PadData.current_state.circle_up = 1 if current PadEntry.circle_pad_y >= 41 -// * Set PadData.current_state.circle_left = 1 if current PadEntry.circle_pad_x <= -41 -// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41 +static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { + constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions + constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction + PadState state; + state.hex = 0; + + if (circle_pad_x * circle_pad_x + circle_pad_y * circle_pad_y > CIRCLE_PAD_THRESHOLD_SQUARE) { + float t = std::abs(static_cast<float>(circle_pad_y) / circle_pad_x); + + if (circle_pad_x != 0 && t < TAN60) { + if (circle_pad_x > 0) + state.circle_right.Assign(1); + else + state.circle_left.Assign(1); + } + + if (circle_pad_x == 0 || t > TAN30) { + if (circle_pad_y > 0) + state.circle_up.Assign(1); + else + state.circle_down.Assign(1); + } + } + + return state; +} void Update() { SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); - const PadState state = VideoCore::g_emu_window->GetPadState(); if (mem == nullptr) { LOG_DEBUG(Service_HID, "Cannot update HID prior to mapping shared memory!"); return; } + PadState state = VideoCore::g_emu_window->GetPadState(); + + // Get current circle pad position and update circle pad direction + s16 circle_pad_x, circle_pad_y; + std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState(); + state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex; + mem->pad.current_state.hex = state.hex; mem->pad.index = next_pad_index; next_pad_index = (next_pad_index + 1) % mem->pad.entries.size(); @@ -88,13 +98,9 @@ void Update() { // Update entry properties pad_entry.current_state.hex = state.hex; pad_entry.delta_additions.hex = changed.hex & state.hex; - pad_entry.delta_removals.hex = changed.hex & old_state.hex;; - - // Set circle Pad - pad_entry.circle_pad_x = state.circle_left ? -MAX_CIRCLEPAD_POS : - state.circle_right ? MAX_CIRCLEPAD_POS : 0x0; - pad_entry.circle_pad_y = state.circle_down ? -MAX_CIRCLEPAD_POS : - state.circle_up ? MAX_CIRCLEPAD_POS : 0x0; + pad_entry.delta_removals.hex = changed.hex & old_state.hex; + pad_entry.circle_pad_x = circle_pad_x; + pad_entry.circle_pad_y = circle_pad_y; // If we just updated index 0, provide a new timestamp if (mem->pad.index == 0) { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 170d19ea8..669b1f723 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -215,9 +215,6 @@ const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; const PadState PAD_CIRCLE_UP = {{1u << 30}}; const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; - -extern const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping; - /** * HID::GetIPCHandles service function * Inputs: diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index aae955bf8..8bd36d5ea 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright 2016 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -15,23 +15,64 @@ namespace SRV { static Kernel::SharedPtr<Kernel::Event> event_handle; -static void Initialize(Service::Interface* self) { +/** + * SRV::RegisterClient service function + * Inputs: + * 0: 0x00010002 + * 1: ProcessId Header (must be 0x20) + * Outputs: + * 0: 0x00010040 + * 1: ResultCode + */ +static void RegisterClient(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = 0; // No error + if (cmd_buff[1] != IPC::CallingPidDesc()) { + cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); //0x40 + cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; + return; + } + cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); //0x10040 + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_SRV, "(STUBBED) called"); } -static void GetProcSemaphore(Service::Interface* self) { +/** + * SRV::EnableNotification service function + * Inputs: + * 0: 0x00020000 + * Outputs: + * 0: 0x00020042 + * 1: ResultCode + * 2: Translation descriptor: 0x20 + * 3: Handle to semaphore signaled on process notification + */ +static void EnableNotification(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Change to a semaphore once these have been implemented event_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "SRV:Event"); event_handle->Clear(); - cmd_buff[1] = 0; // No error + cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042 + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[2] = IPC::TransferHandleDesc(); cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); + LOG_WARNING(Service_SRV, "(STUBBED) called"); } +/** + * SRV::GetServiceHandle service function + * Inputs: + * 0: 0x00050100 + * 1-2: 8-byte UTF-8 service name + * 3: Name length + * 4: Flags (bit0: if not set, return port-handle if session-handle unavailable) + * Outputs: + * 1: ResultCode + * 3: Service handle + */ static void GetServiceHandle(Service::Interface* self) { ResultCode res = RESULT_SUCCESS; u32* cmd_buff = Kernel::GetCommandBuffer(); @@ -49,16 +90,80 @@ static void GetServiceHandle(Service::Interface* self) { cmd_buff[1] = res.raw; } +/** + * SRV::Subscribe service function + * Inputs: + * 0: 0x00090040 + * 1: Notification ID + * Outputs: + * 0: 0x00090040 + * 1: ResultCode + */ +static void Subscribe(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + u32 notification_id = cmd_buff[1]; + + cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040 + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); +} + +/** + * SRV::Unsubscribe service function + * Inputs: + * 0: 0x000A0040 + * 1: Notification ID + * Outputs: + * 0: 0x000A0040 + * 1: ResultCode + */ +static void Unsubscribe(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + u32 notification_id = cmd_buff[1]; + + cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040 + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); +} + +/** + * SRV::PublishToSubscriber service function + * Inputs: + * 0: 0x000C0080 + * 1: Notification ID + * 2: Flags (bit0: only fire if not fired, bit1: report errors) + * Outputs: + * 0: 0x000C0040 + * 1: ResultCode + */ +static void PublishToSubscriber(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + u32 notification_id = cmd_buff[1]; + u8 flags = cmd_buff[2] & 0xFF; + + cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040 + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, flags); +} + const Interface::FunctionInfo FunctionTable[] = { - {0x00010002, Initialize, "Initialize"}, - {0x00020000, GetProcSemaphore, "GetProcSemaphore"}, - {0x00030100, nullptr, "RegisterService"}, - {0x000400C0, nullptr, "UnregisterService"}, - {0x00050100, GetServiceHandle, "GetServiceHandle"}, - {0x000600C2, nullptr, "RegisterHandle"}, - {0x00090040, nullptr, "Subscribe"}, - {0x000B0000, nullptr, "ReceiveNotification"}, - {0x000C0080, nullptr, "PublishToSubscriber"}, + {0x00010002, RegisterClient, "RegisterClient"}, + {0x00020000, EnableNotification, "EnableNotification"}, + {0x00030100, nullptr, "RegisterService"}, + {0x000400C0, nullptr, "UnregisterService"}, + {0x00050100, GetServiceHandle, "GetServiceHandle"}, + {0x000600C2, nullptr, "RegisterPort"}, + {0x000700C0, nullptr, "UnregisterPort"}, + {0x00080100, nullptr, "GetPort"}, + {0x00090040, Subscribe, "Subscribe"}, + {0x000A0040, Unsubscribe, "Unsubscribe"}, + {0x000B0000, nullptr, "ReceiveNotification"}, + {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, + {0x000D0040, nullptr, "PublishAndGetSubscriber"}, + {0x000E00C0, nullptr, "IsServiceRegistered"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -66,10 +171,11 @@ const Interface::FunctionInfo FunctionTable[] = { Interface::Interface() { Register(FunctionTable); + event_handle = nullptr; } Interface::~Interface() { event_handle = nullptr; } -} // namespace +} // namespace SRV diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 0ce72de87..5d71d5619 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -14,12 +14,14 @@ #include "core/arm/arm_interface.h" #include "core/hle/kernel/address_arbiter.h" +#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/semaphore.h" +#include "core/hle/kernel/server_port.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" @@ -834,6 +836,23 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 return RESULT_SUCCESS; } +static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) { + // TODO(Subv): Implement named ports. + ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); + + using Kernel::ServerPort; + using Kernel::ClientPort; + using Kernel::SharedPtr; + + auto ports = ServerPort::CreatePortPair(max_sessions); + CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); + // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be created. + CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); + + LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); + return RESULT_SUCCESS; +} + static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) { using Kernel::MemoryRegion; @@ -1011,7 +1030,7 @@ static const FunctionDef SVC_Table[] = { {0x44, nullptr, "Unknown"}, {0x45, nullptr, "Unknown"}, {0x46, nullptr, "Unknown"}, - {0x47, nullptr, "CreatePort"}, + {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, {0x48, nullptr, "CreateSessionToPort"}, {0x49, nullptr, "CreateSession"}, {0x4A, nullptr, "AcceptSession"}, diff --git a/src/core/settings.h b/src/core/settings.h index ea72f4d9c..f95e62390 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -13,29 +13,40 @@ namespace Settings { namespace NativeInput { enum Values { + // directly mapped keys A, B, X, Y, L, R, ZL, ZR, START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, - SUP, SDOWN, SLEFT, SRIGHT, CUP, CDOWN, CLEFT, CRIGHT, + + // indirectly mapped keys + CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, + CIRCLE_MODIFIER, + NUM_INPUTS }; + static const std::array<const char*, NUM_INPUTS> Mapping = {{ + // directly mapped keys "pad_a", "pad_b", "pad_x", "pad_y", "pad_l", "pad_r", "pad_zl", "pad_zr", "pad_start", "pad_select", "pad_home", "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", - "pad_sup", "pad_sdown", "pad_sleft", "pad_sright", - "pad_cup", "pad_cdown", "pad_cleft", "pad_cright" + "pad_cup", "pad_cdown", "pad_cleft", "pad_cright", + + // indirectly mapped keys + "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right", + "pad_circle_modifier", }}; static const std::array<Values, NUM_INPUTS> All = {{ A, B, X, Y, L, R, ZL, ZR, START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, - SUP, SDOWN, SLEFT, SRIGHT, - CUP, CDOWN, CLEFT, CRIGHT + CUP, CDOWN, CLEFT, CRIGHT, + CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, + CIRCLE_MODIFIER, }}; } @@ -46,6 +57,7 @@ struct Values { // Controls std::array<int, NativeInput::NUM_INPUTS> input_mappings; + float pad_circle_modifier_scale; // Core int frame_skip; |