1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

The instruction parser can now recognize ZP locations and set the addressing mode for them.

This commit is contained in:
acqn 2020-01-21 10:39:19 +08:00 committed by Oliver Schmidt
parent 81550ca1ee
commit f8c9dde989
4 changed files with 105 additions and 20 deletions

View File

@ -349,23 +349,23 @@ static const FuncInfo FuncInfoTable[] = {
/* Table with names of zero page locations used by the compiler */
static const ZPInfo ZPInfoTable[] = {
{ 0, "ptr1", REG_PTR1_LO, REG_PTR1 },
{ 0, "ptr1+1", REG_PTR1_HI, REG_PTR1 },
{ 0, "ptr2", REG_PTR2_LO, REG_PTR2 },
{ 0, "ptr2+1", REG_PTR2_HI, REG_PTR2 },
{ 4, "ptr3", REG_NONE, REG_NONE },
{ 4, "ptr4", REG_NONE, REG_NONE },
{ 7, "regbank", REG_NONE, REG_NONE },
{ 0, "regsave", REG_SAVE_LO, REG_SAVE },
{ 0, "regsave+1", REG_SAVE_HI, REG_SAVE },
{ 0, "sp", REG_SP_LO, REG_SP },
{ 0, "sp+1", REG_SP_HI, REG_SP },
{ 0, "sreg", REG_SREG_LO, REG_SREG },
{ 0, "sreg+1", REG_SREG_HI, REG_SREG },
{ 0, "tmp1", REG_TMP1, REG_TMP1 },
{ 0, "tmp2", REG_NONE, REG_NONE },
{ 0, "tmp3", REG_NONE, REG_NONE },
{ 0, "tmp4", REG_NONE, REG_NONE },
{ 0, "ptr1", 2, REG_PTR1_LO, REG_PTR1 },
{ 0, "ptr1+1", 1, REG_PTR1_HI, REG_PTR1 },
{ 0, "ptr2", 2, REG_PTR2_LO, REG_PTR2 },
{ 0, "ptr2+1", 1, REG_PTR2_HI, REG_PTR2 },
{ 4, "ptr3", 2, REG_NONE, REG_NONE },
{ 4, "ptr4", 2, REG_NONE, REG_NONE },
{ 7, "regbank", 6, REG_NONE, REG_NONE },
{ 0, "regsave", 4, REG_SAVE_LO, REG_SAVE },
{ 0, "regsave+1", 3, REG_SAVE_HI, REG_SAVE },
{ 0, "sp", 2, REG_SP_LO, REG_SP },
{ 0, "sp+1", 1, REG_SP_HI, REG_SP },
{ 0, "sreg", 2, REG_SREG_LO, REG_SREG },
{ 0, "sreg+1", 1, REG_SREG_HI, REG_SREG },
{ 0, "tmp1", 1, REG_TMP1, REG_TMP1 },
{ 0, "tmp2", 1, REG_NONE, REG_NONE },
{ 0, "tmp3", 1, REG_NONE, REG_NONE },
{ 0, "tmp4", 1, REG_NONE, REG_NONE },
};
#define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0]))
@ -377,6 +377,83 @@ static const ZPInfo ZPInfoTable[] = {
static int IsAddrOnZP (long Address)
/* Return true if the Address is within the ZP range.
** FIXME: ZP range may vary depending on the CPU settings.
*/
{
/* ZP in range [0x00, 0xFF] */
return Address >= 0 && Address < 0x100;
}
int IsZPArg (const char* Name)
/* Exam if the main part of the arg string indicates a ZP loc */
{
unsigned short ArgInfo = 0;
long Offset = 0;
StrBuf NameBuf = AUTO_STRBUF_INITIALIZER;
SymEntry* E = 0;
const ZPInfo* Info = 0;
if (!ParseOpcArgStr (Name, &ArgInfo, &NameBuf, &Offset)) {
/* Parsing failed */
SB_Done (&NameBuf);
return 0;
}
if ((ArgInfo & AIF_HAS_NAME) == 0) {
/* Numeric locs have no names */
SB_Done (&NameBuf);
/* We can check it against the ZP boundary if it is known */
return IsAddrOnZP (Offset);
}
if ((ArgInfo & AIF_BUILTIN) != 0) {
/* Search for the name in the list of builtin ZPs */
Info = GetZPInfo (SB_GetConstBuf (&NameBuf));
SB_Done (&NameBuf);
/* Do we know the ZP? */
if (Info != 0) {
/* Use the information we have */
return Offset >= 0 && Offset < (int)Info->Size;
}
/* Assume it be non-ZP */
return 0;
}
if ((ArgInfo & AIF_EXTERNAL) == 0) {
/* We don't support local variables on ZP */
SB_Done (&NameBuf);
return 0;
}
/* Search for the symbol in the global symbol table skipping the underline
** in its name.
*/
E = FindGlobalSym (SB_GetConstBuf (&NameBuf) + 1);
SB_Done (&NameBuf);
/* We are checking the offset against the symbol size rather than the actual
** zeropage boundary, since we can't magically ensure that until linking and
** can only trust the user in writing the correct code for now.
*/
if (E != 0 && (E->Flags & SC_ZEROPAGE) != 0) {
return Offset >= 0 && (unsigned)Offset < CheckedSizeOf (E->Type);
}
/* Not found on ZP */
return 0;
}
static int CompareFuncInfo (const void* Key, const void* Info)
/* Compare function for bsearch */
{

View File

@ -119,7 +119,8 @@ struct RegContents;
typedef struct ZPInfo ZPInfo;
struct ZPInfo {
unsigned char Len; /* Length of the following string */
char Name[11]; /* Name of zero page symbol */
char Name[10]; /* Name of zero page symbol */
unsigned char Size; /* Maximum buffer size of this register */
unsigned short ByteUse; /* Register info for this symbol */
unsigned short WordUse; /* Register info for 16 bit access */
};
@ -162,6 +163,9 @@ typedef enum {
int IsZPArg (const char* Arg);
/* Exam if the main part of the arg string indicates a ZP loc */
fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg);
/* For the given function, lookup register information and store it into
** the given variables. If the function is unknown, assume it will use and

View File

@ -403,7 +403,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
if ((OPC->Info & OF_BRA) != 0) {
/* Branch */
AM = AM65_BRA;
} else if (GetZPInfo(Arg) != 0) {
} else if (IsZPArg (Arg)) {
AM = AM65_ZP;
} else {
/* Check for subroutine call to local label */
@ -424,12 +424,15 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
Reg = toupper (*L);
L = SkipSpace (L+1);
if (Reg == 'X') {
if (GetZPInfo(Arg) != 0) {
if (IsZPArg (Arg)) {
AM = AM65_ZPX;
} else {
AM = AM65_ABSX;
}
} else if (Reg == 'Y') {
/* On 6502 only LDX and STX support AM65_ZPY.
** We just play it simple and safe for now.
*/
AM = AM65_ABSY;
} else {
Error ("ASM code error: syntax error");

View File

@ -649,6 +649,7 @@ unsigned GetInsnSize (opc_t OPC, am_t AM)
case AM65_IMM: return 2;
case AM65_ZP: return 2;
case AM65_ZPX: return 2;
case AM65_ZPY: return 2;
case AM65_ABS: return 3;
case AM65_ABSX: return 3;
case AM65_ABSY: return 3;