Mercurial > hg > forks > dxa
annotate scan.c @ 14:84c0facfc43c
Merge changes from upstream v0.1.4.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 14 Oct 2021 01:38:52 +0300 |
parents | fe4d840c13eb |
children | a2a81589380d |
rev | line source |
---|---|
0 | 1 /*\ |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
2 * dxa -- symbolic 65xx disassembler |
0 | 3 * |
4 * Copyright (C) 1993, 1994 Marko M\"akel\"a | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
5 * Copyright (C) 2019 Cameron Kaiser |
0 | 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 \*/ | |
22 | |
23 #define _SCAN_C_ | |
24 #include <stdio.h> | |
25 #include "proto.h" | |
26 #include "opcodes.h" | |
27 #include "options.h" | |
28 | |
29 | |
30 int ScanSure (ADDR_T scanstart) | |
31 { | |
32 ADDR_T address, addr; | |
33 opcodes *instr; | |
34 | |
35 unsigned int size, counter; | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
36 if (fVerbose) |
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
37 fprintf(stderr, "\n%s: scanning sure section $%04x", prog, scanstart); |
0 | 38 |
39 for (address = scanstart;; address += size) { | |
40 if (GetMemFlag (address)) /* rest of routine not valid */ | |
41 return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT); | |
42 | |
43 instr = &opset[Memory[address]]; | |
44 | |
45 if (!instr->mnemonic) /* invalid opcode */ | |
46 return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT); | |
47 | |
48 size = sizes[instr->admode]; | |
49 if ((ADDR_T)(address + size - StartAddress) > | |
50 (ADDR_T)(EndAddress - StartAddress)) | |
51 break; /* end of program code encountered */ | |
52 | |
53 switch (GetMemType (address)) { | |
54 case MEM_INSTRUCTION: | |
55 return 0; /* The rest of the routine has already been processed. */ | |
56 | |
57 case MEM_DATA: | |
58 AddEntry (address, scanstart, WRN_INSTR_WRITTEN_TO); | |
59 break; | |
60 | |
61 case MEM_PARAMETER: | |
62 AddEntry (address, scanstart, WRN_PARAM_JUMPED_TO); | |
63 } | |
64 | |
65 SetMemType (address, MEM_INSTRUCTION); | |
66 | |
67 for (counter = size, addr = address + 1; --counter; addr++) | |
68 switch GetMemType(addr) { | |
69 case MEM_INSTRUCTION: | |
70 AddEntry (addr, scanstart, WRN_PARAM_JUMPED_TO); | |
71 break; | |
72 case MEM_DATA: | |
73 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); | |
74 /* fall through */ | |
75 default: | |
76 SetMemType (addr, MEM_PARAMETER); | |
77 } | |
78 | |
79 if (instr->admode == zrel) { | |
80 addr = Memory[(ADDR_T)(address + 1)]; | |
81 | |
82 if (GetMemFlag (addr) && GetMemType (addr) == MEM_UNPROCESSED) | |
83 return (Options & M_DATA_BLOCKS) == O_DBL_STRICT; | |
84 | |
85 if (((ADDR_T)(addr - StartAddress) < | |
86 (ADDR_T)(EndAddress - StartAddress) || | |
87 Options & B_LBL_ALWAYS)) { | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
88 |
0 | 89 PutLabel (addr); |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
90 PutReference (addr); |
0 | 91 PutLowByte (addr); |
92 PutHighByte (addr); | |
93 } | |
94 | |
95 addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 2)] + | |
96 address + size); | |
97 goto IsJump; | |
98 } | |
99 | |
100 if (instr->admode == rel) { | |
101 addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] + | |
102 address + size); | |
103 | |
104 goto IsJump; | |
105 } | |
106 if ((instr->mnemonic == S_JSR || instr->mnemonic == S_JMP) && | |
107 instr->admode == abso) { | |
108 addr = Memory[(ADDR_T)(address + 1)] + | |
109 (Memory[(ADDR_T)(address + 2)] << 8); | |
110 | |
111 IsJump: | |
112 if (GetMemFlag (addr)) | |
113 return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT); | |
114 | |
115 if ((ADDR_T)(addr - StartAddress) < | |
116 (ADDR_T)(EndAddress - StartAddress)) { | |
117 if (GetMemType (addr) == MEM_INSTRUCTION) { | |
118 PutLabel (addr); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
119 PutReference (addr); |
0 | 120 PutLowByte (addr); |
121 PutHighByte (addr); | |
122 } | |
123 else | |
124 AddEntry (addr, scanstart, Options & B_SCEPTIC && | |
125 instr->admode == rel && instr->mnemonic != S_BRA ? | |
126 RTN_POTENTIAL : RTN_SURE); | |
127 } | |
128 else if (Options & B_LBL_ALWAYS) { | |
129 PutLabel (addr); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
130 PutReference (addr); |
0 | 131 PutLowByte (addr); |
132 PutHighByte (addr); | |
133 } | |
134 | |
135 if ((Options & M_DATA_BLOCKS) == O_DBL_STRICT && | |
136 Options & B_JMP_STRICT && | |
137 addr == address && instr->mnemonic != S_BVC) | |
138 return 1; | |
139 } | |
140 | |
141 switch (instr->mnemonic) { | |
142 case S_JMP: | |
143 addr = Memory[(ADDR_T)(address + 1)] + | |
144 (Memory[(ADDR_T)(address + 2)] << 8); | |
145 | |
146 if (instr->admode == iabs && (ADDR_T)(addr - StartAddress) < | |
147 (ADDR_T)(EndAddress - StartAddress)) { | |
148 PutLabel (addr); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
149 PutReference (addr); |
0 | 150 PutLowByte (addr); |
151 PutHighByte (addr); | |
152 | |
153 /* Mark pointer as data. */ | |
154 switch (GetMemType (addr)) { | |
155 case MEM_UNPROCESSED: | |
156 SetMemType (addr, MEM_DATA); | |
157 break; | |
158 case MEM_INSTRUCTION: | |
159 AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); | |
160 break; | |
161 case MEM_PARAMETER: | |
162 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); | |
163 break; | |
164 } | |
165 | |
166 addr++; | |
167 | |
168 if ((ADDR_T)(addr - StartAddress) < | |
169 (ADDR_T)(EndAddress - StartAddress)) | |
170 switch (GetMemType (addr)) { | |
171 case MEM_UNPROCESSED: | |
172 SetMemType (addr, MEM_DATA); | |
173 break; | |
174 case MEM_INSTRUCTION: | |
175 AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); | |
176 break; | |
177 case MEM_PARAMETER: | |
178 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); | |
179 break; | |
180 } | |
181 } | |
182 else if (Options & B_LBL_ALWAYS) { | |
183 PutLabel (addr); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
184 PutReference (addr); |
0 | 185 PutLowByte (addr); |
186 PutHighByte (addr); | |
187 } | |
9 | 188 return 0; |
189 | |
0 | 190 case S_BRA: |
191 case S_RTS: | |
192 case S_RTI: | |
193 return 0; | |
194 | |
195 case S_BRK: | |
196 case S_STP: | |
197 return (Options & M_DATA_BLOCKS) == O_DBL_STRICT && | |
198 Options & B_BRK_REJECT; | |
199 } | |
200 | |
201 if (instr->admode == rel) { | |
202 if ((ADDR_T)(addr - scanstart) >= (ADDR_T)(address - scanstart) | |
203 || GetMemType (addr) != MEM_INSTRUCTION) { | |
204 if (GetMemType (address + size) != MEM_INSTRUCTION) | |
205 AddEntry (address + size, scanstart, RTN_POTENTIAL); | |
206 | |
207 return 0; | |
208 } | |
209 | |
210 continue; | |
211 } | |
212 | |
213 if (instr->mnemonic == S_JSR) { | |
214 if (!(Options & B_STK_BALANCE)) { | |
215 if (GetMemType (address + size) != MEM_INSTRUCTION) | |
216 AddEntry (address + size, scanstart, RTN_POTENTIAL); | |
217 | |
218 return 0; | |
219 } | |
220 | |
221 continue; | |
222 } | |
223 | |
224 switch (size) { | |
225 case 2: | |
226 addr = Memory[(ADDR_T)(address + 1)]; | |
227 break; | |
228 case 3: | |
229 addr = Memory[(ADDR_T)(address + 1)] + | |
230 (Memory[(ADDR_T)(address + 2)] << 8); | |
231 break; | |
232 } | |
233 | |
234 if (types[instr->admode] != impimm && GetMemFlag (addr) && | |
235 GetMemType (addr) == MEM_UNPROCESSED) | |
236 return (Options & M_DATA_BLOCKS) == O_DBL_STRICT; | |
237 | |
238 if (types[instr->admode] != impimm && | |
239 ((ADDR_T)(addr - StartAddress) < | |
240 (ADDR_T)(EndAddress - StartAddress) || | |
241 Options & B_LBL_ALWAYS)) { | |
242 PutLabel (addr); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
243 PutReference (addr); |
0 | 244 PutLowByte (addr); |
245 PutHighByte (addr); | |
246 } | |
247 | |
248 if (types[instr->admode] != other && types[instr->admode] != impimm) { | |
249 if ((ADDR_T)(addr - StartAddress) < | |
250 (ADDR_T)(EndAddress - StartAddress)) { | |
251 switch (GetMemType (addr)) { | |
252 case MEM_UNPROCESSED: | |
253 SetMemType (addr, MEM_DATA); | |
254 break; | |
255 case MEM_INSTRUCTION: | |
256 AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); | |
257 break; | |
258 case MEM_PARAMETER: | |
259 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); | |
260 break; | |
261 } | |
262 | |
263 if (types[instr->admode] == absindir) { /* indirect mode */ | |
264 addr++; /* set flags for upper vector byte */ | |
265 | |
266 if ((ADDR_T)(addr - StartAddress) < | |
267 (ADDR_T)(EndAddress - StartAddress)) | |
268 switch (GetMemType (addr)) { | |
269 case MEM_UNPROCESSED: | |
270 SetMemType (addr, MEM_DATA); | |
271 break; | |
272 case MEM_INSTRUCTION: | |
273 AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); | |
274 break; | |
275 case MEM_PARAMETER: | |
276 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); | |
277 break; | |
278 } | |
279 } | |
280 } | |
281 } | |
282 } | |
283 | |
284 /* end of program (unexpectedly) encountered */ | |
285 | |
286 if (Options & O_DBL_STRICT) return 1; | |
287 | |
288 AddEntry (EndAddress, scanstart, WRN_RTN_TRUNCATED); | |
289 return 0; | |
290 } | |
291 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
1
diff
changeset
|
292 |
0 | 293 int ScanPotential (ADDR_T scanstart) |
294 { | |
295 ADDR_T address, addr; | |
296 opcodes *instr; | |
297 | |
298 unsigned int size, counter; | |
299 | |
300 for (address = scanstart;; address += size) { | |
301 if (GetMemFlag (address)) /* rest of routine not valid */ | |
302 return 1; | |
303 | |
304 instr = &opset[Memory[address]]; | |
305 | |
306 if (!instr->mnemonic) { /* invalid opcode */ | |
307 SetMemFlag (address); | |
308 | |
309 if (GetMemType (address) == MEM_UNPROCESSED) | |
310 SetMemType (address, MEM_DATA); | |
311 return 1; | |
312 } | |
313 | |
314 size = sizes[instr->admode]; | |
315 if ((ADDR_T)(address + size - StartAddress) > | |
316 (ADDR_T)(EndAddress - StartAddress)) | |
317 break; /* end of program code encountered */ | |
318 | |
319 if (GetMemType (address) == MEM_INSTRUCTION) | |
320 return 0; /* The rest of the routine has already been processed. */ | |
321 | |
322 if (instr->admode == zrel) { | |
323 addr = Memory[(ADDR_T)(address + 1)]; | |
324 | |
325 if (GetMemFlag (addr) && GetMemType (addr) == MEM_UNPROCESSED) | |
326 goto Failure; | |
327 | |
328 if (((ADDR_T)(addr - StartAddress) < | |
329 (ADDR_T)(EndAddress - StartAddress) || | |
330 Options & B_LBL_ALWAYS)) | |
331 AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); | |
332 | |
333 addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] + | |
334 address + size); | |
335 | |
336 goto IsJump; | |
337 } | |
338 | |
339 if (instr->admode == rel) { | |
340 addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] + | |
341 address + size); | |
342 | |
343 goto IsJump; | |
344 } | |
345 | |
346 switch (size) { | |
347 case 2: | |
348 addr = Memory[(ADDR_T)(address + 1)]; | |
349 break; | |
350 case 3: | |
351 addr = Memory[(ADDR_T)(address + 1)] + | |
352 (Memory[(ADDR_T)(address + 2)] << 8); | |
353 break; | |
354 default: | |
355 addr = address; | |
356 } | |
357 | |
358 if (types[instr->admode] != impimm && GetMemFlag (addr) && | |
359 GetMemType (addr) == MEM_UNPROCESSED) { | |
360 Failure: | |
361 SetMemFlag (address); | |
362 | |
363 if (GetMemType (address) == MEM_UNPROCESSED) | |
364 SetMemType (address, MEM_DATA); | |
365 return 1; | |
366 } | |
367 | |
368 if ((instr->mnemonic == S_JSR || instr->mnemonic == S_JMP) && | |
369 instr->admode == abso) { | |
370 IsJump: | |
371 if (GetMemFlag (addr)) { | |
372 SetMemFlag (address); | |
373 | |
374 if (GetMemType (address) == MEM_UNPROCESSED) | |
375 SetMemType (address, MEM_DATA); | |
376 return 1; | |
377 } | |
378 | |
379 if ((ADDR_T)(addr - StartAddress) < | |
380 (ADDR_T)(EndAddress - StartAddress)) | |
381 AddEntry (addr, scanstart, Options & B_SCEPTIC && | |
382 instr->admode == rel && instr->mnemonic != S_BRA ? | |
383 RTN_SUSP_POT : RTN_SUSPECTED); | |
384 else if (Options & B_LBL_ALWAYS) | |
385 AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); | |
386 | |
387 if (Options & B_JMP_STRICT && addr == address && | |
388 instr->mnemonic != S_BVC) { | |
389 SetMemFlag (address); | |
390 | |
391 if (GetMemType (address) == MEM_UNPROCESSED) | |
392 SetMemType (address, MEM_DATA); | |
393 return 1; | |
394 } | |
395 } | |
396 | |
397 switch (instr->mnemonic) { | |
398 case S_BRK: | |
399 case S_STP: | |
400 if (Options & B_BRK_REJECT) { | |
401 SetMemFlag (address); | |
402 | |
403 if (GetMemType (address) == MEM_UNPROCESSED) | |
404 SetMemType (address, MEM_DATA); | |
405 return 1; | |
406 } | |
407 } | |
408 | |
409 if (!GetMemFlag (address)) | |
410 switch (GetMemType (address)) { | |
411 case MEM_DATA: | |
412 AddEntry (address, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); | |
413 break; | |
414 | |
415 case MEM_PARAMETER: | |
416 AddEntry (address, scanstart, WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY); | |
417 } | |
418 | |
419 SetMemType (address, MEM_INSTRUCTION); | |
420 | |
421 for (counter = size, addr = address + 1; --counter; addr++) | |
422 switch (GetMemType (addr)) { | |
423 case MEM_INSTRUCTION: | |
424 AddEntry (addr, scanstart, WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY); | |
425 break; | |
426 case MEM_DATA: | |
427 if (!GetMemFlag (addr)) | |
428 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); | |
429 break; | |
430 default: | |
431 SetMemType (addr, MEM_PARAMETER); | |
432 } | |
433 | |
434 switch (instr->mnemonic) { | |
435 case S_BRK: | |
436 case S_STP: | |
437 case S_RTS: | |
438 case S_BRA: | |
439 case S_RTI: | |
440 return 0; | |
441 | |
442 case S_JMP: | |
443 addr = Memory[(ADDR_T)(address + 1)] + | |
444 (Memory[(ADDR_T)(address + 2)] << 8); | |
445 | |
446 if (instr->admode == iabs && (ADDR_T)(addr - StartAddress) < | |
447 (ADDR_T)(EndAddress - StartAddress)) { | |
448 AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); | |
449 | |
450 /* Mark pointer as data. */ | |
451 switch (GetMemType (addr)) { | |
452 case MEM_UNPROCESSED: | |
453 AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); | |
454 break; | |
455 case MEM_INSTRUCTION: | |
456 AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); | |
457 break; | |
458 case MEM_PARAMETER: | |
459 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); | |
460 break; | |
461 } | |
462 | |
463 addr++; | |
464 | |
465 if ((ADDR_T)(addr - StartAddress) < | |
466 (ADDR_T)(EndAddress - StartAddress)) | |
467 switch (GetMemType (addr)) { | |
468 case MEM_UNPROCESSED: | |
469 AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); | |
470 break; | |
471 case MEM_INSTRUCTION: | |
472 AddEntry (addr, scanstart, | |
473 WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); | |
474 break; | |
475 case MEM_PARAMETER: | |
476 AddEntry (addr, scanstart, | |
477 WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); | |
478 break; | |
479 } | |
480 } | |
481 else if (Options & B_LBL_ALWAYS) | |
482 AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); | |
483 | |
484 return 0; | |
485 } | |
486 | |
487 if (instr->admode == rel && | |
488 GetMemType (address + size) != MEM_INSTRUCTION) { | |
489 AddEntry (address + size, scanstart, RTN_SUSP_POT); | |
490 | |
491 return 0; | |
492 } | |
493 | |
494 if (instr->mnemonic == S_JSR) { | |
495 if (!(Options & B_STK_BALANCE)) { | |
496 if (GetMemType (address + size) != MEM_INSTRUCTION) | |
497 AddEntry (address + size, scanstart, RTN_SUSP_POT); | |
498 | |
499 return 0; | |
500 } | |
501 | |
502 continue; | |
503 } | |
504 | |
505 switch (size) { | |
506 case 2: | |
507 addr = Memory[(ADDR_T)(address + 1)]; | |
508 break; | |
509 case 3: | |
510 addr = Memory[(ADDR_T)(address + 1)] + | |
511 (Memory[(ADDR_T)(address + 2)] << 8); | |
512 break; | |
513 } | |
514 | |
515 if (types[instr->admode] != impimm && | |
516 ((ADDR_T)(addr - StartAddress) < | |
517 (ADDR_T)(EndAddress - StartAddress) || | |
518 Options & B_LBL_ALWAYS)) | |
519 AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); | |
520 | |
521 if (types[instr->admode] != other && types[instr->admode] != impimm) { | |
522 if ((ADDR_T)(addr - StartAddress) < | |
523 (ADDR_T)(EndAddress - StartAddress)) { | |
524 switch (GetMemType (addr)) { | |
525 case MEM_UNPROCESSED: | |
526 AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); | |
527 break; | |
528 case MEM_INSTRUCTION: | |
529 AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); | |
530 break; | |
531 case MEM_PARAMETER: | |
532 AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); | |
533 break; | |
534 } | |
535 | |
536 if (types[instr->admode] == absindir) { /* indirect mode */ | |
537 addr++; /* set flags for upper vector byte */ | |
538 | |
539 if ((ADDR_T)(addr - StartAddress) < | |
540 (ADDR_T)(EndAddress - StartAddress)) | |
541 switch (GetMemType (addr)) { | |
542 case MEM_UNPROCESSED: | |
543 AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); | |
544 break; | |
545 case MEM_INSTRUCTION: | |
546 AddEntry (addr, scanstart, | |
547 WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); | |
548 break; | |
549 case MEM_PARAMETER: | |
550 AddEntry (addr, scanstart, | |
551 WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); | |
552 break; | |
553 } | |
554 } | |
555 } | |
556 } | |
557 } | |
558 | |
559 /* end of program (unexpectedly) encountered */ | |
560 | |
561 return 1; | |
562 } | |
563 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
1
diff
changeset
|
564 |
0 | 565 int ScanSpecified (void) |
566 { | |
567 table *entry; | |
568 | |
569 if (fVerbose) | |
570 fprintf (stderr, "%s: scanning the routines at specified address(es)", | |
571 prog); | |
572 | |
573 while ((entry = FindNextEntryType (NULL, ~0, RTN_SURE))) { | |
574 PutLabel (entry->address); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
575 PutReference (entry->address); |
0 | 576 PutLowByte (entry->address); |
577 PutHighByte (entry->address); | |
578 | |
579 if (ScanSure (entry->address)) { | |
580 fprintf(stderr,"For routine specified at %i:", | |
581 (unsigned int)entry->address); | |
582 return 1; | |
583 } | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
584 entry = FindNextEntryType (NULL, ~0, RTN_SURE); // valgrind fart |
0 | 585 DeleteEntry (entry); |
586 } | |
587 | |
588 return 0; | |
589 } | |
590 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
1
diff
changeset
|
591 |
0 | 592 void UnDoScan (ADDR_T scanstart) |
593 { | |
594 opcodes *instr; | |
595 unsigned counter; | |
596 ADDR_T address; | |
597 | |
598 for (address = scanstart; address != EndAddress; address++) { | |
599 if (GetMemFlag (address)) return; | |
600 | |
601 switch (GetMemType (address)) { | |
602 case MEM_UNPROCESSED: | |
603 return; | |
604 | |
605 case MEM_INSTRUCTION: | |
606 SetMemFlag (address); | |
607 SetMemType (address, MEM_DATA); /* This could cause WRN_PARAM_WRITTEN_TO | |
608 in vain. */ | |
609 instr = &opset[Memory[address++]]; | |
610 for (counter = sizes[instr->admode]; --counter; address++) | |
611 if (GetMemType (address) == MEM_PARAMETER) | |
612 SetMemType (address, MEM_UNPROCESSED); | |
613 else if (GetMemType (address) == MEM_INSTRUCTION) | |
614 break; | |
615 | |
616 if (instr->mnemonic == S_STP || instr->mnemonic == S_BRK || | |
617 instr->mnemonic == S_RTI || instr->mnemonic == S_RTS || | |
618 instr->mnemonic == S_JMP || instr->admode == rel) | |
619 return; | |
620 | |
621 address--; | |
622 break; | |
623 | |
624 case MEM_PARAMETER: | |
625 SetMemType (address, MEM_UNPROCESSED); | |
626 } | |
627 } | |
628 } | |
629 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
1
diff
changeset
|
630 |
0 | 631 void DeleteSuspectedParents (ADDR_T child) |
632 { | |
633 table *entry = NULL; | |
634 | |
635 while ((entry = FindNextEntry (entry, child, ~(RTN_B_PROCESSED | | |
636 RTN_B_TEMPORARY), | |
637 RTN_SUSPECTED))) { | |
638 if (entry->type & RTN_B_PROCESSED && entry->parent != child) | |
639 DeleteSuspectedParents (entry->parent); | |
640 | |
641 DeleteEntry (entry); | |
642 } | |
643 | |
644 entry = NULL; | |
645 | |
646 while ((entry = FindNextEntryTypeParent (entry, child, ~0, RTN_SUSP_POT))) | |
647 DeleteEntry (entry); | |
648 | |
649 entry = NULL; | |
650 | |
651 while ((entry = FindNextEntryTypeParent (entry, child, | |
652 MASK_ANY | WRN_B_TEMPORARY, | |
653 WRN_ANY | WRN_B_TEMPORARY))) { | |
654 if (entry->type == (WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY)) | |
655 SetMemType (entry->address, MEM_PARAMETER); | |
656 | |
657 DeleteEntry (entry); | |
658 } | |
659 | |
660 UnDoScan (child); | |
661 } | |
662 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
1
diff
changeset
|
663 |
0 | 664 void ScanPotentials (void) |
665 { | |
666 table *entry; | |
667 ADDR_T address; | |
668 | |
669 if (fVerbose) | |
670 fprintf (stderr, "\n%s: scanning potential routines\n", prog); | |
671 | |
672 while ((entry = FindNextEntryType (NULL, ~0, RTN_POTENTIAL))) { | |
673 address = entry->address; | |
674 DeleteEntry (entry); | |
675 | |
676 if (!ScanPotential (address)) { | |
677 while ((entry = FindNextEntryType (NULL, ~RTN_B_TEMPORARY, | |
678 RTN_SUSPECTED))) { | |
679 entry->type |= RTN_B_PROCESSED; | |
680 | |
681 if (ScanPotential (entry->address) && | |
682 (Options & M_DATA_BLOCKS) != O_DBL_IGNORE) { | |
683 DeleteSuspectedParents (entry->address); | |
684 SetMemType (address, MEM_DATA); | |
685 } | |
686 } | |
687 | |
688 if (GetMemType (address) != MEM_DATA) { | |
689 PutLabel (address); | |
690 PutLowByte (address); | |
691 PutHighByte (address); | |
692 } | |
693 | |
694 entry = NULL; | |
695 | |
696 while ((entry = FindNextEntryType (entry, ~0, RTN_B_TEMPORARY | | |
697 RTN_SUSPECTED | RTN_B_PROCESSED))) | |
698 DeleteEntry (entry); | |
699 | |
700 entry = NULL; | |
701 | |
702 while ((entry = FindNextEntryType (entry, ~0, | |
703 RTN_SUSPECTED | RTN_B_PROCESSED))) { | |
704 PutLabel (entry->address); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
705 PutReference (entry->address); |
0 | 706 PutLowByte (entry->address); |
707 PutHighByte (entry->address); | |
708 DeleteEntry (entry); | |
709 } | |
710 | |
711 entry = NULL; | |
712 | |
713 while ((entry = FindNextEntryType (entry, ~0, RTN_SUSP_POT))) | |
714 entry->type = RTN_POTENTIAL; | |
715 | |
716 entry = NULL; | |
717 | |
718 while ((entry = FindNextEntryType (entry, MASK_ANY | WRN_B_TEMPORARY, | |
719 WRN_ANY | WRN_B_TEMPORARY))) { | |
720 switch (entry->type & ~WRN_B_TEMPORARY) { | |
721 case WRN_PARAM_WRITTEN_TO: | |
722 if (GetMemType (entry->address) == MEM_DATA) | |
723 SetMemType (entry->address, MEM_PARAMETER); | |
724 entry->type &= ~WRN_B_TEMPORARY; | |
725 break; | |
726 | |
727 case WRN_INSTR_WRITTEN_TO: | |
728 if (GetMemType (entry->address) == MEM_DATA) | |
729 SetMemType (entry->address, MEM_INSTRUCTION); | |
730 entry->type &= ~WRN_B_TEMPORARY; | |
731 break; | |
732 | |
733 case WRN_I_ACCESSED: | |
734 SetMemType (entry->address, MEM_DATA); | |
735 /* fall through */ | |
736 case WRN_I_LABEL_NEEDED: | |
737 PutLabel (entry->address); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
738 PutReference (entry->address); |
0 | 739 PutLowByte (entry->address); |
740 PutHighByte (entry->address); | |
741 DeleteEntry (entry); | |
742 break; | |
743 | |
744 default: | |
745 entry->type &= ~WRN_B_TEMPORARY; | |
746 } | |
747 } | |
748 } | |
749 else { | |
750 DeleteSuspectedParents (address); | |
751 SetMemType (address, MEM_DATA); | |
752 } | |
753 } | |
754 } | |
755 | |
2
ec2f8f6f1dc9
Cleanup pass #1: Get rid of some ancient K&R-isms.
Matti Hamalainen <ccr@tnsp.org>
parents:
1
diff
changeset
|
756 |
0 | 757 void ScanTheRest (void) |
758 { | |
759 ADDR_T address; | |
760 table *entry; | |
761 unsigned int fPotentials; | |
762 | |
763 if ((Options & M_DATA_BLOCKS) == O_DBL_NOSCAN) { | |
764 for (address = StartAddress; address != EndAddress; address++) | |
765 if (GetMemType (address) == MEM_UNPROCESSED) | |
766 SetMemType (address, MEM_DATA); | |
767 | |
768 return; | |
769 } | |
770 | |
771 if (fVerbose) | |
772 fprintf (stderr, "%s: scanning the remaining bytes for routines\n", prog); | |
773 | |
774 for (address = StartAddress; address != EndAddress; address++) { | |
775 if (GetMemType (address) || GetMemFlag (address)) | |
776 continue; /* scan only unprocessed bytes */ | |
777 | |
778 if (Options & B_RSC_STRICT) | |
779 switch (opset[Memory[address]].mnemonic) { | |
780 case S_RTI: | |
781 case S_RTS: | |
782 case S_BRK: | |
783 case S_STP: | |
784 continue; | |
785 | |
786 case S_BRA: | |
787 break; | |
788 | |
789 default: | |
790 if (opset[Memory[address]].admode == rel && | |
791 GetMemType (address + sizes[rel]) != MEM_INSTRUCTION) | |
792 AddEntry (address + sizes[rel], address, | |
793 RTN_SUSPECTED | RTN_B_TEMPORARY); | |
794 } | |
795 | |
796 if (fVerbose) | |
14
84c0facfc43c
Merge changes from upstream v0.1.4.
Matti Hamalainen <ccr@tnsp.org>
parents:
11
diff
changeset
|
797 fprintf (stderr, "\n%s: scanning at $%04x", prog, address); |
0 | 798 |
799 if (!ScanPotential (address)) { | |
800 while ((entry = FindNextEntryType (NULL, ~RTN_B_TEMPORARY, | |
801 RTN_SUSPECTED))) { | |
802 entry->type |= RTN_B_PROCESSED; | |
803 | |
804 if (ScanPotential (entry->address) && | |
805 (Options & M_DATA_BLOCKS) != O_DBL_IGNORE) { | |
806 DeleteSuspectedParents (entry->address); | |
807 SetMemType (address, MEM_DATA); | |
808 } | |
809 } | |
810 | |
811 if (GetMemType (address) != MEM_DATA) { | |
812 PutLabel (address); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
813 PutReference (address); |
0 | 814 PutLowByte (address); |
815 PutHighByte (address); | |
816 } | |
817 | |
818 fPotentials = FALSE; | |
819 entry = NULL; | |
820 | |
821 while ((entry = FindNextEntryType (entry, ~0, RTN_SUSP_POT))) { | |
822 fPotentials = TRUE; | |
823 entry->type = RTN_POTENTIAL; | |
824 } | |
825 | |
826 entry = NULL; | |
827 | |
828 while ((entry = FindNextEntryType (entry, ~0, RTN_B_TEMPORARY | | |
829 RTN_SUSPECTED | RTN_B_PROCESSED))) | |
830 DeleteEntry (entry); | |
831 | |
832 entry = NULL; | |
833 | |
834 while ((entry = FindNextEntryType (entry, ~0, | |
835 RTN_SUSPECTED | RTN_B_PROCESSED))) { | |
836 PutLabel (entry->address); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
837 PutReference (entry->address); |
0 | 838 PutLowByte (entry->address); |
839 PutHighByte (entry->address); | |
840 DeleteEntry (entry); | |
841 } | |
842 | |
843 entry = NULL; | |
844 | |
845 while ((entry = FindNextEntryType (entry, MASK_ANY | WRN_B_TEMPORARY, | |
846 WRN_ANY | WRN_B_TEMPORARY))) { | |
847 switch (entry->type & ~WRN_B_TEMPORARY) { | |
848 case WRN_PARAM_WRITTEN_TO: | |
849 if (GetMemType (entry->address) == MEM_DATA) | |
850 SetMemType (entry->address, MEM_PARAMETER); | |
851 entry->type &= ~WRN_B_TEMPORARY; | |
852 break; | |
853 | |
854 case WRN_INSTR_WRITTEN_TO: | |
855 if (GetMemType (entry->address) == MEM_DATA) | |
856 SetMemType (entry->address, MEM_INSTRUCTION); | |
857 entry->type &= ~WRN_B_TEMPORARY; | |
858 break; | |
859 | |
860 case WRN_I_ACCESSED: | |
861 SetMemType (entry->address, MEM_DATA); | |
862 /* fall through */ | |
863 case WRN_I_LABEL_NEEDED: | |
864 PutLabel (entry->address); | |
11
fe4d840c13eb
Implement reference checking to reduce outputting of useless labels.
Matti Hamalainen <ccr@tnsp.org>
parents:
9
diff
changeset
|
865 PutReference (entry->address); |
0 | 866 PutLowByte (entry->address); |
867 PutHighByte (entry->address); | |
868 DeleteEntry (entry); | |
869 break; | |
870 | |
871 default: | |
872 entry->type &= ~WRN_B_TEMPORARY; | |
873 } | |
874 } | |
875 | |
876 if (fPotentials) ScanPotentials (); | |
877 } | |
878 else { | |
879 DeleteSuspectedParents (address); | |
880 SetMemType (address, MEM_DATA); | |
881 } | |
882 } | |
883 | |
884 if (fVerbose) | |
885 fprintf (stderr, "\n"); | |
886 | |
887 for (address = StartAddress; address != EndAddress; address++) | |
888 if (GetMemType (address) == MEM_UNPROCESSED) { | |
889 fPotentials = GetMemFlag (address) ? MEM_PARAMETER : MEM_DATA; | |
890 SetMemType (address, fPotentials); | |
891 } | |
892 } |