summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp25
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h16
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp93
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp28
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h28
-rw-r--r--src/core/arm/skyeye_common/armstate.h25
6 files changed, 91 insertions, 124 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 3ab9f2c17..ee4288314 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -5,7 +5,7 @@
5#include "core/arm/dyncom/arm_dyncom_dec.h" 5#include "core/arm/dyncom/arm_dyncom_dec.h"
6#include "core/arm/skyeye_common/armsupp.h" 6#include "core/arm/skyeye_common/armsupp.h"
7 7
8const ISEITEM arm_instruction[] = { 8const InstructionSetEncodingItem arm_instruction[] = {
9 { "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }}, 9 { "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }},
10 { "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }}, 10 { "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }},
11 { "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }}, 11 { "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }},
@@ -207,7 +207,7 @@ const ISEITEM arm_instruction[] = {
207 { "bbl", 1, 0, { 25, 27, 0x00000005 }}, 207 { "bbl", 1, 0, { 25, 27, 0x00000005 }},
208}; 208};
209 209
210const ISEITEM arm_exclusion_code[] = { 210const InstructionSetEncodingItem arm_exclusion_code[] = {
211 { "vmla", 0, ARMVFP2, { 0 }}, 211 { "vmla", 0, ARMVFP2, { 0 }},
212 { "vmls", 0, ARMVFP2, { 0 }}, 212 { "vmls", 0, ARMVFP2, { 0 }},
213 { "vnmla", 0, ARMVFP2, { 0 }}, 213 { "vnmla", 0, ARMVFP2, { 0 }},
@@ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = {
414 { "invalid", 0, INVALID, { 0 }} 414 { "invalid", 0, INVALID, { 0 }}
415}; 415};
416 416
417int decode_arm_instr(u32 instr, s32* idx) { 417ARMDecodeStatus 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; 420 int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem);
421 int i = 0; 421 ARMDecodeStatus ret = ARMDecodeStatus::FAILURE;
422 int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM);
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..d7170e0fc 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.h
+++ b/src/core/arm/dyncom/arm_dyncom_dec.h
@@ -6,22 +6,20 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9int decode_arm_instr(u32 instr, s32* idx); 9enum class ARMDecodeStatus {
10 10 SUCCESS,
11enum DECODE_STATUS { 11 FAILURE
12 DECODE_SUCCESS,
13 DECODE_FAILURE
14}; 12};
15 13
16struct instruction_set_encoding_item { 14ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx);
15
16struct InstructionSetEncodingItem {
17 const char *name; 17 const char *name;
18 int attribute_value; 18 int attribute_value;
19 int version; 19 int version;
20 u32 content[21]; 20 u32 content[21];
21}; 21};
22 22
23typedef struct instruction_set_encoding_item ISEITEM;
24
25// ARM versions 23// ARM versions
26enum { 24enum {
27 INVALID = 0, 25 INVALID = 0,
@@ -38,4 +36,4 @@ enum {
38 ARMV6K, 36 ARMV6K,
39}; 37};
40 38
41extern const ISEITEM arm_instruction[]; 39extern const InstructionSetEncodingItem arm_instruction[];
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index cf09acb4e..d022546ed 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -47,27 +47,6 @@ enum {
47 47
48typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); 48typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
49 49
50// Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
51// This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
52// support LDR/STREXD.
53static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
54
55// Exclusive memory access
56static int exclusive_detect(ARMul_State* state, u32 addr) {
57 if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK))
58 return 0;
59 else
60 return -1;
61}
62
63static void add_exclusive_addr(ARMul_State* state, u32 addr){
64 state->exclusive_tag = addr & RESERVATION_GRANULE_MASK;
65}
66
67static void remove_exclusive(ARMul_State* state, u32 addr){
68 state->exclusive_tag = 0xFFFFFFFF;
69}
70
71static int CondPassed(ARMul_State* cpu, unsigned int cond) { 50static int CondPassed(ARMul_State* cpu, unsigned int cond) {
72 const u32 NFLAG = cpu->NFlag; 51 const u32 NFLAG = cpu->NFlag;
73 const u32 ZFLAG = cpu->ZFlag; 52 const u32 ZFLAG = cpu->ZFlag;
@@ -3489,21 +3468,15 @@ enum {
3489 FETCH_FAILURE 3468 FETCH_FAILURE
3490}; 3469};
3491 3470
3492static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { 3471static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) {
3493 // Check if in Thumb mode 3472 // Check if in Thumb mode
3494 tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); 3473 ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size);
3495 if(ret == t_branch){ 3474 if (ret == ThumbDecodeStatus::BRANCH) {
3496 // TODO: FIXME, endian should be judged
3497 u32 tinstr;
3498 if((addr & 0x3) != 0)
3499 tinstr = inst >> 16;
3500 else
3501 tinstr = inst & 0xFFFF;
3502
3503 int inst_index; 3475 int inst_index;
3504 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);
3505 3478
3506 switch((tinstr & 0xF800) >> 11){ 3479 switch ((tinstr & 0xF800) >> 11) {
3507 case 26: 3480 case 26:
3508 case 27: 3481 case 27:
3509 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ 3482 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
3536 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 3509 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3537 break; 3510 break;
3538 default: 3511 default:
3539 ret = t_undefined; 3512 ret = ThumbDecodeStatus::UNDEFINED;
3540 break; 3513 break;
3541 } 3514 }
3542 } 3515 }
@@ -3548,10 +3521,6 @@ enum {
3548 FETCH_EXCEPTION 3521 FETCH_EXCEPTION
3549}; 3522};
3550 3523
3551typedef struct instruction_set_encoding_item ISEITEM;
3552
3553extern const ISEITEM arm_instruction[];
3554
3555static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { 3524static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
3556 Common::Profiling::ScopeTimer timer_decode(profile_decode); 3525 Common::Profiling::ScopeTimer timer_decode(profile_decode);
3557 3526
@@ -3573,20 +3542,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
3573 inst = Memory::Read32(phys_addr & 0xFFFFFFFC); 3542 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
3574 3543
3575 size++; 3544 size++;
3576 // 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
3577 if (cpu->TFlag) { 3546 if (cpu->TFlag) {
3578 uint32_t arm_inst; 3547 uint32_t arm_inst;
3579 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);
3580 3549
3581 // We have translated the branch instruction of thumb in thumb decoder 3550 // We have translated the Thumb branch instruction in the Thumb decoder
3582 if(state == t_branch){ 3551 if (state == ThumbDecodeStatus::BRANCH) {
3583 goto translated; 3552 goto translated;
3584 } 3553 }
3585 inst = arm_inst; 3554 inst = arm_inst;
3586 } 3555 }
3587 3556
3588 ret = decode_arm_instr(inst, &idx); 3557 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
3589 if (ret == DECODE_FAILURE) {
3590 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); 3558 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
3591 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);
3592 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]);
@@ -4174,9 +4142,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4174 4142
4175 CLREX_INST: 4143 CLREX_INST:
4176 { 4144 {
4177 remove_exclusive(cpu, 0); 4145 cpu->UnsetExclusiveMemoryAddress();
4178 cpu->exclusive_state = 0;
4179
4180 cpu->Reg[15] += cpu->GetInstructionSize(); 4146 cpu->Reg[15] += cpu->GetInstructionSize();
4181 INC_PC(sizeof(clrex_inst)); 4147 INC_PC(sizeof(clrex_inst));
4182 FETCH_INST; 4148 FETCH_INST;
@@ -4543,8 +4509,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4543 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4509 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4544 unsigned int read_addr = RN; 4510 unsigned int read_addr = RN;
4545 4511
4546 add_exclusive_addr(cpu, read_addr); 4512 cpu->SetExclusiveMemoryAddress(read_addr);
4547 cpu->exclusive_state = 1;
4548 4513
4549 RD = cpu->ReadMemory32(read_addr); 4514 RD = cpu->ReadMemory32(read_addr);
4550 if (inst_cream->Rd == 15) { 4515 if (inst_cream->Rd == 15) {
@@ -4563,8 +4528,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4563 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4528 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4564 unsigned int read_addr = RN; 4529 unsigned int read_addr = RN;
4565 4530
4566 add_exclusive_addr(cpu, read_addr); 4531 cpu->SetExclusiveMemoryAddress(read_addr);
4567 cpu->exclusive_state = 1;
4568 4532
4569 RD = Memory::Read8(read_addr); 4533 RD = Memory::Read8(read_addr);
4570 if (inst_cream->Rd == 15) { 4534 if (inst_cream->Rd == 15) {
@@ -4583,8 +4547,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4583 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4547 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4584 unsigned int read_addr = RN; 4548 unsigned int read_addr = RN;
4585 4549
4586 add_exclusive_addr(cpu, read_addr); 4550 cpu->SetExclusiveMemoryAddress(read_addr);
4587 cpu->exclusive_state = 1;
4588 4551
4589 RD = cpu->ReadMemory16(read_addr); 4552 RD = cpu->ReadMemory16(read_addr);
4590 if (inst_cream->Rd == 15) { 4553 if (inst_cream->Rd == 15) {
@@ -4603,8 +4566,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4603 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4566 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4604 unsigned int read_addr = RN; 4567 unsigned int read_addr = RN;
4605 4568
4606 add_exclusive_addr(cpu, read_addr); 4569 cpu->SetExclusiveMemoryAddress(read_addr);
4607 cpu->exclusive_state = 1;
4608 4570
4609 RD = cpu->ReadMemory32(read_addr); 4571 RD = cpu->ReadMemory32(read_addr);
4610 RD2 = cpu->ReadMemory32(read_addr + 4); 4572 RD2 = cpu->ReadMemory32(read_addr + 4);
@@ -6089,10 +6051,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6089 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6051 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6090 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6052 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6091 6053
6092 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6054 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6093 remove_exclusive(cpu, write_addr); 6055 cpu->UnsetExclusiveMemoryAddress();
6094 cpu->exclusive_state = 0;
6095
6096 cpu->WriteMemory32(write_addr, RM); 6056 cpu->WriteMemory32(write_addr, RM);
6097 RD = 0; 6057 RD = 0;
6098 } else { 6058 } else {
@@ -6111,10 +6071,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6111 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6071 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6112 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6072 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6113 6073
6114 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6074 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6115 remove_exclusive(cpu, write_addr); 6075 cpu->UnsetExclusiveMemoryAddress();
6116 cpu->exclusive_state = 0;
6117
6118 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); 6076 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]);
6119 RD = 0; 6077 RD = 0;
6120 } else { 6078 } else {
@@ -6133,9 +6091,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6133 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6091 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6134 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6092 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6135 6093
6136 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6094 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6137 remove_exclusive(cpu, write_addr); 6095 cpu->UnsetExclusiveMemoryAddress();
6138 cpu->exclusive_state = 0;
6139 6096
6140 const u32 rt = cpu->Reg[inst_cream->Rm + 0]; 6097 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
6141 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; 6098 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
@@ -6165,10 +6122,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6165 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6122 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6166 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6123 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6167 6124
6168 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6125 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6169 remove_exclusive(cpu, write_addr); 6126 cpu->UnsetExclusiveMemoryAddress();
6170 cpu->exclusive_state = 0;
6171
6172 cpu->WriteMemory16(write_addr, RM); 6127 cpu->WriteMemory16(write_addr, RM);
6173 RD = 0; 6128 RD = 0;
6174 } else { 6129 } else {
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index 2860af376..29272fd5d 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -12,15 +12,9 @@
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
15tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { 15ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
16 tdstate valid = t_uninitialized; 16 ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED;
17 u32 tinstr = instr; 17 u32 tinstr = GetThumbInstruction(instr, addr);
18
19 // The endian should be judge here
20 if((addr & 0x3) != 0)
21 tinstr = instr >> 16;
22 else
23 tinstr &= 0xFFFF;
24 18
25 *ainstr = 0xDEADC0DE; // Debugging to catch non updates 19 *ainstr = 0xDEADC0DE; // Debugging to catch non updates
26 20
@@ -357,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
357 else 351 else
358 *ainstr |= (tinstr & 0x00FF); 352 *ainstr |= (tinstr & 0x00FF);
359 } else if ((tinstr & 0x0F00) != 0x0E00) 353 } else if ((tinstr & 0x0F00) != 0x0E00)
360 valid = t_branch; 354 valid = ThumbDecodeStatus::BRANCH;
361 else // UNDEFINED : cc=1110(AL) uses different format 355 else // UNDEFINED : cc=1110(AL) uses different format
362 valid = t_undefined; 356 valid = ThumbDecodeStatus::UNDEFINED;
363 357
364 break; 358 break;
365 359
366 case 28: // B 360 case 28: // B
367 valid = t_branch; 361 valid = ThumbDecodeStatus::BRANCH;
368 break; 362 break;
369 363
370 case 29: 364 case 29:
371 if(tinstr & 0x1) 365 if (tinstr & 0x1)
372 valid = t_undefined; 366 valid = ThumbDecodeStatus::UNDEFINED;
373 else 367 else
374 valid = t_branch; 368 valid = ThumbDecodeStatus::BRANCH;
375 break; 369 break;
376 370
377 case 30: // BL instruction 1 371 case 30: // BL instruction 1
@@ -380,7 +374,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
380 // 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
381 // 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
382 376
383 valid = t_branch; 377 valid = ThumbDecodeStatus::BRANCH;
384 break; 378 break;
385 379
386 case 31: // BL instruction 2 380 case 31: // BL instruction 2
@@ -389,7 +383,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
389 // 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
390 // 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.
391 385
392 valid = t_branch; 386 valid = ThumbDecodeStatus::BRANCH;
393 break; 387 break;
394 } 388 }
395 389
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
index c06f09580..447974363 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -28,20 +28,22 @@
28 28
29#include "common/common_types.h" 29#include "common/common_types.h"
30 30
31enum tdstate { 31enum 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
38tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size); 38// Translates a Thumb mode instruction into its ARM equivalent.
39ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
39 40
40static inline u32 get_thumb_instr(u32 instr, u32 pc) { 41static inline u32 GetThumbInstruction(u32 instr, u32 address) {
41 u32 tinstr; 42 // Normally you would need to handle instruction endianness,
42 if ((pc & 0x3) != 0) 43 // however, it is fixed to little-endian on the MPCore, so
43 tinstr = instr >> 16; 44 // there's no need to check for this beforehand.
44 else 45 if ((address & 0x3) != 0)
45 tinstr = instr & 0xFFFF; 46 return instr >> 16;
46 return tinstr; 47
48 return instr & 0xFFFF;
47} 49}
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h
index 88c1dab9d..b364e2621 100644
--- a/src/core/arm/skyeye_common/armstate.h
+++ b/src/core/arm/skyeye_common/armstate.h
@@ -163,6 +163,19 @@ public:
163 u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; 163 u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const;
164 void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); 164 void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
165 165
166 // Exclusive memory access functions
167 bool IsExclusiveMemoryAccess(u32 address) const {
168 return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK);
169 }
170 void SetExclusiveMemoryAddress(u32 address) {
171 exclusive_tag = address & RESERVATION_GRANULE_MASK;
172 exclusive_state = true;
173 }
174 void UnsetExclusiveMemoryAddress() {
175 exclusive_tag = 0xFFFFFFFF;
176 exclusive_state = false;
177 }
178
166 // Whether or not the given CPU is in big endian mode (E bit is set) 179 // Whether or not the given CPU is in big endian mode (E bit is set)
167 bool InBigEndianMode() const { 180 bool InBigEndianMode() const {
168 return (Cpsr & (1 << 9)) != 0; 181 return (Cpsr & (1 << 9)) != 0;
@@ -203,9 +216,6 @@ public:
203 216
204 u32 Mode; // The current mode 217 u32 Mode; // The current mode
205 u32 Bank; // The current register bank 218 u32 Bank; // The current register bank
206 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
207 u32 exclusive_state;
208 u32 exclusive_result;
209 219
210 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed 220 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
211 unsigned int shifter_carry_out; 221 unsigned int shifter_carry_out;
@@ -230,4 +240,13 @@ public:
230 240
231private: 241private:
232 void ResetMPCoreCP15Registers(); 242 void ResetMPCoreCP15Registers();
243
244 // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
245 // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
246 // support LDR/STREXD.
247 static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
248
249 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
250 u32 exclusive_result;
251 bool exclusive_state;
233}; 252};