mirror of
https://github.com/citra-emu/citra.git
synced 2025-04-04 09:41:07 +00:00
323 lines
12 KiB
C++
323 lines
12 KiB
C++
// Copyright 2016 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <functional>
|
|
#include <memory>
|
|
|
|
#include <boost/optional.hpp>
|
|
|
|
#include "common/common_types.h"
|
|
#include "common/common_funcs.h"
|
|
|
|
namespace ArmDecoder {
|
|
|
|
// This is a generic ARMv6 decoder using double dispatch.
|
|
|
|
class Instruction;
|
|
class Visitor;
|
|
|
|
boost::optional<const Instruction&> DecodeArm(u32 instruction);
|
|
const Instruction& DecodeThumb(u16 instruction);
|
|
|
|
struct Matcher {
|
|
u32 bit_mask;
|
|
u32 expected;
|
|
FORCE_INLINE bool Match(u32 x) const {
|
|
return (x & bit_mask) == expected;
|
|
}
|
|
virtual void visit(Visitor* v, u32 inst) = 0;
|
|
};
|
|
|
|
class Instruction {
|
|
private:
|
|
const std::unique_ptr<Matcher> matcher;
|
|
|
|
public:
|
|
Instruction(const char* const name, std::unique_ptr<Matcher> matcher) : matcher(std::move(matcher)), name(name) {}
|
|
|
|
const char* const name;
|
|
|
|
FORCE_INLINE bool Match(u32 instruction) const {
|
|
return (instruction & matcher->bit_mask) == matcher->expected;
|
|
}
|
|
|
|
FORCE_INLINE void Visit(Visitor* v, u32 instruction) const {
|
|
matcher->visit(v, instruction);
|
|
}
|
|
};
|
|
|
|
using Cond = u8;
|
|
using Imm5 = u32;
|
|
using Imm8 = u32;
|
|
using Imm11 = u32;
|
|
using Imm24 = u32;
|
|
using Register = int;
|
|
using ShiftType = int;
|
|
|
|
class Visitor {
|
|
public:
|
|
virtual ~Visitor() = default;
|
|
|
|
// Branch instructions
|
|
virtual void B(Cond cond, Imm24 imm24) = 0;
|
|
virtual void BL(Cond cond, Imm24 imm24) = 0;
|
|
virtual void BLX_imm(bool H, Imm24 imm24) = 0;
|
|
virtual void BLX_reg(Cond cond, Register Rm) = 0;
|
|
virtual void BX(Cond cond, Register Rm) = 0;
|
|
virtual void BXJ(Cond cond, Register Rm) = 0;
|
|
|
|
// Coprocessor instructions
|
|
virtual void CDP() = 0;
|
|
virtual void LDC() = 0;
|
|
virtual void MCR() = 0;
|
|
virtual void MCRR() = 0;
|
|
virtual void MRC() = 0;
|
|
virtual void MRRC() = 0;
|
|
virtual void STC() = 0;
|
|
|
|
// Data processing instructions
|
|
virtual void ADC_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void ADC_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void ADC_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void ADD_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void ADD_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void ADD_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void AND_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void AND_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void AND_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void BIC_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void BIC_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void BIC_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void CMN_imm(Cond cond, Register Rn, int rotate, Imm8 imm8) = 0;
|
|
virtual void CMN_reg(Cond cond, Register Rn, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void CMN_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void CMP_imm(Cond cond, Register Rn, int rotate, Imm8 imm8) = 0;
|
|
virtual void CMP_reg(Cond cond, Register Rn, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void CMP_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void EOR_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void EOR_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void EOR_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void MOV_imm(Cond cond, bool S, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void MOV_reg(Cond cond, bool S, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void MOV_rsr(Cond cond, bool S, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void MVN_imm(Cond cond, bool S, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void MVN_reg(Cond cond, bool S, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void MVN_rsr(Cond cond, bool S, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void ORR_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void ORR_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void ORR_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void RSB_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void RSB_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void RSB_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void RSC_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void RSC_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void RSC_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void SBC_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void SBC_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void SBC_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void SUB_imm(Cond cond, bool S, Register Rn, Register Rd, int rotate, Imm8 imm8) = 0;
|
|
virtual void SUB_reg(Cond cond, bool S, Register Rn, Register Rd, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void SUB_rsr(Cond cond, bool S, Register Rn, Register Rd, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void TEQ_imm(Cond cond, Register Rn, int rotate, Imm8 imm8) = 0;
|
|
virtual void TEQ_reg(Cond cond, Register Rn, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void TEQ_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
virtual void TST_imm(Cond cond, Register Rn, int rotate, Imm8 imm8) = 0;
|
|
virtual void TST_reg(Cond cond, Register Rn, Imm5 imm5, ShiftType shift, Register Rm) = 0;
|
|
virtual void TST_rsr(Cond cond, Register Rn, Register Rs, ShiftType shift, Register Rm) = 0;
|
|
|
|
// Exception generation instructions
|
|
virtual void BKPT() = 0;
|
|
virtual void SVC() = 0;
|
|
virtual void UDF() = 0;
|
|
|
|
// Extension functions
|
|
virtual void SXTAB() = 0;
|
|
virtual void SXTAB16() = 0;
|
|
virtual void SXTAH() = 0;
|
|
virtual void SXTB() = 0;
|
|
virtual void SXTB16() = 0;
|
|
virtual void SXTH() = 0;
|
|
virtual void UXTAB() = 0;
|
|
virtual void UXTAB16() = 0;
|
|
virtual void UXTAH() = 0;
|
|
virtual void UXTB() = 0;
|
|
virtual void UXTB16() = 0;
|
|
virtual void UXTH() = 0;
|
|
|
|
// Hint instructions
|
|
virtual void PLD() = 0;
|
|
virtual void SEV() = 0;
|
|
virtual void WFE() = 0;
|
|
virtual void WFI() = 0;
|
|
virtual void YIELD() = 0;
|
|
|
|
// Load/Store instructions
|
|
virtual void LDR_imm() = 0;
|
|
virtual void LDR_reg() = 0;
|
|
virtual void LDRB_imm() = 0;
|
|
virtual void LDRB_reg() = 0;
|
|
virtual void LDRBT() = 0;
|
|
virtual void LDRD_imm() = 0;
|
|
virtual void LDRD_reg() = 0;
|
|
virtual void LDRH_imm() = 0;
|
|
virtual void LDRH_reg() = 0;
|
|
virtual void LDRHT() = 0;
|
|
virtual void LDRSB_imm() = 0;
|
|
virtual void LDRSB_reg() = 0;
|
|
virtual void LDRSBT() = 0;
|
|
virtual void LDRSH_imm() = 0;
|
|
virtual void LDRSH_reg() = 0;
|
|
virtual void LDRSHT() = 0;
|
|
virtual void LDRT() = 0;
|
|
virtual void STR_imm() = 0;
|
|
virtual void STR_reg() = 0;
|
|
virtual void STRB_imm() = 0;
|
|
virtual void STRB_reg() = 0;
|
|
virtual void STRBT() = 0;
|
|
virtual void STRD_imm() = 0;
|
|
virtual void STRD_reg() = 0;
|
|
virtual void STRH_imm() = 0;
|
|
virtual void STRH_reg() = 0;
|
|
virtual void STRHT() = 0;
|
|
virtual void STRT() = 0;
|
|
|
|
// Load/Store multiple instructions
|
|
virtual void LDM() = 0;
|
|
virtual void STM() = 0;
|
|
|
|
// Miscellaneous instructions
|
|
virtual void CLZ() = 0;
|
|
virtual void NOP() = 0;
|
|
virtual void SEL() = 0;
|
|
|
|
// Unsigned sum of absolute difference functions
|
|
virtual void USAD8() = 0;
|
|
virtual void USADA8() = 0;
|
|
|
|
// Packing instructions
|
|
virtual void PKHBT(Cond cond, Register Rn, Register Rd, Imm5 imm5, Register Rm) = 0;
|
|
virtual void PKHTB(Cond cond, Register Rn, Register Rd, Imm5 imm5, Register Rm) = 0;
|
|
|
|
// Reversal instructions
|
|
virtual void REV() = 0;
|
|
virtual void REV16() = 0;
|
|
virtual void REVSH() = 0;
|
|
|
|
// Saturation instructions
|
|
virtual void SSAT() = 0;
|
|
virtual void SSAT16() = 0;
|
|
virtual void USAT() = 0;
|
|
virtual void USAT16() = 0;
|
|
|
|
// Multiply (Normal) instructions
|
|
virtual void MLA() = 0;
|
|
virtual void MUL() = 0;
|
|
|
|
// Multiply (Long) instructions
|
|
virtual void SMLAL() = 0;
|
|
virtual void SMULL() = 0;
|
|
virtual void UMAAL() = 0;
|
|
virtual void UMLAL() = 0;
|
|
virtual void UMULL() = 0;
|
|
|
|
// Multiply (Halfword) instructions
|
|
virtual void SMLALxy() = 0;
|
|
virtual void SMLAxy() = 0;
|
|
virtual void SMULxy() = 0;
|
|
|
|
// Multiply (word by halfword) instructions
|
|
virtual void SMLAWy() = 0;
|
|
virtual void SMULWy() = 0;
|
|
|
|
// Multiply (Most significant word) instructions
|
|
virtual void SMMLA() = 0;
|
|
virtual void SMMLS() = 0;
|
|
virtual void SMMUL() = 0;
|
|
|
|
// Multiply (Dual) instructions
|
|
virtual void SMLAD() = 0;
|
|
virtual void SMLALD() = 0;
|
|
virtual void SMLSD() = 0;
|
|
virtual void SMLSLD() = 0;
|
|
virtual void SMUAD() = 0;
|
|
virtual void SMUSD() = 0;
|
|
|
|
// Parallel Add/Subtract (Modulo arithmetic) instructions
|
|
virtual void SADD8() = 0;
|
|
virtual void SADD16() = 0;
|
|
virtual void SASX() = 0;
|
|
virtual void SSAX() = 0;
|
|
virtual void SSUB8() = 0;
|
|
virtual void SSUB16() = 0;
|
|
virtual void UADD8() = 0;
|
|
virtual void UADD16() = 0;
|
|
virtual void UASX() = 0;
|
|
virtual void USAX() = 0;
|
|
virtual void USUB8() = 0;
|
|
virtual void USUB16() = 0;
|
|
|
|
// Parallel Add/Subtract (Saturating) instructions
|
|
virtual void QADD8() = 0;
|
|
virtual void QADD16() = 0;
|
|
virtual void QASX() = 0;
|
|
virtual void QSAX() = 0;
|
|
virtual void QSUB8() = 0;
|
|
virtual void QSUB16() = 0;
|
|
virtual void UQADD8() = 0;
|
|
virtual void UQADD16() = 0;
|
|
virtual void UQASX() = 0;
|
|
virtual void UQSAX() = 0;
|
|
virtual void UQSUB8() = 0;
|
|
virtual void UQSUB16() = 0;
|
|
|
|
// Parallel Add/Subtract (Halving) instructions
|
|
virtual void SHADD8() = 0;
|
|
virtual void SHADD16() = 0;
|
|
virtual void SHASX() = 0;
|
|
virtual void SHSAX() = 0;
|
|
virtual void SHSUB8() = 0;
|
|
virtual void SHSUB16() = 0;
|
|
virtual void UHADD8() = 0;
|
|
virtual void UHADD16() = 0;
|
|
virtual void UHASX() = 0;
|
|
virtual void UHSAX() = 0;
|
|
virtual void UHSUB8() = 0;
|
|
virtual void UHSUB16() = 0;
|
|
|
|
// Saturated Add/Subtract instructions
|
|
virtual void QADD() = 0;
|
|
virtual void QSUB() = 0;
|
|
virtual void QDADD() = 0;
|
|
virtual void QDSUB() = 0;
|
|
|
|
// Synchronization Primitive instructions
|
|
virtual void CLREX() = 0;
|
|
virtual void LDREX() = 0;
|
|
virtual void LDREXB() = 0;
|
|
virtual void LDREXD() = 0;
|
|
virtual void LDREXH() = 0;
|
|
virtual void STREX() = 0;
|
|
virtual void STREXB() = 0;
|
|
virtual void STREXD() = 0;
|
|
virtual void STREXH() = 0;
|
|
virtual void SWP() = 0;
|
|
|
|
// Status register access instructions
|
|
virtual void CPS() = 0;
|
|
virtual void MRS() = 0;
|
|
virtual void MSR() = 0;
|
|
virtual void RFE() = 0;
|
|
virtual void SETEND(bool E) = 0;
|
|
virtual void SRS() = 0;
|
|
|
|
// Thumb specific instructions
|
|
virtual void thumb_BLX_prefix(Imm11 imm11) = 0;
|
|
virtual void thumb_BLX_suffix(bool L, Imm11 imm11) = 0;
|
|
};
|
|
|
|
};
|