mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-04 07:38:47 +00:00 
			
		
		
		
	dyncom: Use enum class for instruction decoding results
This commit is contained in:
		
							parent
							
								
									7e4fb4db19
								
							
						
					
					
						commit
						89540ea761
					
				
					 5 changed files with 40 additions and 41 deletions
				
			
		| 
						 | 
				
			
			@ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = {
 | 
			
		|||
    { "invalid", 0, INVALID,     { 0 }}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int decode_arm_instr(u32 instr, s32* idx) {
 | 
			
		||||
ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
 | 
			
		||||
    int n = 0;
 | 
			
		||||
    int base = 0;
 | 
			
		||||
    int ret = DECODE_FAILURE;
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM);
 | 
			
		||||
    ARMDecodeStatus ret = ARMDecodeStatus::FAILURE;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < instr_slots; i++) {
 | 
			
		||||
    for (int i = 0; i < instr_slots; i++) {
 | 
			
		||||
        n = arm_instruction[i].attribute_value;
 | 
			
		||||
        base = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -438,11 +437,11 @@ int decode_arm_instr(u32 instr, s32* idx) {
 | 
			
		|||
            n--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // All conditions is satisfied.
 | 
			
		||||
        // All conditions are satisfied.
 | 
			
		||||
        if (n == 0)
 | 
			
		||||
            ret = DECODE_SUCCESS;
 | 
			
		||||
            ret = ARMDecodeStatus::SUCCESS;
 | 
			
		||||
 | 
			
		||||
        if (ret == DECODE_SUCCESS) {
 | 
			
		||||
        if (ret == ARMDecodeStatus::SUCCESS) {
 | 
			
		||||
            n = arm_exclusion_code[i].attribute_value;
 | 
			
		||||
            if (n != 0) {
 | 
			
		||||
                base = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -454,13 +453,13 @@ int decode_arm_instr(u32 instr, s32* idx) {
 | 
			
		|||
                    n--;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // All conditions is satisfied.
 | 
			
		||||
                // All conditions are satisfied.
 | 
			
		||||
                if (n == 0)
 | 
			
		||||
                    ret = DECODE_FAILURE;
 | 
			
		||||
                    ret = ARMDecodeStatus::FAILURE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ret == DECODE_SUCCESS) {
 | 
			
		||||
        if (ret == ARMDecodeStatus::SUCCESS) {
 | 
			
		||||
            *idx = i;
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,13 +6,13 @@
 | 
			
		|||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
int decode_arm_instr(u32 instr, s32* idx);
 | 
			
		||||
 | 
			
		||||
enum DECODE_STATUS {
 | 
			
		||||
    DECODE_SUCCESS,
 | 
			
		||||
    DECODE_FAILURE
 | 
			
		||||
enum class ARMDecodeStatus {
 | 
			
		||||
    SUCCESS,
 | 
			
		||||
    FAILURE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx);
 | 
			
		||||
 | 
			
		||||
struct instruction_set_encoding_item {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    int attribute_value;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3468,10 +3468,10 @@ enum {
 | 
			
		|||
    FETCH_FAILURE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) {
 | 
			
		||||
static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) {
 | 
			
		||||
    // Check if in Thumb mode
 | 
			
		||||
    tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size);
 | 
			
		||||
    if (ret == t_branch) {
 | 
			
		||||
    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);
 | 
			
		||||
        u32 tinstr = GetThumbInstruction(inst, addr);
 | 
			
		||||
| 
						 | 
				
			
			@ -3509,7 +3509,7 @@ static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_s
 | 
			
		|||
            *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            ret = t_undefined;
 | 
			
		||||
            ret = ThumbDecodeStatus::UNDEFINED;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -3542,20 +3542,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
 | 
			
		|||
        inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
 | 
			
		||||
 | 
			
		||||
        size++;
 | 
			
		||||
        // If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction
 | 
			
		||||
        // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
 | 
			
		||||
        if (cpu->TFlag) {
 | 
			
		||||
            uint32_t arm_inst;
 | 
			
		||||
            tdstate state = decode_thumb_instr(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
 | 
			
		||||
            ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
 | 
			
		||||
 | 
			
		||||
            // We have translated the branch instruction of thumb in thumb decoder
 | 
			
		||||
            if(state == t_branch){
 | 
			
		||||
            // We have translated the Thumb branch instruction in the Thumb decoder
 | 
			
		||||
            if (state == ThumbDecodeStatus::BRANCH) {
 | 
			
		||||
                goto translated;
 | 
			
		||||
            }
 | 
			
		||||
            inst = arm_inst;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = decode_arm_instr(inst, &idx);
 | 
			
		||||
        if (ret == DECODE_FAILURE) {
 | 
			
		||||
        if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
 | 
			
		||||
            std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
 | 
			
		||||
            LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst);
 | 
			
		||||
            LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,8 @@
 | 
			
		|||
// with the following Thumb instruction held in the high 16-bits.  Passing in two Thumb instructions
 | 
			
		||||
// allows easier simulation of the special dual BL instruction.
 | 
			
		||||
 | 
			
		||||
tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
 | 
			
		||||
    tdstate valid = t_uninitialized;
 | 
			
		||||
ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
 | 
			
		||||
    ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED;
 | 
			
		||||
    u32 tinstr = GetThumbInstruction(instr, addr);
 | 
			
		||||
 | 
			
		||||
    *ainstr = 0xDEADC0DE; // Debugging to catch non updates
 | 
			
		||||
| 
						 | 
				
			
			@ -351,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
 | 
			
		|||
            else
 | 
			
		||||
                *ainstr |= (tinstr & 0x00FF);
 | 
			
		||||
        } else if ((tinstr & 0x0F00) != 0x0E00)
 | 
			
		||||
            valid = t_branch;
 | 
			
		||||
            valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        else //  UNDEFINED : cc=1110(AL) uses different format
 | 
			
		||||
            valid = t_undefined;
 | 
			
		||||
            valid = ThumbDecodeStatus::UNDEFINED;
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 28: // B
 | 
			
		||||
        valid = t_branch;
 | 
			
		||||
        valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 29:
 | 
			
		||||
        if(tinstr & 0x1)
 | 
			
		||||
            valid = t_undefined;
 | 
			
		||||
        if (tinstr & 0x1)
 | 
			
		||||
            valid = ThumbDecodeStatus::UNDEFINED;
 | 
			
		||||
        else
 | 
			
		||||
            valid = t_branch;
 | 
			
		||||
            valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 30: // BL instruction 1
 | 
			
		||||
| 
						 | 
				
			
			@ -374,7 +374,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
 | 
			
		|||
        // simulation simple (from the user perspective) we check if the following instruction is
 | 
			
		||||
        // the second half of this BL, and if it is we simulate it immediately
 | 
			
		||||
 | 
			
		||||
        valid = t_branch;
 | 
			
		||||
        valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 31: // BL instruction 2
 | 
			
		||||
| 
						 | 
				
			
			@ -383,7 +383,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
 | 
			
		|||
        // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
 | 
			
		||||
        // simulation of it on its own, with undefined results if r14 is not suitably initialised.
 | 
			
		||||
 | 
			
		||||
        valid = t_branch;
 | 
			
		||||
        valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,14 +28,15 @@
 | 
			
		|||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
enum tdstate {
 | 
			
		||||
    t_undefined,    // Undefined Thumb instruction
 | 
			
		||||
    t_decoded,      // Instruction decoded to ARM equivalent
 | 
			
		||||
    t_branch,       // Thumb branch (already processed)
 | 
			
		||||
    t_uninitialized,
 | 
			
		||||
enum class ThumbDecodeStatus {
 | 
			
		||||
    UNDEFINED,    // Undefined Thumb instruction
 | 
			
		||||
    DECODED,      // Instruction decoded to ARM equivalent
 | 
			
		||||
    BRANCH,       // Thumb branch (already processed)
 | 
			
		||||
    UNINITIALIZED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
 | 
			
		||||
// Translates a Thumb mode instruction into its ARM equivalent.
 | 
			
		||||
ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
 | 
			
		||||
 | 
			
		||||
static inline u32 GetThumbInstruction(u32 instr, u32 address) {
 | 
			
		||||
    // Normally you would need to handle instruction endianness,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue