mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2025-02-17 07:30:50 +00:00
git subrepo pull (merge) deps/lightrec
subrepo: subdir: "deps/lightrec" merged: "b9cf86d3" upstream: origin: "https://github.com/pcercuei/lightrec.git" branch: "master" commit: "9a14de7d" git-subrepo: version: "0.4.1" origin: "https://github.com/ingydotnet/git-subrepo" commit: "a04d8c2"
This commit is contained in:
parent
c42a85b2a8
commit
3f7fe0deeb
2
deps/lightrec/.gitrepo
vendored
2
deps/lightrec/.gitrepo
vendored
@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/pcercuei/lightrec.git
|
||||
branch = master
|
||||
commit = 96b4f0314f1906d78069ec45a18d7cc660e73aeb
|
||||
commit = 9a14de7dca83b4e52de043b45e7288c87e74a8f2
|
||||
parent = 9f797430963d9cf0fcef7d963466f9cac7026de2
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
|
2
deps/lightrec/CMakeLists.txt
vendored
2
deps/lightrec/CMakeLists.txt
vendored
@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(lightrec LANGUAGES C VERSION 0.2)
|
||||
project(lightrec LANGUAGES C VERSION 0.3)
|
||||
|
||||
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
|
78
deps/lightrec/blockcache.c
vendored
78
deps/lightrec/blockcache.c
vendored
@ -21,12 +21,10 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Must be power of two */
|
||||
#define TINY_LUT_SIZE 0x100
|
||||
#define LUT_SIZE 0x4000
|
||||
|
||||
struct blockcache {
|
||||
struct lightrec_state *state;
|
||||
struct block * tiny_lut[TINY_LUT_SIZE];
|
||||
struct block * lut[LUT_SIZE];
|
||||
};
|
||||
|
||||
@ -36,39 +34,36 @@ struct block * lightrec_find_block(struct blockcache *cache, u32 pc)
|
||||
|
||||
pc = kunseg(pc);
|
||||
|
||||
block = cache->tiny_lut[(pc >> 2) & (TINY_LUT_SIZE - 1)];
|
||||
if (likely(block && kunseg(block->pc) == pc))
|
||||
return block;
|
||||
|
||||
block = cache->lut[(pc >> 2) & (LUT_SIZE - 1)];
|
||||
for (block = cache->lut[(pc >> 2) & (LUT_SIZE - 1)];
|
||||
block; block = block->next) {
|
||||
if (kunseg(block->pc) == pc) {
|
||||
cache->tiny_lut[(pc >> 2) & (TINY_LUT_SIZE - 1)] = block;
|
||||
block; block = block->next)
|
||||
if (kunseg(block->pc) == pc)
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void remove_from_code_lut(struct blockcache *cache, struct block *block)
|
||||
void remove_from_code_lut(struct blockcache *cache, struct block *block)
|
||||
{
|
||||
struct lightrec_state *state = block->state;
|
||||
const struct opcode *op;
|
||||
u32 offset = lut_offset(block->pc);
|
||||
|
||||
/* Use state->get_next_block in the code LUT, which basically
|
||||
* calls back get_next_block_func(), until the compiler
|
||||
* overrides this. This is required, as a NULL value in the code
|
||||
* LUT means an outdated block. */
|
||||
state->code_lut[lut_offset(block->pc)] = state->get_next_block;
|
||||
state->code_lut[offset] = state->get_next_block;
|
||||
|
||||
for (op = block->opcode_list; op; op = op->next)
|
||||
if (op->c.i.op == OP_META_SYNC)
|
||||
state->code_lut[offset + op->offset] = NULL;
|
||||
|
||||
}
|
||||
|
||||
void lightrec_mark_for_recompilation(struct blockcache *cache,
|
||||
struct block *block)
|
||||
{
|
||||
block->flags |= BLOCK_SHOULD_RECOMPILE;
|
||||
|
||||
remove_from_code_lut(cache, block);
|
||||
}
|
||||
|
||||
void lightrec_register_block(struct blockcache *cache, struct block *block)
|
||||
@ -81,7 +76,6 @@ void lightrec_register_block(struct blockcache *cache, struct block *block)
|
||||
block->next = old;
|
||||
|
||||
cache->lut[(pc >> 2) & (LUT_SIZE - 1)] = block;
|
||||
cache->tiny_lut[(pc >> 2) & (TINY_LUT_SIZE - 1)] = block;
|
||||
|
||||
remove_from_code_lut(cache, block);
|
||||
}
|
||||
@ -91,9 +85,7 @@ void lightrec_unregister_block(struct blockcache *cache, struct block *block)
|
||||
u32 pc = kunseg(block->pc);
|
||||
struct block *old = cache->lut[(pc >> 2) & (LUT_SIZE - 1)];
|
||||
|
||||
block->state->code_lut[lut_offset(pc)] = NULL;
|
||||
|
||||
cache->tiny_lut[(pc >> 2) & (TINY_LUT_SIZE - 1)] = NULL;
|
||||
remove_from_code_lut(cache, block);
|
||||
|
||||
if (old == block) {
|
||||
cache->lut[(pc >> 2) & (LUT_SIZE - 1)] = old->next;
|
||||
@ -138,7 +130,51 @@ struct blockcache * lightrec_blockcache_init(struct lightrec_state *state)
|
||||
return cache;
|
||||
}
|
||||
|
||||
u32 lightrec_calculate_block_hash(const struct block *block)
|
||||
{
|
||||
const struct lightrec_mem_map *map = block->map;
|
||||
u32 pc, hash = 0xffffffff;
|
||||
const u32 *code;
|
||||
unsigned int i;
|
||||
|
||||
pc = kunseg(block->pc) - map->pc;
|
||||
|
||||
while (map->mirror_of)
|
||||
map = map->mirror_of;
|
||||
|
||||
code = map->address + pc;
|
||||
|
||||
/* Jenkins one-at-a-time hash algorithm */
|
||||
for (i = 0; i < block->nb_ops; i++) {
|
||||
hash += *code++;
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool lightrec_block_is_outdated(struct block *block)
|
||||
{
|
||||
return !block->state->code_lut[lut_offset(block->pc)];
|
||||
void **lut_entry = &block->state->code_lut[lut_offset(block->pc)];
|
||||
bool outdated;
|
||||
|
||||
if (*lut_entry)
|
||||
return false;
|
||||
|
||||
outdated = block->hash != lightrec_calculate_block_hash(block);
|
||||
if (likely(!outdated)) {
|
||||
/* The block was marked as outdated, but the content is still
|
||||
* the same */
|
||||
if (block->function)
|
||||
*lut_entry = block->function;
|
||||
else
|
||||
*lut_entry = block->state->get_next_block;
|
||||
}
|
||||
|
||||
return outdated;
|
||||
}
|
||||
|
2
deps/lightrec/blockcache.h
vendored
2
deps/lightrec/blockcache.h
vendored
@ -26,7 +26,7 @@ void lightrec_unregister_block(struct blockcache *cache, struct block *block);
|
||||
struct blockcache * lightrec_blockcache_init(struct lightrec_state *state);
|
||||
void lightrec_free_block_cache(struct blockcache *cache);
|
||||
|
||||
u32 calculate_block_hash(const struct block *block);
|
||||
u32 lightrec_calculate_block_hash(const struct block *block);
|
||||
_Bool lightrec_block_is_outdated(struct block *block);
|
||||
|
||||
void lightrec_mark_for_recompilation(struct blockcache *cache,
|
||||
|
8
deps/lightrec/emitter.c
vendored
8
deps/lightrec/emitter.c
vendored
@ -86,7 +86,8 @@ static void lightrec_emit_end_of_block(const struct block *block,
|
||||
pr_debug("EOB: %u cycles\n", cycles);
|
||||
}
|
||||
|
||||
state->branches[state->nb_branches++] = jit_jmpi();
|
||||
if (op->next && ((op->flags & LIGHTREC_NO_DS) || op->next->next))
|
||||
state->branches[state->nb_branches++] = jit_jmpi();
|
||||
}
|
||||
|
||||
void lightrec_emit_eob(const struct block *block,
|
||||
@ -1365,15 +1366,12 @@ static void rec_meta_unload(const struct block *block,
|
||||
struct lightrec_state *state = block->state;
|
||||
struct regcache *reg_cache = state->reg_cache;
|
||||
jit_state_t *_jit = block->_jit;
|
||||
u8 reg;
|
||||
|
||||
jit_name(__func__);
|
||||
jit_note(__FILE__, __LINE__);
|
||||
|
||||
reg = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rs);
|
||||
|
||||
pr_debug("Unloading reg %s\n", lightrec_reg_name(op->i.rs));
|
||||
lightrec_unload_reg(reg_cache, _jit, reg);
|
||||
lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rs, true);
|
||||
}
|
||||
|
||||
static void rec_meta_BEQZ(const struct block *block,
|
||||
|
3
deps/lightrec/lightrec-private.h
vendored
3
deps/lightrec/lightrec-private.h
vendored
@ -73,6 +73,7 @@ struct block {
|
||||
struct opcode *opcode_list;
|
||||
void (*function)(void);
|
||||
u32 pc;
|
||||
u32 hash;
|
||||
#if ENABLE_THREADED_COMPILER
|
||||
atomic_flag op_list_freed;
|
||||
#endif
|
||||
@ -131,6 +132,8 @@ u32 lightrec_rw(struct lightrec_state *state, union code op,
|
||||
|
||||
void lightrec_free_block(struct block *block);
|
||||
|
||||
void remove_from_code_lut(struct blockcache *cache, struct block *block);
|
||||
|
||||
static inline u32 kunseg(u32 addr)
|
||||
{
|
||||
if (unlikely(addr >= 0xa0000000))
|
||||
|
3
deps/lightrec/lightrec.c
vendored
3
deps/lightrec/lightrec.c
vendored
@ -396,6 +396,7 @@ static void * get_next_block_func(struct lightrec_state *state, u32 pc)
|
||||
if (ENABLE_THREADED_COMPILER)
|
||||
lightrec_recompiler_remove(state->rec, block);
|
||||
|
||||
remove_from_code_lut(state->block_cache, block);
|
||||
lightrec_unregister(MEM_FOR_CODE, block->code_size);
|
||||
if (block->_jit)
|
||||
_jit_destroy_state(block->_jit);
|
||||
@ -784,6 +785,8 @@ static struct block * lightrec_precompile_block(struct lightrec_state *state,
|
||||
if (list->flags & LIGHTREC_EMULATE_BRANCH)
|
||||
block->flags |= BLOCK_NEVER_COMPILE;
|
||||
|
||||
block->hash = lightrec_calculate_block_hash(block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user