1
0
Fork 0

Added exclusive reservation granule from ARMv7 spec to dyncom to protect LDR/STREX.

This commit is contained in:
Kevin Hartman 2015-01-05 02:17:00 -05:00
parent 9ac2272e25
commit 8132c01830
2 changed files with 18 additions and 16 deletions

View File

@ -63,16 +63,21 @@ extern void switch_mode(arm_core_t *core, uint32_t mode);
typedef arm_core_t arm_processor; typedef arm_core_t arm_processor;
typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); typedef unsigned int (*shtop_fp_t)(arm_processor *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 ARMword RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
// Exclusive memory access // Exclusive memory access
static int exclusive_detect(ARMul_State* state, ARMword addr){ static int exclusive_detect(ARMul_State* state, ARMword addr){
if(state->exclusive_tag == addr) if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK))
return 0; return 0;
else else
return -1; return -1;
} }
static void add_exclusive_addr(ARMul_State* state, ARMword addr){ static void add_exclusive_addr(ARMul_State* state, ARMword addr){
state->exclusive_tag = addr; state->exclusive_tag = addr & RESERVATION_GRANULE_MASK;
return; return;
} }
@ -80,7 +85,6 @@ static void remove_exclusive(ARMul_State* state, ARMword addr){
state->exclusive_tag = 0xFFFFFFFF; state->exclusive_tag = 0xFFFFFFFF;
} }
unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) { unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) {
unsigned int immed_8 = BITS(sht_oper, 0, 7); unsigned int immed_8 = BITS(sht_oper, 0, 7);
unsigned int rotate_imm = BITS(sht_oper, 8, 11); unsigned int rotate_imm = BITS(sht_oper, 8, 11);
@ -4551,7 +4555,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
add_exclusive_addr(cpu, read_addr); add_exclusive_addr(cpu, read_addr);
cpu->exclusive_state = 1; cpu->exclusive_state = 1;
// TODO(bunnei): Do we need to also make [read_addr + 4] exclusive?
RD = Memory::Read32(read_addr); RD = Memory::Read32(read_addr);
RD2 = Memory::Read32(read_addr + 4); RD2 = Memory::Read32(read_addr + 4);
@ -5978,7 +5981,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
remove_exclusive(cpu, write_addr); remove_exclusive(cpu, write_addr);
cpu->exclusive_state = 0; cpu->exclusive_state = 0;
// TODO(bunnei): Remove exclusive from [write_addr + 4] if we implement this in LDREXD
Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]); Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]);

View File

@ -175,7 +175,7 @@ struct ARMul_State
ARMword Spsr[7]; /* the exception psr's */ ARMword Spsr[7]; /* the exception psr's */
ARMword Mode; /* the current mode */ ARMword Mode; /* the current mode */
ARMword Bank; /* the current register bank */ ARMword Bank; /* the current register bank */
ARMword exclusive_tag; ARMword exclusive_tag; /* the address for which the local monitor is in exclusive access mode */
ARMword exclusive_state; ARMword exclusive_state;
ARMword exclusive_result; ARMword exclusive_result;
ARMword CP15[VFP_BASE - CP15_BASE]; ARMword CP15[VFP_BASE - CP15_BASE];