Finished indirect function calls.
Debugged zero page location tracking. git-svn-id: svn://svn.cc65.org/cc65/trunk@968 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -137,7 +137,7 @@ static int NumArg (const char* Arg, unsigned long* Num)
|
|||||||
static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
||||||
/* Set the Use and Chg in E */
|
/* 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,
|
/* 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
|
* 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_ZPX:
|
||||||
case AM65_ABSX:
|
case AM65_ABSX:
|
||||||
case AM65_ABSY:
|
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 ||
|
if (E->OPC == OP65_ASL || E->OPC == OP65_DEC ||
|
||||||
E->OPC == OP65_INC || E->OPC == OP65_LSR ||
|
E->OPC == OP65_INC || E->OPC == OP65_LSR ||
|
||||||
E->OPC == OP65_ROL || E->OPC == OP65_ROR ||
|
E->OPC == OP65_ROL || E->OPC == OP65_ROR ||
|
||||||
E->OPC == OP65_TRB || E->OPC == OP65_TSB) {
|
E->OPC == OP65_TRB || E->OPC == OP65_TSB) {
|
||||||
/* The zp loc is both, input and output */
|
/* The zp loc is both, input and output */
|
||||||
E->Chg |= Use;
|
E->Chg |= Info->ByteUse;
|
||||||
E->Use |= Use;
|
E->Use |= Info->ByteUse;
|
||||||
} else if ((E->Info & OF_STORE) != 0) {
|
} else if ((E->Info & OF_STORE) != 0) {
|
||||||
/* Just output */
|
/* Just output */
|
||||||
E->Chg |= Use;
|
E->Chg |= Info->ByteUse;
|
||||||
} else {
|
} else {
|
||||||
/* Input only */
|
/* Input only */
|
||||||
E->Use |= Use;
|
E->Use |= Info->ByteUse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -183,9 +184,10 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
|||||||
case AM65_ZPX_IND:
|
case AM65_ZPX_IND:
|
||||||
case AM65_ZP_INDY:
|
case AM65_ZP_INDY:
|
||||||
case AM65_ZP_IND:
|
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 */
|
/* These addressing modes will never change the zp loc */
|
||||||
E->Use |= Use;
|
E->Use |= Info->WordUse;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -821,17 +823,10 @@ static char* RegInfoDesc (unsigned U, char* Buf)
|
|||||||
strcat (Buf, U & REG_A? "A" : "_");
|
strcat (Buf, U & REG_A? "A" : "_");
|
||||||
strcat (Buf, U & REG_X? "X" : "_");
|
strcat (Buf, U & REG_X? "X" : "_");
|
||||||
strcat (Buf, U & REG_Y? "Y" : "_");
|
strcat (Buf, U & REG_Y? "Y" : "_");
|
||||||
strcat (Buf, U & REG_SP? "S" : "_");
|
|
||||||
strcat (Buf, U & REG_TMP1? "T1" : "__");
|
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_PTR1? "1" : "_");
|
||||||
strcat (Buf, U & REG_PTR2? "2" : "_");
|
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_SAVE? "V" : "_");
|
||||||
strcat (Buf, U & REG_BANK? "B" : "_");
|
|
||||||
|
|
||||||
return Buf;
|
return Buf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2373,15 +2373,33 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void g_callind (unsigned Flags, unsigned ArgSize)
|
void g_callind (unsigned Flags, unsigned ArgSize, int Offs)
|
||||||
/* Call subroutine with address in AX */
|
/* Call subroutine indirect */
|
||||||
{
|
{
|
||||||
|
if ((Flags & CF_LOCAL) == 0) {
|
||||||
|
/* Address is in a/x */
|
||||||
if ((Flags & CF_FIXARGC) == 0) {
|
if ((Flags & CF_FIXARGC) == 0) {
|
||||||
/* Pass arg count */
|
/* Pass arg count */
|
||||||
ldyconst (ArgSize);
|
ldyconst (ArgSize);
|
||||||
}
|
}
|
||||||
AddCodeLine ("jsr callax"); /* do the call */
|
AddCodeLine ("jsr callax");
|
||||||
oursp += ArgSize; /* callee pops args */
|
} 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callee pops args */
|
||||||
|
oursp += ArgSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -370,8 +370,8 @@ void g_swap (unsigned flags);
|
|||||||
void g_call (unsigned Flags, const char* Label, unsigned ArgSize);
|
void g_call (unsigned Flags, const char* Label, unsigned ArgSize);
|
||||||
/* Call the specified subroutine name */
|
/* Call the specified subroutine name */
|
||||||
|
|
||||||
void g_callind (unsigned Flags, unsigned ArgSize);
|
void g_callind (unsigned Flags, unsigned ArgSize, int Offs);
|
||||||
/* Call subroutine with address in AX */
|
/* Call subroutine indirect */
|
||||||
|
|
||||||
void g_jump (unsigned Label);
|
void g_jump (unsigned Label);
|
||||||
/* Jump to specified internal label number */
|
/* Jump to specified internal label number */
|
||||||
|
|||||||
@@ -112,9 +112,9 @@ static const FuncInfo FuncInfoTable[] = {
|
|||||||
{ "incsp6", REG_NONE, REG_Y },
|
{ "incsp6", REG_NONE, REG_Y },
|
||||||
{ "incsp7", REG_NONE, REG_Y },
|
{ "incsp7", REG_NONE, REG_Y },
|
||||||
{ "incsp8", REG_NONE, REG_Y },
|
{ "incsp8", REG_NONE, REG_Y },
|
||||||
{ "laddeq", REG_EAXY | REG_PTR1, REG_EAXY },
|
{ "laddeq", REG_EAXY|REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
|
||||||
{ "laddeq1", REG_Y | REG_PTR1, REG_EAXY },
|
{ "laddeq1", REG_Y | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
|
||||||
{ "laddeqa", REG_AY | REG_PTR1, REG_EAXY },
|
{ "laddeqa", REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
|
||||||
{ "ldaidx", REG_AXY, REG_AX | REG_PTR1 },
|
{ "ldaidx", REG_AXY, REG_AX | REG_PTR1 },
|
||||||
{ "ldauidx", REG_AXY, REG_AX | REG_PTR1 },
|
{ "ldauidx", REG_AXY, REG_AX | REG_PTR1 },
|
||||||
{ "ldax0sp", REG_Y, REG_AX },
|
{ "ldax0sp", REG_Y, REG_AX },
|
||||||
@@ -143,6 +143,7 @@ static const FuncInfo FuncInfoTable[] = {
|
|||||||
{ "shreax4", REG_EAX, REG_AX | REG_TMP1 },
|
{ "shreax4", REG_EAX, REG_AX | REG_TMP1 },
|
||||||
{ "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 },
|
{ "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 },
|
||||||
{ "stax0sp", REG_AX, REG_Y },
|
{ "stax0sp", REG_AX, REG_Y },
|
||||||
|
{ "staxysp", REG_AXY, REG_Y },
|
||||||
{ "tosicmp", REG_AX, REG_AXY | REG_SREG },
|
{ "tosicmp", REG_AX, REG_AXY | REG_SREG },
|
||||||
{ "tosdiva0", REG_AX, REG_ALL },
|
{ "tosdiva0", REG_AX, REG_ALL },
|
||||||
{ "tosdivax", REG_AX, REG_ALL },
|
{ "tosdivax", REG_AX, REG_ALL },
|
||||||
@@ -158,26 +159,23 @@ static const FuncInfo FuncInfoTable[] = {
|
|||||||
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
|
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
|
||||||
|
|
||||||
/* Table with names of zero page locations used by the compiler */
|
/* 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[] = {
|
static const ZPInfo ZPInfoTable[] = {
|
||||||
{ 4, "ptr1", REG_PTR1 },
|
{ 0, "ptr1", REG_PTR1_LO, REG_PTR1 },
|
||||||
{ 4, "ptr2", REG_PTR2 },
|
{ 0, "ptr1+1", REG_PTR1_HI, REG_PTR1 },
|
||||||
{ 4, "ptr3", REG_PTR3 },
|
{ 0, "ptr2", REG_PTR2_LO, REG_PTR2 },
|
||||||
{ 4, "ptr4", REG_PTR4 },
|
{ 0, "ptr2+1", REG_PTR2_HI, REG_PTR2 },
|
||||||
{ 7, "regbank", REG_BANK },
|
{ 4, "ptr3", REG_NONE, REG_NONE },
|
||||||
{ 7, "regsave", REG_SAVE },
|
{ 4, "ptr4", REG_NONE, REG_NONE },
|
||||||
{ 2, "sp", REG_SP },
|
{ 7, "regbank", REG_NONE, REG_NONE },
|
||||||
{ 0, "sreg", REG_SREG_LO },
|
{ 0, "regsave", REG_SAVE_LO, REG_SAVE },
|
||||||
{ 0, "sreg+1", REG_SREG_HI },
|
{ 0, "regsave+1", REG_SAVE_HI, REG_SAVE },
|
||||||
{ 4, "tmp1", REG_TMP1 },
|
{ 2, "sp", REG_NONE, REG_NONE },
|
||||||
{ 4, "tmp2", REG_TMP2 },
|
{ 0, "sreg", REG_SREG_LO, REG_SREG },
|
||||||
{ 4, "tmp3", REG_TMP3 },
|
{ 0, "sreg+1", REG_SREG_HI, REG_SREG },
|
||||||
{ 4, "tmp4", REG_TMP4 },
|
{ 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]))
|
#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
|
* registers are changed
|
||||||
*/
|
*/
|
||||||
*Use = REG_AXY;
|
*Use = REG_EAXY;
|
||||||
*Chg = REG_ALL;
|
*Chg = REG_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,27 +292,14 @@ static int CompareZPInfo (const void* Name, const void* Info)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int IsZPName (const char* Name, unsigned short* RegInfo)
|
const ZPInfo* GetZPInfo (const char* Name)
|
||||||
/* Return true if the given name is a zero page symbol. If the RegInfo
|
/* If the given name is a zero page symbol, return a pointer to the info
|
||||||
* pointer is not NULL, it is filled with the register info for the
|
* struct for this symbol, otherwise return NULL.
|
||||||
* zero page location found.
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Search for the zp location in the list */
|
/* Search for the zp location in the list */
|
||||||
const ZPInfo* Info = bsearch (Name, ZPInfoTable, ZPInfoCount,
|
return bsearch (Name, ZPInfoTable, ZPInfoCount,
|
||||||
sizeof(ZPInfo), CompareZPInfo);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,32 +60,42 @@ struct CodeSeg;
|
|||||||
#define REG_X 0x0002U
|
#define REG_X 0x0002U
|
||||||
#define REG_Y 0x0004U
|
#define REG_Y 0x0004U
|
||||||
#define REG_TMP1 0x0008U
|
#define REG_TMP1 0x0008U
|
||||||
#define REG_TMP2 0x0010U
|
#define REG_PTR1_LO 0x0010U
|
||||||
#define REG_TMP3 0x0020U
|
#define REG_PTR1_HI 0x0020U
|
||||||
#define REG_TMP4 0x0040U
|
#define REG_PTR2_LO 0x0040U
|
||||||
#define REG_PTR1 0x0080U
|
#define REG_PTR2_HI 0x0080U
|
||||||
#define REG_PTR2 0x0100U
|
#define REG_SREG_LO 0x0100U
|
||||||
#define REG_PTR3 0x0200U
|
#define REG_SREG_HI 0x0200U
|
||||||
#define REG_PTR4 0x0400U
|
#define REG_SAVE_LO 0x0400U
|
||||||
#define REG_SREG_LO 0x0800U
|
#define REG_SAVE_HI 0x0800U
|
||||||
#define REG_SREG_HI 0x1000U
|
|
||||||
#define REG_SP 0x2000U
|
|
||||||
#define REG_SAVE 0x4000U
|
|
||||||
#define REG_BANK 0x8000U
|
|
||||||
|
|
||||||
/* Combined register defines */
|
/* 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_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_AX (REG_A | REG_X)
|
||||||
#define REG_AY (REG_A | REG_Y)
|
#define REG_AY (REG_A | REG_Y)
|
||||||
#define REG_XY (REG_X | REG_Y)
|
#define REG_XY (REG_X | REG_Y)
|
||||||
#define REG_AXY (REG_AX | REG_Y)
|
#define REG_AXY (REG_AX | REG_Y)
|
||||||
#define REG_EAX (REG_AX | REG_SREG)
|
#define REG_EAX (REG_AX | REG_SREG)
|
||||||
#define REG_EAXY (REG_EAX | REG_Y)
|
#define REG_EAXY (REG_EAX | REG_Y)
|
||||||
#define REG_ZP 0xFFF0U
|
#define REG_ZP 0xFFF8U
|
||||||
#define REG_ALL 0xFFFFU
|
#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 */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -98,10 +108,9 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg);
|
|||||||
* load all registers.
|
* load all registers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int IsZPName (const char* Name, unsigned short* RegInfo);
|
const ZPInfo* GetZPInfo (const char* Name);
|
||||||
/* Return true if the given name is a zero page symbol. If the RegInfo
|
/* If the given name is a zero page symbol, return a pointer to the info
|
||||||
* pointer is not NULL, it is filled with the register info for the
|
* struct for this symbol, otherwise return NULL.
|
||||||
* zero page location found.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted);
|
unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted);
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
|
|||||||
if ((OPC->Info & OF_BRA) != 0) {
|
if ((OPC->Info & OF_BRA) != 0) {
|
||||||
/* Branch */
|
/* Branch */
|
||||||
AM = AM65_BRA;
|
AM = AM65_BRA;
|
||||||
} else if (IsZPName (Arg, 0)) {
|
} else if (GetZPInfo(Arg) != 0) {
|
||||||
AM = AM65_ZP;
|
AM = AM65_ZP;
|
||||||
} else {
|
} else {
|
||||||
AM = AM65_ABS;
|
AM = AM65_ABS;
|
||||||
@@ -338,7 +338,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
|
|||||||
Reg = toupper (*L);
|
Reg = toupper (*L);
|
||||||
L = SkipSpace (L+1);
|
L = SkipSpace (L+1);
|
||||||
if (Reg == 'X') {
|
if (Reg == 'X') {
|
||||||
if (IsZPName (Arg, 0)) {
|
if (GetZPInfo(Arg) != 0) {
|
||||||
AM = AM65_ZPX;
|
AM = AM65_ZPX;
|
||||||
} else {
|
} else {
|
||||||
AM = AM65_ABSX;
|
AM = AM65_ABSX;
|
||||||
|
|||||||
@@ -774,7 +774,7 @@ static void FunctionCall (int k, ExprDesc* lval)
|
|||||||
/* If the function is not a fastcall function, load the pointer to
|
/* If the function is not a fastcall function, load the pointer to
|
||||||
* the function into the primary.
|
* the function into the primary.
|
||||||
*/
|
*/
|
||||||
if (!IsFastCallFunc (lval->Type)) {
|
if (!IsFastCall) {
|
||||||
|
|
||||||
/* Not a fastcall function - we may use the primary */
|
/* Not a fastcall function - we may use the primary */
|
||||||
if (PtrOnStack) {
|
if (PtrOnStack) {
|
||||||
@@ -796,13 +796,7 @@ static void FunctionCall (int k, ExprDesc* lval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Call the function */
|
/* Call the function */
|
||||||
g_callind (TypeOf (lval->Type), ParamSize);
|
g_callind (TypeOf (lval->Type), ParamSize, PtrOffs);
|
||||||
|
|
||||||
/* If we have a pointer on stack, remove it */
|
|
||||||
if (PtrOnStack) {
|
|
||||||
g_space (- (int) sizeofarg (CF_PTR));
|
|
||||||
pop (CF_PTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -811,7 +805,12 @@ static void FunctionCall (int k, ExprDesc* lval)
|
|||||||
* Since fastcall functions may never be variadic, we can use the
|
* Since fastcall functions may never be variadic, we can use the
|
||||||
* index register for this purpose.
|
* index register for this purpose.
|
||||||
*/
|
*/
|
||||||
Error ("Not implemented");
|
g_callind (CF_LOCAL, ParamSize, PtrOffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have a pointer on stack, remove it */
|
||||||
|
if (PtrOnStack) {
|
||||||
|
g_space (- (int) sizeofarg (CF_PTR));
|
||||||
pop (CF_PTR);
|
pop (CF_PTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user