1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-16 13:31:16 +00:00

More source splitting.

Remove the -Wno-unused-parameter in favour of __atribute__((unused)).


git-svn-id: svn://svn.cc65.org/cc65/trunk@986 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-09-30 21:56:45 +00:00
parent 0a6895ca05
commit c8415fc17c
11 changed files with 753 additions and 516 deletions

View File

@ -190,7 +190,7 @@ static void ParseWordArg (StrBuf* T, unsigned Arg)
static void ParseLongArg (StrBuf* T, unsigned Arg)
static void ParseLongArg (StrBuf* T, unsigned Arg attribute ((unused)))
/* Parse the %l format specifier */
{
ExprDesc Expr;

View File

@ -752,23 +752,15 @@ void g_getlocal (unsigned flags, int offs)
AddCodeLine ("dey");
AddCodeLine ("lda (sp),y");
} else {
if (offs) {
ldyconst (offs+1);
AddCodeLine ("jsr ldaxysp");
} else {
AddCodeLine ("jsr ldax0sp");
}
ldyconst (offs+1);
AddCodeLine ("jsr ldaxysp");
}
}
break;
case CF_LONG:
if (offs) {
ldyconst (offs+3);
AddCodeLine ("jsr ldeaxysp");
} else {
AddCodeLine ("jsr ldeax0sp");
}
ldyconst (offs+3);
AddCodeLine ("jsr ldeaxysp");
break;
default:
@ -812,22 +804,14 @@ void g_getind (unsigned flags, unsigned offs)
AddCodeLine ("iny");
AddCodeLine ("ora (ptr1),y");
} else {
if (offs == 0) {
AddCodeLine ("jsr ldaxi");
} else {
ldyconst (offs+1);
AddCodeLine ("jsr ldaxidx");
}
ldyconst (offs+1);
AddCodeLine ("jsr ldaxidx");
}
break;
case CF_LONG:
if (offs == 0) {
AddCodeLine ("jsr ldeaxi");
} else {
ldyconst (offs+3);
AddCodeLine ("jsr ldeaxidx");
}
ldyconst (offs+3);
AddCodeLine ("jsr ldeaxidx");
if (flags & CF_TEST) {
AddCodeLine ("jsr tsteax");
}
@ -1034,12 +1018,8 @@ void g_putlocal (unsigned Flags, int Offs, long Val)
if (Flags & CF_CONST) {
g_getimmed (Flags, Val, 0);
}
if (Offs) {
ldyconst (Offs);
AddCodeLine ("jsr steaxysp");
} else {
AddCodeLine ("jsr steax0sp");
}
ldyconst (Offs);
AddCodeLine ("jsr steaxysp");
break;
default:
@ -1527,28 +1507,6 @@ void g_addstatic (unsigned flags, unsigned long label, unsigned offs)
/*****************************************************************************/
/* Compares of ax with a variable with fixed address */
/*****************************************************************************/
void g_cmplocal (unsigned flags, int offs)
/* Compare a local variable to ax */
{
Internal ("g_cmplocal not implemented");
}
void g_cmpstatic (unsigned flags, unsigned label, unsigned offs)
/* Compare a static variable to ax */
{
Internal ("g_cmpstatic not implemented");
}
/*****************************************************************************/
/* Special op= functions */
/*****************************************************************************/
@ -1728,12 +1686,8 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
if (flags & CF_CONST) {
g_getimmed (flags, val, 0);
}
if (offs == 0) {
AddCodeLine ("jsr laddeq0sp");
} else {
ldyconst (offs);
AddCodeLine ("jsr laddeqysp");
}
ldyconst (offs);
AddCodeLine ("jsr laddeqysp");
break;
default:
@ -1881,12 +1835,8 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs,
AddCodeLine ("ldy #<(%s)", lbuf);
AddCodeLine ("sty ptr1");
AddCodeLine ("ldy #>(%s+1)", lbuf);
if (val == 1) {
AddCodeLine ("jsr lsubeq1");
} else {
AddCodeLine ("lda #$%02X", (unsigned char)val);
AddCodeLine ("jsr lsubeqa");
}
AddCodeLine ("lda #$%02X", (unsigned char)val);
AddCodeLine ("jsr lsubeqa");
} else {
g_getstatic (flags, label, offs);
g_dec (flags, val);
@ -1945,24 +1895,16 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val)
if (flags & CF_CONST) {
g_getimmed (flags, val, 0);
}
if (offs == 0) {
AddCodeLine ("jsr subeq0sp");
} else {
ldyconst (offs);
AddCodeLine ("jsr subeqysp");
}
ldyconst (offs);
AddCodeLine ("jsr subeqysp");
break;
case CF_LONG:
if (flags & CF_CONST) {
g_getimmed (flags, val, 0);
}
if (offs == 0) {
AddCodeLine ("jsr lsubeq0sp");
} else {
ldyconst (offs);
AddCodeLine ("jsr lsubeqysp");
}
ldyconst (offs);
AddCodeLine ("jsr lsubeqysp");
break;
default:
@ -2037,7 +1979,7 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
void g_addaddr_local (unsigned flags, int offs)
void g_addaddr_local (unsigned flags attribute ((unused)), int offs)
/* Add the address of a local variable to ax */
{
unsigned L = 0;
@ -2281,36 +2223,20 @@ void g_test (unsigned flags)
void g_push (unsigned flags, unsigned long val)
/* Push the primary register or a constant value onto the stack */
{
unsigned char hi;
if (flags & CF_CONST && (flags & CF_TYPE) != CF_LONG) {
/* We have a constant 8 or 16 bit value */
if ((flags & CF_TYPE) == CF_CHAR && (flags & CF_FORCECHAR)) {
/* Handle as 8 bit value */
if (CodeSizeFactor >= 165 || val > 2) {
ldaconst (val);
AddCodeLine ("jsr pusha");
} else {
AddCodeLine ("jsr pushc%d", (int) val);
}
ldaconst (val);
AddCodeLine ("jsr pusha");
} else {
/* Handle as 16 bit value */
hi = (unsigned char) (val >> 8);
if (val <= 7) {
AddCodeLine ("jsr push%u", (unsigned) val);
} else if (hi == 0 || hi == 0xFF) {
/* Use special function */
ldaconst (val);
AddCodeLine ("jsr %s", (hi == 0)? "pusha0" : "pushaFF");
} else {
/* Long way ... */
g_getimmed (flags, val, 0);
AddCodeLine ("jsr pushax");
}
g_getimmed (flags, val, 0);
AddCodeLine ("jsr pushax");
}
} else {
@ -2475,7 +2401,7 @@ void g_case (unsigned flags, unsigned label, unsigned long val)
void g_truejump (unsigned flags, unsigned label)
void g_truejump (unsigned flags attribute ((unused)), unsigned label)
/* Jump to label if zero flag clear */
{
AddCodeLine ("jne %s", LocalLabelName (label));
@ -2483,7 +2409,7 @@ void g_truejump (unsigned flags, unsigned label)
void g_falsejump (unsigned flags, unsigned label)
void g_falsejump (unsigned flags attribute ((unused)), unsigned label)
/* Jump to label if zero flag set */
{
AddCodeLine ("jeq %s", LocalLabelName (label));

View File

@ -50,6 +50,7 @@
#include "coptadd.h"
#include "coptcmp.h"
#include "coptind.h"
#include "coptneg.h"
#include "coptstop.h"
#include "coptsub.h"
#include "copttest.h"
@ -114,383 +115,6 @@ static unsigned OptShift1 (CodeSeg* S)
/*****************************************************************************/
/* nega optimizations */
/*****************************************************************************/
static unsigned OptNegA1 (CodeSeg* S)
/* Check for
*
* ldx #$00
* lda ..
* jsr bnega
*
* Remove the ldx if the lda does not use it.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for a ldx */
if (E->OPC == OP65_LDX &&
E->AM == AM65_IMM &&
(E->Flags & CEF_NUMARG) != 0 &&
E->Num == 0 &&
CS_GetEntries (S, L, I+1, 2) &&
L[0]->OPC == OP65_LDA &&
(L[0]->Use & REG_X) == 0 &&
!CE_HasLabel (L[0]) &&
CE_IsCall (L[1], "bnega") &&
!CE_HasLabel (L[1])) {
/* Remove the ldx instruction */
CS_DelEntry (S, I);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegA2 (CodeSeg* S)
/* Check for
*
* lda ..
* jsr bnega
* jeq/jne ..
*
* Adjust the conditional branch and remove the call to the subroutine.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if ((E->OPC == OP65_ADC ||
E->OPC == OP65_AND ||
E->OPC == OP65_DEA ||
E->OPC == OP65_EOR ||
E->OPC == OP65_INA ||
E->OPC == OP65_LDA ||
E->OPC == OP65_ORA ||
E->OPC == OP65_PLA ||
E->OPC == OP65_SBC ||
E->OPC == OP65_TXA ||
E->OPC == OP65_TYA) &&
CS_GetEntries (S, L, I+1, 2) &&
CE_IsCall (L[0], "bnega") &&
!CE_HasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[1])) {
/* Invert the branch */
CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* Delete the subroutine call */
CS_DelEntry (S, I+1);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* negax optimizations */
/*****************************************************************************/
static unsigned OptNegAX1 (CodeSeg* S)
/* On a call to bnegax, if X is zero, the result depends only on the value in
* A, so change the call to a call to bnega. This will get further optimized
* later if possible.
*/
{
unsigned Changes = 0;
unsigned I;
/* Generate register info for this step */
CS_GenRegInfo (S);
/* Walk over the entries */
I = 0;
while (I < CS_GetEntryCount (S)) {
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check if this is a call to bnegax, and if X is known and zero */
if (E->RI->In.RegX == 0 &&
CE_IsCall (E, "bnegax")) {
/* We're cheating somewhat here ... */
E->Arg[5] = '\0';
E->Use &= ~REG_X;
/* We had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Free register info */
CS_FreeRegInfo (S);
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegAX2 (CodeSeg* S)
/* Search for the sequence:
*
* lda (xx),y
* tax
* dey
* lda (xx),y
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda (xx),y
* dey
* ora (xx),y
* jeq/jne ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[5];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if (E->OPC == OP65_LDA &&
E->AM == AM65_ZP_INDY &&
CS_GetEntries (S, L, I+1, 5) &&
L[0]->OPC == OP65_TAX &&
L[1]->OPC == OP65_DEY &&
L[2]->OPC == OP65_LDA &&
L[2]->AM == AM65_ZP_INDY &&
strcmp (L[2]->Arg, E->Arg) == 0 &&
!CE_HasLabel (L[2]) &&
CE_IsCall (L[3], "bnegax") &&
!CE_HasLabel (L[3]) &&
(L[4]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[4])) {
/* lda --> ora */
CE_ReplaceOPC (L[2], OP65_ORA);
/* Invert the branch */
CE_ReplaceOPC (L[4], GetInverseBranch (L[4]->OPC));
/* Delete the entries no longer needed. Beware: Deleting entries
* will change the indices.
*/
CS_DelEntry (S, I+4); /* jsr bnegax */
CS_DelEntry (S, I+1); /* tax */
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegAX3 (CodeSeg* S)
/* Search for the sequence:
*
* lda xx
* ldx yy
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda xx
* ora xx+1
* jeq/jne ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[3];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if (E->OPC == OP65_LDA &&
CS_GetEntries (S, L, I+1, 3) &&
L[0]->OPC == OP65_LDX &&
!CE_HasLabel (L[0]) &&
CE_IsCall (L[1], "bnegax") &&
!CE_HasLabel (L[1]) &&
(L[2]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[2])) {
/* ldx --> ora */
CE_ReplaceOPC (L[0], OP65_ORA);
/* Invert the branch */
CE_ReplaceOPC (L[2], GetInverseBranch (L[2]->OPC));
/* Delete the subroutine call */
CS_DelEntry (S, I+2);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegAX4 (CodeSeg* S)
/* Search for the sequence:
*
* jsr xxx
* jsr bnega(x)
* jeq/jne ...
*
* and replace it by:
*
* jsr xxx
* <boolean test>
* jne/jeq ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if (E->OPC == OP65_JSR &&
CS_GetEntries (S, L, I+1, 2) &&
L[0]->OPC == OP65_JSR &&
strncmp (L[0]->Arg,"bnega",5) == 0 &&
!CE_HasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[1])) {
CodeEntry* X;
/* Check if we're calling bnega or bnegax */
int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
/* Insert apropriate test code */
if (ByteSized) {
/* Test bytes */
X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[0]->LI);
CS_InsertEntry (S, X, I+2);
} else {
/* Test words */
X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI);
CS_InsertEntry (S, X, I+2);
X = NewCodeEntry (OP65_ORA, AM65_ZP, "tmp1", 0, L[0]->LI);
CS_InsertEntry (S, X, I+3);
}
/* Delete the subroutine call */
CS_DelEntry (S, I+1);
/* Invert the branch */
CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* Optimize stores through pointers */
/*****************************************************************************/
@ -1403,7 +1027,118 @@ static unsigned OptDecouple (CodeSeg* S)
static unsigned OptSize (CodeSeg* S)
static unsigned OptSize1 (CodeSeg* S)
/* Do size optimization by calling special subroutines that preload registers.
* This routine does not work standalone, it needs a following register load
* removal pass.
*/
{
#if 0
static const char* Func = {
"stax0sp", /* staxysp, y = 0 */
"addeq0sp",
"ldax0sp", /* ldaxysp, y = 1 */
"ldeax0sp", /* ldeaxysp, y = 3 */
"push0", /* pushax, a = 0, x = 0 */
"pusha0", /* pushax, x = 0 */
"pushaFF", /* pushax, x = ff */
"pusha0sp", /* pushaysp, y = 0 */
"tosadda0", /* tosaddax, x = 0 */
"tosanda0", /* tosandax, x = 0 */
"tosdiva0", /* tosdivax, x = 0 */
"toseqa0", /* toseqax, x = 0 */
"tosgea0", /* tosgeax, x = 0 */
"tosgta0", /* tosgtax, x = 0 */
"tosadd0ax", /* tosaddeax, sreg = 0 */
"laddeqa", /* laddeq, sreg = 0, x = 0 */
"laddeq1", /* laddeq, sreg = 0, x = 0, a = 1 */
"laddeq0sp", /* laddeqysp, y = 0 */
"tosand0ax", /* tosandeax, sreg = 0 */
"ldaxi", /* ldaxidx, y = 1 */
"ldeaxi", /* ldeaxidx, y = 3 */
"ldeax0sp", /* ldeaxysp, y = 3 */
"tosdiv0ax", /* tosdiveax, sreg = 0 */
"toslea0", /* tosleax, x = 0 */
"tosmod0ax", /* tosmodeax, sreg = 0 */
"tosmul0ax", /* tosmuleax, sreg = 0 */
"tosumul0ax", /* tosumuleax, sreg = 0 */
"tosor0ax", /* tosoreax, sreg = 0 */
"push0ax", /* pusheax, sreg = 0 */
"tosrsub0ax", /* tosrsubeax, sreg = 0 */
"tosshl0ax", /* tosshleax, sreg = 0 */
"tosasl0ax", /* tosasleax, sreg = 0 */
"tosshr0ax", /* tosshreax, sreg = 0 */
"tosasr0ax", /* tosasreax, sreg = 0 */
"tossub0ax", /* tossubeax, sreg = 0 */
"lsubeqa", /* lsubeq, sreg = 0, x = 0 */
"lsubeq1", /* lsubeq, sreg = 0, x = 0, a = 1 */
"lsubeq0sp", /* lsubeqysp, y = 0 */
"toslta0", /* tosltax, x = 0 */
"tosudiv0ax", /* tosudiveax, sreg = 0 */
"tosumod0ax", /* tosumodeax, sreg = 0 */
"tosxor0ax", /* tosxoreax, sreg = 0 */
"tosmoda0", /* tosmodax, x = 0 */
"tosmula0", /* tosmulax, x = 0 */
"tosumula0", /* tosumulax, x = 0 */
"tosnea0", /* tosneax, x = 0 */
"tosora0", /* tosorax, x = 0 */
"push1", /* pushax, x = 0, a = 1 */
"push2", /* pushax, x = 0, a = 2 */
"push3", /* pushax, x = 0, a = 3 */
"push4", /* pushax, x = 0, a = 4 */
"push5", /* pushax, x = 0, a = 5 */
"push6", /* pushax, x = 0, a = 6 */
"push7", /* pushax, x = 0, a = 7 */
"pushc0", /* pusha, a = 0 */
"pushc1", /* pusha, a = 1 */
"pushc2", /* pusha, a = 2 */
"tosrsuba0", /* tosrsubax, x = 0 */
"tosshla0", /* tosshlax, x = 0 */
"tosasla0", /* tosaslax, x = 0 */
"tosshra0", /* tosshrax, x = 0 */
"tosasra0", /* tosasrax, x = 0 */
"steax0sp", /* steaxsp, y = 0 */
"tossuba0", /* tossubax, x = 0 */
"subeq0sp", /* subeqysp, y = 0 */
"tosudiva0", /* tosudivax, x = 0 */
"tosugea0", /* tosugeax, x = 0 */
"tosugta0", /* tosugtax, x = 0 */
"tosulea0", /* tosuleax, x = 0 */
"tosulta0", /* tosultax, x = 0 */
"tosumoda0", /* tosumodax, x = 0 */
"tosxora0", /* tosxorax, x = 0 */
};
#endif
unsigned Changes = 0;
unsigned I;
/* Generate register info for the following step */
CS_GenRegInfo (S);
/* Walk over the entries */
I = 0;
while (I < CS_GetEntryCount (S)) {
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Next entry */
++I;
}
/* Free register info */
CS_FreeRegInfo (S);
/* Return the number of changes made */
return Changes;
}
static unsigned OptSize2 (CodeSeg* S)
/* Do size optimization by using shorter code sequences, even if this
* introduces relations between instructions. This step must be one of the
* last steps, because it makes further work much more difficult.
@ -1443,7 +1178,7 @@ static unsigned OptSize (CodeSeg* S)
X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
}
}
}
}
break;
case OP65_LDX:
@ -1564,7 +1299,8 @@ static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 0, 0, 0, 0
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 0, 0, 0, 0, 0 };
static OptFunc DOptShift1 = { OptShift1, "OptShift1", 0, 0, 0, 0, 0 };
static OptFunc DOptSize = { OptSize, "OptSize", 0, 0, 0, 0, 0 };
static OptFunc DOptSize1 = { OptSize1, "OptSize1", 0, 0, 0, 0, 0 };
static OptFunc DOptSize2 = { OptSize2, "OptSize2", 0, 0, 0, 0, 0 };
static OptFunc DOptStackOps = { OptStackOps, "OptStackOps", 0, 0, 0, 0, 0 };
static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, 0, 0, 0 };
static OptFunc DOptSub1 = { OptSub1, "OptSub1", 0, 0, 0, 0, 0 };
@ -1602,22 +1338,23 @@ static OptFunc* OptFuncs[] = {
&DOptNegAX2,
&DOptNegAX3,
&DOptNegAX4,
&DOptPtrStore1,
&DOptPtrStore2,
&DOptPtrLoad1,
&DOptPtrLoad2,
&DOptPtrLoad3,
&DOptPtrLoad4,
&DOptPtrLoad5,
&DOptPtrLoad6,
&DOptPtrStore1,
&DOptPtrStore2,
&DOptRTS,
&DOptRTSJumps,
&DOptShift1,
&DOptSize,
&DOptSub1,
&DOptSub2,
&DOptSize1,
&DOptSize2,
&DOptStackOps,
&DOptStoreLoad,
&DOptSub1,
&DOptSub2,
&DOptTest1,
&DOptTransfers,
&DOptUnusedLoads,
@ -1929,7 +1666,7 @@ static void RunOptGroup4 (CodeSeg* S)
* if this does hinder further optimizations (no problem since we're
* done soon).
*/
RunOptFunc (S, &DOptSize, 1);
RunOptFunc (S, &DOptSize2, 1);
/* Run the jump target optimization again, since the size optimization
* above may have opened new oportunities.

View File

@ -246,7 +246,7 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
static int IsImmCmp16 (CodeSeg* S, CodeEntry** L)
static int IsImmCmp16 (CodeEntry** L)
/* Check if the instructions at L are an immidiate compare of a/x:
*
*
@ -405,7 +405,7 @@ unsigned OptBoolTrans (CodeSeg* S)
/*****************************************************************************/
/* Optimizations for compares */
/*****************************************************************************/
unsigned OptCmp1 (CodeSeg* S)
@ -565,7 +565,7 @@ unsigned OptCmp3 (CodeSeg* S)
CS_GetEntries (S, L, I+1, 5) &&
L[0]->OPC == OP65_LDX &&
!CE_HasLabel (L[0]) &&
IsImmCmp16 (S, L+1)) {
IsImmCmp16 (L+1)) {
if (L[1]->Num == 0 && L[3]->Num == 0) {
/* The value is zero, we may use the simple code version. */
@ -628,7 +628,7 @@ unsigned OptCmp4 (CodeSeg* S)
CodeEntry* L[9];
/* Check for the sequence */
if (IsLocalLoad16 (S, I, L, 9) && IsImmCmp16 (S, L+5)) {
if (IsLocalLoad16 (S, I, L, 9) && IsImmCmp16 (L+5)) {
if (L[5]->Num == 0 && L[7]->Num == 0) {

419
src/cc65/coptneg.c Normal file
View File

@ -0,0 +1,419 @@
/*****************************************************************************/
/* */
/* coptneg.c */
/* */
/* Optimize negation sequences */
/* */
/* */
/* */
/* (C) 2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
/* cc65 */
#include "codeent.h"
#include "codeinfo.h"
#include "coptneg.h"
/*****************************************************************************/
/* nega optimizations */
/*****************************************************************************/
unsigned OptNegA1 (CodeSeg* S)
/* Check for
*
* ldx #$00
* lda ..
* jsr bnega
*
* Remove the ldx if the lda does not use it.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for a ldx */
if (E->OPC == OP65_LDX &&
E->AM == AM65_IMM &&
(E->Flags & CEF_NUMARG) != 0 &&
E->Num == 0 &&
CS_GetEntries (S, L, I+1, 2) &&
L[0]->OPC == OP65_LDA &&
(L[0]->Use & REG_X) == 0 &&
!CE_HasLabel (L[0]) &&
CE_IsCall (L[1], "bnega") &&
!CE_HasLabel (L[1])) {
/* Remove the ldx instruction */
CS_DelEntry (S, I);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptNegA2 (CodeSeg* S)
/* Check for
*
* lda ..
* jsr bnega
* jeq/jne ..
*
* Adjust the conditional branch and remove the call to the subroutine.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if ((E->OPC == OP65_ADC ||
E->OPC == OP65_AND ||
E->OPC == OP65_DEA ||
E->OPC == OP65_EOR ||
E->OPC == OP65_INA ||
E->OPC == OP65_LDA ||
E->OPC == OP65_ORA ||
E->OPC == OP65_PLA ||
E->OPC == OP65_SBC ||
E->OPC == OP65_TXA ||
E->OPC == OP65_TYA) &&
CS_GetEntries (S, L, I+1, 2) &&
CE_IsCall (L[0], "bnega") &&
!CE_HasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[1])) {
/* Invert the branch */
CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* Delete the subroutine call */
CS_DelEntry (S, I+1);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* negax optimizations */
/*****************************************************************************/
unsigned OptNegAX1 (CodeSeg* S)
/* On a call to bnegax, if X is zero, the result depends only on the value in
* A, so change the call to a call to bnega. This will get further optimized
* later if possible.
*/
{
unsigned Changes = 0;
unsigned I;
/* Generate register info for this step */
CS_GenRegInfo (S);
/* Walk over the entries */
I = 0;
while (I < CS_GetEntryCount (S)) {
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check if this is a call to bnegax, and if X is known and zero */
if (E->RI->In.RegX == 0 &&
CE_IsCall (E, "bnegax")) {
/* We're cheating somewhat here ... */
E->Arg[5] = '\0';
E->Use &= ~REG_X;
/* We had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Free register info */
CS_FreeRegInfo (S);
/* Return the number of changes made */
return Changes;
}
unsigned OptNegAX2 (CodeSeg* S)
/* Search for the sequence:
*
* lda (xx),y
* tax
* dey
* lda (xx),y
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda (xx),y
* dey
* ora (xx),y
* jeq/jne ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[5];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if (E->OPC == OP65_LDA &&
E->AM == AM65_ZP_INDY &&
CS_GetEntries (S, L, I+1, 5) &&
L[0]->OPC == OP65_TAX &&
L[1]->OPC == OP65_DEY &&
L[2]->OPC == OP65_LDA &&
L[2]->AM == AM65_ZP_INDY &&
strcmp (L[2]->Arg, E->Arg) == 0 &&
!CE_HasLabel (L[2]) &&
CE_IsCall (L[3], "bnegax") &&
!CE_HasLabel (L[3]) &&
(L[4]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[4])) {
/* lda --> ora */
CE_ReplaceOPC (L[2], OP65_ORA);
/* Invert the branch */
CE_ReplaceOPC (L[4], GetInverseBranch (L[4]->OPC));
/* Delete the entries no longer needed. Beware: Deleting entries
* will change the indices.
*/
CS_DelEntry (S, I+4); /* jsr bnegax */
CS_DelEntry (S, I+1); /* tax */
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptNegAX3 (CodeSeg* S)
/* Search for the sequence:
*
* lda xx
* ldx yy
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda xx
* ora xx+1
* jeq/jne ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[3];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if (E->OPC == OP65_LDA &&
CS_GetEntries (S, L, I+1, 3) &&
L[0]->OPC == OP65_LDX &&
!CE_HasLabel (L[0]) &&
CE_IsCall (L[1], "bnegax") &&
!CE_HasLabel (L[1]) &&
(L[2]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[2])) {
/* ldx --> ora */
CE_ReplaceOPC (L[0], OP65_ORA);
/* Invert the branch */
CE_ReplaceOPC (L[2], GetInverseBranch (L[2]->OPC));
/* Delete the subroutine call */
CS_DelEntry (S, I+2);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptNegAX4 (CodeSeg* S)
/* Search for the sequence:
*
* jsr xxx
* jsr bnega(x)
* jeq/jne ...
*
* and replace it by:
*
* jsr xxx
* <boolean test>
* jne/jeq ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Check for the sequence */
if (E->OPC == OP65_JSR &&
CS_GetEntries (S, L, I+1, 2) &&
L[0]->OPC == OP65_JSR &&
strncmp (L[0]->Arg,"bnega",5) == 0 &&
!CE_HasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0 &&
!CE_HasLabel (L[1])) {
CodeEntry* X;
/* Check if we're calling bnega or bnegax */
int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
/* Insert apropriate test code */
if (ByteSized) {
/* Test bytes */
X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[0]->LI);
CS_InsertEntry (S, X, I+2);
} else {
/* Test words */
X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI);
CS_InsertEntry (S, X, I+2);
X = NewCodeEntry (OP65_ORA, AM65_ZP, "tmp1", 0, L[0]->LI);
CS_InsertEntry (S, X, I+3);
}
/* Delete the subroutine call */
CS_DelEntry (S, I+1);
/* Invert the branch */
CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}

140
src/cc65/coptneg.h Normal file
View File

@ -0,0 +1,140 @@
/*****************************************************************************/
/* */
/* coptneg.h */
/* */
/* Optimize negation sequences */
/* */
/* */
/* */
/* (C) 2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef COPTNEG_H
#define COPTNEG_H
/* cc65 */
#include "codeseg.h"
/*****************************************************************************/
/* nega optimizations */
/*****************************************************************************/
unsigned OptNegA1 (CodeSeg* S);
/* Check for
*
* ldx #$00
* lda ..
* jsr bnega
*
* Remove the ldx if the lda does not use it.
*/
unsigned OptNegA2 (CodeSeg* S);
/* Check for
*
* lda ..
* jsr bnega
* jeq/jne ..
*
* Adjust the conditional branch and remove the call to the subroutine.
*/
/*****************************************************************************/
/* negax optimizations */
/*****************************************************************************/
unsigned OptNegAX1 (CodeSeg* S);
/* On a call to bnegax, if X is zero, the result depends only on the value in
* A, so change the call to a call to bnega. This will get further optimized
* later if possible.
*/
unsigned OptNegAX2 (CodeSeg* S);
/* Search for the sequence:
*
* lda (xx),y
* tax
* dey
* lda (xx),y
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda (xx),y
* dey
* ora (xx),y
* jeq/jne ...
*/
unsigned OptNegAX3 (CodeSeg* S);
/* Search for the sequence:
*
* lda xx
* ldx yy
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda xx
* ora xx+1
* jeq/jne ...
*/
unsigned OptNegAX4 (CodeSeg* S);
/* Search for the sequence:
*
* jsr xxx
* jsr bnega(x)
* jeq/jne ...
*
* and replace it by:
*
* jsr xxx
* <boolean test>
* jne/jeq ...
*/
/* End of coptneg.h */
#endif

View File

@ -463,7 +463,7 @@ static void MakeConstIntExpr (ExprDesc* Expr, long Value)
{
Expr->Flags = E_MCONST;
Expr->Type = type_int;
Expr->ConstVal = 1;
Expr->ConstVal = Value;
}
@ -813,7 +813,7 @@ static void FunctionCall (int k, ExprDesc* lval)
g_space (- (int) sizeofarg (CF_PTR));
pop (CF_PTR);
}
/* Skip T_PTR */
++lval->Type;

View File

@ -277,7 +277,8 @@ static void CheckSegName (const char* Seg)
static void OptAddSource (const char* Opt, const char* Arg)
static void OptAddSource (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Add source lines as comments in generated assembler file */
{
AddSource = 1;
@ -285,7 +286,8 @@ static void OptAddSource (const char* Opt, const char* Arg)
static void OptAnsi (const char* Opt, const char* Arg)
static void OptAnsi (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Compile in strict ANSI mode */
{
ANSI = 1;
@ -293,7 +295,7 @@ static void OptAnsi (const char* Opt, const char* Arg)
static void OptBssName (const char* Opt, const char* Arg)
static void OptBssName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --bss-name option */
{
/* Check for a valid name */
@ -305,7 +307,8 @@ static void OptBssName (const char* Opt, const char* Arg)
static void OptCheckStack (const char* Opt, const char* Arg)
static void OptCheckStack (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --check-stack option */
{
CheckStack = 1;
@ -313,7 +316,7 @@ static void OptCheckStack (const char* Opt, const char* Arg)
static void OptCodeName (const char* Opt, const char* Arg)
static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --code-name option */
{
/* Check for a valid name */
@ -338,7 +341,8 @@ static void OptCodeSize (const char* Opt, const char* Arg)
static void OptCreateDep (const char* Opt, const char* Arg)
static void OptCreateDep (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --create-dep option */
{
CreateDep = 1;
@ -354,13 +358,13 @@ static void OptCPU (const char* Opt, const char* Arg)
} else if (strcmp (Arg, "65C02") == 0) {
CPU = CPU_65C02;
} else {
AbEnd ("Invalid CPU: `%s'", Arg);
AbEnd ("Invalid argument for %s: `%s'", Opt, Arg);
}
}
static void OptDataName (const char* Opt, const char* Arg)
static void OptDataName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --data-name option */
{
/* Check for a valid name */
@ -372,7 +376,8 @@ static void OptDataName (const char* Opt, const char* Arg)
static void OptDebug (const char* Opt, const char* Arg)
static void OptDebug (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Compiler debug mode */
{
Debug = 1;
@ -380,7 +385,8 @@ static void OptDebug (const char* Opt, const char* Arg)
static void OptDebugInfo (const char* Opt, const char* Arg)
static void OptDebugInfo (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Add debug info to the object file */
{
DebugInfo = 1;
@ -388,7 +394,7 @@ static void OptDebugInfo (const char* Opt, const char* Arg)
static void OptDebugOpt (const char* Opt, const char* Arg)
static void OptDebugOpt (const char* Opt attribute ((unused)), const char* Arg)
/* Debug optimization steps */
{
char Buf [128];
@ -455,7 +461,7 @@ static void OptDebugOpt (const char* Opt, const char* Arg)
static void OptDisableOpt (const char* Opt, const char* Arg)
static void OptDisableOpt (const char* Opt attribute ((unused)), const char* Arg)
/* Disable an optimization step */
{
DisableOpt (Arg);
@ -463,7 +469,7 @@ static void OptDisableOpt (const char* Opt, const char* Arg)
static void OptEnableOpt (const char* Opt, const char* Arg)
static void OptEnableOpt (const char* Opt attribute ((unused)), const char* Arg)
/* Enable an optimization step */
{
EnableOpt (Arg);
@ -471,7 +477,8 @@ static void OptEnableOpt (const char* Opt, const char* Arg)
static void OptHelp (const char* Opt, const char* Arg)
static void OptHelp (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Print usage information and exit */
{
Usage ();
@ -480,7 +487,7 @@ static void OptHelp (const char* Opt, const char* Arg)
static void OptIncludeDir (const char* Opt, const char* Arg)
static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg)
/* Add an include search path */
{
AddIncludePath (Arg, INC_SYS | INC_USER);
@ -488,7 +495,8 @@ static void OptIncludeDir (const char* Opt, const char* Arg)
static void OptListOptSteps (const char* Opt, const char* Arg)
static void OptListOptSteps (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* List all optimizer steps */
{
/* List the optimizer steps */
@ -500,7 +508,7 @@ static void OptListOptSteps (const char* Opt, const char* Arg)
static void OptRodataName (const char* Opt, const char* Arg)
static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --rodata-name option */
{
/* Check for a valid name */
@ -512,7 +520,8 @@ static void OptRodataName (const char* Opt, const char* Arg)
static void OptSignedChars (const char* Opt, const char* Arg)
static void OptSignedChars (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Make default characters signed */
{
SignedChars = 1;
@ -520,7 +529,8 @@ static void OptSignedChars (const char* Opt, const char* Arg)
static void OptStaticLocals (const char* Opt, const char* Arg)
static void OptStaticLocals (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Place local variables in static storage */
{
StaticLocals = 1;
@ -528,7 +538,7 @@ static void OptStaticLocals (const char* Opt, const char* Arg)
static void OptTarget (const char* Opt, const char* Arg)
static void OptTarget (const char* Opt attribute ((unused)), const char* Arg)
/* Set the target system */
{
SetSys (Arg);
@ -536,7 +546,8 @@ static void OptTarget (const char* Opt, const char* Arg)
static void OptVerbose (const char* Opt, const char* Arg)
static void OptVerbose (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Increase verbosity */
{
++Verbosity;
@ -544,7 +555,8 @@ static void OptVerbose (const char* Opt, const char* Arg)
static void OptVersion (const char* Opt, const char* Arg)
static void OptVersion (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Print the assembler version */
{
fprintf (stderr,

View File

@ -14,7 +14,7 @@ COMMON = ../common
# Default for the compiler lib search path as compiler define
CDEFS=-DCC65_INC=\"/usr/lib/cc65/include/\"
CFLAGS = -O2 -g -Wall -W -Wno-unused-parameter -I$(COMMON) $(CDEFS)
CFLAGS = -O2 -g -Wall -W -I$(COMMON) $(CDEFS)
CC=gcc
EBIND=emxbind
LDFLAGS=
@ -36,6 +36,7 @@ OBJS = anonname.o \
coptadd.o \
coptcmp.o \
coptind.o \
coptneg.o \
coptstop.o \
coptsub.o \
copttest.o \

View File

@ -81,6 +81,7 @@ OBJS = anonname.obj \
coptadd.obj \
coptcmp.obj \
coptind.obj \
coptneg.obj \
coptstop.obj \
coptsub.obj \
copttest.obj \
@ -155,6 +156,7 @@ FILE compile.obj
FILE coptadd.obj
FILE coptcmp.obj
FILE coptind.obj
FILE coptneg.obj
FILE coptstop.obj
FILE coptsub.obj
FILE copttest.obj

View File

@ -107,7 +107,7 @@ static struct StdFuncDesc* FindFunc (const char* Name)
static void StdFunc_strlen (ExprDesc* lval)
static void StdFunc_strlen (ExprDesc* lval attribute ((unused)))
/* Handle the strlen function */
{
ExprDesc pval;