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
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;
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;
Out->RegX = In->RegA;
break;
- case OP65_TAY:
+ case OP65_TAY:
Out->RegY = In->RegA;
break;
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;
}
-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;
}
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 */
{ "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 },
{ "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 },
#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]))
}
}
- /* 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;
}
-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);
}
#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 */
/*****************************************************************************/
* 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);
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;
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;
/* 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 {
* 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 {