diff options
| author | 2015-01-05 02:17:00 -0500 | |
|---|---|---|
| committer | 2015-01-05 22:29:51 -0500 | |
| commit | 8132c01830c9e71e75e6bc1e365326cf07c5b00f (patch) | |
| tree | ad7c0dc3e66c477a42280a9672d68d0be48607cc | |
| parent | Merge pull request #397 from bunnei/vfp-cleanup (diff) | |
| download | yuzu-8132c01830c9e71e75e6bc1e365326cf07c5b00f.tar.gz yuzu-8132c01830c9e71e75e6bc1e365326cf07c5b00f.tar.xz yuzu-8132c01830c9e71e75e6bc1e365326cf07c5b00f.zip | |
Added exclusive reservation granule from ARMv7 spec to dyncom to protect LDR/STREX.
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 12 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 22 |
2 files changed, 18 insertions, 16 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 64335b9c2..ba23ef383 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -63,16 +63,21 @@ extern void switch_mode(arm_core_t *core, uint32_t mode); | |||
| 63 | typedef arm_core_t arm_processor; | 63 | typedef arm_core_t arm_processor; |
| 64 | typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); | 64 | typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); |
| 65 | 65 | ||
| 66 | // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. | ||
| 67 | // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to | ||
| 68 | // support LDR/STREXD. | ||
| 69 | static const ARMword RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | ||
| 70 | |||
| 66 | // Exclusive memory access | 71 | // Exclusive memory access |
| 67 | static int exclusive_detect(ARMul_State* state, ARMword addr){ | 72 | static int exclusive_detect(ARMul_State* state, ARMword addr){ |
| 68 | if(state->exclusive_tag == addr) | 73 | if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK)) |
| 69 | return 0; | 74 | return 0; |
| 70 | else | 75 | else |
| 71 | return -1; | 76 | return -1; |
| 72 | } | 77 | } |
| 73 | 78 | ||
| 74 | static void add_exclusive_addr(ARMul_State* state, ARMword addr){ | 79 | static void add_exclusive_addr(ARMul_State* state, ARMword addr){ |
| 75 | state->exclusive_tag = addr; | 80 | state->exclusive_tag = addr & RESERVATION_GRANULE_MASK; |
| 76 | return; | 81 | return; |
| 77 | } | 82 | } |
| 78 | 83 | ||
| @@ -80,7 +85,6 @@ static void remove_exclusive(ARMul_State* state, ARMword addr){ | |||
| 80 | state->exclusive_tag = 0xFFFFFFFF; | 85 | state->exclusive_tag = 0xFFFFFFFF; |
| 81 | } | 86 | } |
| 82 | 87 | ||
| 83 | |||
| 84 | unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) { | 88 | unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) { |
| 85 | unsigned int immed_8 = BITS(sht_oper, 0, 7); | 89 | unsigned int immed_8 = BITS(sht_oper, 0, 7); |
| 86 | unsigned int rotate_imm = BITS(sht_oper, 8, 11); | 90 | unsigned int rotate_imm = BITS(sht_oper, 8, 11); |
| @@ -4551,7 +4555,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4551 | 4555 | ||
| 4552 | add_exclusive_addr(cpu, read_addr); | 4556 | add_exclusive_addr(cpu, read_addr); |
| 4553 | cpu->exclusive_state = 1; | 4557 | cpu->exclusive_state = 1; |
| 4554 | // TODO(bunnei): Do we need to also make [read_addr + 4] exclusive? | ||
| 4555 | 4558 | ||
| 4556 | RD = Memory::Read32(read_addr); | 4559 | RD = Memory::Read32(read_addr); |
| 4557 | RD2 = Memory::Read32(read_addr + 4); | 4560 | RD2 = Memory::Read32(read_addr + 4); |
| @@ -5978,7 +5981,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 5978 | if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { | 5981 | if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |
| 5979 | remove_exclusive(cpu, write_addr); | 5982 | remove_exclusive(cpu, write_addr); |
| 5980 | cpu->exclusive_state = 0; | 5983 | cpu->exclusive_state = 0; |
| 5981 | // TODO(bunnei): Remove exclusive from [write_addr + 4] if we implement this in LDREXD | ||
| 5982 | 5984 | ||
| 5983 | Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); | 5985 | Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); |
| 5984 | Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]); | 5986 | Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]); |
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index c2c78cd5a..4592c5808 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h | |||
| @@ -162,20 +162,20 @@ struct ARMul_State | |||
| 162 | unsigned ErrorCode; /* type of illegal instruction */ | 162 | unsigned ErrorCode; /* type of illegal instruction */ |
| 163 | 163 | ||
| 164 | /* Order of the following register should not be modified */ | 164 | /* Order of the following register should not be modified */ |
| 165 | ARMword Reg[16]; /* the current register file */ | 165 | ARMword Reg[16]; /* the current register file */ |
| 166 | ARMword Cpsr; /* the current psr */ | 166 | ARMword Cpsr; /* the current psr */ |
| 167 | ARMword Spsr_copy; | 167 | ARMword Spsr_copy; |
| 168 | ARMword phys_pc; | 168 | ARMword phys_pc; |
| 169 | ARMword Reg_usr[2]; | 169 | ARMword Reg_usr[2]; |
| 170 | ARMword Reg_svc[2]; /* R13_SVC R14_SVC */ | 170 | ARMword Reg_svc[2]; /* R13_SVC R14_SVC */ |
| 171 | ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */ | 171 | ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */ |
| 172 | ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */ | 172 | ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */ |
| 173 | ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */ | 173 | ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */ |
| 174 | ARMword Reg_firq[7]; /* R8---R14 FIRQ */ | 174 | ARMword Reg_firq[7]; /* R8---R14 FIRQ */ |
| 175 | ARMword Spsr[7]; /* the exception psr's */ | 175 | ARMword Spsr[7]; /* the exception psr's */ |
| 176 | ARMword Mode; /* the current mode */ | 176 | ARMword Mode; /* the current mode */ |
| 177 | ARMword Bank; /* the current register bank */ | 177 | ARMword Bank; /* the current register bank */ |
| 178 | ARMword exclusive_tag; | 178 | ARMword exclusive_tag; /* the address for which the local monitor is in exclusive access mode */ |
| 179 | ARMword exclusive_state; | 179 | ARMword exclusive_state; |
| 180 | ARMword exclusive_result; | 180 | ARMword exclusive_result; |
| 181 | ARMword CP15[VFP_BASE - CP15_BASE]; | 181 | ARMword CP15[VFP_BASE - CP15_BASE]; |