mirror of
https://github.com/cc65/cc65.git
synced 2025-01-12 02:30:44 +00:00
Added code replacements for several missing compare functions. Fixed a bug in
coptstop.c that popped up if transfer instructions were used to load a value into X. git-svn-id: svn://svn.cc65.org/cc65/trunk@4111 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
7c613f7a83
commit
7cd92c82fa
@ -56,18 +56,21 @@ typedef enum {
|
|||||||
LI_NONE = 0x00,
|
LI_NONE = 0x00,
|
||||||
LI_DIRECT = 0x01, /* Direct op may be used */
|
LI_DIRECT = 0x01, /* Direct op may be used */
|
||||||
LI_RELOAD_Y = 0x02, /* Reload index register Y */
|
LI_RELOAD_Y = 0x02, /* Reload index register Y */
|
||||||
LI_REMOVE = 0x04, /* Load may be removed */
|
LI_TRANSFER = 0x04, /* Loaded value is transfered */
|
||||||
|
LI_REMOVE = 0x08, /* Load may be removed */
|
||||||
} LI_FLAGS;
|
} LI_FLAGS;
|
||||||
|
|
||||||
/* Structure that tells us how to load the lhs values */
|
/* Structure that tells us how to load the lhs values */
|
||||||
typedef struct LoadRegInfo LoadRegInfo;
|
typedef struct LoadRegInfo LoadRegInfo;
|
||||||
struct LoadRegInfo {
|
struct LoadRegInfo {
|
||||||
|
LI_FLAGS Flags; /* Tells us how to load */
|
||||||
int LoadIndex; /* Index of load insn, -1 if invalid */
|
int LoadIndex; /* Index of load insn, -1 if invalid */
|
||||||
CodeEntry* LoadEntry; /* The actual entry, 0 if invalid */
|
CodeEntry* LoadEntry; /* The actual entry, 0 if invalid */
|
||||||
LI_FLAGS Flags; /* Tells us how to load */
|
int XferIndex; /* Index of transfer insn */
|
||||||
|
CodeEntry* XferEntry; /* The actual transfer entry */
|
||||||
unsigned char Offs; /* Stack offset if data is on stack */
|
unsigned char Offs; /* Stack offset if data is on stack */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Now combined for both registers */
|
/* Now combined for both registers */
|
||||||
typedef struct LoadInfo LoadInfo;
|
typedef struct LoadInfo LoadInfo;
|
||||||
struct LoadInfo {
|
struct LoadInfo {
|
||||||
@ -150,6 +153,17 @@ static void ClearLoadRegInfo (LoadRegInfo* RI)
|
|||||||
/* Clear a LoadRegInfo struct */
|
/* Clear a LoadRegInfo struct */
|
||||||
{
|
{
|
||||||
RI->LoadIndex = -1;
|
RI->LoadIndex = -1;
|
||||||
|
RI->XferIndex = -1;
|
||||||
|
RI->Flags = LI_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void InvalidateLoadRegInfo (LoadRegInfo* RI)
|
||||||
|
/* Invalidate a LoadRegInfo struct */
|
||||||
|
{
|
||||||
|
RI->LoadIndex = -1;
|
||||||
|
RI->XferIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -157,13 +171,17 @@ static void ClearLoadRegInfo (LoadRegInfo* RI)
|
|||||||
static void FinalizeLoadRegInfo (LoadRegInfo* RI, CodeSeg* S)
|
static void FinalizeLoadRegInfo (LoadRegInfo* RI, CodeSeg* S)
|
||||||
/* Prepare a LoadRegInfo struct for use */
|
/* Prepare a LoadRegInfo struct for use */
|
||||||
{
|
{
|
||||||
/* Get the entry */
|
/* Get the entries */
|
||||||
if (RI->LoadIndex >= 0) {
|
if (RI->LoadIndex >= 0) {
|
||||||
RI->LoadEntry = CS_GetEntry (S, RI->LoadIndex);
|
RI->LoadEntry = CS_GetEntry (S, RI->LoadIndex);
|
||||||
} else {
|
} else {
|
||||||
RI->LoadEntry = 0;
|
RI->LoadEntry = 0;
|
||||||
}
|
}
|
||||||
RI->Flags = LI_NONE;
|
if (RI->XferIndex >= 0) {
|
||||||
|
RI->XferEntry = CS_GetEntry (S, RI->XferIndex);
|
||||||
|
} else {
|
||||||
|
RI->XferEntry = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +196,7 @@ static void ClearLoadInfo (LoadInfo* LI)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void AdjustLoadRegInfo (LoadRegInfo* RI, int DelIndex, int Change)
|
static void AdjustLoadRegInfo (LoadRegInfo* RI, int Index, int Change)
|
||||||
/* Adjust a load register info struct after deleting or inserting an entry
|
/* Adjust a load register info struct after deleting or inserting an entry
|
||||||
* with a given index
|
* with a given index
|
||||||
*/
|
*/
|
||||||
@ -186,18 +204,28 @@ static void AdjustLoadRegInfo (LoadRegInfo* RI, int DelIndex, int Change)
|
|||||||
CHECK (abs (Change) == 1);
|
CHECK (abs (Change) == 1);
|
||||||
if (Change < 0) {
|
if (Change < 0) {
|
||||||
/* Deletion */
|
/* Deletion */
|
||||||
if (DelIndex < RI->LoadIndex) {
|
if (Index < RI->LoadIndex) {
|
||||||
--RI->LoadIndex;
|
--RI->LoadIndex;
|
||||||
} else if (DelIndex == RI->LoadIndex) {
|
} else if (Index == RI->LoadIndex) {
|
||||||
/* Has been removed */
|
/* Has been removed */
|
||||||
RI->LoadIndex = -1;
|
RI->LoadIndex = -1;
|
||||||
RI->LoadEntry = 0;
|
RI->LoadEntry = 0;
|
||||||
}
|
}
|
||||||
|
if (Index < RI->XferIndex) {
|
||||||
|
--RI->XferIndex;
|
||||||
|
} else if (Index == RI->XferIndex) {
|
||||||
|
/* Has been removed */
|
||||||
|
RI->XferIndex = -1;
|
||||||
|
RI->XferEntry = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Insertion */
|
/* Insertion */
|
||||||
if (DelIndex <= RI->LoadIndex) {
|
if (Index <= RI->LoadIndex) {
|
||||||
++RI->LoadIndex;
|
++RI->LoadIndex;
|
||||||
}
|
}
|
||||||
|
if (Index <= RI->XferIndex) {
|
||||||
|
++RI->XferIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,12 +242,12 @@ static void FinalizeLoadInfo (LoadInfo* LI, CodeSeg* S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void AdjustLoadInfo (LoadInfo* LI, int DelIndex, int Change)
|
static void AdjustLoadInfo (LoadInfo* LI, int Index, int Change)
|
||||||
/* Adjust a load info struct after deleting entry with a given index */
|
/* Adjust a load info struct after deleting entry with a given index */
|
||||||
{
|
{
|
||||||
AdjustLoadRegInfo (&LI->A, DelIndex, Change);
|
AdjustLoadRegInfo (&LI->A, Index, Change);
|
||||||
AdjustLoadRegInfo (&LI->X, DelIndex, Change);
|
AdjustLoadRegInfo (&LI->X, Index, Change);
|
||||||
AdjustLoadRegInfo (&LI->Y, DelIndex, Change);
|
AdjustLoadRegInfo (&LI->Y, Index, Change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -230,35 +258,53 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I)
|
|||||||
if (E->Info & OF_LOAD) {
|
if (E->Info & OF_LOAD) {
|
||||||
if (E->Chg & REG_A) {
|
if (E->Chg & REG_A) {
|
||||||
LI->A.LoadIndex = I;
|
LI->A.LoadIndex = I;
|
||||||
|
LI->A.XferIndex = -1;
|
||||||
}
|
}
|
||||||
if (E->Chg & REG_X) {
|
if (E->Chg & REG_X) {
|
||||||
LI->X.LoadIndex = I;
|
LI->X.LoadIndex = I;
|
||||||
|
LI->X.XferIndex = -1;
|
||||||
}
|
}
|
||||||
if (E->Chg & REG_Y) {
|
if (E->Chg & REG_Y) {
|
||||||
LI->Y.LoadIndex = I;
|
LI->Y.LoadIndex = I;
|
||||||
|
LI->Y.XferIndex = -1;
|
||||||
}
|
}
|
||||||
} else if (E->Info & OF_XFR) {
|
} else if (E->Info & OF_XFR) {
|
||||||
switch (E->OPC) {
|
switch (E->OPC) {
|
||||||
case OP65_TAX: LI->X.LoadIndex = LI->A.LoadIndex; break;
|
case OP65_TAX:
|
||||||
case OP65_TAY: LI->Y.LoadIndex = LI->A.LoadIndex; break;
|
LI->X.LoadIndex = LI->A.LoadIndex;
|
||||||
case OP65_TXA: LI->A.LoadIndex = LI->X.LoadIndex; break;
|
LI->X.XferIndex = I;
|
||||||
case OP65_TYA: LI->A.LoadIndex = LI->Y.LoadIndex; break;
|
break;
|
||||||
default: break;
|
case OP65_TAY:
|
||||||
|
LI->Y.LoadIndex = LI->A.LoadIndex;
|
||||||
|
LI->Y.XferIndex = I;
|
||||||
|
break;
|
||||||
|
case OP65_TXA:
|
||||||
|
LI->A.LoadIndex = LI->X.LoadIndex;
|
||||||
|
LI->A.XferIndex = I;
|
||||||
|
break;
|
||||||
|
case OP65_TYA:
|
||||||
|
LI->A.LoadIndex = LI->Y.LoadIndex;
|
||||||
|
LI->A.XferIndex = I;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (CE_IsCallTo (E, "ldaxysp")) {
|
} else if (CE_IsCallTo (E, "ldaxysp")) {
|
||||||
/* Both registers set, Y changed */
|
/* Both registers set, Y changed */
|
||||||
LI->A.LoadIndex = I;
|
LI->A.LoadIndex = I;
|
||||||
LI->X.LoadIndex = I;
|
LI->A.XferIndex = -1;
|
||||||
LI->Y.LoadIndex = -1;
|
LI->X.LoadIndex = I;
|
||||||
|
LI->X.XferIndex = -1;
|
||||||
|
InvalidateLoadRegInfo (&LI->Y);
|
||||||
} else {
|
} else {
|
||||||
if (E->Chg & REG_A) {
|
if (E->Chg & REG_A) {
|
||||||
LI->A.LoadIndex = -1;
|
InvalidateLoadRegInfo (&LI->A);
|
||||||
}
|
}
|
||||||
if (E->Chg & REG_X) {
|
if (E->Chg & REG_X) {
|
||||||
LI->X.LoadIndex = -1;
|
InvalidateLoadRegInfo (&LI->X);
|
||||||
}
|
}
|
||||||
if (E->Chg & REG_Y) {
|
if (E->Chg & REG_Y) {
|
||||||
LI->Y.LoadIndex = -1;
|
InvalidateLoadRegInfo (&LI->Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,88 +317,6 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void AdjustStackOffset (StackOpData* D, unsigned Offs)
|
|
||||||
/* Adjust the offset for all stack accesses in the range PushIndex to OpIndex.
|
|
||||||
* OpIndex is adjusted according to the insertions.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
/* Walk over all entries */
|
|
||||||
int I = D->PushIndex + 1;
|
|
||||||
while (I < D->OpIndex) {
|
|
||||||
|
|
||||||
CodeEntry* E = CS_GetEntry (D->Code, I);
|
|
||||||
|
|
||||||
int NeedCorrection = 0;
|
|
||||||
if ((E->Use & REG_SP) != 0) {
|
|
||||||
|
|
||||||
/* Check for some things that should not happen */
|
|
||||||
CHECK (E->AM == AM65_ZP_INDY || E->RI->In.RegY >= (short) Offs);
|
|
||||||
CHECK (strcmp (E->Arg, "sp") == 0);
|
|
||||||
|
|
||||||
/* We need to correct this one */
|
|
||||||
NeedCorrection = 1;
|
|
||||||
|
|
||||||
} else if (CE_IsCallTo (E, "ldaxysp")) {
|
|
||||||
|
|
||||||
/* We need to correct this one */
|
|
||||||
NeedCorrection = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NeedCorrection) {
|
|
||||||
|
|
||||||
/* Get the code entry before this one. If it's a LDY, adjust the
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
CodeEntry* P = CS_GetPrevEntry (D->Code, I);
|
|
||||||
if (P && P->OPC == OP65_LDY && CE_IsConstImm (P)) {
|
|
||||||
|
|
||||||
/* The Y load is just before the stack access, adjust it */
|
|
||||||
CE_SetNumArg (P, P->Num - Offs);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Insert a new load instruction before the stack access */
|
|
||||||
const char* Arg = MakeHexArg (E->RI->In.RegY - Offs);
|
|
||||||
CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
|
|
||||||
CS_InsertEntry (D->Code, X, I++);
|
|
||||||
|
|
||||||
/* One more inserted entries */
|
|
||||||
++D->OpIndex;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we need the value of Y later, be sure to reload it */
|
|
||||||
if (RegYUsed (D->Code, I+1)) {
|
|
||||||
const char* Arg = MakeHexArg (E->RI->In.RegY);
|
|
||||||
CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
|
|
||||||
CS_InsertEntry (D->Code, X, I+1);
|
|
||||||
|
|
||||||
/* One more inserted entries */
|
|
||||||
++D->OpIndex;
|
|
||||||
|
|
||||||
/* Skip this instruction in the next round */
|
|
||||||
++I;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next entry */
|
|
||||||
++I;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have rhs load insns that load from stack, we'll have to adjust
|
|
||||||
* the offsets for these also.
|
|
||||||
*/
|
|
||||||
if (D->Rhs.A.Flags & LI_RELOAD_Y) {
|
|
||||||
D->Rhs.A.Offs -= Offs;
|
|
||||||
}
|
|
||||||
if (D->Rhs.X.Flags & LI_RELOAD_Y) {
|
|
||||||
D->Rhs.X.Offs -= Offs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void InsertEntry (StackOpData* D, CodeEntry* E, int Index)
|
static void InsertEntry (StackOpData* D, CodeEntry* E, int Index)
|
||||||
/* Insert a new entry. Depending on Index, D->PushIndex and D->OpIndex will
|
/* Insert a new entry. Depending on Index, D->PushIndex and D->OpIndex will
|
||||||
* be adjusted by this function.
|
* be adjusted by this function.
|
||||||
@ -403,6 +367,82 @@ static void DelEntry (StackOpData* D, int Index)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void AdjustStackOffset (StackOpData* D, unsigned Offs)
|
||||||
|
/* Adjust the offset for all stack accesses in the range PushIndex to OpIndex.
|
||||||
|
* OpIndex is adjusted according to the insertions.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Walk over all entries */
|
||||||
|
int I = D->PushIndex + 1;
|
||||||
|
while (I < D->OpIndex) {
|
||||||
|
|
||||||
|
CodeEntry* E = CS_GetEntry (D->Code, I);
|
||||||
|
|
||||||
|
int NeedCorrection = 0;
|
||||||
|
if ((E->Use & REG_SP) != 0) {
|
||||||
|
|
||||||
|
/* Check for some things that should not happen */
|
||||||
|
CHECK (E->AM == AM65_ZP_INDY || E->RI->In.RegY >= (short) Offs);
|
||||||
|
CHECK (strcmp (E->Arg, "sp") == 0);
|
||||||
|
|
||||||
|
/* We need to correct this one */
|
||||||
|
NeedCorrection = 1;
|
||||||
|
|
||||||
|
} else if (CE_IsCallTo (E, "ldaxysp")) {
|
||||||
|
|
||||||
|
/* We need to correct this one */
|
||||||
|
NeedCorrection = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NeedCorrection) {
|
||||||
|
|
||||||
|
/* Get the code entry before this one. If it's a LDY, adjust the
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
CodeEntry* P = CS_GetPrevEntry (D->Code, I);
|
||||||
|
if (P && P->OPC == OP65_LDY && CE_IsConstImm (P)) {
|
||||||
|
|
||||||
|
/* The Y load is just before the stack access, adjust it */
|
||||||
|
CE_SetNumArg (P, P->Num - Offs);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Insert a new load instruction before the stack access */
|
||||||
|
const char* Arg = MakeHexArg (E->RI->In.RegY - Offs);
|
||||||
|
CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
|
||||||
|
InsertEntry (D, X, I++);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we need the value of Y later, be sure to reload it */
|
||||||
|
if (RegYUsed (D->Code, I+1)) {
|
||||||
|
const char* Arg = MakeHexArg (E->RI->In.RegY);
|
||||||
|
CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
|
||||||
|
InsertEntry (D, X, I+1);
|
||||||
|
|
||||||
|
/* Skip this instruction in the next round */
|
||||||
|
++I;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next entry */
|
||||||
|
++I;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have rhs load insns that load from stack, we'll have to adjust
|
||||||
|
* the offsets for these also.
|
||||||
|
*/
|
||||||
|
if (D->Rhs.A.Flags & LI_RELOAD_Y) {
|
||||||
|
D->Rhs.A.Offs -= Offs;
|
||||||
|
}
|
||||||
|
if (D->Rhs.X.Flags & LI_RELOAD_Y) {
|
||||||
|
D->Rhs.X.Offs -= Offs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void CheckOneDirectOp (LoadRegInfo* LI, unsigned char Offs)
|
static void CheckOneDirectOp (LoadRegInfo* LI, unsigned char Offs)
|
||||||
/* Check if the given entry is a lda instruction with an addressing mode
|
/* Check if the given entry is a lda instruction with an addressing mode
|
||||||
* that allows us to replace it by another operation (like ora). If so, we may
|
* that allows us to replace it by another operation (like ora). If so, we may
|
||||||
@ -616,11 +656,21 @@ static void RemoveRegLoads (StackOpData* D, LoadInfo* LI)
|
|||||||
/* Both registers may be loaded with one insn, but DelEntry will in this
|
/* Both registers may be loaded with one insn, but DelEntry will in this
|
||||||
* case clear the other one.
|
* case clear the other one.
|
||||||
*/
|
*/
|
||||||
if (LI->A.LoadIndex >= 0 && (LI->A.Flags & LI_REMOVE)) {
|
if (LI->A.Flags & LI_REMOVE) {
|
||||||
DelEntry (D, LI->A.LoadIndex);
|
if (LI->A.LoadIndex >= 0) {
|
||||||
|
DelEntry (D, LI->A.LoadIndex);
|
||||||
|
}
|
||||||
|
if (LI->A.XferIndex >= 0) {
|
||||||
|
DelEntry (D, LI->A.XferIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (LI->X.LoadIndex >= 0 && (LI->X.Flags & LI_REMOVE)) {
|
if (LI->X.Flags & LI_REMOVE) {
|
||||||
DelEntry (D, LI->X.LoadIndex);
|
if (LI->X.LoadIndex >= 0) {
|
||||||
|
DelEntry (D, LI->X.LoadIndex);
|
||||||
|
}
|
||||||
|
if (LI->X.XferIndex >= 0) {
|
||||||
|
DelEntry (D, LI->X.XferIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1344,6 +1394,99 @@ static unsigned Opt_tosugeax (StackOpData* D)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned Opt_tosugtax (StackOpData* D)
|
||||||
|
/* Optimize the tosugtax sequence */
|
||||||
|
{
|
||||||
|
CodeEntry* X;
|
||||||
|
|
||||||
|
|
||||||
|
/* Inline the sbc */
|
||||||
|
D->IP = D->OpIndex+1;
|
||||||
|
|
||||||
|
/* Must be true because of OP_RHS_LOAD */
|
||||||
|
CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0);
|
||||||
|
|
||||||
|
/* Add code for low operand */
|
||||||
|
AddOpLow (D, OP65_CMP, &D->Rhs);
|
||||||
|
|
||||||
|
/* Add code for high operand */
|
||||||
|
AddOpHigh (D, OP65_SBC, &D->Rhs, 0);
|
||||||
|
|
||||||
|
/* Transform to boolean */
|
||||||
|
X = NewCodeEntry (OP65_JSR, AM65_ABS, "boolugt", 0, D->OpEntry->LI);
|
||||||
|
InsertEntry (D, X, D->IP++);
|
||||||
|
|
||||||
|
/* Remove the push and the call to the operator function */
|
||||||
|
RemoveRemainders (D);
|
||||||
|
|
||||||
|
/* We changed the sequence */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned Opt_tosuleax (StackOpData* D)
|
||||||
|
/* Optimize the tosuleax sequence */
|
||||||
|
{
|
||||||
|
CodeEntry* X;
|
||||||
|
|
||||||
|
|
||||||
|
/* Inline the sbc */
|
||||||
|
D->IP = D->OpIndex+1;
|
||||||
|
|
||||||
|
/* Must be true because of OP_RHS_LOAD */
|
||||||
|
CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0);
|
||||||
|
|
||||||
|
/* Add code for low operand */
|
||||||
|
AddOpLow (D, OP65_CMP, &D->Rhs);
|
||||||
|
|
||||||
|
/* Add code for high operand */
|
||||||
|
AddOpHigh (D, OP65_SBC, &D->Rhs, 0);
|
||||||
|
|
||||||
|
/* Transform to boolean */
|
||||||
|
X = NewCodeEntry (OP65_JSR, AM65_ABS, "boolule", 0, D->OpEntry->LI);
|
||||||
|
InsertEntry (D, X, D->IP++);
|
||||||
|
|
||||||
|
/* Remove the push and the call to the operator function */
|
||||||
|
RemoveRemainders (D);
|
||||||
|
|
||||||
|
/* We changed the sequence */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned Opt_tosultax (StackOpData* D)
|
||||||
|
/* Optimize the tosultax sequence */
|
||||||
|
{
|
||||||
|
CodeEntry* X;
|
||||||
|
|
||||||
|
|
||||||
|
/* Inline the sbc */
|
||||||
|
D->IP = D->OpIndex+1;
|
||||||
|
|
||||||
|
/* Must be true because of OP_RHS_LOAD */
|
||||||
|
CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0);
|
||||||
|
|
||||||
|
/* Add code for low operand */
|
||||||
|
AddOpLow (D, OP65_CMP, &D->Rhs);
|
||||||
|
|
||||||
|
/* Add code for high operand */
|
||||||
|
AddOpHigh (D, OP65_SBC, &D->Rhs, 0);
|
||||||
|
|
||||||
|
/* Transform to boolean */
|
||||||
|
X = NewCodeEntry (OP65_JSR, AM65_ABS, "boolult", 0, D->OpEntry->LI);
|
||||||
|
InsertEntry (D, X, D->IP++);
|
||||||
|
|
||||||
|
/* Remove the push and the call to the operator function */
|
||||||
|
RemoveRemainders (D);
|
||||||
|
|
||||||
|
/* We changed the sequence */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned Opt_tosxorax (StackOpData* D)
|
static unsigned Opt_tosxorax (StackOpData* D)
|
||||||
/* Optimize the tosxorax sequence */
|
/* Optimize the tosxorax sequence */
|
||||||
{
|
{
|
||||||
@ -1397,6 +1540,9 @@ static const OptFuncDesc FuncTable[] = {
|
|||||||
{ "tosorax", Opt_tosorax, REG_NONE, OP_NONE },
|
{ "tosorax", Opt_tosorax, REG_NONE, OP_NONE },
|
||||||
{ "tossubax", Opt_tossubax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
{ "tossubax", Opt_tossubax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
||||||
{ "tosugeax", Opt_tosugeax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
{ "tosugeax", Opt_tosugeax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
||||||
|
{ "tosugtax", Opt_tosugtax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
||||||
|
{ "tosuleax", Opt_tosuleax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
||||||
|
{ "tosultax", Opt_tosultax, REG_NONE, OP_RHS_LOAD_DIRECT },
|
||||||
{ "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE },
|
{ "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE },
|
||||||
};
|
};
|
||||||
#define FUNC_COUNT (sizeof(FuncTable) / sizeof(FuncTable[0]))
|
#define FUNC_COUNT (sizeof(FuncTable) / sizeof(FuncTable[0]))
|
||||||
@ -1715,6 +1861,12 @@ unsigned OptStackOps (CodeSeg* S)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare the remainder of the data structure. */
|
||||||
|
Data.PrevEntry = CS_GetPrevEntry (S, Data.PushIndex);
|
||||||
|
Data.PushEntry = CS_GetEntry (S, Data.PushIndex);
|
||||||
|
Data.OpEntry = CS_GetEntry (S, Data.OpIndex);
|
||||||
|
Data.NextEntry = CS_GetNextEntry (S, Data.OpIndex);
|
||||||
|
|
||||||
/* Adjust stack offsets to account for the upcoming removal */
|
/* Adjust stack offsets to account for the upcoming removal */
|
||||||
AdjustStackOffset (&Data, 2);
|
AdjustStackOffset (&Data, 2);
|
||||||
|
|
||||||
@ -1723,12 +1875,6 @@ unsigned OptStackOps (CodeSeg* S)
|
|||||||
*/
|
*/
|
||||||
CS_GenRegInfo (S);
|
CS_GenRegInfo (S);
|
||||||
|
|
||||||
/* Prepare the remainder of the data structure. */
|
|
||||||
Data.PrevEntry = CS_GetPrevEntry (S, Data.PushIndex);
|
|
||||||
Data.PushEntry = CS_GetEntry (S, Data.PushIndex);
|
|
||||||
Data.OpEntry = CS_GetEntry (S, Data.OpIndex);
|
|
||||||
Data.NextEntry = CS_GetNextEntry (S, Data.OpIndex);
|
|
||||||
|
|
||||||
/* Call the optimizer function */
|
/* Call the optimizer function */
|
||||||
Changes += Data.OptFunc->Func (&Data);
|
Changes += Data.OptFunc->Func (&Data);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user