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