Mercurial > repos > blastem
comparison disasm.c @ 2206:4c265d2f6c88
Minor refactor of 68K disassembler
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 27 Aug 2022 17:07:57 -0700 |
parents | |
children | de3d20e58555 |
comparison
equal
deleted
inserted
replaced
2205:90297f1fb3fe | 2206:4c265d2f6c88 |
---|---|
1 #include "disasm.h" | |
2 | |
3 label_def *find_label(disasm_context *context, uint32_t address) | |
4 { | |
5 char key[MAX_INT_KEY_SIZE]; | |
6 tern_int_key(address & context->address_mask, key); | |
7 return tern_find_ptr(context->labels, key); | |
8 } | |
9 | |
10 label_def *add_find_label(disasm_context *context, uint32_t address) | |
11 { | |
12 char key[MAX_INT_KEY_SIZE]; | |
13 tern_int_key(address & context->address_mask, key); | |
14 label_def *def = tern_find_ptr(context->labels, key); | |
15 if (!def) | |
16 { | |
17 def = calloc(1, sizeof(label_def)); | |
18 context->labels = tern_insert_ptr(context->labels, key, def); | |
19 } | |
20 def->full_address = address; | |
21 return def; | |
22 } | |
23 | |
24 void weak_label(disasm_context *context, const char *name, uint32_t address) | |
25 { | |
26 label_def *def = add_find_label(context, address); | |
27 if (def->num_labels == def->storage) { | |
28 def->storage = def->storage ? def->storage * 2 : 4; | |
29 def->labels = realloc(def->labels, def->storage * sizeof(char*));; | |
30 } | |
31 def->labels[def->num_labels++] = strdup(name); | |
32 } | |
33 | |
34 void reference(disasm_context *context, uint32_t address) | |
35 { | |
36 label_def *def = add_find_label(context, address); | |
37 def->referenced = 1; | |
38 } | |
39 | |
40 void add_label(disasm_context *context, const char *name, uint32_t address) | |
41 { | |
42 reference(context, address);; | |
43 weak_label(context, name, address); | |
44 } | |
45 | |
46 void visit(disasm_context *context, uint32_t address) | |
47 { | |
48 if (!context->visited) { | |
49 uint32_t size = context->address_mask + 1; | |
50 size >>= context->visit_preshift; | |
51 size >>= 3; | |
52 context->visited = calloc(1, size); | |
53 } | |
54 address &= context->address_mask; | |
55 address >>= context->visit_preshift; | |
56 context->visited[address >> 3] |= 1 << (address & 7); | |
57 } | |
58 | |
59 uint8_t is_visited(disasm_context *context, uint32_t address) | |
60 { | |
61 if (!context->visited) { | |
62 return 0; | |
63 } | |
64 address &= context->address_mask; | |
65 address >>= context->visit_preshift; | |
66 return (context->visited[address >> 3] & (1 << (address & 7))) != 0; | |
67 } | |
68 | |
69 void defer_disasm(disasm_context *context, uint32_t address) | |
70 { | |
71 if (is_visited(context, address) || address & context->invalid_inst_addr_mask) { | |
72 return; | |
73 } | |
74 context->deferred = defer_address(context->deferred, address, NULL); | |
75 } | |
76 | |
77 void process_m68k_vectors(disasm_context *context, uint16_t *table, uint8_t labels_only) | |
78 { | |
79 static const char* names[] = { | |
80 "access_fault", | |
81 "address_error", | |
82 "illegal_instruction", | |
83 "integer_divide_by_zero", | |
84 "chk_exception", | |
85 "trap_exception", | |
86 "privilege_violation", | |
87 "trace_exception", | |
88 "line_1010_emulator", | |
89 "line_1111_emulator" | |
90 }; | |
91 uint32_t address = table[2] << 16 | table[3]; | |
92 add_label(context, "start", address); | |
93 if (!labels_only) { | |
94 defer_disasm(context, address); | |
95 } | |
96 for (int i = 0; i < sizeof(names)/sizeof(*names); i++) | |
97 { | |
98 address = table[i*2+4] << 16 | table[i*2 + 5]; | |
99 add_label(context, names[i], address); | |
100 if (!labels_only) { | |
101 defer_disasm(context, address); | |
102 } | |
103 } | |
104 char int_name[] = "int_0"; | |
105 for (int i = 0; i < 7; i++) | |
106 { | |
107 int_name[4] = '1' + i; | |
108 address = table[i*2+50] << 16 | table[i*2 + 51]; | |
109 add_label(context, int_name, address); | |
110 if (!labels_only) { | |
111 defer_disasm(context, address); | |
112 } | |
113 } | |
114 | |
115 char trap_name[] = "trap_0"; | |
116 for (int i = 0; i < 16; i++) | |
117 { | |
118 trap_name[5] = i < 0xA ? '0' + i : 'a' + i - 0xA; | |
119 address = table[i*2+50] << 16 | table[i*2 + 51]; | |
120 add_label(context, trap_name, address); | |
121 if (!labels_only) { | |
122 defer_disasm(context, address); | |
123 } | |
124 } | |
125 } | |
126 | |
127 void add_segacd_maincpu_labels(disasm_context *context) | |
128 { | |
129 weak_label(context, "_bios_reset", 0x280); | |
130 weak_label(context, "_bios_entry", 0x284); | |
131 weak_label(context, "_bios_init", 0x288); | |
132 weak_label(context, "_bios_init_sp", 0x28C); | |
133 weak_label(context, "_bios_vint", 0x290); | |
134 weak_label(context, "_bios_set_hint", 0x294); | |
135 weak_label(context, "_bios_poll_io", 0x298); | |
136 weak_label(context, "_bios_detect_io", 0x29C); | |
137 weak_label(context, "_bios_clear_vram", 0x2A0); | |
138 weak_label(context, "_bios_clear_nmtbl", 0x2A4); | |
139 weak_label(context, "_bios_clear_vsram", 0x2A8); | |
140 weak_label(context, "_bios_init_vdp", 0x2AC); | |
141 weak_label(context, "_bios_vdp_loadregs", 0x2B0); | |
142 weak_label(context, "_bios_vdp_fill", 0x2B4); | |
143 weak_label(context, "_bios_clear_vram_range", 0x2B8); | |
144 weak_label(context, "_bios_clear_vram_range_dma", 0x2BC); | |
145 weak_label(context, "_bios_vram_dma_fill", 0x2C0); | |
146 weak_label(context, "_bios_update_nmtbl", 0x2C4); | |
147 weak_label(context, "_bios_update_nmtbl_template", 0x2C8); | |
148 weak_label(context, "_bios_fill_nmtbl", 0x2CC); | |
149 weak_label(context, "_bios_vdp_dma", 0x2D0); | |
150 weak_label(context, "_bios_vdp_dma_wordram", 0x2D4); | |
151 weak_label(context, "_bios_vdp_display_enable", 0x2D8); | |
152 weak_label(context, "_bios_vdp_display_disable", 0x2DC); | |
153 weak_label(context, "_bios_pal_buffer", 0x2E0); | |
154 weak_label(context, "_bios_pal_buffer_update", 0x2E4); | |
155 weak_label(context, "_bios_pal_dma", 0x2E8); | |
156 weak_label(context, "_bios_gfx_decomp", 0x2EC); | |
157 weak_label(context, "_bios_gfx_decomp_ram", 0x2F0); | |
158 weak_label(context, "_bios_update_sprites", 0x2F4); | |
159 weak_label(context, "_bios_clear_ram", 0x2F8); | |
160 weak_label(context, "_bios_display_sprite", 0x300); | |
161 weak_label(context, "_bios_wait_vint", 0x304); | |
162 weak_label(context, "_bios_wait_vint_flags", 0x308); | |
163 weak_label(context, "_bios_dma_sat", 0x30C); | |
164 weak_label(context, "_bios_set_hint_direct", 0x314); | |
165 weak_label(context, "_bios_disable_hint", 0x318); | |
166 weak_label(context, "_bios_print", 0x31C); | |
167 weak_label(context, "_bios_load_user_font", 0x320); | |
168 weak_label(context, "_bios_load_bios_font", 0x324); | |
169 weak_label(context, "_bios_load_bios_font_default", 0x328); | |
170 //TODO: more functions in the middle here | |
171 weak_label(context, "_bios_prng_mod", 0x338); | |
172 weak_label(context, "_bios_prng", 0x33C); | |
173 weak_label(context, "_bios_clear_comm", 0x340); | |
174 weak_label(context, "_bios_comm_update", 0x344); | |
175 //TODO: more functions in the middle here | |
176 weak_label(context, "_bios_sega_logo", 0x364); | |
177 weak_label(context, "_bios_set_vint", 0x368); | |
178 //TODO: more functions at the end here | |
179 | |
180 weak_label(context, "WORD_RAM", 0x200000); | |
181 weak_label(context, "CD_RESET_IFL2", 0xA12000); | |
182 weak_label(context, "CD_RESET_IFL2_BYTE", 0xA12001); | |
183 weak_label(context, "CD_WRITE_PROTECT", 0xA12002); | |
184 weak_label(context, "CD_MEM_MODE", 0xA12003); | |
185 weak_label(context, "CDC_CTRL", 0xA12004); | |
186 weak_label(context, "HINT_VECTOR", 0xA12006); | |
187 weak_label(context, "CDC_HOST_DATA", 0xA12008); | |
188 weak_label(context, "STOP_WATCH", 0xA1200C); | |
189 weak_label(context, "COMM_MAIN_FLAG", 0xA1200E); | |
190 weak_label(context, "COMM_SUB_FLAG", 0xA1200F); | |
191 weak_label(context, "COMM_CMD0", 0xA12010); | |
192 weak_label(context, "COMM_CMD1", 0xA12012); | |
193 weak_label(context, "COMM_CMD2", 0xA12014); | |
194 weak_label(context, "COMM_CMD3", 0xA12016); | |
195 weak_label(context, "COMM_CMD4", 0xA12018); | |
196 weak_label(context, "COMM_CMD5", 0xA1201A); | |
197 weak_label(context, "COMM_CMD6", 0xA1201C); | |
198 weak_label(context, "COMM_CMD7", 0xA1201E); | |
199 weak_label(context, "COMM_STATUS0", 0xA12020); | |
200 weak_label(context, "COMM_STATUS1", 0xA12022); | |
201 weak_label(context, "COMM_STATUS2", 0xA12024); | |
202 weak_label(context, "COMM_STATUS3", 0xA12026); | |
203 weak_label(context, "COMM_STATUS4", 0xA12028); | |
204 weak_label(context, "COMM_STATUS5", 0xA1202A); | |
205 weak_label(context, "COMM_STATUS6", 0xA1202C); | |
206 weak_label(context, "COMM_STATUS7", 0xA1202E); | |
207 } | |
208 | |
209 void add_segacd_subcpu_labels(disasm_context *context) | |
210 { | |
211 weak_label(context, "bios_common_work", 0x5E80); | |
212 weak_label(context, "_setjmptbl", 0x5F0A); | |
213 weak_label(context, "_waitvsync", 0x5F10); | |
214 weak_label(context, "_buram", 0x5F16); | |
215 weak_label(context, "_cdboot", 0x5F1C); | |
216 weak_label(context, "_cdbios", 0x5F22); | |
217 weak_label(context, "_usercall0", 0x5F28); | |
218 weak_label(context, "_usercall1", 0x5F2E); | |
219 weak_label(context, "_usercall2", 0x5F34); | |
220 weak_label(context, "_usercall2Address", 0x5F36); | |
221 weak_label(context, "_usercall3", 0x5F3A); | |
222 weak_label(context, "_adrerr", 0x5F40); | |
223 weak_label(context, "_adrerrAddress", 0x5F42); | |
224 weak_label(context, "_coderr", 0x5F46); | |
225 weak_label(context, "_coderrAddress", 0x5F48); | |
226 weak_label(context, "_diverr", 0x5F4C); | |
227 weak_label(context, "_diverrAddress", 0x5F4E); | |
228 weak_label(context, "_chkerr", 0x5F52); | |
229 weak_label(context, "_chkerrAddress", 0x5F54); | |
230 weak_label(context, "_trperr", 0x5F58); | |
231 weak_label(context, "_trperrAddress", 0x5F5A); | |
232 weak_label(context, "_spverr", 0x5F5E); | |
233 weak_label(context, "_spverrAddress", 0x5F60); | |
234 weak_label(context, "_trace", 0x5F64); | |
235 weak_label(context, "_traceAddress", 0x5F66); | |
236 weak_label(context, "_nocod0", 0x5F6A); | |
237 weak_label(context, "_nocod0Address", 0x5F6C); | |
238 weak_label(context, "_nocod0", 0x5F70); | |
239 weak_label(context, "_nocod0Address", 0x5F72); | |
240 weak_label(context, "_slevel1", 0x5F76); | |
241 weak_label(context, "_slevel1Address", 0x5F78); | |
242 weak_label(context, "_slevel2", 0x5F7C); | |
243 weak_label(context, "_slevel2Address", 0x5F7E); | |
244 weak_label(context, "_slevel3", 0x5F82); | |
245 weak_label(context, "_slevel3Address", 0x5F84); | |
246 weak_label(context, "WORD_RAM_2M", 0x80000); | |
247 weak_label(context, "WORD_RAM_1M", 0xC0000); | |
248 weak_label(context, "LED_CONTROL", 0xFFFF8000); | |
249 weak_label(context, "VERSION_RESET", 0xFFFF8001); | |
250 weak_label(context, "MEM_MODE_WORD", 0xFFFF8002); | |
251 weak_label(context, "MEM_MODE_BYTE", 0xFFFF8003); | |
252 weak_label(context, "CDC_CTRL", 0xFFFF8004); | |
253 weak_label(context, "CDC_AR", 0xFFFF8005); | |
254 weak_label(context, "CDC_REG_DATA_WORD", 0xFFFF8006); | |
255 weak_label(context, "CDC_REG_DATA", 0xFFFF8007); | |
256 weak_label(context, "CDC_HOST_DATA", 0xFFFF8008); | |
257 weak_label(context, "CDC_DMA_ADDR", 0xFFFF800A); | |
258 weak_label(context, "STOP_WATCH", 0xFFFF800C); | |
259 weak_label(context, "COMM_MAIN_FLAG", 0xFFFF800E); | |
260 weak_label(context, "COMM_SUB_FLAG", 0xFFFF800F); | |
261 weak_label(context, "COMM_CMD0", 0xFFFF8010); | |
262 weak_label(context, "COMM_CMD1", 0xFFFF8012); | |
263 weak_label(context, "COMM_CMD2", 0xFFFF8014); | |
264 weak_label(context, "COMM_CMD3", 0xFFFF8016); | |
265 weak_label(context, "COMM_CMD4", 0xFFFF8018); | |
266 weak_label(context, "COMM_CMD5", 0xFFFF801A); | |
267 weak_label(context, "COMM_CMD6", 0xFFFF801C); | |
268 weak_label(context, "COMM_CMD7", 0xFFFF801E); | |
269 weak_label(context, "COMM_STATUS0", 0xFFFF8020); | |
270 weak_label(context, "COMM_STATUS1", 0xFFFF8022); | |
271 weak_label(context, "COMM_STATUS2", 0xFFFF8024); | |
272 weak_label(context, "COMM_STATUS3", 0xFFFF8026); | |
273 weak_label(context, "COMM_STATUS4", 0xFFFF8028); | |
274 weak_label(context, "COMM_STATUS5", 0xFFFF802A); | |
275 weak_label(context, "COMM_STATUS6", 0xFFFF802C); | |
276 weak_label(context, "COMM_STATUS7", 0xFFFF802E); | |
277 weak_label(context, "TIMER_WORD", 0xFFFF8030); | |
278 weak_label(context, "TIMER", 0xFFFF8031); | |
279 weak_label(context, "INT_MASK_WORD", 0xFFFF8032); | |
280 weak_label(context, "INT_MASK", 0xFFFF8033); | |
281 weak_label(context, "CDD_FADER", 0xFFFF8034); | |
282 weak_label(context, "CDD_CTRL_WORD", 0xFFFF8036); | |
283 weak_label(context, "CDD_CTRL_BYTE", 0xFFFF8037); | |
284 } | |
285 | |
286 disasm_context *create_68000_disasm(void) | |
287 { | |
288 disasm_context *context = calloc(1, sizeof(disasm_context)); | |
289 context->address_mask = 0xFFFFFF; | |
290 context->invalid_inst_addr_mask = 1; | |
291 context->visit_preshift = 1; | |
292 return context; | |
293 } | |
294 |