diff --git a/src/cache.c b/src/cache.c index f78b81663..ab13b06d4 100644 --- a/src/cache.c +++ b/src/cache.c @@ -11,10 +11,7 @@ #include "cache.h" #include "mpool.h" - -#define GOLDEN_RATIO_32 0x61C88647 -#define HASH(val) \ - (((val) * (GOLDEN_RATIO_32)) >> (32 - (cache_size_bits))) & (cache_size - 1) +#include "utils.h" /* THRESHOLD is set to identify hot spots. Once the frequency of use for a block * exceeds the THRESHOLD, the JIT compiler flow is triggered. @@ -337,16 +334,23 @@ static inline void move_to_mru(cache_t *cache, void *cache_get(cache_t *cache, uint32_t key) { - if (!cache->capacity || hlist_empty(&cache->map->ht_list_head[HASH(key)])) + if (!cache->capacity || + hlist_empty( + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)])) return NULL; #if RV32_HAS(ARC) arc_entry_t *entry = NULL; #ifdef __HAVE_TYPEOF - hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list) + hlist_for_each_entry ( + entry, + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)], + ht_list) #else - hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list, - arc_entry_t) + hlist_for_each_entry ( + entry, + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)], + ht_list, arc_entry_t) #endif { if (entry->key == key) @@ -388,10 +392,15 @@ void *cache_get(cache_t *cache, uint32_t key) #else /* !RV32_HAS(ARC) */ lfu_entry_t *entry = NULL; #ifdef __HAVE_TYPEOF - hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list) + hlist_for_each_entry ( + entry, + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)], + ht_list) #else - hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list, - lfu_entry_t) + hlist_for_each_entry ( + entry, + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)], + ht_list, lfu_entry_t) #endif { if (entry->key == key) @@ -478,7 +487,9 @@ void *cache_put(cache_t *cache, uint32_t key, void *value) list_add(&new_entry->list, cache->lists[LRU_ghost_list]); cache->list_size[LRU_ghost_list]++; } - hlist_add_head(&new_entry->ht_list, &cache->map->ht_list_head[HASH(key)]); + hlist_add_head( + &new_entry->ht_list, + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)]); CACHE_ASSERT(cache); #else /* !RV32_HAS(ARC) */ @@ -504,7 +515,9 @@ void *cache_put(cache_t *cache, uint32_t key, void *value) new_entry->frequency = 0; list_add(&new_entry->list, cache->lists[new_entry->frequency++]); cache->list_size++; - hlist_add_head(&new_entry->ht_list, &cache->map->ht_list_head[HASH(key)]); + hlist_add_head( + &new_entry->ht_list, + &cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)]); assert(cache->list_size <= cache->capacity); #endif return delete_value; diff --git a/src/emulate.c b/src/emulate.c index 740ef823c..5896aeee8 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -277,18 +277,6 @@ void rv_debug(riscv_t *rv) } #endif /* RV32_HAS(GDBSTUB) */ -/* hash function is used when mapping address into the block map */ -static inline uint32_t hash(size_t k) -{ - k ^= k << 21; - k ^= k >> 17; -#if (SIZE_MAX > 0xFFFFFFFF) - k ^= k >> 35; - k ^= k >> 51; -#endif - return k; -} - /* allocate a basic block */ static block_t *block_alloc(riscv_t *rv) { @@ -304,7 +292,8 @@ static void block_insert(block_map_t *map, const block_t *block) { assert(map && block); const uint32_t mask = map->block_capacity - 1; - uint32_t index = hash(block->pc_start); + uint32_t index = hash(block->pc_start, BLOCK_MAP_CAPACITY_BITS, + 1 << BLOCK_MAP_CAPACITY_BITS); /* insert into the block map */ for (;; index++) { @@ -320,7 +309,8 @@ static void block_insert(block_map_t *map, const block_t *block) static block_t *block_find(const block_map_t *map, const uint32_t addr) { assert(map); - uint32_t index = hash(addr); + uint32_t index = + hash(addr, BLOCK_MAP_CAPACITY_BITS, 1 << BLOCK_MAP_CAPACITY_BITS); const uint32_t mask = map->block_capacity - 1; /* find block in block map */ diff --git a/src/riscv.c b/src/riscv.c index 332fff48c..0f3682a2f 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -11,7 +11,6 @@ #include "riscv_private.h" #include "state.h" -#define BLOCK_MAP_CAPACITY_BITS 10 #define BLOCK_IR_MAP_CAPACITY_BITS 10 /* initialize the block map */ diff --git a/src/riscv.h b/src/riscv.h index 100c4dd3b..506ac82ca 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -79,6 +79,8 @@ enum { #define MSTATUS_MPIE (1 << MSTATUS_MPIE_SHIFT) #define MSTATUS_MPP (3 << MSTATUS_MPP_SHIFT) +#define BLOCK_MAP_CAPACITY_BITS 10 + /* forward declaration for internal structure */ typedef struct riscv_internal riscv_t; typedef void *riscv_user_t; diff --git a/src/utils.h b/src/utils.h index 1611b2249..72bde1573 100644 --- a/src/utils.h +++ b/src/utils.h @@ -10,3 +10,10 @@ void rv_gettimeofday(struct timeval *tv); /* Retrieve the value used by a clock which is specified by clock_id. */ void rv_clock_gettime(struct timespec *tp); + +/* Detect the instruction is RV32C or not */ +FORCE_INLINE uint32_t hash(uint32_t val, uint8_t size_bits, uint32_t size) +{ + /* 0x61C88647 is 32-bit golden ratio*/ + return (val * 0x61C88647 >> (32 - size_bits)) & (size - 1); +}