- block_desc *btab = block_tables[tcache_id];
- u16 *p = drc_ram_blk + ((a & mask) >> shift);
- u16 *pmax = drc_ram_blk + (mask >> shift);
- u32 id = ~0, end_addr;
- int max_zeros = MAX_LITERAL_OFFSET >> shift;
- int i, zeros;
-
- if (*p == 0 || (*p >> 1) >= BLOCKID_MAX) {
- u32 from = ~0, to = 0;
- dbg(1, "slow-remove blocks at @%08x", a);
- for (i = 0; i < block_counts[tcache_id]; i++) {
- if (btab[i].addr <= a && a < btab[i].end_addr) {
- if (btab[i].addr < from)
- from = btab[i].addr;
- if (btab[i].end_addr > to)
- to = btab[i].end_addr;
- sh2_smc_rm_block_entry(&btab[i], tcache_id);
- }
- }
- if (from < to) {
- p = drc_ram_blk + ((from & mask) >> shift);
- memset(p, 0, (to - from) >> (shift - 1));
- }
- return;
- }
-
- // use end_addr to distinguish the same block
- end_addr = btab[*p >> 1].end_addr;
-
- // go up to the start
- for (zeros = 0; p > drc_ram_blk && zeros < max_zeros; p--) {
- // there can be holes because games sometimes keep variables
- // directly in literal pool and we don't inline them
- // to avoid recompile (Star Wars Arcade)
- if (p[-1] == 0) {
- zeros++;
+ struct block_list **blist = NULL, *entry;
+ u32 from = ~0, to = 0;
+ block_desc *block;
+
+ blist = &inval_lookup[tcache_id][(a & mask) / ADDR_TO_BLOCK_PAGE];
+ entry = *blist;
+ while (entry != NULL) {
+ block = entry->block;
+ if (block->addr <= a && a < block->end_addr) {
+ if (block->addr < from)
+ from = block->addr;
+ if (block->end_addr > to)
+ to = block->end_addr;
+
+ sh2_smc_rm_block_entry(block, tcache_id, mask);
+
+ // entry lost, restart search
+ entry = *blist;