Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/dreamcast/sh2rec/sh2rec_htab.c
2 views
1
/* Copyright 2010 Lawrence Sebald
2
3
This file is part of Yabause.
4
5
Yabause is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
9
10
Yabause is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with Yabause; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include <inttypes.h>
24
25
#include "core.h"
26
#include "sh2core.h"
27
#include "sh2rec.h"
28
#include "sh2rec_htab.h"
29
#include "sh2rec_mem.h"
30
31
typedef struct htab_entry {
32
sh2rec_block_t block;
33
34
struct htab_entry *next;
35
} htab_entry_t;
36
37
/* The actual hash table. It can't be resized dynamically, and is essentially
38
just an array of singly-linked lists. */
39
static htab_entry_t *table[SH2REC_HTAB_ENTRIES];
40
41
/* Internal functions */
42
static void htab_free_chain(htab_entry_t *ent) {
43
htab_entry_t *i, *tmp;
44
45
i = ent;
46
while(i) {
47
tmp = i->next;
48
free(i->block.block);
49
free(i);
50
i = tmp;
51
}
52
}
53
54
/* Hash an address into something slightly nicer to work with. The large
55
constant in here is about 2^32 / phi (where phi is the golden ratio). Why use
56
the golden ratio? Because its always fun to use in code. */
57
static inline int hash_addr(u32 addr) {
58
return ((addr ^ 2654435761U) >> 2) & (SH2REC_HTAB_ENTRIES - 1);
59
}
60
61
/* Public functions */
62
void sh2rec_htab_init(void) {
63
memset(table, 0, sizeof(htab_entry_t *) * SH2REC_HTAB_ENTRIES);
64
}
65
66
void sh2rec_htab_reset(void) {
67
int i;
68
69
for(i = 0; i < SH2REC_HTAB_ENTRIES; ++i) {
70
if(table[i]) {
71
htab_free_chain(table[i]);
72
}
73
}
74
75
memset(table, 0, sizeof(htab_entry_t *) * SH2REC_HTAB_ENTRIES);
76
}
77
78
sh2rec_block_t *sh2rec_htab_lookup(u32 addr) {
79
htab_entry_t *i = table[hash_addr(addr)];
80
81
/* Look through the chain for the entry we're after */
82
while(i) {
83
if(i->block.start_pc == addr) {
84
return &i->block;
85
}
86
87
i = i->next;
88
}
89
90
/* Didn't find it, punt. */
91
return NULL;
92
}
93
94
/* Create a new block assuming an old one does not exist. */
95
sh2rec_block_t *sh2rec_htab_block_create(u32 addr, int length) {
96
uint8_t *ptr;
97
htab_entry_t *ent;
98
int index = hash_addr(addr);
99
100
ptr = (uint8_t *)sh2rec_mem_alloc(length + sizeof(htab_entry_t));
101
102
#ifdef DEBUG
103
if(!ptr) {
104
return NULL;
105
}
106
#endif
107
108
/* Allocate space for the block */
109
ent = (htab_entry_t *)ptr;
110
ent->block.block = (u16 *)(ptr + sizeof(htab_entry_t));
111
112
/* Fill in the struct */
113
ent->block.start_pc = addr;
114
ent->block.cycles = 0;
115
ent->block.pc = addr;
116
ent->block.length = length;
117
ent->block.ptr = ent->block.block;
118
119
/* Put the item in the list (puts it at the head of the index in the table
120
where it would go) */
121
ent->next = table[index];
122
table[index] = ent;
123
124
return &ent->block;
125
}
126
127
void sh2rec_htab_block_remove(u32 addr) {
128
int index = hash_addr(addr);
129
htab_entry_t *i, *tmp, *last;
130
131
i = table[index];
132
last = NULL;
133
134
/* Look through everything for the entry we're supposed to remove */
135
while(i) {
136
tmp = i->next;
137
138
/* Is this the entry we're looking for? */
139
if(i->block.start_pc == addr) {
140
/* Unhook the entry from the list */
141
if(last) {
142
last->next = tmp;
143
}
144
else {
145
table[index] = tmp;
146
}
147
148
/* Free any memory used by the block */
149
sh2rec_mem_free(i);
150
151
return;
152
}
153
154
last = i;
155
i = tmp;
156
}
157
}
158
159