X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=deps%2Flightrec%2Fregcache.c;h=1f11d8a27ae81496a982796f0033e12d5b6234f4;hb=ba3814c189d3bd2332b66fb6c633a7d028e618fe;hp=791a9c5c728a971008c2084ffc048cf5f0fd15ff;hpb=3e629be971c683d914844b487e366e0acf55539a;p=pcsx_rearmed.git diff --git a/deps/lightrec/regcache.c b/deps/lightrec/regcache.c index 791a9c5c..1f11d8a2 100644 --- a/deps/lightrec/regcache.c +++ b/deps/lightrec/regcache.c @@ -11,10 +11,22 @@ #include #include +enum reg_priority { + REG_IS_TEMP, + REG_IS_TEMP_VALUE, + REG_IS_ZERO, + REG_IS_LOADED, + REG_IS_DIRTY, + + REG_NB_PRIORITIES, +}; + struct native_register { - bool used, loaded, dirty, output, extend, extended, + bool used, output, extend, extended, zero_extend, zero_extended, locked; s8 emulated_register; + intptr_t value; + enum reg_priority prio; }; struct regcache { @@ -69,7 +81,11 @@ static inline u8 lightrec_reg_to_lightning(const struct regcache *cache, const struct native_register *nreg) { u8 offset = lightrec_reg_number(cache, nreg); - return offset < NUM_REGS ? JIT_V(offset) : JIT_R(offset - NUM_REGS); + + if (offset < NUM_REGS) + return JIT_V(FIRST_REG + offset); + else + return JIT_R(FIRST_TEMP + offset - NUM_REGS); } static inline struct native_register * lightning_reg_to_lightrec( @@ -78,14 +94,14 @@ static inline struct native_register * lightning_reg_to_lightrec( if ((JIT_V0 > JIT_R0 && reg >= JIT_V0) || (JIT_V0 < JIT_R0 && reg < JIT_R0)) { if (JIT_V1 > JIT_V0) - return &cache->lightrec_regs[reg - JIT_V0]; + return &cache->lightrec_regs[reg - JIT_V(FIRST_REG)]; else - return &cache->lightrec_regs[JIT_V0 - reg]; + return &cache->lightrec_regs[JIT_V(FIRST_REG) - reg]; } else { if (JIT_R1 > JIT_R0) - return &cache->lightrec_regs[NUM_REGS + reg - JIT_R0]; + return &cache->lightrec_regs[NUM_REGS + reg - JIT_R(FIRST_TEMP)]; else - return &cache->lightrec_regs[NUM_REGS + JIT_R0 - reg]; + return &cache->lightrec_regs[NUM_REGS + JIT_R(FIRST_TEMP) - reg]; } } @@ -119,6 +135,8 @@ void lightrec_set_reg_out_flags(struct regcache *cache, u8 jit_reg, u8 flags) static struct native_register * alloc_temp(struct regcache *cache) { + struct native_register *elm, *nreg = NULL; + enum reg_priority best = REG_NB_PRIORITIES; unsigned int i; /* We search the register list in reverse order. As temporaries are @@ -126,18 +144,18 @@ static struct native_register * alloc_temp(struct regcache *cache) * caller-saved registers, as they won't have to be saved back to * memory. */ for (i = ARRAY_SIZE(cache->lightrec_regs); i; i--) { - struct native_register *nreg = &cache->lightrec_regs[i - 1]; - if (!nreg->used && !nreg->loaded && !nreg->dirty) - return nreg; - } + elm = &cache->lightrec_regs[i - 1]; - for (i = ARRAY_SIZE(cache->lightrec_regs); i; i--) { - struct native_register *nreg = &cache->lightrec_regs[i - 1]; - if (!nreg->used) - return nreg; + if (!elm->used && elm->prio < best) { + nreg = elm; + best = elm->prio; + + if (best == REG_IS_TEMP) + break; + } } - return NULL; + return nreg; } static struct native_register * find_mapped_reg(struct regcache *cache, @@ -147,9 +165,9 @@ static struct native_register * find_mapped_reg(struct regcache *cache, for (i = 0; i < ARRAY_SIZE(cache->lightrec_regs); i++) { struct native_register *nreg = &cache->lightrec_regs[i]; - if ((!reg || nreg->loaded || nreg->dirty) && - nreg->emulated_register == reg && - (!out || !nreg->locked)) + if ((nreg->prio >= REG_IS_ZERO) && + nreg->emulated_register == reg && + (!out || !nreg->locked)) return nreg; } @@ -159,7 +177,8 @@ static struct native_register * find_mapped_reg(struct regcache *cache, static struct native_register * alloc_in_out(struct regcache *cache, u8 reg, bool out) { - struct native_register *nreg; + struct native_register *elm, *nreg = NULL; + enum reg_priority best = REG_NB_PRIORITIES; unsigned int i; /* Try to find if the register is already mapped somewhere */ @@ -167,48 +186,39 @@ static struct native_register * alloc_in_out(struct regcache *cache, if (nreg) return nreg; - /* Try to allocate a non-dirty, non-loaded register. - * Loaded registers may be re-used later, so it's better to avoid - * re-using one if possible. */ - for (i = 0; i < ARRAY_SIZE(cache->lightrec_regs); i++) { - nreg = &cache->lightrec_regs[i]; - if (!nreg->used && !nreg->dirty && !nreg->loaded) - return nreg; - } + nreg = NULL; - /* Try to allocate a non-dirty register */ for (i = 0; i < ARRAY_SIZE(cache->lightrec_regs); i++) { - nreg = &cache->lightrec_regs[i]; - if (!nreg->used && !nreg->dirty) - return nreg; - } + elm = &cache->lightrec_regs[i]; - for (i = 0; i < ARRAY_SIZE(cache->lightrec_regs); i++) { - nreg = &cache->lightrec_regs[i]; - if (!nreg->used) - return nreg; + if (!elm->used && elm->prio < best) { + nreg = elm; + best = elm->prio; + + if (best == REG_IS_TEMP) + break; + } } - return NULL; + return nreg; } static void lightrec_discard_nreg(struct native_register *nreg) { nreg->extended = false; nreg->zero_extended = false; - nreg->loaded = false; nreg->output = false; - nreg->dirty = false; nreg->used = false; nreg->locked = false; nreg->emulated_register = -1; + nreg->prio = 0; } static void lightrec_unload_nreg(struct regcache *cache, jit_state_t *_jit, struct native_register *nreg, u8 jit_reg) { /* If we get a dirty register, store back the old value */ - if (nreg->dirty) { + if (nreg->prio == REG_IS_DIRTY) { s16 offset = offsetof(struct lightrec_state, regs.gpr) + (nreg->emulated_register << 2); @@ -253,6 +263,7 @@ u8 lightrec_alloc_reg(struct regcache *cache, jit_state_t *_jit, u8 jit_reg) lightrec_unload_nreg(cache, _jit, reg, jit_reg); reg->used = true; + reg->prio = REG_IS_LOADED; return jit_reg; } @@ -269,10 +280,38 @@ u8 lightrec_alloc_reg_temp(struct regcache *cache, jit_state_t *_jit) jit_reg = lightrec_reg_to_lightning(cache, nreg); lightrec_unload_nreg(cache, _jit, nreg, jit_reg); + nreg->prio = REG_IS_TEMP; nreg->used = true; return jit_reg; } +s8 lightrec_get_reg_with_value(struct regcache *cache, intptr_t value) +{ + struct native_register *nreg; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cache->lightrec_regs); i++) { + nreg = &cache->lightrec_regs[i]; + + if (nreg->prio == REG_IS_TEMP_VALUE && nreg->value == value) { + nreg->used = true; + return lightrec_reg_to_lightning(cache, nreg); + } + } + + return -1; +} + +void lightrec_temp_set_value(struct regcache *cache, u8 jit_reg, intptr_t value) +{ + struct native_register *nreg; + + nreg = lightning_reg_to_lightrec(cache, jit_reg); + + nreg->prio = REG_IS_TEMP_VALUE; + nreg->value = value; +} + u8 lightrec_alloc_reg_out(struct regcache *cache, jit_state_t *_jit, u8 reg, u8 flags) { @@ -303,6 +342,7 @@ u8 lightrec_alloc_reg_out(struct regcache *cache, jit_state_t *_jit, nreg->emulated_register = reg; nreg->extend = flags & REG_EXT; nreg->zero_extend = flags & REG_ZEXT; + nreg->prio = reg ? REG_IS_LOADED : REG_IS_ZERO; return jit_reg; } @@ -333,7 +373,7 @@ u8 lightrec_alloc_reg_in(struct regcache *cache, jit_state_t *_jit, if (reg_changed) lightrec_unload_nreg(cache, _jit, nreg, jit_reg); - if (!nreg->loaded && !nreg->dirty && reg != 0) { + if (nreg->prio < REG_IS_LOADED && reg != 0) { s16 offset = offsetof(struct lightrec_state, regs.gpr) + (reg << 2); @@ -346,15 +386,15 @@ u8 lightrec_alloc_reg_in(struct regcache *cache, jit_state_t *_jit, else jit_ldxi_i(jit_reg, LIGHTREC_REG_STATE, offset); - nreg->loaded = true; + nreg->prio = REG_IS_LOADED; } /* Clear register r0 before use */ - if (reg == 0 && (!nreg->loaded || nreg->dirty)) { + if (reg == 0 && nreg->prio != REG_IS_ZERO) { jit_movi(jit_reg, 0); nreg->extended = true; nreg->zero_extended = true; - nreg->loaded = true; + nreg->prio = REG_IS_ZERO; } nreg->used = true; @@ -399,8 +439,8 @@ u8 lightrec_request_reg_in(struct regcache *cache, jit_state_t *_jit, nreg->extended = true; nreg->zero_extended = false; nreg->used = true; - nreg->loaded = true; nreg->emulated_register = reg; + nreg->prio = REG_IS_LOADED; return jit_reg; } @@ -409,7 +449,7 @@ static void free_reg(struct native_register *nreg) { /* Set output registers as dirty */ if (nreg->used && nreg->output && nreg->emulated_register > 0) - nreg->dirty = true; + nreg->prio = REG_IS_DIRTY; if (nreg->output) { nreg->extended = nreg->extend; nreg->zero_extended = nreg->zero_extend; @@ -434,13 +474,18 @@ void lightrec_free_regs(struct regcache *cache) static void clean_reg(jit_state_t *_jit, struct native_register *nreg, u8 jit_reg, bool clean) { - if (nreg->dirty) { + if (nreg->prio == REG_IS_DIRTY) { s16 offset = offsetof(struct lightrec_state, regs.gpr) + (nreg->emulated_register << 2); jit_stxi_i(offset, LIGHTREC_REG_STATE, jit_reg); - nreg->loaded |= nreg->dirty; - nreg->dirty ^= clean; + + if (clean) { + if (nreg->emulated_register == 0) + nreg->prio = REG_IS_ZERO; + else + nreg->prio = REG_IS_LOADED; + } } } @@ -448,11 +493,13 @@ static void clean_regs(struct regcache *cache, jit_state_t *_jit, bool clean) { unsigned int i; - for (i = 0; i < NUM_REGS; i++) - clean_reg(_jit, &cache->lightrec_regs[i], JIT_V(i), clean); + for (i = 0; i < NUM_REGS; i++) { + clean_reg(_jit, &cache->lightrec_regs[i], + JIT_V(FIRST_REG + i), clean); + } for (i = 0; i < NUM_TEMPS; i++) { clean_reg(_jit, &cache->lightrec_regs[i + NUM_REGS], - JIT_R(i), clean); + JIT_R(FIRST_TEMP + i), clean); } } @@ -466,6 +513,17 @@ void lightrec_clean_regs(struct regcache *cache, jit_state_t *_jit) clean_regs(cache, _jit, true); } +bool lightrec_has_dirty_regs(struct regcache *cache) +{ + unsigned int i; + + for (i = 0; i < NUM_REGS + NUM_TEMPS; i++) + if (cache->lightrec_regs[i].prio == REG_IS_DIRTY) + return true; + + return false; +} + void lightrec_clean_reg(struct regcache *cache, jit_state_t *_jit, u8 jit_reg) { struct native_register *reg; @@ -557,15 +615,18 @@ void lightrec_regcache_mark_live(struct regcache *cache, jit_state_t *_jit) for (i = 0; i < NUM_REGS; i++) { nreg = &cache->lightrec_regs[i]; - if (nreg->used || nreg->loaded || nreg->dirty) - jit_live(JIT_V(i)); + if (nreg->used || nreg->prio > REG_IS_TEMP) + jit_live(JIT_V(FIRST_REG + i)); } #endif for (i = 0; i < NUM_TEMPS; i++) { nreg = &cache->lightrec_regs[NUM_REGS + i]; - if (nreg->used || nreg->loaded || nreg->dirty) - jit_live(JIT_R(i)); + if (nreg->used || nreg->prio > REG_IS_TEMP) + jit_live(JIT_R(FIRST_TEMP + i)); } + + jit_live(LIGHTREC_REG_STATE); + jit_live(LIGHTREC_REG_CYCLE); }