From 5d0a52b7accc43672275d6331c576c2512b1074b Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 25 Sep 2001 10:30:48 +0000 Subject: [PATCH] Finished indirect function calls. Debugged zero page location tracking. git-svn-id: svn://svn.cc65.org/cc65/trunk@968 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 39 +++++++++++-------------- src/cc65/codegen.c | 34 ++++++++++++++++------ src/cc65/codegen.h | 4 +-- src/cc65/codeinfo.c | 69 ++++++++++++++++++--------------------------- src/cc65/codeinfo.h | 43 +++++++++++++++++----------- src/cc65/codeseg.c | 4 +-- src/cc65/expr.c | 45 +++++++++++++++-------------- 7 files changed, 122 insertions(+), 116 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index e37d079f5..7cca0bd78 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -137,7 +137,7 @@ 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; + const ZPInfo* Info; /* 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 @@ -162,20 +162,21 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) case AM65_ZPX: case AM65_ABSX: case AM65_ABSY: - if (IsZPName (E->Arg, &Use) && Use != REG_NONE) { + Info = GetZPInfo (E->Arg); + if (Info && Info->ByteUse != REG_NONE) { if (E->OPC == OP65_ASL || E->OPC == OP65_DEC || - E->OPC == OP65_INC || E->OPC == OP65_LSR || - E->OPC == OP65_ROL || E->OPC == OP65_ROR || - E->OPC == OP65_TRB || E->OPC == OP65_TSB) { - /* The zp loc is both, input and output */ - E->Chg |= Use; - E->Use |= Use; + E->OPC == OP65_INC || E->OPC == OP65_LSR || + E->OPC == OP65_ROL || E->OPC == OP65_ROR || + E->OPC == OP65_TRB || E->OPC == OP65_TSB) { + /* The zp loc is both, input and output */ + E->Chg |= Info->ByteUse; + E->Use |= Info->ByteUse; } else if ((E->Info & OF_STORE) != 0) { - /* Just output */ - E->Chg |= Use; + /* Just output */ + E->Chg |= Info->ByteUse; } else { - /* Input only */ - E->Use |= Use; + /* Input only */ + E->Use |= Info->ByteUse; } } break; @@ -183,9 +184,10 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) case AM65_ZPX_IND: case AM65_ZP_INDY: case AM65_ZP_IND: - if (IsZPName (E->Arg, &Use) && Use != REG_NONE) { + Info = GetZPInfo (E->Arg); + if (Info && Info->ByteUse != REG_NONE) { /* These addressing modes will never change the zp loc */ - E->Use |= Use; + E->Use |= Info->WordUse; } break; @@ -774,7 +776,7 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) Out->RegX = In->RegA; break; - case OP65_TAY: + case OP65_TAY: Out->RegY = In->RegA; break; @@ -821,17 +823,10 @@ static char* RegInfoDesc (unsigned U, char* Buf) strcat (Buf, U & REG_A? "A" : "_"); strcat (Buf, U & REG_X? "X" : "_"); strcat (Buf, U & REG_Y? "Y" : "_"); - strcat (Buf, U & REG_SP? "S" : "_"); strcat (Buf, U & REG_TMP1? "T1" : "__"); - strcat (Buf, U & REG_TMP2? "T2" : "__"); - strcat (Buf, U & REG_TMP3? "T3" : "__"); - strcat (Buf, U & REG_TMP4? "T4" : "__"); strcat (Buf, U & REG_PTR1? "1" : "_"); strcat (Buf, U & REG_PTR2? "2" : "_"); - strcat (Buf, U & REG_PTR3? "3" : "_"); - strcat (Buf, U & REG_PTR4? "4" : "_"); strcat (Buf, U & REG_SAVE? "V" : "_"); - strcat (Buf, U & REG_BANK? "B" : "_"); return Buf; } diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 74a1710d4..d936c1572 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -2373,15 +2373,33 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize) -void g_callind (unsigned Flags, unsigned ArgSize) -/* Call subroutine with address in AX */ -{ - if ((Flags & CF_FIXARGC) == 0) { - /* Pass arg count */ - ldyconst (ArgSize); +void g_callind (unsigned Flags, unsigned ArgSize, int Offs) +/* Call subroutine indirect */ +{ + if ((Flags & CF_LOCAL) == 0) { + /* Address is in a/x */ + if ((Flags & CF_FIXARGC) == 0) { + /* Pass arg count */ + ldyconst (ArgSize); + } + AddCodeLine ("jsr callax"); + } else { + /* The address is on stack, offset is on Val */ + Offs -= oursp; + CheckLocalOffs (Offs); + AddCodeLine ("pha"); + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta jmpvec+1"); + AddCodeLine ("iny"); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta jmpvec+2"); + AddCodeLine ("pla"); + AddCodeLine ("jsr jmpvec"); } - AddCodeLine ("jsr callax"); /* do the call */ - oursp += ArgSize; /* callee pops args */ + + /* Callee pops args */ + oursp += ArgSize; } diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 91274ec42..704032ea4 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -370,8 +370,8 @@ void g_swap (unsigned flags); void g_call (unsigned Flags, const char* Label, unsigned ArgSize); /* Call the specified subroutine name */ -void g_callind (unsigned Flags, unsigned ArgSize); -/* Call subroutine with address in AX */ +void g_callind (unsigned Flags, unsigned ArgSize, int Offs); +/* Call subroutine indirect */ void g_jump (unsigned Label); /* Jump to specified internal label number */ diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index abf8a3bf5..9dd6e9b95 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -112,9 +112,9 @@ static const FuncInfo FuncInfoTable[] = { { "incsp6", REG_NONE, REG_Y }, { "incsp7", REG_NONE, REG_Y }, { "incsp8", REG_NONE, REG_Y }, - { "laddeq", REG_EAXY | REG_PTR1, REG_EAXY }, - { "laddeq1", REG_Y | REG_PTR1, REG_EAXY }, - { "laddeqa", REG_AY | REG_PTR1, REG_EAXY }, + { "laddeq", REG_EAXY|REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, + { "laddeq1", REG_Y | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, + { "laddeqa", REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "ldaidx", REG_AXY, REG_AX | REG_PTR1 }, { "ldauidx", REG_AXY, REG_AX | REG_PTR1 }, { "ldax0sp", REG_Y, REG_AX }, @@ -143,6 +143,7 @@ static const FuncInfo FuncInfoTable[] = { { "shreax4", REG_EAX, REG_AX | REG_TMP1 }, { "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 }, { "stax0sp", REG_AX, REG_Y }, + { "staxysp", REG_AXY, REG_Y }, { "tosicmp", REG_AX, REG_AXY | REG_SREG }, { "tosdiva0", REG_AX, REG_ALL }, { "tosdivax", REG_AX, REG_ALL }, @@ -158,26 +159,23 @@ static const FuncInfo FuncInfoTable[] = { #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 short RegInfo; /* Register info for this symbol */ -}; static const ZPInfo ZPInfoTable[] = { - { 4, "ptr1", REG_PTR1 }, - { 4, "ptr2", REG_PTR2 }, - { 4, "ptr3", REG_PTR3 }, - { 4, "ptr4", REG_PTR4 }, - { 7, "regbank", REG_BANK }, - { 7, "regsave", REG_SAVE }, - { 2, "sp", REG_SP }, - { 0, "sreg", REG_SREG_LO }, - { 0, "sreg+1", REG_SREG_HI }, - { 4, "tmp1", REG_TMP1 }, - { 4, "tmp2", REG_TMP2 }, - { 4, "tmp3", REG_TMP3 }, - { 4, "tmp4", REG_TMP4 }, + { 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 }, + { 2, "sp", REG_NONE, REG_NONE }, + { 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 }, }; #define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0])) @@ -259,10 +257,10 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) } } - /* Function not found - assume all CPU registers are input, and all + /* Function not found - assume that the primary register is input, and all * registers are changed */ - *Use = REG_AXY; + *Use = REG_EAXY; *Chg = REG_ALL; } @@ -294,27 +292,14 @@ static int CompareZPInfo (const void* Name, const void* Info) -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. +const ZPInfo* GetZPInfo (const char* Name) +/* If the given name is a zero page symbol, return a pointer to the info + * struct for this symbol, otherwise return NULL. */ { /* Search for the zp location in the list */ - const ZPInfo* Info = bsearch (Name, ZPInfoTable, ZPInfoCount, - sizeof(ZPInfo), CompareZPInfo); - - /* Did we find it? */ - if (Info) { - /* Found, store register info if requested. */ - if (RegInfo) { - *RegInfo = Info->RegInfo; - } - return 1; - } else { - /* Not found */ - return 0; - } + return bsearch (Name, ZPInfoTable, ZPInfoCount, + sizeof(ZPInfo), CompareZPInfo); } diff --git a/src/cc65/codeinfo.h b/src/cc65/codeinfo.h index b4df0dd03..c445bd431 100644 --- a/src/cc65/codeinfo.h +++ b/src/cc65/codeinfo.h @@ -60,32 +60,42 @@ struct CodeSeg; #define REG_X 0x0002U #define REG_Y 0x0004U #define REG_TMP1 0x0008U -#define REG_TMP2 0x0010U -#define REG_TMP3 0x0020U -#define REG_TMP4 0x0040U -#define REG_PTR1 0x0080U -#define REG_PTR2 0x0100U -#define REG_PTR3 0x0200U -#define REG_PTR4 0x0400U -#define REG_SREG_LO 0x0800U -#define REG_SREG_HI 0x1000U -#define REG_SP 0x2000U -#define REG_SAVE 0x4000U -#define REG_BANK 0x8000U +#define REG_PTR1_LO 0x0010U +#define REG_PTR1_HI 0x0020U +#define REG_PTR2_LO 0x0040U +#define REG_PTR2_HI 0x0080U +#define REG_SREG_LO 0x0100U +#define REG_SREG_HI 0x0200U +#define REG_SAVE_LO 0x0400U +#define REG_SAVE_HI 0x0800U /* Combined register defines */ +#define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI) +#define REG_PTR2 (REG_PTR2_LO | REG_PTR2_HI) #define REG_SREG (REG_SREG_LO | REG_SREG_HI) +#define REG_SAVE (REG_SAVE_LO | REG_SAVE_HI) #define REG_AX (REG_A | REG_X) #define REG_AY (REG_A | REG_Y) #define REG_XY (REG_X | REG_Y) #define REG_AXY (REG_AX | REG_Y) #define REG_EAX (REG_AX | REG_SREG) #define REG_EAXY (REG_EAX | REG_Y) -#define REG_ZP 0xFFF0U +#define REG_ZP 0xFFF8U #define REG_ALL 0xFFFFU +/* Zero page register info */ +typedef struct ZPInfo ZPInfo; +struct ZPInfo { + unsigned char Len; /* Length of the following string */ + char Name[11]; /* Name of zero page symbol */ + unsigned short ByteUse; /* Register info for this symbol */ + unsigned short WordUse; /* Register info for 16 bit access */ +}; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -98,10 +108,9 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg); * load all registers. */ -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. +const ZPInfo* GetZPInfo (const char* Name); +/* If the given name is a zero page symbol, return a pointer to the info + * struct for this symbol, otherwise return NULL. */ unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted); diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index f29c6767e..567b2e96b 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -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, 0)) { + } else if (GetZPInfo(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, 0)) { + if (GetZPInfo(Arg) != 0) { AM = AM65_ZPX; } else { AM = AM65_ABSX; diff --git a/src/cc65/expr.c b/src/cc65/expr.c index ed0b1cf1e..745d42b45 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -774,35 +774,29 @@ static void FunctionCall (int k, ExprDesc* lval) /* If the function is not a fastcall function, load the pointer to * the function into the primary. */ - if (!IsFastCallFunc (lval->Type)) { + if (!IsFastCall) { /* Not a fastcall function - we may use the primary */ if (PtrOnStack) { - /* If we have no parameters, the pointer is still in the - * primary. Remove the code to push it and correct the - * stack pointer. - */ - if (ParamSize == 0) { - RemoveCode (Mark); - pop (CF_PTR); - PtrOnStack = 0; - } else { - /* Load from the saved copy */ - g_getlocal (CF_PTR, PtrOffs); - } + /* If we have no parameters, the pointer is still in the + * primary. Remove the code to push it and correct the + * stack pointer. + */ + if (ParamSize == 0) { + RemoveCode (Mark); + pop (CF_PTR); + PtrOnStack = 0; + } else { + /* Load from the saved copy */ + g_getlocal (CF_PTR, PtrOffs); + } } else { /* Load from original location */ exprhs (CF_NONE, k, lval); } /* Call the function */ - g_callind (TypeOf (lval->Type), ParamSize); - - /* If we have a pointer on stack, remove it */ - if (PtrOnStack) { - g_space (- (int) sizeofarg (CF_PTR)); - pop (CF_PTR); - } + g_callind (TypeOf (lval->Type), ParamSize, PtrOffs); } else { @@ -811,11 +805,16 @@ static void FunctionCall (int k, ExprDesc* lval) * Since fastcall functions may never be variadic, we can use the * index register for this purpose. */ - Error ("Not implemented"); - pop (CF_PTR); + g_callind (CF_LOCAL, ParamSize, PtrOffs); } - /* Skip T_PTR */ + /* If we have a pointer on stack, remove it */ + if (PtrOnStack) { + g_space (- (int) sizeofarg (CF_PTR)); + pop (CF_PTR); + } + + /* Skip T_PTR */ ++lval->Type; } else { -- 2.39.5