Mercurial > hg > forks > dxa
annotate dump.c @ 11:fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 14 May 2020 20:35:40 +0300 |
parents | 122134900c0e |
children | 84c0facfc43c |
rev | line source |
---|---|
0 | 1 /*\ |
2 * dxa v0.1.3 -- symbolic 65xx disassembler | |
3 * | |
4 * Copyright (C) 1993, 1994 Marko M\"akel\"a | |
5 * Changes for dxa (C) 2004, 2006 Cameron Kaiser | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 * | |
21 * Marko does not maintain dxa, so questions specific to dxa should be | |
22 * sent to me at ckaiser@floodgap.com . Otherwise, | |
23 * | |
24 * Contacting the author: | |
25 * | |
26 * Via Internet E-mail: | |
27 * <Marko.Makela@FTP.FUNET.FI> | |
28 * | |
29 * Via Snail Mail: | |
30 * Marko M\"akel\"a | |
31 * Sillitie 10 A | |
32 * FIN-01480 VANTAA | |
33 * Finland | |
34 \*/ | |
35 | |
36 #define _DUMP_C_ | |
37 #include <stdio.h> | |
38 #include <stdlib.h> | |
39 | |
40 #include "proto.h" | |
41 #include "options.h" | |
42 #include "opcodes.h" | |
43 | |
44 void Dump (void) | |
45 { | |
46 ADDR_T address, addr; | |
47 unsigned counter, size, maxwidth; | |
48 char *lineprefix, *lineinfix; | |
49 table *entry; | |
50 opcodes *instr; | |
51 | |
52 if (fVerbose) | |
53 fprintf (stderr, "%s: Dumping the source code.\n", prog); | |
54 | |
55 /* determine the maximum amount of bytes dumped per line */ | |
56 | |
57 maxwidth = listwidth < 2 ? 2 : listwidth; | |
58 | |
59 for (counter = 0; counter < 256; counter++) | |
60 if (maxwidth < sizes[opset[counter].admode]) | |
61 maxwidth = sizes[opset[counter].admode]; | |
62 | |
63 /* create prefix string for lines without address information */ | |
64 switch (Options & M_ADDRESSES) { | |
65 case O_ADR_ADRPFIX: | |
66 counter = 5; | |
67 break; | |
68 | |
69 case O_ADR_ADR_DMP: | |
70 counter = 5 + 3 * maxwidth; | |
71 break; | |
72 | |
73 default: | |
74 counter = 0; | |
75 } | |
76 | |
77 lineprefix = malloc (counter + 1); | |
78 | |
79 if (counter >= 5) { | |
80 lineinfix = lineprefix + 5; | |
81 | |
82 for (lineprefix[counter] = 0; counter--; lineprefix[counter] = ' '); | |
83 } | |
84 else { | |
85 *lineprefix = 0; | |
86 lineinfix = lineprefix; | |
87 } | |
88 | |
89 /* print the label definitions */ | |
90 for (address = EndAddress < StartAddress ? EndAddress : 0; | |
91 address != StartAddress; address++) | |
10 | 92 { |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
10
diff
changeset
|
93 if (IsLabeled (address) && !IsInsideRegion(address) && IsReferenced(address)) |
10 | 94 { |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
95 fprintf (stdout, "%s%s = $%x\n", lineprefix, Label (address, abso, 0), |
0 | 96 address); |
10 | 97 } |
98 } | |
0 | 99 |
100 if (EndAddress >= StartAddress) | |
10 | 101 { |
0 | 102 for (address = EndAddress; address; address++) |
10 | 103 { |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
10
diff
changeset
|
104 if (IsLabeled (address) && !IsInsideRegion(address) && IsReferenced(address)) |
10 | 105 { |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
106 fprintf (stdout, "%s%s = $%x\n", lineprefix, Label (address, abso, 0), |
0 | 107 address); |
10 | 108 } |
109 } | |
110 } | |
0 | 111 |
112 /* dump the program */ | |
7 | 113 fprintf(stdout, "\n\n"); |
0 | 114 |
115 if(Options & B_SA_WORD) | |
116 fprintf(stdout, "%s\t.word $%04x", lineprefix, StartAddress); | |
7 | 117 |
0 | 118 fprintf (stdout, "\n%s\t* = $%04x\n\n", lineprefix, StartAddress); |
119 | |
7 | 120 |
0 | 121 for (address = StartAddress; (ADDR_T)(address - StartAddress) < |
122 (ADDR_T)(EndAddress - StartAddress); address += size) | |
123 if (GetMemType (address) == MEM_INSTRUCTION) { | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
10
diff
changeset
|
124 |
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
10
diff
changeset
|
125 if (IsLabeled (address) && IsReferenced(address)) { |
0 | 126 if (Options & M_ADDRESSES) |
127 fprintf (stdout, "%04x %s%s:\n", address, | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
128 lineinfix, Label (address, abso, 0)); |
0 | 129 else { |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
130 fprintf (stdout, "%s", Label (address, abso, 0)); |
0 | 131 if (Options & B_LABCOL) |
132 fprintf(stdout, ":\n"); | |
133 } | |
134 } | |
135 | |
136 instr = &opset[Memory[address]]; | |
137 size = sizes[instr->admode]; | |
138 | |
139 for (counter = 1; counter < size; counter++) { | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
10
diff
changeset
|
140 if (IsLabeled (address + counter)) |
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
10
diff
changeset
|
141 { |
0 | 142 if (Options & M_ADDRESSES) |
143 fprintf (stdout, "\t%04x %s%s = * + %u\n", | |
144 (ADDR_T)(address + counter), | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
145 lineinfix, Label (address + counter, abso, 0), counter); |
0 | 146 else |
147 fprintf (stdout, "\t%s = * + %u\n", | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
148 Label (address + counter, abso, 0), counter); |
0 | 149 } |
150 | |
151 if (FindNextEntry (NULL, address, ~0, WRN_INSTR_WRITTEN_TO)) | |
152 fprintf (stdout, "%s; Instruction opcode accessed.\n", lineprefix); | |
153 | |
154 entry = NULL; | |
155 | |
156 while ((entry = FindNextEntry (entry, address + counter, 0, 0))) | |
157 switch (entry->type) { | |
158 case WRN_PARAM_WRITTEN_TO: | |
159 fprintf (stdout, "%s; Instruction parameter accessed.\n", | |
160 lineprefix); | |
161 break; | |
162 | |
163 case WRN_PARAM_JUMPED_TO: | |
164 fprintf (stdout, "%s; Instruction parameter jumped to.\n", | |
165 lineprefix); | |
166 break; | |
167 } | |
168 } | |
169 | |
170 switch (Options & M_ADDRESSES) { | |
171 case O_ADR_ADRPFIX: | |
172 fprintf (stdout, "%04x ", address); | |
173 break; | |
174 | |
175 case O_ADR_ADR_DMP: | |
176 fprintf (stdout, "%04x ", address); | |
177 | |
178 for (counter = 0; counter < size; counter++) | |
179 fprintf (stdout, "%02x ", Memory[(ADDR_T)(address + counter)]); | |
180 | |
181 fputs (lineinfix + 3 * counter, stdout); | |
182 } | |
183 | |
184 fputs ("\t", stdout); | |
185 | |
186 switch (instr->admode) { | |
187 case accu: | |
188 case impl: | |
189 fprintf (stdout, "%s%s\n", mne[instr->mnemonic], | |
190 postfix[instr->admode]); | |
191 break; | |
192 case imm: | |
193 addr = Memory[(ADDR_T)(address + 1)]; | |
194 fprintf (stdout, "%s #$%02x\n", mne[instr->mnemonic], addr); | |
195 break; | |
196 case abso: | |
197 case absx: | |
198 case absy: | |
199 case iabs: | |
200 case iabsx: | |
201 addr = Memory[(ADDR_T)(address + 1)] | | |
202 (Memory[(ADDR_T)(address + 2)] << 8); | |
203 /* Fix to ensure 16-bit addresses to zero-page are maintained as 16-bit */ | |
204 fprintf (stdout, "%s %s%s%s%s\n", mne[instr->mnemonic], | |
205 prefix[instr->admode], | |
206 ((addr < 256 && instr->mnemonic != S_JMP && | |
207 instr->mnemonic != S_JSR) ? "!" : ""), | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
208 Label (addr, abso, 1), postfix[instr->admode]); |
0 | 209 break; |
210 case zp: | |
211 case zpx: | |
212 case zpy: | |
213 case ind: | |
214 case indx: | |
215 case indy: | |
216 addr = Memory[(ADDR_T)(address + 1)]; | |
217 fprintf (stdout, "%s %s%s%s\n", mne[instr->mnemonic], | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
218 prefix[instr->admode], Label (addr, zp, 1), |
0 | 219 postfix[instr->admode]); |
220 break; | |
221 case rel: | |
222 addr = (int)(char)Memory[(ADDR_T)(address + 1)]; | |
223 /* addr -= (addr > 127) ? 256 : 0; BUGFIX: sign extend already done */ | |
224 /*fprintf(stderr, "%d %d %d\n", address, size, addr);*/ | |
225 addr += address + size; | |
226 fprintf (stdout, "%s %s%s%s\n", mne[instr->mnemonic], | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
227 prefix[instr->admode], Label (addr, abso, 1), |
0 | 228 postfix[instr->admode]); |
229 break; | |
230 case zrel: /* BBR0, etc. 65C02 instructions */ | |
231 addr = (int)(char)Memory[(ADDR_T)(address + 2)]; | |
232 /* addr -= (addr > 127) ? 256 : 0; BUGFIX: sign extend already done */ | |
233 addr += address + size; | |
234 fprintf (stdout, "%s %s, %s\n", mne[instr->mnemonic], | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
235 Label (Memory[(ADDR_T)(address + 1)], abso, 1), |
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
236 Label (addr, abso, 1)); |
0 | 237 break; |
238 } | |
239 } | |
240 else if (address != (addr = WordTableEnd (address))) { /* word table */ | |
241 for (size = (ADDR_T)(addr - address); size; | |
242 address += (counter = size > (maxwidth & ~1) ? | |
243 (maxwidth & ~1) : size), size -= counter) { | |
244 if (IsLabeled (address)) { | |
245 if (Options & M_ADDRESSES) | |
246 fprintf (stdout, "%04x %s%s:\n", address, lineinfix, | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
247 Label (address, abso, 0)); |
0 | 248 else |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
249 fprintf (stdout, "%s ", Label (address, abso, 0)); |
0 | 250 } |
251 for (counter = size > (maxwidth & ~1) ? (maxwidth & ~1) : size, | |
252 addr = address + 1; --counter; addr++) | |
253 if (IsLabeled (addr)) { | |
254 if (Options & M_ADDRESSES) | |
255 fprintf (stdout, "%04x %s%s = * + %u\n", addr, lineinfix, | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
256 Label (addr, abso, 0), (ADDR_T)(addr - address)); |
0 | 257 else |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
258 fprintf (stdout, "\t%s = * + %u\n", Label (addr, abso, 0), |
0 | 259 (ADDR_T)(addr - address)); |
260 } | |
261 | |
262 if (Options & M_ADDRESSES) | |
263 fprintf (stdout, "%04x ", address); | |
264 | |
265 if ((Options & M_ADDRESSES) == O_ADR_ADR_DMP) { | |
266 for (counter = size > (maxwidth & ~1) ? (maxwidth & ~1) : size, | |
267 addr = address; counter--; addr++) { | |
268 fprintf (stdout, "%02x ", Memory[addr]); | |
269 } | |
270 fputs (lineinfix + 3 * (size > (maxwidth & ~1) ? | |
271 (maxwidth & ~1) : size), stdout); | |
272 } | |
273 | |
274 fprintf (stdout, " .word %s", | |
275 Label (Memory[address] | | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
276 (Memory[(ADDR_T)(address + 1)] << 8), abso, 0)); |
0 | 277 |
278 for (counter = size > (maxwidth & ~1) ? (maxwidth & ~1) : size, | |
279 addr = address + 2; counter -= 2; addr += 2) | |
280 fprintf (stdout, ",%s", | |
281 Label (Memory[addr] | (Memory[(ADDR_T)(addr + 1)] << 8), | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
282 abso, 0)); |
0 | 283 |
284 | |
285 fputc ('\n', stdout); | |
286 } | |
287 } | |
288 else { /* data block */ | |
289 for (size = 1; size < maxwidth; size++) { /* determine the size */ | |
290 addr = address + size; | |
291 | |
292 if (GetMemType (addr) == MEM_INSTRUCTION || | |
293 addr != WordTableEnd (addr)) | |
294 break; | |
295 } | |
296 | |
297 if (IsLabeled (address)) { | |
298 if (Options & M_ADDRESSES) | |
299 fprintf (stdout, "%04x %s%s:\n", address, lineinfix, | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
300 Label (address, abso, 0)); |
0 | 301 else |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
302 fprintf (stdout, "%s ", Label (address, abso, 0)); |
0 | 303 } |
304 | |
305 for (counter = size, addr = address + 1; --counter; addr++) | |
306 if (IsLabeled (addr)) { | |
307 if (Options & M_ADDRESSES) | |
308 fprintf (stdout, "%04x %s%s = * + %u\n", addr, lineinfix, | |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
309 Label (addr, abso, 0), (ADDR_T)(addr - address)); |
0 | 310 else |
4
0990d9322fc8
Implement address-ranged labels. Breaks compatibility of label files.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
311 fprintf (stdout, "\t%s = * + %u\n", Label (addr, abso, 0), |
0 | 312 (ADDR_T)(addr - address)); |
313 } | |
314 | |
315 if (Options & M_ADDRESSES) | |
316 fprintf (stdout, "%04x ", address); | |
317 | |
318 if ((Options & M_ADDRESSES) == O_ADR_ADR_DMP) { | |
319 for (counter = size, addr = address; counter--; addr++) | |
320 fprintf (stdout, "%02x ", Memory[addr]); | |
321 | |
322 fputs (lineinfix + 3 * size, stdout); | |
323 } | |
324 | |
325 fprintf (stdout, "\t.byt $%02x", Memory[address]); | |
326 | |
327 for (counter = size, addr = address + 1; --counter; addr++) | |
328 if (addr < EndAddress) /* problems with this overflowing */ | |
329 fprintf (stdout, ",$%02x", Memory[addr]); | |
330 | |
331 fputc ('\n', stdout); | |
332 } | |
333 } |