mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-11-18 18:05:21 +00:00
- Rewrite blockinfo allocator et al. Use a template class so that this
can work with other types related to blockinfos. - Add new method to compute checksums. This should permit code inlining and follow-ups of const_jumps without breaking the lazy cache invalidator. aka. chain infos for checksuming. TODO: Incomplete support thus disabled.
This commit is contained in:
parent
518f982775
commit
21909f1eed
@ -37,6 +37,9 @@ union cacheline {
|
||||
*/
|
||||
#define USE_SEPARATE_BIA 1
|
||||
|
||||
/* Use chain of checksum_info_t to compute the block checksum */
|
||||
#define USE_CHECKSUM_INFO 0
|
||||
|
||||
#define USE_F_ALIAS 1
|
||||
#define USE_OFFSET 1
|
||||
#define COMP_DEBUG 1
|
||||
@ -485,6 +488,14 @@ typedef struct dep_t {
|
||||
struct dep_t* next;
|
||||
} dependency;
|
||||
|
||||
typedef struct checksum_info_t {
|
||||
uae_u8 *start_p;
|
||||
uae_u32 length;
|
||||
uae_u32 c1;
|
||||
uae_u32 c2;
|
||||
struct checksum_info_t *next;
|
||||
} checksum_info;
|
||||
|
||||
typedef struct blockinfo_t {
|
||||
uae_s32 count;
|
||||
cpuop_func* direct_handler_to_use;
|
||||
@ -497,19 +508,28 @@ typedef struct blockinfo_t {
|
||||
cpuop_func* direct_pen;
|
||||
cpuop_func* direct_pcc;
|
||||
|
||||
uae_u8* nexthandler;
|
||||
uae_u8* pc_p;
|
||||
|
||||
#if USE_CHECKSUM_INFO
|
||||
checksum_info *csi;
|
||||
# define CSI_TYPE checksum_info
|
||||
# define CSI_START_P(csi) (csi)->start_p
|
||||
# define CSI_LENGTH(csi) (csi)->length
|
||||
#else
|
||||
uae_u32 c1;
|
||||
uae_u32 c2;
|
||||
uae_u32 len;
|
||||
uae_u32 min_pcp;
|
||||
# define CSI_TYPE blockinfo
|
||||
# define CSI_START_P(csi) (csi)->min_pcp
|
||||
# define CSI_LENGTH(csi) (csi)->len
|
||||
#endif
|
||||
|
||||
struct blockinfo_t* next_same_cl;
|
||||
struct blockinfo_t** prev_same_cl_p;
|
||||
struct blockinfo_t* next;
|
||||
struct blockinfo_t** prev_p;
|
||||
|
||||
uae_u32 min_pcp;
|
||||
uae_u8 optlevel;
|
||||
uae_u8 needed_flags;
|
||||
uae_u8 status;
|
||||
|
@ -490,74 +490,113 @@ static void prepare_block(blockinfo* bi);
|
||||
compiled. If the list of free blockinfos is empty, we allocate a new
|
||||
pool of blockinfos and link the newly created blockinfos altogether
|
||||
into the list of free blockinfos. Otherwise, we simply pop a structure
|
||||
of the free list.
|
||||
off the free list.
|
||||
|
||||
Blockinfo are lazily deallocated, i.e. chained altogether in the
|
||||
list of free blockinfos whenvever a translation cache flush (hard or
|
||||
soft) request occurs.
|
||||
*/
|
||||
|
||||
#if USE_SEPARATE_BIA
|
||||
const int BLOCKINFO_POOL_SIZE = 128;
|
||||
struct blockinfo_pool {
|
||||
blockinfo bi[BLOCKINFO_POOL_SIZE];
|
||||
blockinfo_pool *next;
|
||||
template< class T >
|
||||
class LazyBlockAllocator
|
||||
{
|
||||
enum {
|
||||
kPoolSize = 1 + 4096 / sizeof(T)
|
||||
};
|
||||
struct Pool {
|
||||
T chunk[kPoolSize];
|
||||
Pool * next;
|
||||
};
|
||||
Pool * mPools;
|
||||
T * mChunks;
|
||||
public:
|
||||
LazyBlockAllocator() : mPools(0), mChunks(0) { }
|
||||
~LazyBlockAllocator();
|
||||
T * acquire();
|
||||
void release(T * const);
|
||||
};
|
||||
static blockinfo_pool * blockinfo_pools = 0;
|
||||
static blockinfo * free_blockinfos = 0;
|
||||
|
||||
template< class T >
|
||||
LazyBlockAllocator<T>::~LazyBlockAllocator()
|
||||
{
|
||||
Pool * currentPool = mPools;
|
||||
while (currentPool) {
|
||||
Pool * deadPool = currentPool;
|
||||
currentPool = currentPool->next;
|
||||
free(deadPool);
|
||||
}
|
||||
}
|
||||
|
||||
template< class T >
|
||||
T * LazyBlockAllocator<T>::acquire()
|
||||
{
|
||||
if (!mChunks) {
|
||||
// There is no chunk left, allocate a new pool and link the
|
||||
// chunks into the free list
|
||||
Pool * newPool = (Pool *)malloc(sizeof(Pool));
|
||||
for (T * chunk = &newPool->chunk[0]; chunk < &newPool->chunk[kPoolSize]; chunk++) {
|
||||
chunk->next = mChunks;
|
||||
mChunks = chunk;
|
||||
}
|
||||
newPool->next = mPools;
|
||||
mPools = newPool;
|
||||
}
|
||||
T * chunk = mChunks;
|
||||
mChunks = chunk->next;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
void LazyBlockAllocator<T>::release(T * const chunk)
|
||||
{
|
||||
chunk->next = mChunks;
|
||||
mChunks = chunk;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
class HardBlockAllocator
|
||||
{
|
||||
public:
|
||||
T * acquire() {
|
||||
T * data = (T *)current_compile_p;
|
||||
current_compile_p += sizeof(T);
|
||||
return data;
|
||||
}
|
||||
|
||||
void release(T * const chunk) {
|
||||
// Deallocated on invalidation
|
||||
}
|
||||
};
|
||||
|
||||
#if USE_SEPARATE_BIA
|
||||
static LazyBlockAllocator<blockinfo> BlockInfoAllocator;
|
||||
static LazyBlockAllocator<checksum_info> ChecksumInfoAllocator;
|
||||
#else
|
||||
static HardBlockAllocator<blockinfo> BlockInfoAllocator;
|
||||
static HardBlockAllocator<checksum_info> ChecksumInfoAllocator;
|
||||
#endif
|
||||
|
||||
|
||||
static __inline__ blockinfo *alloc_blockinfo(void)
|
||||
{
|
||||
#if USE_SEPARATE_BIA
|
||||
if (!free_blockinfos) {
|
||||
// There is no blockinfo struct left, allocate a new
|
||||
// pool and link the chunks into the free list
|
||||
blockinfo_pool *bi_pool = (blockinfo_pool *)malloc(sizeof(blockinfo_pool));
|
||||
for (blockinfo *bi = &bi_pool->bi[0]; bi < &bi_pool->bi[BLOCKINFO_POOL_SIZE]; bi++) {
|
||||
bi->next = free_blockinfos;
|
||||
free_blockinfos = bi;
|
||||
}
|
||||
bi_pool->next = blockinfo_pools;
|
||||
blockinfo_pools = bi_pool;
|
||||
}
|
||||
blockinfo *bi = free_blockinfos;
|
||||
free_blockinfos = bi->next;
|
||||
#else
|
||||
blockinfo *bi = (blockinfo*)current_compile_p;
|
||||
current_compile_p += sizeof(blockinfo);
|
||||
blockinfo *bi = BlockInfoAllocator.acquire();
|
||||
#if USE_CHECKSUM_INFO
|
||||
bi->csi = NULL;
|
||||
#endif
|
||||
return bi;
|
||||
}
|
||||
|
||||
static __inline__ void free_blockinfo(blockinfo *bi)
|
||||
{
|
||||
#if USE_SEPARATE_BIA
|
||||
bi->next = free_blockinfos;
|
||||
free_blockinfos = bi;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void free_blockinfo_pools(void)
|
||||
{
|
||||
#if USE_SEPARATE_BIA
|
||||
int blockinfo_pool_count = 0;
|
||||
blockinfo_pool *curr_pool = blockinfo_pools;
|
||||
while (curr_pool) {
|
||||
blockinfo_pool_count++;
|
||||
blockinfo_pool *dead_pool = curr_pool;
|
||||
curr_pool = curr_pool->next;
|
||||
free(dead_pool);
|
||||
#if USE_CHECKSUM_INFO
|
||||
checksum_info *csi = bi->csi;
|
||||
while (csi != NULL) {
|
||||
checksum_info *csi2 = csi->next;
|
||||
ChecksumInfoAllocator.release(csi);
|
||||
csi = csi2;
|
||||
}
|
||||
|
||||
uae_u32 blockinfo_pools_size = blockinfo_pool_count * BLOCKINFO_POOL_SIZE * sizeof(blockinfo);
|
||||
write_log("### Blockinfo allocation statistics\n");
|
||||
write_log("Number of blockinfo pools : %d\n", blockinfo_pool_count);
|
||||
write_log("Total number of blockinfos : %d (%d KB)\n",
|
||||
blockinfo_pool_count * BLOCKINFO_POOL_SIZE,
|
||||
blockinfo_pools_size / 1024);
|
||||
write_log("\n");
|
||||
#endif
|
||||
BlockInfoAllocator.release(bi);
|
||||
}
|
||||
|
||||
static __inline__ void alloc_blockinfos(void)
|
||||
@ -4597,9 +4636,6 @@ void compiler_exit(void)
|
||||
compiled_code = 0;
|
||||
}
|
||||
|
||||
// Deallocate blockinfo pools
|
||||
free_blockinfo_pools();
|
||||
|
||||
#ifndef WIN32
|
||||
// Close /dev/zero
|
||||
if (zero_fd > 0)
|
||||
@ -5172,12 +5208,12 @@ void alloc_cache(void)
|
||||
|
||||
extern cpuop_rettype op_illg_1 (uae_u32 opcode) REGPARAM;
|
||||
|
||||
static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
|
||||
static void calc_checksum(CSI_TYPE* csi, uae_u32* c1, uae_u32* c2)
|
||||
{
|
||||
uae_u32 k1=0;
|
||||
uae_u32 k2=0;
|
||||
uae_s32 len=bi->len;
|
||||
uae_u32 tmp=bi->min_pcp;
|
||||
uae_s32 len=CSI_LENGTH(csi);
|
||||
uae_u32 tmp=(uae_u32)CSI_START_P(csi);
|
||||
uae_u32* pos;
|
||||
|
||||
len+=(tmp&3);
|
||||
@ -5200,12 +5236,12 @@ static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
|
||||
}
|
||||
}
|
||||
|
||||
static void show_checksum(blockinfo* bi)
|
||||
static void show_checksum(CSI_TYPE* csi)
|
||||
{
|
||||
uae_u32 k1=0;
|
||||
uae_u32 k2=0;
|
||||
uae_s32 len=bi->len;
|
||||
uae_u32 tmp=(uae_u32)bi->pc_p;
|
||||
uae_s32 len=CSI_LENGTH(csi);
|
||||
uae_u32 tmp=(uae_u32)CSI_START_P(csi);
|
||||
uae_u32* pos;
|
||||
|
||||
len+=(tmp&3);
|
||||
@ -5277,19 +5313,35 @@ static int called_check_checksum(blockinfo* bi);
|
||||
static inline int block_check_checksum(blockinfo* bi)
|
||||
{
|
||||
uae_u32 c1,c2;
|
||||
int isgood;
|
||||
bool isgood;
|
||||
|
||||
if (bi->status!=BI_NEED_CHECK)
|
||||
return 1; /* This block is in a checked state */
|
||||
|
||||
checksum_count++;
|
||||
|
||||
#if USE_CHECKSUM_INFO
|
||||
checksum_info *csi = bi->csi;
|
||||
Dif(!csi) abort();
|
||||
isgood = true;
|
||||
while (csi && isgood) {
|
||||
if (csi->c1 || csi->c2)
|
||||
calc_checksum(csi,&c1,&c2);
|
||||
else
|
||||
c1 = c2 = 1; /* Make sure it doesn't match */
|
||||
isgood = isgood && (c1 == csi->c1 && c2 == csi->c2);
|
||||
csi = csi->next;
|
||||
}
|
||||
#else
|
||||
if (bi->c1 || bi->c2)
|
||||
calc_checksum(bi,&c1,&c2);
|
||||
else {
|
||||
c1=c2=1; /* Make sure it doesn't match */
|
||||
}
|
||||
}
|
||||
|
||||
isgood=(c1==bi->c1 && c2==bi->c2);
|
||||
#endif
|
||||
|
||||
if (isgood) {
|
||||
/* This block is still OK. So we reactivate. Of course, that
|
||||
means we have to move it into the needs-to-be-flushed list */
|
||||
@ -6197,9 +6249,17 @@ static void compile_block(cpu_history* pc_hist, int blocklen)
|
||||
max_pcp=next_pc_p+extra_len; /* extra_len covers flags magic */
|
||||
else
|
||||
max_pcp+=LONGEST_68K_INST;
|
||||
|
||||
#if USE_CHECKSUM_INFO
|
||||
checksum_info *csi = (bi->csi = ChecksumInfoAllocator.acquire());
|
||||
csi->next = NULL;
|
||||
csi->length = max_pcp - min_pcp;
|
||||
csi->start_p = (uae_u8 *)min_pcp;
|
||||
#else
|
||||
bi->len=max_pcp-min_pcp;
|
||||
bi->min_pcp=min_pcp;
|
||||
|
||||
#endif
|
||||
|
||||
remove_from_list(bi);
|
||||
if (isinrom(min_pcp) && isinrom(max_pcp)) {
|
||||
add_to_dormant(bi); /* No need to checksum it on cache flush.
|
||||
@ -6207,7 +6267,11 @@ static void compile_block(cpu_history* pc_hist, int blocklen)
|
||||
flight! */
|
||||
}
|
||||
else {
|
||||
#if USE_CHECKSUM_INFO
|
||||
calc_checksum(csi,&csi->c1,&csi->c2);
|
||||
#else
|
||||
calc_checksum(bi,&(bi->c1),&(bi->c2));
|
||||
#endif
|
||||
add_to_active(bi);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user