mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 15:29:46 +00:00
Replace staxspidx if possible
git-svn-id: svn://svn.cc65.org/cc65/trunk@1153 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
18b591e268
commit
164310971c
@ -157,6 +157,55 @@ static unsigned Opt_staspidx (CodeSeg* S, unsigned Push, unsigned Store,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned Opt_staxspidx (CodeSeg* S, unsigned Push, unsigned Store,
|
||||||
|
const char* ZPLo, const char* ZPHi)
|
||||||
|
/* Optimize the staxspidx sequence if possible */
|
||||||
|
{
|
||||||
|
CodeEntry* X;
|
||||||
|
CodeEntry* PushEntry;
|
||||||
|
CodeEntry* StoreEntry;
|
||||||
|
|
||||||
|
/* Get the push entry */
|
||||||
|
PushEntry = CS_GetEntry (S, Push);
|
||||||
|
|
||||||
|
/* Store the value into the zeropage instead of pushing it */
|
||||||
|
X = NewCodeEntry (OP65_STA, AM65_ZP, ZPLo, 0, PushEntry->LI);
|
||||||
|
CS_InsertEntry (S, X, Push+1);
|
||||||
|
X = NewCodeEntry (OP65_STX, AM65_ZP, ZPHi, 0, PushEntry->LI);
|
||||||
|
CS_InsertEntry (S, X, Push+2);
|
||||||
|
|
||||||
|
/* Correct the index of the store and get a pointer to the entry */
|
||||||
|
Store += 2;
|
||||||
|
StoreEntry = CS_GetEntry (S, Store);
|
||||||
|
|
||||||
|
/* Inline the store */
|
||||||
|
X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, StoreEntry->LI);
|
||||||
|
CS_InsertEntry (S, X, Store+1);
|
||||||
|
X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, StoreEntry->LI);
|
||||||
|
CS_InsertEntry (S, X, Store+2);
|
||||||
|
if (StoreEntry->RI->In.RegX >= 0) {
|
||||||
|
/* Value of X is known */
|
||||||
|
char Buf [16];
|
||||||
|
xsprintf (Buf, sizeof (Buf), "$%02X", StoreEntry->RI->In.RegX);
|
||||||
|
X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, StoreEntry->LI);
|
||||||
|
} else {
|
||||||
|
/* Value unknown */
|
||||||
|
X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, StoreEntry->LI);
|
||||||
|
}
|
||||||
|
CS_InsertEntry (S, X, Store+3);
|
||||||
|
X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, StoreEntry->LI);
|
||||||
|
CS_InsertEntry (S, X, Store+4);
|
||||||
|
|
||||||
|
/* Remove the push and the call to the staspidx function */
|
||||||
|
CS_DelEntry (S, Store);
|
||||||
|
CS_DelEntry (S, Push);
|
||||||
|
|
||||||
|
/* We changed the sequence */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned Opt_tosaddax (CodeSeg* S, unsigned Push, unsigned Add,
|
static unsigned Opt_tosaddax (CodeSeg* S, unsigned Push, unsigned Add,
|
||||||
const char* ZPLo, const char* ZPHi)
|
const char* ZPLo, const char* ZPHi)
|
||||||
/* Optimize the tosaddax sequence if possible */
|
/* Optimize the tosaddax sequence if possible */
|
||||||
@ -492,20 +541,29 @@ static unsigned Opt_tosxorax (CodeSeg* S, unsigned Push, unsigned Xor,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Flags for the functions */
|
||||||
|
typedef enum {
|
||||||
|
STOP_NONE, /* Nothing special */
|
||||||
|
STOP_A_UNUSED /* Call only if a unused later */
|
||||||
|
} STOP_FLAGS;
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned (*OptFunc) (CodeSeg* S, unsigned Push, unsigned Store,
|
typedef unsigned (*OptFunc) (CodeSeg* S, unsigned Push, unsigned Store,
|
||||||
const char* ZPLo, const char* ZPHi);
|
const char* ZPLo, const char* ZPHi);
|
||||||
typedef struct OptFuncDesc OptFuncDesc;
|
typedef struct OptFuncDesc OptFuncDesc;
|
||||||
struct OptFuncDesc {
|
struct OptFuncDesc {
|
||||||
const char* Name; /* Name of the replaced runtime function */
|
const char* Name; /* Name of the replaced runtime function */
|
||||||
OptFunc Func; /* Function pointer */
|
OptFunc Func; /* Function pointer */
|
||||||
|
STOP_FLAGS Flags; /* Flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const OptFuncDesc FuncTable[] = {
|
static const OptFuncDesc FuncTable[] = {
|
||||||
{ "staspidx", Opt_staspidx },
|
{ "staspidx", Opt_staspidx, STOP_NONE },
|
||||||
{ "tosaddax", Opt_tosaddax },
|
{ "staxspidx", Opt_staxspidx, STOP_A_UNUSED },
|
||||||
{ "tosandax", Opt_tosandax },
|
{ "tosaddax", Opt_tosaddax, STOP_NONE },
|
||||||
{ "tosorax", Opt_tosorax },
|
{ "tosandax", Opt_tosandax, STOP_NONE },
|
||||||
{ "tosxorax", Opt_tosxorax },
|
{ "tosorax", Opt_tosorax, STOP_NONE },
|
||||||
|
{ "tosxorax", Opt_tosxorax, STOP_NONE },
|
||||||
};
|
};
|
||||||
#define FUNC_COUNT (sizeof(FuncTable) / sizeof(FuncTable[0]))
|
#define FUNC_COUNT (sizeof(FuncTable) / sizeof(FuncTable[0]))
|
||||||
|
|
||||||
@ -586,28 +644,40 @@ unsigned OptStackOps (CodeSeg* S)
|
|||||||
const OptFuncDesc* F = FindFunc (E->Arg);
|
const OptFuncDesc* F = FindFunc (E->Arg);
|
||||||
if (F) {
|
if (F) {
|
||||||
|
|
||||||
/* Determine the register to use */
|
const char* ZPLo = 0;
|
||||||
const char* ZPLo;
|
const char* ZPHi = 0;
|
||||||
const char* ZPHi;
|
int PreCondOk = 1;
|
||||||
UsedRegs |= GetRegInfo (S, I+1, REG_SREG | REG_PTR1 | REG_PTR2);
|
|
||||||
if ((UsedRegs & REG_SREG) == REG_NONE) {
|
|
||||||
/* SREG is available */
|
|
||||||
ZPLo = "sreg";
|
|
||||||
ZPHi = "sreg+1";
|
|
||||||
} else if ((UsedRegs & REG_PTR1) == REG_NONE) {
|
|
||||||
ZPLo = "ptr1";
|
|
||||||
ZPHi = "ptr1+1";
|
|
||||||
} else if ((UsedRegs & REG_PTR2) == REG_NONE) {
|
|
||||||
ZPLo = "ptr2";
|
|
||||||
ZPHi = "ptr2+1";
|
|
||||||
} else {
|
|
||||||
/* No registers available */
|
|
||||||
ZPLo = 0;
|
|
||||||
ZPHi = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have a register, call the optimizer function */
|
/* Check the flags */
|
||||||
if (ZPLo && ZPHi) {
|
if (F->Flags & STOP_A_UNUSED) {
|
||||||
|
/* a must be unused later */
|
||||||
|
if (RegAUsed (S, I+1)) {
|
||||||
|
/* Cannot optimize */
|
||||||
|
PreCondOk = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the zero page locations to use */
|
||||||
|
if (PreCondOk) {
|
||||||
|
UsedRegs |= GetRegInfo (S, I+1, REG_SREG | REG_PTR1 | REG_PTR2);
|
||||||
|
if ((UsedRegs & REG_SREG) == REG_NONE) {
|
||||||
|
/* SREG is available */
|
||||||
|
ZPLo = "sreg";
|
||||||
|
ZPHi = "sreg+1";
|
||||||
|
} else if ((UsedRegs & REG_PTR1) == REG_NONE) {
|
||||||
|
ZPLo = "ptr1";
|
||||||
|
ZPHi = "ptr1+1";
|
||||||
|
} else if ((UsedRegs & REG_PTR2) == REG_NONE) {
|
||||||
|
ZPLo = "ptr2";
|
||||||
|
ZPHi = "ptr2+1";
|
||||||
|
} else {
|
||||||
|
/* No registers available */
|
||||||
|
PreCondOk = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If preconditions are ok, call the optimizer function */
|
||||||
|
if (PreCondOk) {
|
||||||
|
|
||||||
/* Adjust stack offsets */
|
/* Adjust stack offsets */
|
||||||
unsigned Op = I + AdjustStackOffset (S, Push, I, 2);
|
unsigned Op = I + AdjustStackOffset (S, Push, I, 2);
|
||||||
|
Loading…
Reference in New Issue
Block a user