Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/dreamcast/sh2rec/sh2rec_mem.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 <inttypes.h>
23
24
#include "sh2rec_mem.h"
25
26
typedef struct block_s {
27
uint8_t *ptr;
28
int size;
29
struct block_s *prev;
30
struct block_s *next;
31
} sh2rec_mem_block;
32
33
typedef struct usedblock_s {
34
sh2rec_mem_block base;
35
sh2rec_mem_block *freespace;
36
} sh2rec_mem_usedblock;
37
38
typedef struct allocblock_s {
39
struct allocblock_s *next;
40
} sh2rec_mem_allocblock;
41
42
static sh2rec_mem_block *freeblocks = NULL;
43
static sh2rec_mem_usedblock *usedblocks = NULL;
44
static sh2rec_mem_usedblock *usedblocks_tail = NULL;
45
static sh2rec_mem_allocblock *allocblocks = NULL;
46
47
static int cur_allocation = 0;
48
49
#define BSSIZE (sizeof(sh2rec_mem_allocblock) + sizeof(sh2rec_mem_block) + \
50
sizeof(sh2rec_mem_usedblock))
51
52
int sh2rec_mem_init(void) {
53
sh2rec_mem_block *initblock;
54
sh2rec_mem_allocblock *allocblock;
55
uint8_t *block;
56
57
/* Allocate our initial space for storing rec'd instructions in */
58
block = (uint8_t *)malloc(SH2REC_MEM_INITIAL);
59
60
#ifdef DEBUG
61
if(!block) {
62
return -1;
63
}
64
#endif
65
66
/* Carve our structures out of the beginning of the block */
67
allocblock = (sh2rec_mem_allocblock *)block;
68
initblock = (sh2rec_mem_block *)(block + sizeof(sh2rec_mem_allocblock));
69
cur_allocation = SH2REC_MEM_INITIAL;
70
71
/* Fill in the rest of the structs */
72
initblock->size = SH2REC_MEM_INITIAL - sizeof(sh2rec_mem_allocblock) -
73
sizeof(sh2rec_mem_block);
74
initblock->prev = NULL;
75
initblock->next = NULL;
76
77
allocblock->next = NULL;
78
allocblocks = allocblock;
79
80
/* The whole block is free, so put it in the free list */
81
freeblocks = initblock;
82
83
return 0;
84
}
85
86
void sh2rec_mem_shutdown(void) {
87
sh2rec_mem_allocblock *i, *tmp;
88
89
/* Loop through and free any blocks we allocated */
90
i = allocblocks;
91
while(i) {
92
tmp = i->next;
93
free(i);
94
i = tmp;
95
}
96
97
/* Clean up the stale pointers */
98
allocblocks = NULL;
99
freeblocks = NULL;
100
usedblocks = NULL;
101
}
102
103
void *sh2rec_mem_alloc(int sz) {
104
sh2rec_mem_block *i;
105
sh2rec_mem_usedblock *rv;
106
sh2rec_mem_allocblock *b;
107
int szlook = sz + SH2REC_MEM_FUDGE + sizeof(sh2rec_mem_usedblock);
108
uint8_t *block;
109
110
/* Look for a free block of enough size */
111
i = freeblocks;
112
while(i) {
113
if(i->size >= szlook) {
114
/* We've found a candidate, so, start working with it */
115
rv = (sh2rec_mem_usedblock *)i->ptr;
116
rv->freespace = i;
117
rv->base.ptr = i->ptr + sizeof(sh2rec_mem_usedblock);
118
rv->base.size = sz;
119
rv->base.prev = (sh2rec_mem_block *)usedblocks_tail;
120
rv->base.next = NULL;
121
122
/* Update the tail */
123
if(usedblocks_tail) {
124
usedblocks_tail->base.next = (sh2rec_mem_block *)rv;
125
}
126
127
usedblocks_tail = rv;
128
129
/* The freeblock is now smaller, so reflect that */
130
i->size -= sz + sizeof(sh2rec_mem_usedblock);
131
132
return rv;
133
}
134
135
i = i->next;
136
}
137
138
/* We didn't find one, so allocate a new block */
139
block = malloc(SH2REC_MEM_ALLOCSZ);
140
141
#ifdef DEBUG
142
if(!block) {
143
return NULL;
144
}
145
#endif
146
147
/* Fill in the allocblock */
148
b = (sh2rec_mem_allocblock *)block;
149
b->next = allocblocks;
150
allocblocks = b;
151
152
/* Now, create a freeblock, and work from that */
153
i = (sh2rec_mem_block *)(block + sizeof(sh2rec_mem_allocblock));
154
i->ptr = block + BSSIZE + sz;
155
i->prev = NULL;
156
i->next = freeblocks;
157
i->size = SH2REC_MEM_ALLOCSZ - BSSIZE - sz;
158
freeblocks = i;
159
160
/* Create the usedblock */
161
rv = (sh2rec_mem_usedblock *)(i->ptr - sz);
162
rv->freespace = i;
163
rv->base.ptr = i->ptr;
164
rv->base.size = sz;
165
rv->base.prev = (sh2rec_mem_block *)usedblocks_tail;
166
rv->base.next = NULL;
167
168
/* Update the tail */
169
if(usedblocks_tail) {
170
usedblocks_tail->base.next = (sh2rec_mem_block *)rv;
171
}
172
173
usedblocks_tail = rv;
174
175
/* Keep track of our allocation */
176
cur_allocation += SH2REC_MEM_ALLOCSZ;
177
178
return rv;
179
}
180
181
int sh2rec_mem_expand(void *block, int amt) {
182
sh2rec_mem_usedblock *b = (sh2rec_mem_usedblock *)block;
183
184
/* If the freeblock has space, allow it */
185
if(b->freespace->size > amt) {
186
b->freespace->size -= amt;
187
b->base.size += amt;
188
b->freespace->ptr += amt;
189
return 1;
190
}
191
192
return 0;
193
}
194
195
void sh2rec_mem_free(void *block) {
196
sh2rec_mem_usedblock *b = (sh2rec_mem_usedblock *)block;
197
198
/* Remove the usedblock from the chain */
199
if(b->base.next) {
200
b->base.next->prev = b->base.prev;
201
}
202
203
if(b->base.prev) {
204
b->base.prev->next = b->base.next;
205
}
206
207
if(b == usedblocks) {
208
usedblocks = (sh2rec_mem_usedblock *)b->base.next;
209
}
210
211
if(b == usedblocks_tail) {
212
usedblocks_tail = (sh2rec_mem_usedblock *)b->base.prev;
213
}
214
215
/* Treat the usedblock like its a freeblock (it is an extension of the
216
freeblock), and just link it into the free blocks list */
217
b->freespace = NULL;
218
b->base.next = freeblocks;
219
b->base.prev = NULL;
220
b->base.size += sizeof(sh2rec_mem_usedblock) - sizeof(sh2rec_mem_block);
221
freeblocks = (sh2rec_mem_block *)b;
222
}
223
224