diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.cpp | 19 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.h | 10 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 19 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_thumb.cpp | 20 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_thumb.h | 13 |
5 files changed, 40 insertions, 41 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 3ab9f2c17..48fc1c683 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp | |||
| @@ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = { | |||
| 414 | { "invalid", 0, INVALID, { 0 }} | 414 | { "invalid", 0, INVALID, { 0 }} |
| 415 | }; | 415 | }; |
| 416 | 416 | ||
| 417 | int decode_arm_instr(u32 instr, s32* idx) { | 417 | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { |
| 418 | int n = 0; | 418 | int n = 0; |
| 419 | int base = 0; | 419 | int base = 0; |
| 420 | int ret = DECODE_FAILURE; | ||
| 421 | int i = 0; | ||
| 422 | int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM); | 420 | int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM); |
| 421 | ARMDecodeStatus ret = ARMDecodeStatus::FAILURE; | ||
| 423 | 422 | ||
| 424 | for (i = 0; i < instr_slots; i++) { | 423 | for (int i = 0; i < instr_slots; i++) { |
| 425 | n = arm_instruction[i].attribute_value; | 424 | n = arm_instruction[i].attribute_value; |
| 426 | base = 0; | 425 | base = 0; |
| 427 | 426 | ||
| @@ -438,11 +437,11 @@ int decode_arm_instr(u32 instr, s32* idx) { | |||
| 438 | n--; | 437 | n--; |
| 439 | } | 438 | } |
| 440 | 439 | ||
| 441 | // All conditions is satisfied. | 440 | // All conditions are satisfied. |
| 442 | if (n == 0) | 441 | if (n == 0) |
| 443 | ret = DECODE_SUCCESS; | 442 | ret = ARMDecodeStatus::SUCCESS; |
| 444 | 443 | ||
| 445 | if (ret == DECODE_SUCCESS) { | 444 | if (ret == ARMDecodeStatus::SUCCESS) { |
| 446 | n = arm_exclusion_code[i].attribute_value; | 445 | n = arm_exclusion_code[i].attribute_value; |
| 447 | if (n != 0) { | 446 | if (n != 0) { |
| 448 | base = 0; | 447 | base = 0; |
| @@ -454,13 +453,13 @@ int decode_arm_instr(u32 instr, s32* idx) { | |||
| 454 | n--; | 453 | n--; |
| 455 | } | 454 | } |
| 456 | 455 | ||
| 457 | // All conditions is satisfied. | 456 | // All conditions are satisfied. |
| 458 | if (n == 0) | 457 | if (n == 0) |
| 459 | ret = DECODE_FAILURE; | 458 | ret = ARMDecodeStatus::FAILURE; |
| 460 | } | 459 | } |
| 461 | } | 460 | } |
| 462 | 461 | ||
| 463 | if (ret == DECODE_SUCCESS) { | 462 | if (ret == ARMDecodeStatus::SUCCESS) { |
| 464 | *idx = i; | 463 | *idx = i; |
| 465 | return ret; | 464 | return ret; |
| 466 | } | 465 | } |
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index 5f6279627..80d910218 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h | |||
| @@ -6,13 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | int decode_arm_instr(u32 instr, s32* idx); | 9 | enum class ARMDecodeStatus { |
| 10 | 10 | SUCCESS, | |
| 11 | enum DECODE_STATUS { | 11 | FAILURE |
| 12 | DECODE_SUCCESS, | ||
| 13 | DECODE_FAILURE | ||
| 14 | }; | 12 | }; |
| 15 | 13 | ||
| 14 | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); | ||
| 15 | |||
| 16 | struct instruction_set_encoding_item { | 16 | struct instruction_set_encoding_item { |
| 17 | const char *name; | 17 | const char *name; |
| 18 | int attribute_value; | 18 | int attribute_value; |
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index cdef72be6..d022546ed 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -3468,10 +3468,10 @@ enum { | |||
| 3468 | FETCH_FAILURE | 3468 | FETCH_FAILURE |
| 3469 | }; | 3469 | }; |
| 3470 | 3470 | ||
| 3471 | static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { | 3471 | static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { |
| 3472 | // Check if in Thumb mode | 3472 | // Check if in Thumb mode |
| 3473 | tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); | 3473 | ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); |
| 3474 | if (ret == t_branch) { | 3474 | if (ret == ThumbDecodeStatus::BRANCH) { |
| 3475 | int inst_index; | 3475 | int inst_index; |
| 3476 | int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); | 3476 | int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); |
| 3477 | u32 tinstr = GetThumbInstruction(inst, addr); | 3477 | u32 tinstr = GetThumbInstruction(inst, addr); |
| @@ -3509,7 +3509,7 @@ static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_s | |||
| 3509 | *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); | 3509 | *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); |
| 3510 | break; | 3510 | break; |
| 3511 | default: | 3511 | default: |
| 3512 | ret = t_undefined; | 3512 | ret = ThumbDecodeStatus::UNDEFINED; |
| 3513 | break; | 3513 | break; |
| 3514 | } | 3514 | } |
| 3515 | } | 3515 | } |
| @@ -3542,20 +3542,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | |||
| 3542 | inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | 3542 | inst = Memory::Read32(phys_addr & 0xFFFFFFFC); |
| 3543 | 3543 | ||
| 3544 | size++; | 3544 | size++; |
| 3545 | // If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction | 3545 | // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction |
| 3546 | if (cpu->TFlag) { | 3546 | if (cpu->TFlag) { |
| 3547 | uint32_t arm_inst; | 3547 | uint32_t arm_inst; |
| 3548 | tdstate state = decode_thumb_instr(inst, phys_addr, &arm_inst, &inst_size, &inst_base); | 3548 | ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); |
| 3549 | 3549 | ||
| 3550 | // We have translated the branch instruction of thumb in thumb decoder | 3550 | // We have translated the Thumb branch instruction in the Thumb decoder |
| 3551 | if(state == t_branch){ | 3551 | if (state == ThumbDecodeStatus::BRANCH) { |
| 3552 | goto translated; | 3552 | goto translated; |
| 3553 | } | 3553 | } |
| 3554 | inst = arm_inst; | 3554 | inst = arm_inst; |
| 3555 | } | 3555 | } |
| 3556 | 3556 | ||
| 3557 | ret = decode_arm_instr(inst, &idx); | 3557 | if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { |
| 3558 | if (ret == DECODE_FAILURE) { | ||
| 3559 | std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); | 3558 | std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); |
| 3560 | LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); | 3559 | LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); |
| 3561 | LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); | 3560 | LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); |
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp index 6eb03fb5a..29272fd5d 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp +++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | // with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions | 12 | // with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions |
| 13 | // allows easier simulation of the special dual BL instruction. | 13 | // allows easier simulation of the special dual BL instruction. |
| 14 | 14 | ||
| 15 | tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | 15 | ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { |
| 16 | tdstate valid = t_uninitialized; | 16 | ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED; |
| 17 | u32 tinstr = GetThumbInstruction(instr, addr); | 17 | u32 tinstr = GetThumbInstruction(instr, addr); |
| 18 | 18 | ||
| 19 | *ainstr = 0xDEADC0DE; // Debugging to catch non updates | 19 | *ainstr = 0xDEADC0DE; // Debugging to catch non updates |
| @@ -351,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 351 | else | 351 | else |
| 352 | *ainstr |= (tinstr & 0x00FF); | 352 | *ainstr |= (tinstr & 0x00FF); |
| 353 | } else if ((tinstr & 0x0F00) != 0x0E00) | 353 | } else if ((tinstr & 0x0F00) != 0x0E00) |
| 354 | valid = t_branch; | 354 | valid = ThumbDecodeStatus::BRANCH; |
| 355 | else // UNDEFINED : cc=1110(AL) uses different format | 355 | else // UNDEFINED : cc=1110(AL) uses different format |
| 356 | valid = t_undefined; | 356 | valid = ThumbDecodeStatus::UNDEFINED; |
| 357 | 357 | ||
| 358 | break; | 358 | break; |
| 359 | 359 | ||
| 360 | case 28: // B | 360 | case 28: // B |
| 361 | valid = t_branch; | 361 | valid = ThumbDecodeStatus::BRANCH; |
| 362 | break; | 362 | break; |
| 363 | 363 | ||
| 364 | case 29: | 364 | case 29: |
| 365 | if(tinstr & 0x1) | 365 | if (tinstr & 0x1) |
| 366 | valid = t_undefined; | 366 | valid = ThumbDecodeStatus::UNDEFINED; |
| 367 | else | 367 | else |
| 368 | valid = t_branch; | 368 | valid = ThumbDecodeStatus::BRANCH; |
| 369 | break; | 369 | break; |
| 370 | 370 | ||
| 371 | case 30: // BL instruction 1 | 371 | case 30: // BL instruction 1 |
| @@ -374,7 +374,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 374 | // simulation simple (from the user perspective) we check if the following instruction is | 374 | // simulation simple (from the user perspective) we check if the following instruction is |
| 375 | // the second half of this BL, and if it is we simulate it immediately | 375 | // the second half of this BL, and if it is we simulate it immediately |
| 376 | 376 | ||
| 377 | valid = t_branch; | 377 | valid = ThumbDecodeStatus::BRANCH; |
| 378 | break; | 378 | break; |
| 379 | 379 | ||
| 380 | case 31: // BL instruction 2 | 380 | case 31: // BL instruction 2 |
| @@ -383,7 +383,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { | |||
| 383 | // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the | 383 | // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the |
| 384 | // simulation of it on its own, with undefined results if r14 is not suitably initialised. | 384 | // simulation of it on its own, with undefined results if r14 is not suitably initialised. |
| 385 | 385 | ||
| 386 | valid = t_branch; | 386 | valid = ThumbDecodeStatus::BRANCH; |
| 387 | break; | 387 | break; |
| 388 | } | 388 | } |
| 389 | 389 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h index 74e69e13a..447974363 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.h +++ b/src/core/arm/dyncom/arm_dyncom_thumb.h | |||
| @@ -28,14 +28,15 @@ | |||
| 28 | 28 | ||
| 29 | #include "common/common_types.h" | 29 | #include "common/common_types.h" |
| 30 | 30 | ||
| 31 | enum tdstate { | 31 | enum class ThumbDecodeStatus { |
| 32 | t_undefined, // Undefined Thumb instruction | 32 | UNDEFINED, // Undefined Thumb instruction |
| 33 | t_decoded, // Instruction decoded to ARM equivalent | 33 | DECODED, // Instruction decoded to ARM equivalent |
| 34 | t_branch, // Thumb branch (already processed) | 34 | BRANCH, // Thumb branch (already processed) |
| 35 | t_uninitialized, | 35 | UNINITIALIZED, |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size); | 38 | // Translates a Thumb mode instruction into its ARM equivalent. |
| 39 | ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size); | ||
| 39 | 40 | ||
| 40 | static inline u32 GetThumbInstruction(u32 instr, u32 address) { | 41 | static inline u32 GetThumbInstruction(u32 instr, u32 address) { |
| 41 | // Normally you would need to handle instruction endianness, | 42 | // Normally you would need to handle instruction endianness, |