mirror of
https://github.com/cc65/cc65.git
synced 2024-11-19 06:31:31 +00:00
Generate info about zp register usage
git-svn-id: svn://svn.cc65.org/cc65/trunk@964 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
5532a80beb
commit
a6aa5512d5
@ -40,6 +40,7 @@
|
||||
#include "chartype.h"
|
||||
#include "check.h"
|
||||
#include "xmalloc.h"
|
||||
#include "xsprintf.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "codeinfo.h"
|
||||
@ -136,6 +137,8 @@ static int NumArg (const char* Arg, unsigned long* Num)
|
||||
static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
||||
/* Set the Use and Chg in E */
|
||||
{
|
||||
unsigned short Use;
|
||||
|
||||
/* If this is a subroutine call, or a jump to an external function,
|
||||
* lookup the information about this function and use it. The jump itself
|
||||
* does not change any registers, so we don't need to use the data from D.
|
||||
@ -145,10 +148,45 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
||||
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
|
||||
} else {
|
||||
/* Some other instruction. Use the values from the opcode description
|
||||
* plus addressing mode info
|
||||
* plus addressing mode info.
|
||||
*/
|
||||
E->Use = D->Use | GetAMUseInfo (E->AM);
|
||||
E->Chg = D->Chg;
|
||||
|
||||
/* Check for special zero page registers used */
|
||||
switch (E->AM) {
|
||||
|
||||
case AM65_ZP:
|
||||
case AM65_ABS:
|
||||
/* Be conservative: */
|
||||
case AM65_ZPX:
|
||||
case AM65_ABSX:
|
||||
case AM65_ABSY:
|
||||
if (IsZPName (E->Arg, &Use) && Use != REG_NONE) {
|
||||
if (E->OPC == OP65_INC || E->OPC == OP65_DEC) {
|
||||
E->Chg |= Use;
|
||||
E->Use |= Use;
|
||||
} else if ((E->Info & OF_STORE) != 0) {
|
||||
E->Chg |= Use;
|
||||
} else {
|
||||
E->Use |= Use;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AM65_ZPX_IND:
|
||||
case AM65_ZP_INDY:
|
||||
case AM65_ZP_IND:
|
||||
if (IsZPName (E->Arg, &Use) && Use != REG_NONE) {
|
||||
/* These addressing modes will never change the zp loc */
|
||||
E->Use |= Use;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Keep gcc silent */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,14 +303,35 @@ void CE_MoveLabel (CodeLabel* L, CodeEntry* E)
|
||||
|
||||
|
||||
|
||||
void CE_SetArg (CodeEntry* E, const char* Arg)
|
||||
/* Set a new argument for the given code entry. An old string is deleted. */
|
||||
void CE_SetNumArg (CodeEntry* E, long Num)
|
||||
/* Set a new numeric argument for the given code entry that must already
|
||||
* have a numeric argument.
|
||||
*/
|
||||
{
|
||||
char Buf[16];
|
||||
|
||||
/* Check that the entry has a numerical argument */
|
||||
CHECK (E->Flags & CEF_NUMARG);
|
||||
|
||||
/* Make the new argument string */
|
||||
if (E->Size == 2) {
|
||||
Num &= 0xFF;
|
||||
xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned) Num);
|
||||
} else if (E->Size == 3) {
|
||||
Num &= 0xFFFF;
|
||||
xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned) Num);
|
||||
} else {
|
||||
Internal ("Invalid instruction size in CE_SetNumArg");
|
||||
}
|
||||
|
||||
/* Free the old argument */
|
||||
FreeArg (E->Arg);
|
||||
|
||||
/* Assign the new one */
|
||||
E->Arg = GetArgCopy (Arg);
|
||||
E->Arg = GetArgCopy (Buf);
|
||||
|
||||
/* Use the new numerical value */
|
||||
E->Num = Num;
|
||||
}
|
||||
|
||||
|
||||
@ -655,6 +714,48 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
|
||||
|
||||
|
||||
|
||||
static char* RegInfoDesc (unsigned U, char* Buf)
|
||||
/* Return a string containing register info */
|
||||
{
|
||||
Buf[0] = '\0';
|
||||
if (U & REG_SREG) {
|
||||
strcat (Buf, "E");
|
||||
}
|
||||
if (U & REG_A) {
|
||||
strcat (Buf, "A");
|
||||
}
|
||||
if (U & REG_X) {
|
||||
strcat (Buf, "X");
|
||||
}
|
||||
if (U & REG_Y) {
|
||||
strcat (Buf, "Y");
|
||||
}
|
||||
if (U & REG_TMP1) {
|
||||
strcat (Buf, "T1");
|
||||
}
|
||||
if (U & REG_TMP2) {
|
||||
strcat (Buf, "T2");
|
||||
}
|
||||
if (U & REG_TMP3) {
|
||||
strcat (Buf, "T3");
|
||||
}
|
||||
if (U & REG_PTR1) {
|
||||
strcat (Buf, "P1");
|
||||
}
|
||||
if (U & REG_PTR2) {
|
||||
strcat (Buf, "P2");
|
||||
}
|
||||
if (U & REG_PTR3) {
|
||||
strcat (Buf, "P3");
|
||||
}
|
||||
if (U & REG_PTR4) {
|
||||
strcat (Buf, "P4");
|
||||
}
|
||||
return Buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CE_Output (const CodeEntry* E, FILE* F)
|
||||
/* Output the code entry to a file */
|
||||
{
|
||||
@ -699,7 +800,7 @@ void CE_Output (const CodeEntry* E, FILE* F)
|
||||
case AM65_ABS:
|
||||
/* zeropage and absolute */
|
||||
Chars += fprintf (F, "%*s%s", 9-Chars, "", E->Arg);
|
||||
break;
|
||||
break;
|
||||
|
||||
case AM65_ZPX:
|
||||
case AM65_ABSX:
|
||||
@ -740,16 +841,14 @@ void CE_Output (const CodeEntry* E, FILE* F)
|
||||
|
||||
/* Print usage info if requested by the debugging flag */
|
||||
if (Debug) {
|
||||
fprintf (F,
|
||||
"%*s; USE: %c%c%c CHG: %c%c%c SIZE: %u\n",
|
||||
30-Chars, "",
|
||||
(E->Use & REG_A)? 'A' : '_',
|
||||
(E->Use & REG_X)? 'X' : '_',
|
||||
(E->Use & REG_Y)? 'Y' : '_',
|
||||
(E->Chg & REG_A)? 'A' : '_',
|
||||
(E->Chg & REG_X)? 'X' : '_',
|
||||
(E->Chg & REG_Y)? 'Y' : '_',
|
||||
E->Size);
|
||||
char Use [128];
|
||||
char Chg [128];
|
||||
fprintf (F,
|
||||
"%*s; USE: %-18s CHG: %-18s SIZE: %u\n",
|
||||
30-Chars, "",
|
||||
RegInfoDesc (E->Use, Use),
|
||||
RegInfoDesc (E->Chg, Chg),
|
||||
E->Size);
|
||||
} else {
|
||||
/* Terminate the line */
|
||||
fprintf (F, "\n");
|
||||
|
@ -169,8 +169,10 @@ INLINE void CE_ResetMark (CodeEntry* E)
|
||||
# define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK)
|
||||
#endif
|
||||
|
||||
void CE_SetArg (CodeEntry* E, const char* Arg);
|
||||
/* Set a new argument for the given code entry. An old string is deleted. */
|
||||
void CE_SetNumArg (CodeEntry* E, long Num);
|
||||
/* Set a new numeric argument for the given code entry that must already
|
||||
* have a numeric argument.
|
||||
*/
|
||||
|
||||
int CE_KnownImm (const CodeEntry* E);
|
||||
/* Return true if the argument of E is a known immediate value */
|
||||
|
@ -62,117 +62,123 @@ typedef struct FuncInfo FuncInfo;
|
||||
struct FuncInfo {
|
||||
const char* Name; /* Function name */
|
||||
unsigned short Use; /* Register usage */
|
||||
unsigned short Chg; /* Changed/destroyed registers */
|
||||
unsigned short Chg; /* Changed/destroyed registers */
|
||||
};
|
||||
|
||||
static const FuncInfo FuncInfoTable[] = {
|
||||
{ "addysp", REG_Y, REG_NONE },
|
||||
{ "aslax1", REG_AX, REG_AX },
|
||||
{ "aslax2", REG_AX, REG_AX },
|
||||
{ "aslax3", REG_AX, REG_AX },
|
||||
{ "aslax4", REG_AX, REG_AX },
|
||||
{ "bnega", REG_A, REG_AX },
|
||||
{ "bnegax", REG_AX, REG_AX },
|
||||
{ "bnegeax", REG_AX, REG_AX },
|
||||
{ "booleq", REG_NONE, REG_AX },
|
||||
{ "boolge", REG_NONE, REG_AX },
|
||||
{ "boolgt", REG_NONE, REG_AX },
|
||||
{ "boolle", REG_NONE, REG_AX },
|
||||
{ "boollt", REG_NONE, REG_AX },
|
||||
{ "boolne", REG_NONE, REG_AX },
|
||||
{ "booluge", REG_NONE, REG_AX },
|
||||
{ "boolugt", REG_NONE, REG_AX },
|
||||
{ "boolule", REG_NONE, REG_AX },
|
||||
{ "boolult", REG_NONE, REG_AX },
|
||||
{ "complax", REG_AX, REG_AX },
|
||||
{ "decax1", REG_AX, REG_AX },
|
||||
{ "decax2", REG_AX, REG_AX },
|
||||
{ "decax3", REG_AX, REG_AX },
|
||||
{ "decax4", REG_AX, REG_AX },
|
||||
{ "decax5", REG_AX, REG_AX },
|
||||
{ "decax6", REG_AX, REG_AX },
|
||||
{ "decax7", REG_AX, REG_AX },
|
||||
{ "decax8", REG_AX, REG_AX },
|
||||
{ "decaxy", REG_AXY, REG_AX },
|
||||
{ "decsp1", REG_NONE, REG_Y },
|
||||
{ "decsp2", REG_NONE, REG_A },
|
||||
{ "decsp3", REG_NONE, REG_A },
|
||||
{ "decsp4", REG_NONE, REG_A },
|
||||
{ "decsp5", REG_NONE, REG_A },
|
||||
{ "decsp6", REG_NONE, REG_A },
|
||||
{ "decsp7", REG_NONE, REG_A },
|
||||
{ "decsp8", REG_NONE, REG_A },
|
||||
{ "incax1", REG_AX, REG_AX },
|
||||
{ "incax2", REG_AX, REG_AX },
|
||||
{ "incsp1", REG_NONE, REG_NONE },
|
||||
{ "incsp2", REG_NONE, REG_Y },
|
||||
{ "incsp3", REG_NONE, REG_Y },
|
||||
{ "incsp4", REG_NONE, REG_Y },
|
||||
{ "incsp5", REG_NONE, REG_Y },
|
||||
{ "incsp6", REG_NONE, REG_Y },
|
||||
{ "incsp7", REG_NONE, REG_Y },
|
||||
{ "incsp8", REG_NONE, REG_Y },
|
||||
{ "ldaidx", REG_AXY, REG_AX },
|
||||
{ "ldauidx", REG_AXY, REG_AX },
|
||||
{ "ldax0sp", REG_Y, REG_AX },
|
||||
{ "ldaxi", REG_AX, REG_AXY },
|
||||
{ "ldaxidx", REG_AXY, REG_AX },
|
||||
{ "ldaxysp", REG_Y, REG_AX },
|
||||
{ "leaasp", REG_A, REG_AX },
|
||||
{ "negax", REG_AX, REG_AX },
|
||||
{ "pusha", REG_A, REG_Y },
|
||||
{ "pusha0", REG_A, REG_XY },
|
||||
{ "pushax", REG_AX, REG_Y },
|
||||
{ "pusheax", REG_AX, REG_Y },
|
||||
{ "pushw0sp", REG_NONE, REG_AXY },
|
||||
{ "pushwysp", REG_Y, REG_AXY },
|
||||
{ "shlax1", REG_AX, REG_AX },
|
||||
{ "shlax2", REG_AX, REG_AX },
|
||||
{ "shlax3", REG_AX, REG_AX },
|
||||
{ "shlax4", REG_AX, REG_AX },
|
||||
{ "shrax1", REG_AX, REG_AX },
|
||||
{ "shrax2", REG_AX, REG_AX },
|
||||
{ "shrax3", REG_AX, REG_AX },
|
||||
{ "shrax4", REG_AX, REG_AX },
|
||||
{ "shreax1", REG_AX, REG_AX },
|
||||
{ "shreax2", REG_AX, REG_AX },
|
||||
{ "shreax3", REG_AX, REG_AX },
|
||||
{ "shreax4", REG_AX, REG_AX },
|
||||
{ "staspidx", REG_A | REG_Y, REG_Y },
|
||||
{ "stax0sp", REG_AX, REG_Y },
|
||||
{ "tosicmp", REG_AX, REG_AXY },
|
||||
{ "tosdiva0", REG_AX, REG_AXY },
|
||||
{ "tosdivax", REG_AX, REG_AXY },
|
||||
{ "tosdiveax", REG_AX, REG_AXY },
|
||||
{ "tosmula0", REG_AX, REG_AXY },
|
||||
{ "tosmulax", REG_AX, REG_AXY },
|
||||
{ "tosmuleax", REG_AX, REG_AXY },
|
||||
{ "tosshreax", REG_AX, REG_AXY },
|
||||
{ "tosumula0", REG_AX, REG_AXY },
|
||||
{ "tosumulax", REG_AX, REG_AXY },
|
||||
{ "tosumuleax", REG_AX, REG_AXY },
|
||||
{ "addysp", REG_Y, REG_NONE },
|
||||
{ "aslax1", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "aslax2", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "aslax3", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "aslax4", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "bnega", REG_A, REG_AX },
|
||||
{ "bnegax", REG_AX, REG_AX },
|
||||
{ "bnegeax", REG_EAX, REG_EAX },
|
||||
{ "booleq", REG_NONE, REG_AX },
|
||||
{ "boolge", REG_NONE, REG_AX },
|
||||
{ "boolgt", REG_NONE, REG_AX },
|
||||
{ "boolle", REG_NONE, REG_AX },
|
||||
{ "boollt", REG_NONE, REG_AX },
|
||||
{ "boolne", REG_NONE, REG_AX },
|
||||
{ "booluge", REG_NONE, REG_AX },
|
||||
{ "boolugt", REG_NONE, REG_AX },
|
||||
{ "boolule", REG_NONE, REG_AX },
|
||||
{ "boolult", REG_NONE, REG_AX },
|
||||
{ "complax", REG_AX, REG_AX },
|
||||
{ "decax1", REG_AX, REG_AX },
|
||||
{ "decax2", REG_AX, REG_AX },
|
||||
{ "decax3", REG_AX, REG_AX },
|
||||
{ "decax4", REG_AX, REG_AX },
|
||||
{ "decax5", REG_AX, REG_AX },
|
||||
{ "decax6", REG_AX, REG_AX },
|
||||
{ "decax7", REG_AX, REG_AX },
|
||||
{ "decax8", REG_AX, REG_AX },
|
||||
{ "decaxy", REG_AXY, REG_AX | REG_TMP1 },
|
||||
{ "decsp1", REG_NONE, REG_Y },
|
||||
{ "decsp2", REG_NONE, REG_A },
|
||||
{ "decsp3", REG_NONE, REG_A },
|
||||
{ "decsp4", REG_NONE, REG_A },
|
||||
{ "decsp5", REG_NONE, REG_A },
|
||||
{ "decsp6", REG_NONE, REG_A },
|
||||
{ "decsp7", REG_NONE, REG_A },
|
||||
{ "decsp8", REG_NONE, REG_A },
|
||||
{ "incax1", REG_AX, REG_AX },
|
||||
{ "incax2", REG_AX, REG_AX },
|
||||
{ "incsp1", REG_NONE, REG_NONE },
|
||||
{ "incsp2", REG_NONE, REG_Y },
|
||||
{ "incsp3", REG_NONE, REG_Y },
|
||||
{ "incsp4", REG_NONE, REG_Y },
|
||||
{ "incsp5", REG_NONE, REG_Y },
|
||||
{ "incsp6", REG_NONE, REG_Y },
|
||||
{ "incsp7", REG_NONE, REG_Y },
|
||||
{ "incsp8", REG_NONE, REG_Y },
|
||||
{ "ldaidx", REG_AXY, REG_AX | REG_PTR1 },
|
||||
{ "ldauidx", REG_AXY, REG_AX | REG_PTR1 },
|
||||
{ "ldax0sp", REG_Y, REG_AX },
|
||||
{ "ldaxi", REG_AX, REG_AXY | REG_PTR1 },
|
||||
{ "ldaxidx", REG_AXY, REG_AX | REG_PTR1 },
|
||||
{ "ldaxysp", REG_Y, REG_AX },
|
||||
{ "leaasp", REG_A, REG_AX },
|
||||
{ "negax", REG_AX, REG_AX },
|
||||
{ "pusha", REG_A, REG_Y },
|
||||
{ "pusha0", REG_A, REG_XY },
|
||||
{ "pushax", REG_AX, REG_Y },
|
||||
{ "pusheax", REG_EAX, REG_Y },
|
||||
{ "pushw0sp", REG_NONE, REG_AXY },
|
||||
{ "pushwysp", REG_Y, REG_AXY },
|
||||
{ "shlax1", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shlax2", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shlax3", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shlax4", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shrax1", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shrax2", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shrax3", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shrax4", REG_AX, REG_AX | REG_TMP1 },
|
||||
{ "shreax1", REG_EAX, REG_AX | REG_TMP1 },
|
||||
{ "shreax2", REG_EAX, REG_AX | REG_TMP1 },
|
||||
{ "shreax3", REG_EAX, REG_AX | REG_TMP1 },
|
||||
{ "shreax4", REG_EAX, REG_AX | REG_TMP1 },
|
||||
{ "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 },
|
||||
{ "stax0sp", REG_AX, REG_Y },
|
||||
{ "tosicmp", REG_AX, REG_AXY | REG_SREG },
|
||||
{ "tosdiva0", REG_AX, REG_ALL },
|
||||
{ "tosdivax", REG_AX, REG_ALL },
|
||||
{ "tosdiveax", REG_EAX, REG_ALL },
|
||||
{ "tosmula0", REG_AX, REG_ALL },
|
||||
{ "tosmulax", REG_AX, REG_ALL },
|
||||
{ "tosmuleax", REG_EAX, REG_ALL },
|
||||
{ "tosshreax", REG_EAX, REG_EAXY | REG_PTR1 | REG_PTR2 },
|
||||
{ "tosumula0", REG_AX, REG_ALL },
|
||||
{ "tosumulax", REG_AX, REG_ALL },
|
||||
{ "tosumuleax", REG_EAX, REG_ALL },
|
||||
};
|
||||
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
|
||||
|
||||
/* Table with names of zero page locations used by the compiler */
|
||||
typedef struct ZPInfo ZPInfo;
|
||||
struct ZPInfo {
|
||||
unsigned char Len; /* Length of the following string */
|
||||
char Name[11]; /* Name of zero page symbol */
|
||||
unsigned char Len; /* Length of the following string */
|
||||
char Name[11]; /* Name of zero page symbol */
|
||||
unsigned short RegInfo; /* Register info for this symbol */
|
||||
};
|
||||
static const ZPInfo ZPInfoTable[] = {
|
||||
{ 4, "ptr1" },
|
||||
{ 7, "regbank" },
|
||||
{ 7, "regsave" },
|
||||
{ 2, "sp" },
|
||||
{ 4, "sreg" },
|
||||
{ 4, "tmp1" },
|
||||
{ 4, "ptr1", REG_PTR1 },
|
||||
{ 4, "ptr2", REG_PTR2 },
|
||||
{ 4, "ptr3", REG_PTR3 },
|
||||
{ 4, "ptr4", REG_PTR4 },
|
||||
{ 7, "regbank", REG_NONE },
|
||||
{ 7, "regsave", REG_NONE },
|
||||
{ 2, "sp", REG_NONE },
|
||||
{ 4, "sreg", REG_SREG },
|
||||
{ 4, "tmp1", REG_TMP1 },
|
||||
{ 4, "tmp2", REG_TMP2 },
|
||||
{ 4, "tmp3", REG_TMP3 },
|
||||
};
|
||||
#define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0]))
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -227,7 +233,7 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
|
||||
}
|
||||
|
||||
/* Will destroy all registers */
|
||||
*Chg = REG_AXY;
|
||||
*Chg = REG_ALL;
|
||||
|
||||
/* Done */
|
||||
return;
|
||||
@ -248,15 +254,20 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Function not found - assume all registers used */
|
||||
/* Function not found - assume all CPU registers are input, and all
|
||||
* registers are changed
|
||||
*/
|
||||
*Use = REG_AXY;
|
||||
*Chg = REG_AXY;
|
||||
*Chg = REG_ALL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsZPName (const char* Name)
|
||||
/* Return true if the given name is a zero page symbol */
|
||||
int IsZPName (const char* Name, unsigned short* RegInfo)
|
||||
/* Return true if the given name is a zero page symbol. If the RegInfo
|
||||
* pointer is not NULL, it is filled with the register info for the
|
||||
* zero page location found.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
const ZPInfo* Info;
|
||||
@ -264,10 +275,13 @@ int IsZPName (const char* Name)
|
||||
/* Because of the low number of symbols, we do a linear search here */
|
||||
for (I = 0, Info = ZPInfoTable; I < ZPInfoCount; ++I, ++Info) {
|
||||
if (strncmp (Name, Info->Name, Info->Len) == 0 &&
|
||||
(Name[Info->Len] == '\0' || Name[Info->Len] == '+')) {
|
||||
/* Found */
|
||||
return 1;
|
||||
}
|
||||
(Name[Info->Len] == '\0' || Name[Info->Len] == '+')) {
|
||||
/* Found */
|
||||
if (RegInfo) {
|
||||
*RegInfo = Info->RegInfo;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
@ -277,9 +291,9 @@ int IsZPName (const char* Name)
|
||||
|
||||
|
||||
static unsigned GetRegInfo1 (CodeSeg* S,
|
||||
CodeEntry* E,
|
||||
int Index,
|
||||
Collection* Visited,
|
||||
CodeEntry* E,
|
||||
int Index,
|
||||
Collection* Visited,
|
||||
unsigned Used,
|
||||
unsigned Unused);
|
||||
/* Recursively called subfunction for GetRegInfo. */
|
||||
|
@ -73,15 +73,16 @@ struct CodeSeg;
|
||||
#define REG_PTR4_LO 0x4000U
|
||||
#define REG_PTR4_HI 0x8000U
|
||||
#define REG_AX (REG_A | REG_X)
|
||||
#define REG_EAX (REG_A | REG_X | REG_SREG_LO | REG_SREG_HI)
|
||||
#define REG_XY (REG_X | REG_Y)
|
||||
#define REG_AXY (REG_A | REG_X | REG_Y)
|
||||
#define REG_SREG (REG_SREG_LO | REG_SREG_HI)
|
||||
#define REG_EAX (REG_AX | REG_SREG)
|
||||
#define REG_XY (REG_X | REG_Y)
|
||||
#define REG_AXY (REG_AX | REG_Y)
|
||||
#define REG_EAXY (REG_EAX | REG_Y)
|
||||
#define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI)
|
||||
#define REG_PTR2 (REG_PTR2_LO | REG_PTR2_HI)
|
||||
#define REG_PTR3 (REG_PTR3_LO | REG_PTR3_HI)
|
||||
#define REG_PTR4 (REG_PTR4_LO | REG_PTR4_HI)
|
||||
|
||||
#define REG_ALL 0xFFFFU
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -96,8 +97,11 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg);
|
||||
* load all registers.
|
||||
*/
|
||||
|
||||
int IsZPName (const char* Name);
|
||||
/* Return true if the given name is a zero page symbol */
|
||||
int IsZPName (const char* Name, unsigned short* RegInfo);
|
||||
/* Return true if the given name is a zero page symbol. If the RegInfo
|
||||
* pointer is not NULL, it is filled with the register info for the
|
||||
* zero page location found.
|
||||
*/
|
||||
|
||||
unsigned GetRegInfo (struct CodeSeg* S, unsigned Index);
|
||||
/* Determine register usage information for the instructions starting at the
|
||||
|
@ -591,15 +591,12 @@ static unsigned OptAdd1 (CodeSeg* S)
|
||||
|
||||
CodeEntry* X;
|
||||
CodeLabel* Label;
|
||||
char Buf [16];
|
||||
|
||||
/* Remove the call to pushax */
|
||||
CS_DelEntry (S, I);
|
||||
|
||||
/* Correct the stack offset (needed since pushax was removed) */
|
||||
L[0]->Num -= 2;
|
||||
xsprintf (Buf, sizeof (Buf), "$%02lX", L[0]->Num);
|
||||
CE_SetArg (L[0], Buf);
|
||||
CE_SetNumArg (L[0], L[0]->Num - 2);
|
||||
|
||||
/* Add the clc . */
|
||||
X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI);
|
||||
@ -1885,7 +1882,7 @@ static unsigned OptPtrStore2 (CodeSeg* S)
|
||||
{
|
||||
unsigned Changes = 0;
|
||||
|
||||
/* Walk over the entries */
|
||||
/* Walk over the entries */
|
||||
unsigned I = 0;
|
||||
while (I < CS_GetEntryCount (S)) {
|
||||
|
||||
|
@ -323,7 +323,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
|
||||
if ((OPC->Info & OF_BRA) != 0) {
|
||||
/* Branch */
|
||||
AM = AM65_BRA;
|
||||
} else if (IsZPName (Arg)) {
|
||||
} else if (IsZPName (Arg, 0)) {
|
||||
AM = AM65_ZP;
|
||||
} else {
|
||||
AM = AM65_ABS;
|
||||
@ -338,7 +338,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
|
||||
Reg = toupper (*L);
|
||||
L = SkipSpace (L+1);
|
||||
if (Reg == 'X') {
|
||||
if (IsZPName (Arg)) {
|
||||
if (IsZPName (Arg, 0)) {
|
||||
AM = AM65_ZPX;
|
||||
} else {
|
||||
AM = AM65_ABSX;
|
||||
@ -484,7 +484,7 @@ void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap)
|
||||
|
||||
void CS_AddLine (CodeSeg* S, LineInfo* LI, const char* Format, ...)
|
||||
/* Add a line to the given code segment */
|
||||
{
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, Format);
|
||||
CS_AddVLine (S, LI, Format, ap);
|
||||
|
@ -197,8 +197,8 @@ typedef struct {
|
||||
opc_t OPC; /* Opcode */
|
||||
char Mnemo[9]; /* Mnemonic */
|
||||
unsigned char Size; /* Size, 0 = check addressing mode */
|
||||
unsigned char Use; /* Registers used by this insn */
|
||||
unsigned char Chg; /* Registers changed by this insn */
|
||||
unsigned short Use; /* Registers used by this insn */
|
||||
unsigned short Chg; /* Registers changed by this insn */
|
||||
unsigned short Info; /* Additional information */
|
||||
} OPCDesc;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user