Mercurial > hg > forks > dxa
diff scan.c @ 0:4410c9c7750d
Initial import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 24 Feb 2015 18:53:52 +0200 |
parents | |
children | cfcae2ef1c2b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scan.c Tue Feb 24 18:53:52 2015 +0200 @@ -0,0 +1,920 @@ +/*\ + * dxa v0.1.1 -- symbolic 65xx disassembler + * + * Copyright (C) 1993, 1994 Marko M\"akel\"a + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contacting the author: + * + * Via Internet E-mail: + * <Marko.Makela@FTP.FUNET.FI> + * + * Via Snail Mail: + * Marko M\"akel\"a + * Sillitie 10 A + * FIN-01480 VANTAA + * Finland +\*/ + +#define _SCAN_C_ +#include <stdio.h> +#include "proto.h" +#include "opcodes.h" +#include "options.h" + +int ScanSure PROTO((ADDR_T scanstart)); +int ScanPotential PROTO((ADDR_T scanstart)); +void UnDoScan PROTO((ADDR_T scanstart)); +void DeleteSuspectedParents PROTO((ADDR_T child)); + +#ifndef __STDC__ +int +ScanSure (scanstart) + ADDR_T scanstart; +#else +int ScanSure (ADDR_T scanstart) +#endif +{ + ADDR_T address, addr; + opcodes *instr; + + unsigned int size, counter; + + for (address = scanstart;; address += size) { + if (GetMemFlag (address)) /* rest of routine not valid */ + return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT); + + instr = &opset[Memory[address]]; + + if (!instr->mnemonic) /* invalid opcode */ + return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT); + + size = sizes[instr->admode]; + if ((ADDR_T)(address + size - StartAddress) > + (ADDR_T)(EndAddress - StartAddress)) + break; /* end of program code encountered */ + + switch (GetMemType (address)) { + case MEM_INSTRUCTION: + return 0; /* The rest of the routine has already been processed. */ + + case MEM_DATA: + AddEntry (address, scanstart, WRN_INSTR_WRITTEN_TO); + break; + + case MEM_PARAMETER: + AddEntry (address, scanstart, WRN_PARAM_JUMPED_TO); + } + + SetMemType (address, MEM_INSTRUCTION); + + for (counter = size, addr = address + 1; --counter; addr++) + switch GetMemType(addr) { + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_PARAM_JUMPED_TO); + break; + case MEM_DATA: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); + /* fall through */ + default: + SetMemType (addr, MEM_PARAMETER); + } + + if (instr->admode == zrel) { + addr = Memory[(ADDR_T)(address + 1)]; + + if (GetMemFlag (addr) && GetMemType (addr) == MEM_UNPROCESSED) + return (Options & M_DATA_BLOCKS) == O_DBL_STRICT; + + if (((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress) || + Options & B_LBL_ALWAYS)) { + PutLabel (addr); + PutLowByte (addr); + PutHighByte (addr); + } + + addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 2)] + + address + size); + goto IsJump; + } + + if (instr->admode == rel) { + addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] + + address + size); + + goto IsJump; + } + if ((instr->mnemonic == S_JSR || instr->mnemonic == S_JMP) && + instr->admode == abso) { + addr = Memory[(ADDR_T)(address + 1)] + + (Memory[(ADDR_T)(address + 2)] << 8); + + IsJump: + if (GetMemFlag (addr)) + return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT); + + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) { + if (GetMemType (addr) == MEM_INSTRUCTION) { + PutLabel (addr); + PutLowByte (addr); + PutHighByte (addr); + } + else + AddEntry (addr, scanstart, Options & B_SCEPTIC && + instr->admode == rel && instr->mnemonic != S_BRA ? + RTN_POTENTIAL : RTN_SURE); + } + else if (Options & B_LBL_ALWAYS) { + PutLabel (addr); + PutLowByte (addr); + PutHighByte (addr); + } + + if ((Options & M_DATA_BLOCKS) == O_DBL_STRICT && + Options & B_JMP_STRICT && + addr == address && instr->mnemonic != S_BVC) + return 1; + } + + switch (instr->mnemonic) { + case S_JMP: + addr = Memory[(ADDR_T)(address + 1)] + + (Memory[(ADDR_T)(address + 2)] << 8); + + if (instr->admode == iabs && (ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) { + PutLabel (addr); + PutLowByte (addr); + PutHighByte (addr); + + /* Mark pointer as data. */ + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + SetMemType (addr, MEM_DATA); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); + break; + } + + addr++; + + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + SetMemType (addr, MEM_DATA); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); + break; + } + } + else if (Options & B_LBL_ALWAYS) { + PutLabel (addr); + PutLowByte (addr); + PutHighByte (addr); + } + case S_BRA: + case S_RTS: + case S_RTI: + return 0; + + case S_BRK: + case S_STP: + return (Options & M_DATA_BLOCKS) == O_DBL_STRICT && + Options & B_BRK_REJECT; + } + + if (instr->admode == rel) { + if ((ADDR_T)(addr - scanstart) >= (ADDR_T)(address - scanstart) + || GetMemType (addr) != MEM_INSTRUCTION) { + if (GetMemType (address + size) != MEM_INSTRUCTION) + AddEntry (address + size, scanstart, RTN_POTENTIAL); + + return 0; + } + + continue; + } + + if (instr->mnemonic == S_JSR) { + if (!(Options & B_STK_BALANCE)) { + if (GetMemType (address + size) != MEM_INSTRUCTION) + AddEntry (address + size, scanstart, RTN_POTENTIAL); + + return 0; + } + + continue; + } + + switch (size) { + case 2: + addr = Memory[(ADDR_T)(address + 1)]; + break; + case 3: + addr = Memory[(ADDR_T)(address + 1)] + + (Memory[(ADDR_T)(address + 2)] << 8); + break; + } + + if (types[instr->admode] != impimm && GetMemFlag (addr) && + GetMemType (addr) == MEM_UNPROCESSED) + return (Options & M_DATA_BLOCKS) == O_DBL_STRICT; + + if (types[instr->admode] != impimm && + ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress) || + Options & B_LBL_ALWAYS)) { + PutLabel (addr); + PutLowByte (addr); + PutHighByte (addr); + } + + if (types[instr->admode] != other && types[instr->admode] != impimm) { + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) { + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + SetMemType (addr, MEM_DATA); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); + break; + } + + if (types[instr->admode] == absindir) { /* indirect mode */ + addr++; /* set flags for upper vector byte */ + + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + SetMemType (addr, MEM_DATA); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO); + break; + } + } + } + } + } + + /* end of program (unexpectedly) encountered */ + + if (Options & O_DBL_STRICT) return 1; + + AddEntry (EndAddress, scanstart, WRN_RTN_TRUNCATED); + return 0; +} + +#ifndef __STDC__ +int +ScanPotential (scanstart) + ADDR_T scanstart; +#else +int ScanPotential (ADDR_T scanstart) +#endif +{ + ADDR_T address, addr; + opcodes *instr; + + unsigned int size, counter; + + for (address = scanstart;; address += size) { + if (GetMemFlag (address)) /* rest of routine not valid */ + return 1; + + instr = &opset[Memory[address]]; + + if (!instr->mnemonic) { /* invalid opcode */ + SetMemFlag (address); + + if (GetMemType (address) == MEM_UNPROCESSED) + SetMemType (address, MEM_DATA); + return 1; + } + + size = sizes[instr->admode]; + if ((ADDR_T)(address + size - StartAddress) > + (ADDR_T)(EndAddress - StartAddress)) + break; /* end of program code encountered */ + + if (GetMemType (address) == MEM_INSTRUCTION) + return 0; /* The rest of the routine has already been processed. */ + + if (instr->admode == zrel) { + addr = Memory[(ADDR_T)(address + 1)]; + + if (GetMemFlag (addr) && GetMemType (addr) == MEM_UNPROCESSED) + goto Failure; + + if (((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress) || + Options & B_LBL_ALWAYS)) + AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); + + addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] + + address + size); + + goto IsJump; + } + + if (instr->admode == rel) { + addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] + + address + size); + + goto IsJump; + } + + switch (size) { + case 2: + addr = Memory[(ADDR_T)(address + 1)]; + break; + case 3: + addr = Memory[(ADDR_T)(address + 1)] + + (Memory[(ADDR_T)(address + 2)] << 8); + break; + default: + addr = address; + } + + if (types[instr->admode] != impimm && GetMemFlag (addr) && + GetMemType (addr) == MEM_UNPROCESSED) { + Failure: + SetMemFlag (address); + + if (GetMemType (address) == MEM_UNPROCESSED) + SetMemType (address, MEM_DATA); + return 1; + } + + if ((instr->mnemonic == S_JSR || instr->mnemonic == S_JMP) && + instr->admode == abso) { + IsJump: + if (GetMemFlag (addr)) { + SetMemFlag (address); + + if (GetMemType (address) == MEM_UNPROCESSED) + SetMemType (address, MEM_DATA); + return 1; + } + + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) + AddEntry (addr, scanstart, Options & B_SCEPTIC && + instr->admode == rel && instr->mnemonic != S_BRA ? + RTN_SUSP_POT : RTN_SUSPECTED); + else if (Options & B_LBL_ALWAYS) + AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); + + if (Options & B_JMP_STRICT && addr == address && + instr->mnemonic != S_BVC) { + SetMemFlag (address); + + if (GetMemType (address) == MEM_UNPROCESSED) + SetMemType (address, MEM_DATA); + return 1; + } + } + + switch (instr->mnemonic) { + case S_BRK: + case S_STP: + if (Options & B_BRK_REJECT) { + SetMemFlag (address); + + if (GetMemType (address) == MEM_UNPROCESSED) + SetMemType (address, MEM_DATA); + return 1; + } + } + + if (!GetMemFlag (address)) + switch (GetMemType (address)) { + case MEM_DATA: + AddEntry (address, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); + break; + + case MEM_PARAMETER: + AddEntry (address, scanstart, WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY); + } + + SetMemType (address, MEM_INSTRUCTION); + + for (counter = size, addr = address + 1; --counter; addr++) + switch (GetMemType (addr)) { + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY); + break; + case MEM_DATA: + if (!GetMemFlag (addr)) + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); + break; + default: + SetMemType (addr, MEM_PARAMETER); + } + + switch (instr->mnemonic) { + case S_BRK: + case S_STP: + case S_RTS: + case S_BRA: + case S_RTI: + return 0; + + case S_JMP: + addr = Memory[(ADDR_T)(address + 1)] + + (Memory[(ADDR_T)(address + 2)] << 8); + + if (instr->admode == iabs && (ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) { + AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); + + /* Mark pointer as data. */ + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); + break; + } + + addr++; + + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, + WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, + WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); + break; + } + } + else if (Options & B_LBL_ALWAYS) + AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); + + return 0; + } + + if (instr->admode == rel && + GetMemType (address + size) != MEM_INSTRUCTION) { + AddEntry (address + size, scanstart, RTN_SUSP_POT); + + return 0; + } + + if (instr->mnemonic == S_JSR) { + if (!(Options & B_STK_BALANCE)) { + if (GetMemType (address + size) != MEM_INSTRUCTION) + AddEntry (address + size, scanstart, RTN_SUSP_POT); + + return 0; + } + + continue; + } + + switch (size) { + case 2: + addr = Memory[(ADDR_T)(address + 1)]; + break; + case 3: + addr = Memory[(ADDR_T)(address + 1)] + + (Memory[(ADDR_T)(address + 2)] << 8); + break; + } + + if (types[instr->admode] != impimm && + ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress) || + Options & B_LBL_ALWAYS)) + AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY); + + if (types[instr->admode] != other && types[instr->admode] != impimm) { + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) { + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); + break; + } + + if (types[instr->admode] == absindir) { /* indirect mode */ + addr++; /* set flags for upper vector byte */ + + if ((ADDR_T)(addr - StartAddress) < + (ADDR_T)(EndAddress - StartAddress)) + switch (GetMemType (addr)) { + case MEM_UNPROCESSED: + AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY); + break; + case MEM_INSTRUCTION: + AddEntry (addr, scanstart, + WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY); + break; + case MEM_PARAMETER: + AddEntry (addr, scanstart, + WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY); + break; + } + } + } + } + } + + /* end of program (unexpectedly) encountered */ + + return 1; +} + +#ifndef __STDC__ +int +ScanSpecified () +#else +int ScanSpecified (void) +#endif +{ + table *entry; + + if (fVerbose) + fprintf (stderr, "%s: scanning the routines at specified address(es)", + prog); + + while ((entry = FindNextEntryType (NULL, ~0, RTN_SURE))) { + PutLabel (entry->address); + PutLowByte (entry->address); + PutHighByte (entry->address); + + if (ScanSure (entry->address)) { + fprintf(stderr,"For routine specified at %i:", + (unsigned int)entry->address); + return 1; + } + DeleteEntry (entry); + } + + return 0; +} + +#ifndef __STDC__ +void +UnDoScan (scanstart) + ADDR_T scanstart; +#else +void UnDoScan (ADDR_T scanstart) +#endif +{ + opcodes *instr; + unsigned counter; + ADDR_T address; + + for (address = scanstart; address != EndAddress; address++) { + if (GetMemFlag (address)) return; + + switch (GetMemType (address)) { + case MEM_UNPROCESSED: + return; + + case MEM_INSTRUCTION: + SetMemFlag (address); + SetMemType (address, MEM_DATA); /* This could cause WRN_PARAM_WRITTEN_TO + in vain. */ + instr = &opset[Memory[address++]]; + for (counter = sizes[instr->admode]; --counter; address++) + if (GetMemType (address) == MEM_PARAMETER) + SetMemType (address, MEM_UNPROCESSED); + else if (GetMemType (address) == MEM_INSTRUCTION) + break; + + if (instr->mnemonic == S_STP || instr->mnemonic == S_BRK || + instr->mnemonic == S_RTI || instr->mnemonic == S_RTS || + instr->mnemonic == S_JMP || instr->admode == rel) + return; + + address--; + break; + + case MEM_PARAMETER: + SetMemType (address, MEM_UNPROCESSED); + } + } +} + +#ifndef __STDC__ +void +DeleteSuspectedParents (child) + ADDR_T child; +#else +void DeleteSuspectedParents (ADDR_T child) +#endif +{ + table *entry = NULL; + + while ((entry = FindNextEntry (entry, child, ~(RTN_B_PROCESSED | + RTN_B_TEMPORARY), + RTN_SUSPECTED))) { + if (entry->type & RTN_B_PROCESSED && entry->parent != child) + DeleteSuspectedParents (entry->parent); + + DeleteEntry (entry); + } + + entry = NULL; + + while ((entry = FindNextEntryTypeParent (entry, child, ~0, RTN_SUSP_POT))) + DeleteEntry (entry); + + entry = NULL; + + while ((entry = FindNextEntryTypeParent (entry, child, + MASK_ANY | WRN_B_TEMPORARY, + WRN_ANY | WRN_B_TEMPORARY))) { + if (entry->type == (WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY)) + SetMemType (entry->address, MEM_PARAMETER); + + DeleteEntry (entry); + } + + UnDoScan (child); +} + +#ifndef __STDC__ +void +ScanPotentials () +#else +void ScanPotentials (void) +#endif +{ + table *entry; + ADDR_T address; + + if (fVerbose) + fprintf (stderr, "\n%s: scanning potential routines\n", prog); + + while ((entry = FindNextEntryType (NULL, ~0, RTN_POTENTIAL))) { + address = entry->address; + DeleteEntry (entry); + + if (!ScanPotential (address)) { + while ((entry = FindNextEntryType (NULL, ~RTN_B_TEMPORARY, + RTN_SUSPECTED))) { + entry->type |= RTN_B_PROCESSED; + + if (ScanPotential (entry->address) && + (Options & M_DATA_BLOCKS) != O_DBL_IGNORE) { + DeleteSuspectedParents (entry->address); + SetMemType (address, MEM_DATA); + } + } + + if (GetMemType (address) != MEM_DATA) { + PutLabel (address); + PutLowByte (address); + PutHighByte (address); + } + + entry = NULL; + + while ((entry = FindNextEntryType (entry, ~0, RTN_B_TEMPORARY | + RTN_SUSPECTED | RTN_B_PROCESSED))) + DeleteEntry (entry); + + entry = NULL; + + while ((entry = FindNextEntryType (entry, ~0, + RTN_SUSPECTED | RTN_B_PROCESSED))) { + PutLabel (entry->address); + PutLowByte (entry->address); + PutHighByte (entry->address); + DeleteEntry (entry); + } + + entry = NULL; + + while ((entry = FindNextEntryType (entry, ~0, RTN_SUSP_POT))) + entry->type = RTN_POTENTIAL; + + entry = NULL; + + while ((entry = FindNextEntryType (entry, MASK_ANY | WRN_B_TEMPORARY, + WRN_ANY | WRN_B_TEMPORARY))) { + switch (entry->type & ~WRN_B_TEMPORARY) { + case WRN_PARAM_WRITTEN_TO: + if (GetMemType (entry->address) == MEM_DATA) + SetMemType (entry->address, MEM_PARAMETER); + entry->type &= ~WRN_B_TEMPORARY; + break; + + case WRN_INSTR_WRITTEN_TO: + if (GetMemType (entry->address) == MEM_DATA) + SetMemType (entry->address, MEM_INSTRUCTION); + entry->type &= ~WRN_B_TEMPORARY; + break; + + case WRN_I_ACCESSED: + SetMemType (entry->address, MEM_DATA); + /* fall through */ + case WRN_I_LABEL_NEEDED: + PutLabel (entry->address); + PutLowByte (entry->address); + PutHighByte (entry->address); + DeleteEntry (entry); + break; + + default: + entry->type &= ~WRN_B_TEMPORARY; + } + } + } + else { + DeleteSuspectedParents (address); + SetMemType (address, MEM_DATA); + } + } +} + +#ifndef __STDC__ +void +ScanTheRest () +#else +void ScanTheRest (void) +#endif +{ + ADDR_T address; + table *entry; + unsigned int fPotentials; + + if ((Options & M_DATA_BLOCKS) == O_DBL_NOSCAN) { + for (address = StartAddress; address != EndAddress; address++) + if (GetMemType (address) == MEM_UNPROCESSED) + SetMemType (address, MEM_DATA); + + return; + } + + if (fVerbose) + fprintf (stderr, "%s: scanning the remaining bytes for routines\n", prog); + + for (address = StartAddress; address != EndAddress; address++) { + if (GetMemType (address) || GetMemFlag (address)) + continue; /* scan only unprocessed bytes */ + + if (Options & B_RSC_STRICT) + switch (opset[Memory[address]].mnemonic) { + case S_RTI: + case S_RTS: + case S_BRK: + case S_STP: + continue; + + case S_BRA: + break; + + default: + if (opset[Memory[address]].admode == rel && + GetMemType (address + sizes[rel]) != MEM_INSTRUCTION) + AddEntry (address + sizes[rel], address, + RTN_SUSPECTED | RTN_B_TEMPORARY); + } + + if (fVerbose) + fprintf (stderr, "\r%s: scanning at %X", prog, address); + + if (!ScanPotential (address)) { + while ((entry = FindNextEntryType (NULL, ~RTN_B_TEMPORARY, + RTN_SUSPECTED))) { + entry->type |= RTN_B_PROCESSED; + + if (ScanPotential (entry->address) && + (Options & M_DATA_BLOCKS) != O_DBL_IGNORE) { + DeleteSuspectedParents (entry->address); + SetMemType (address, MEM_DATA); + } + } + + if (GetMemType (address) != MEM_DATA) { + PutLabel (address); + PutLowByte (address); + PutHighByte (address); + } + + fPotentials = FALSE; + entry = NULL; + + while ((entry = FindNextEntryType (entry, ~0, RTN_SUSP_POT))) { + fPotentials = TRUE; + entry->type = RTN_POTENTIAL; + } + + entry = NULL; + + while ((entry = FindNextEntryType (entry, ~0, RTN_B_TEMPORARY | + RTN_SUSPECTED | RTN_B_PROCESSED))) + DeleteEntry (entry); + + entry = NULL; + + while ((entry = FindNextEntryType (entry, ~0, + RTN_SUSPECTED | RTN_B_PROCESSED))) { + PutLabel (entry->address); + PutLowByte (entry->address); + PutHighByte (entry->address); + DeleteEntry (entry); + } + + entry = NULL; + + while ((entry = FindNextEntryType (entry, MASK_ANY | WRN_B_TEMPORARY, + WRN_ANY | WRN_B_TEMPORARY))) { + switch (entry->type & ~WRN_B_TEMPORARY) { + case WRN_PARAM_WRITTEN_TO: + if (GetMemType (entry->address) == MEM_DATA) + SetMemType (entry->address, MEM_PARAMETER); + entry->type &= ~WRN_B_TEMPORARY; + break; + + case WRN_INSTR_WRITTEN_TO: + if (GetMemType (entry->address) == MEM_DATA) + SetMemType (entry->address, MEM_INSTRUCTION); + entry->type &= ~WRN_B_TEMPORARY; + break; + + case WRN_I_ACCESSED: + SetMemType (entry->address, MEM_DATA); + /* fall through */ + case WRN_I_LABEL_NEEDED: + PutLabel (entry->address); + PutLowByte (entry->address); + PutHighByte (entry->address); + DeleteEntry (entry); + break; + + default: + entry->type &= ~WRN_B_TEMPORARY; + } + } + + if (fPotentials) ScanPotentials (); + } + else { + DeleteSuspectedParents (address); + SetMemType (address, MEM_DATA); + } + } + + if (fVerbose) + fprintf (stderr, "\n"); + + for (address = StartAddress; address != EndAddress; address++) + if (GetMemType (address) == MEM_UNPROCESSED) { + fPotentials = GetMemFlag (address) ? MEM_PARAMETER : MEM_DATA; + SetMemType (address, fPotentials); + } +}