mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #1003 from lioncash/armcruft
dyncom: Minor cleanups.
This commit is contained in:
		
						commit
						fe15cf0019
					
				
					 6 changed files with 91 additions and 124 deletions
				
			
		|  | @ -5,7 +5,7 @@ | ||||||
| #include "core/arm/dyncom/arm_dyncom_dec.h" | #include "core/arm/dyncom/arm_dyncom_dec.h" | ||||||
| #include "core/arm/skyeye_common/armsupp.h" | #include "core/arm/skyeye_common/armsupp.h" | ||||||
| 
 | 
 | ||||||
| const ISEITEM arm_instruction[] = { | const InstructionSetEncodingItem arm_instruction[] = { | ||||||
|     { "vmla", 4, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }}, |     { "vmla", 4, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }}, | ||||||
|     { "vmls", 7, ARMVFP2,      { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }}, |     { "vmls", 7, ARMVFP2,      { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }}, | ||||||
|     { "vnmla", 4, ARMVFP2,     { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }}, |     { "vnmla", 4, ARMVFP2,     { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }}, | ||||||
|  | @ -207,7 +207,7 @@ const ISEITEM arm_instruction[] = { | ||||||
|     { "bbl", 1, 0,         { 25, 27, 0x00000005 }}, |     { "bbl", 1, 0,         { 25, 27, 0x00000005 }}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const ISEITEM arm_exclusion_code[] = { | const InstructionSetEncodingItem arm_exclusion_code[] = { | ||||||
|     { "vmla", 0, ARMVFP2,      { 0 }}, |     { "vmla", 0, ARMVFP2,      { 0 }}, | ||||||
|     { "vmls", 0, ARMVFP2,      { 0 }}, |     { "vmls", 0, ARMVFP2,      { 0 }}, | ||||||
|     { "vnmla", 0, ARMVFP2,     { 0 }}, |     { "vnmla", 0, ARMVFP2,     { 0 }}, | ||||||
|  | @ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = { | ||||||
|     { "invalid", 0, INVALID,     { 0 }} |     { "invalid", 0, INVALID,     { 0 }} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int decode_arm_instr(u32 instr, s32* idx) { | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { | ||||||
|     int n = 0; |     int n = 0; | ||||||
|     int base = 0; |     int base = 0; | ||||||
|     int ret = DECODE_FAILURE; |     int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); | ||||||
|     int i = 0; |     ARMDecodeStatus ret = ARMDecodeStatus::FAILURE; | ||||||
|     int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM); |  | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < instr_slots; i++) { |     for (int i = 0; i < instr_slots; i++) { | ||||||
|         n = arm_instruction[i].attribute_value; |         n = arm_instruction[i].attribute_value; | ||||||
|         base = 0; |         base = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -438,11 +437,11 @@ int decode_arm_instr(u32 instr, s32* idx) { | ||||||
|             n--; |             n--; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // All conditions is satisfied.
 |         // All conditions are satisfied.
 | ||||||
|         if (n == 0) |         if (n == 0) | ||||||
|             ret = DECODE_SUCCESS; |             ret = ARMDecodeStatus::SUCCESS; | ||||||
| 
 | 
 | ||||||
|         if (ret == DECODE_SUCCESS) { |         if (ret == ARMDecodeStatus::SUCCESS) { | ||||||
|             n = arm_exclusion_code[i].attribute_value; |             n = arm_exclusion_code[i].attribute_value; | ||||||
|             if (n != 0) { |             if (n != 0) { | ||||||
|                 base = 0; |                 base = 0; | ||||||
|  | @ -454,13 +453,13 @@ int decode_arm_instr(u32 instr, s32* idx) { | ||||||
|                     n--; |                     n--; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 // All conditions is satisfied.
 |                 // All conditions are satisfied.
 | ||||||
|                 if (n == 0) |                 if (n == 0) | ||||||
|                     ret = DECODE_FAILURE; |                     ret = ARMDecodeStatus::FAILURE; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (ret == DECODE_SUCCESS) { |         if (ret == ARMDecodeStatus::SUCCESS) { | ||||||
|             *idx = i; |             *idx = i; | ||||||
|             return ret; |             return ret; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -6,22 +6,20 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| int decode_arm_instr(u32 instr, s32* idx); | enum class ARMDecodeStatus { | ||||||
| 
 |     SUCCESS, | ||||||
| enum DECODE_STATUS { |     FAILURE | ||||||
|     DECODE_SUCCESS, |  | ||||||
|     DECODE_FAILURE |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct instruction_set_encoding_item { | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); | ||||||
|  | 
 | ||||||
|  | struct InstructionSetEncodingItem { | ||||||
|     const char *name; |     const char *name; | ||||||
|     int attribute_value; |     int attribute_value; | ||||||
|     int version; |     int version; | ||||||
|     u32 content[21]; |     u32 content[21]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct instruction_set_encoding_item ISEITEM; |  | ||||||
| 
 |  | ||||||
| // ARM versions
 | // ARM versions
 | ||||||
| enum { | enum { | ||||||
|     INVALID = 0, |     INVALID = 0, | ||||||
|  | @ -38,4 +36,4 @@ enum { | ||||||
|     ARMV6K, |     ARMV6K, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern const ISEITEM arm_instruction[]; | extern const InstructionSetEncodingItem arm_instruction[]; | ||||||
|  |  | ||||||
|  | @ -47,27 +47,6 @@ enum { | ||||||
| 
 | 
 | ||||||
| typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | ||||||
| 
 | 
 | ||||||
| // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
 |  | ||||||
| // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
 |  | ||||||
| // support LDR/STREXD.
 |  | ||||||
| static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; |  | ||||||
| 
 |  | ||||||
| // Exclusive memory access
 |  | ||||||
| static int exclusive_detect(ARMul_State* state, u32 addr) { |  | ||||||
|     if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK)) |  | ||||||
|         return 0; |  | ||||||
|     else |  | ||||||
|         return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void add_exclusive_addr(ARMul_State* state, u32 addr){ |  | ||||||
|     state->exclusive_tag = addr & RESERVATION_GRANULE_MASK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void remove_exclusive(ARMul_State* state, u32 addr){ |  | ||||||
|     state->exclusive_tag = 0xFFFFFFFF; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int CondPassed(ARMul_State* cpu, unsigned int cond) { | static int CondPassed(ARMul_State* cpu, unsigned int cond) { | ||||||
|     const u32 NFLAG = cpu->NFlag; |     const u32 NFLAG = cpu->NFlag; | ||||||
|     const u32 ZFLAG = cpu->ZFlag; |     const u32 ZFLAG = cpu->ZFlag; | ||||||
|  | @ -3489,21 +3468,15 @@ enum { | ||||||
|     FETCH_FAILURE |     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
 |     // Check if in Thumb mode
 | ||||||
|     tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); |     ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); | ||||||
|     if(ret == t_branch){ |     if (ret == ThumbDecodeStatus::BRANCH) { | ||||||
|         // TODO: FIXME, endian should be judged
 |  | ||||||
|         u32 tinstr; |  | ||||||
|         if((addr & 0x3) != 0) |  | ||||||
|             tinstr = inst >> 16; |  | ||||||
|         else |  | ||||||
|             tinstr = inst & 0xFFFF; |  | ||||||
| 
 |  | ||||||
|         int inst_index; |         int inst_index; | ||||||
|         int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); |         int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); | ||||||
|  |         u32 tinstr = GetThumbInstruction(inst, addr); | ||||||
| 
 | 
 | ||||||
|         switch((tinstr & 0xF800) >> 11){ |         switch ((tinstr & 0xF800) >> 11) { | ||||||
|         case 26: |         case 26: | ||||||
|         case 27: |         case 27: | ||||||
|             if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ |             if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ | ||||||
|  | @ -3536,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); |             *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             ret = t_undefined; |             ret = ThumbDecodeStatus::UNDEFINED; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -3548,10 +3521,6 @@ enum { | ||||||
|     FETCH_EXCEPTION |     FETCH_EXCEPTION | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct instruction_set_encoding_item ISEITEM; |  | ||||||
| 
 |  | ||||||
| extern const ISEITEM arm_instruction[]; |  | ||||||
| 
 |  | ||||||
| static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | ||||||
|     Common::Profiling::ScopeTimer timer_decode(profile_decode); |     Common::Profiling::ScopeTimer timer_decode(profile_decode); | ||||||
| 
 | 
 | ||||||
|  | @ -3573,20 +3542,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | ||||||
|         inst = Memory::Read32(phys_addr & 0xFFFFFFFC); |         inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | ||||||
| 
 | 
 | ||||||
|         size++; |         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) { |         if (cpu->TFlag) { | ||||||
|             uint32_t arm_inst; |             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
 |             // We have translated the Thumb branch instruction in the Thumb decoder
 | ||||||
|             if(state == t_branch){ |             if (state == ThumbDecodeStatus::BRANCH) { | ||||||
|                 goto translated; |                 goto translated; | ||||||
|             } |             } | ||||||
|             inst = arm_inst; |             inst = arm_inst; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         ret = decode_arm_instr(inst, &idx); |         if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { | ||||||
|         if (ret == DECODE_FAILURE) { |  | ||||||
|             std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); |             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, "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]); |             LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); | ||||||
|  | @ -4174,9 +4142,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
| 
 | 
 | ||||||
|     CLREX_INST: |     CLREX_INST: | ||||||
|     { |     { | ||||||
|         remove_exclusive(cpu, 0); |         cpu->UnsetExclusiveMemoryAddress(); | ||||||
|         cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|         cpu->Reg[15] += cpu->GetInstructionSize(); |         cpu->Reg[15] += cpu->GetInstructionSize(); | ||||||
|         INC_PC(sizeof(clrex_inst)); |         INC_PC(sizeof(clrex_inst)); | ||||||
|         FETCH_INST; |         FETCH_INST; | ||||||
|  | @ -4543,8 +4509,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD = cpu->ReadMemory32(read_addr); |             RD = cpu->ReadMemory32(read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|  | @ -4563,8 +4528,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD = Memory::Read8(read_addr); |             RD = Memory::Read8(read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|  | @ -4583,8 +4547,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD = cpu->ReadMemory16(read_addr); |             RD = cpu->ReadMemory16(read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|  | @ -4603,8 +4566,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD  = cpu->ReadMemory32(read_addr); |             RD  = cpu->ReadMemory32(read_addr); | ||||||
|             RD2 = cpu->ReadMemory32(read_addr + 4); |             RD2 = cpu->ReadMemory32(read_addr + 4); | ||||||
|  | @ -6089,10 +6051,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|                 cpu->WriteMemory32(write_addr, RM); |                 cpu->WriteMemory32(write_addr, RM); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|  | @ -6111,10 +6071,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|                 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); |                 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|  | @ -6133,9 +6091,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 | 
 | ||||||
|                 const u32 rt  = cpu->Reg[inst_cream->Rm + 0]; |                 const u32 rt  = cpu->Reg[inst_cream->Rm + 0]; | ||||||
|                 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; |                 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; | ||||||
|  | @ -6165,10 +6122,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|                 cpu->WriteMemory16(write_addr, RM); |                 cpu->WriteMemory16(write_addr, RM); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|  | @ -12,15 +12,9 @@ | ||||||
| // with the following Thumb instruction held in the high 16-bits.  Passing in two Thumb instructions
 | // 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.
 | // allows easier simulation of the special dual BL instruction.
 | ||||||
| 
 | 
 | ||||||
| tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | ||||||
|     tdstate valid = t_uninitialized; |     ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED; | ||||||
|     u32 tinstr = instr; |     u32 tinstr = GetThumbInstruction(instr, addr); | ||||||
| 
 |  | ||||||
|     // The endian should be judge here
 |  | ||||||
|     if((addr & 0x3) != 0) |  | ||||||
|         tinstr = instr >> 16; |  | ||||||
|     else |  | ||||||
|         tinstr &= 0xFFFF; |  | ||||||
| 
 | 
 | ||||||
|     *ainstr = 0xDEADC0DE; // Debugging to catch non updates
 |     *ainstr = 0xDEADC0DE; // Debugging to catch non updates
 | ||||||
| 
 | 
 | ||||||
|  | @ -357,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | ||||||
|             else |             else | ||||||
|                 *ainstr |= (tinstr & 0x00FF); |                 *ainstr |= (tinstr & 0x00FF); | ||||||
|         } else if ((tinstr & 0x0F00) != 0x0E00) |         } else if ((tinstr & 0x0F00) != 0x0E00) | ||||||
|             valid = t_branch; |             valid = ThumbDecodeStatus::BRANCH; | ||||||
|         else //  UNDEFINED : cc=1110(AL) uses different format
 |         else //  UNDEFINED : cc=1110(AL) uses different format
 | ||||||
|             valid = t_undefined; |             valid = ThumbDecodeStatus::UNDEFINED; | ||||||
| 
 | 
 | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case 28: // B
 |     case 28: // B
 | ||||||
|         valid = t_branch; |         valid = ThumbDecodeStatus::BRANCH; | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case 29: |     case 29: | ||||||
|         if(tinstr & 0x1) |         if (tinstr & 0x1) | ||||||
|             valid = t_undefined; |             valid = ThumbDecodeStatus::UNDEFINED; | ||||||
|         else |         else | ||||||
|             valid = t_branch; |             valid = ThumbDecodeStatus::BRANCH; | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case 30: // BL instruction 1
 |     case 30: // BL instruction 1
 | ||||||
|  | @ -380,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
 |         // 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
 |         // the second half of this BL, and if it is we simulate it immediately
 | ||||||
| 
 | 
 | ||||||
|         valid = t_branch; |         valid = ThumbDecodeStatus::BRANCH; | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case 31: // BL instruction 2
 |     case 31: // BL instruction 2
 | ||||||
|  | @ -389,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
 |         // 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.
 |         // simulation of it on its own, with undefined results if r14 is not suitably initialised.
 | ||||||
| 
 | 
 | ||||||
|         valid = t_branch; |         valid = ThumbDecodeStatus::BRANCH; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,20 +28,22 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| enum tdstate { | enum class ThumbDecodeStatus { | ||||||
|     t_undefined,    // Undefined Thumb instruction
 |     UNDEFINED,    // Undefined Thumb instruction
 | ||||||
|     t_decoded,      // Instruction decoded to ARM equivalent
 |     DECODED,      // Instruction decoded to ARM equivalent
 | ||||||
|     t_branch,       // Thumb branch (already processed)
 |     BRANCH,       // Thumb branch (already processed)
 | ||||||
|     t_uninitialized, |     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 get_thumb_instr(u32 instr, u32 pc) { | static inline u32 GetThumbInstruction(u32 instr, u32 address) { | ||||||
|     u32 tinstr; |     // Normally you would need to handle instruction endianness,
 | ||||||
|     if ((pc & 0x3) != 0) |     // however, it is fixed to little-endian on the MPCore, so
 | ||||||
|         tinstr = instr >> 16; |     // there's no need to check for this beforehand.
 | ||||||
|     else |     if ((address & 0x3) != 0) | ||||||
|         tinstr = instr & 0xFFFF; |         return instr >> 16; | ||||||
|     return tinstr; | 
 | ||||||
|  |     return instr & 0xFFFF; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -163,6 +163,19 @@ public: | ||||||
|     u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; |     u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; | ||||||
|     void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); |     void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); | ||||||
| 
 | 
 | ||||||
|  |     // Exclusive memory access functions
 | ||||||
|  |     bool IsExclusiveMemoryAccess(u32 address) const { | ||||||
|  |         return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK); | ||||||
|  |     } | ||||||
|  |     void SetExclusiveMemoryAddress(u32 address) { | ||||||
|  |         exclusive_tag = address & RESERVATION_GRANULE_MASK; | ||||||
|  |         exclusive_state = true; | ||||||
|  |     } | ||||||
|  |     void UnsetExclusiveMemoryAddress() { | ||||||
|  |         exclusive_tag = 0xFFFFFFFF; | ||||||
|  |         exclusive_state = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Whether or not the given CPU is in big endian mode (E bit is set)
 |     // Whether or not the given CPU is in big endian mode (E bit is set)
 | ||||||
|     bool InBigEndianMode() const { |     bool InBigEndianMode() const { | ||||||
|         return (Cpsr & (1 << 9)) != 0; |         return (Cpsr & (1 << 9)) != 0; | ||||||
|  | @ -203,9 +216,6 @@ public: | ||||||
| 
 | 
 | ||||||
|     u32 Mode;          // The current mode
 |     u32 Mode;          // The current mode
 | ||||||
|     u32 Bank;          // The current register bank
 |     u32 Bank;          // The current register bank
 | ||||||
|     u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
 |  | ||||||
|     u32 exclusive_state; |  | ||||||
|     u32 exclusive_result; |  | ||||||
| 
 | 
 | ||||||
|     u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
 |     u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
 | ||||||
|     unsigned int shifter_carry_out; |     unsigned int shifter_carry_out; | ||||||
|  | @ -230,4 +240,13 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void ResetMPCoreCP15Registers(); |     void ResetMPCoreCP15Registers(); | ||||||
|  | 
 | ||||||
|  |     // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
 | ||||||
|  |     // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
 | ||||||
|  |     // support LDR/STREXD.
 | ||||||
|  |     static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | ||||||
|  | 
 | ||||||
|  |     u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
 | ||||||
|  |     u32 exclusive_result; | ||||||
|  |     bool exclusive_state; | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue