X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcoptadd.c;h=76f697d792a22a55dca4f779e1d3413e98cfdd53;hb=c130e597b013e37c94afd6651be1e8859ba7e5ac;hp=49c966ce9f71c7c7e967e51da436c3ef2648095f;hpb=21111ba235f184c962985fd79c4782eaa5990c83;p=cc65 diff --git a/src/cc65/coptadd.c b/src/cc65/coptadd.c index 49c966ce9..76f697d79 100644 --- a/src/cc65/coptadd.c +++ b/src/cc65/coptadd.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -33,10 +33,7 @@ -#include - -/* common */ -#include "xsprintf.h" +#include /* cc65 */ #include "codeent.h" @@ -54,20 +51,27 @@ unsigned OptAdd1 (CodeSeg* S) /* Search for the sequence * - * jsr pushax - * ldy xxx - * ldx #$00 - * lda (sp),y + * ldy #xx + * jsr ldaxysp + * jsr pushax + * ldy #yy + * jsr ldaxysp * jsr tosaddax * * and replace it by: * - * ldy xxx-2 + * ldy #xx-1 + * lda (sp),y * clc + * ldy #yy-3 * adc (sp),y - * bcc L - * inx - * L: + * pha + * ldy #xx + * lda (sp),y + * ldy #yy-2 + * adc (sp),y + * tax + * pla */ { unsigned Changes = 0; @@ -76,60 +80,78 @@ unsigned OptAdd1 (CodeSeg* S) unsigned I = 0; while (I < CS_GetEntryCount (S)) { - CodeEntry* L[5]; + CodeEntry* L[6]; /* Get next entry */ - CodeEntry* E = CS_GetEntry (S, I); + L[0] = CS_GetEntry (S, I); /* Check for the sequence */ - if (E->OPC == OP65_JSR && - strcmp (E->Arg, "pushax") == 0 && - CS_GetEntries (S, L, I+1, 5) && - L[0]->OPC == OP65_LDY && - CE_KnownImm (L[0]) && - !CE_HasLabel (L[0]) && - L[1]->OPC == OP65_LDX && - CE_KnownImm (L[1]) && - L[1]->Num == 0 && - !CE_HasLabel (L[1]) && - L[2]->OPC == OP65_LDA && - !CE_HasLabel (L[2]) && - L[3]->OPC == OP65_JSR && - strcmp (L[3]->Arg, "tosaddax") == 0 && - !CE_HasLabel (L[3])) { + if (L[0]->OPC == OP65_LDY && + CE_KnownImm (L[0]) && + !CS_RangeHasLabel (S, I+1, 5) && + CS_GetEntries (S, L+1, I+1, 5) && + CE_IsCallTo (L[1], "ldaxysp") && + CE_IsCallTo (L[2], "pushax") && + L[3]->OPC == OP65_LDY && + CE_KnownImm (L[3]) && + CE_IsCallTo (L[4], "ldaxysp") && + CE_IsCallTo (L[5], "tosaddax")) { CodeEntry* X; - CodeLabel* Label; - - /* Remove the call to pushax */ - CS_DelEntry (S, I); + const char* Arg; - /* Correct the stack offset (needed since pushax was removed) */ - CE_SetNumArg (L[0], L[0]->Num - 2); - - /* Add the clc . */ - X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI); - CS_InsertEntry (S, X, I+1); + /* Correct the stack of the first Y register load */ + CE_SetNumArg (L[0], L[0]->Num - 1); - /* Remove the load */ - CS_DelEntry (S, I+3); /* lda */ - CS_DelEntry (S, I+2); /* ldx */ + /* lda (sp),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); + CS_InsertEntry (S, X, I+1); - /* Add the adc */ - X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI); + /* clc */ + X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[5]->LI); CS_InsertEntry (S, X, I+2); - /* Generate the branch label and the branch */ - Label = CS_GenLabel (S, L[4]); - X = NewCodeEntry (OP65_BCC, AM65_BRA, Label->Name, Label, L[3]->LI); + /* ldy #yy-3 */ + Arg = MakeHexArg (L[3]->Num - 3); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[4]->LI); CS_InsertEntry (S, X, I+3); - /* Generate the increment of the high byte */ - X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[3]->LI); + /* adc (sp),y */ + X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[5]->LI); CS_InsertEntry (S, X, I+4); - /* Delete the call to tosaddax */ - CS_DelEntry (S, I+5); + /* pha */ + X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[5]->LI); + CS_InsertEntry (S, X, I+5); + + /* ldy #xx (beware: L[0] has changed) */ + Arg = MakeHexArg (L[0]->Num + 1); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); + CS_InsertEntry (S, X, I+6); + + /* lda (sp),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); + CS_InsertEntry (S, X, I+7); + + /* ldy #yy-2 */ + Arg = MakeHexArg (L[3]->Num - 2); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[4]->LI); + CS_InsertEntry (S, X, I+8); + + /* adc (sp),y */ + X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[5]->LI); + CS_InsertEntry (S, X, I+9); + + /* tax */ + X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[5]->LI); + CS_InsertEntry (S, X, I+10); + + /* pla */ + X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[5]->LI); + CS_InsertEntry (S, X, I+11); + + /* Delete the old code */ + CS_DelEntries (S, I+12, 5); /* Remember, we had changes */ ++Changes; @@ -151,11 +173,8 @@ unsigned OptAdd2 (CodeSeg* S) /* Search for the sequence * * ldy #xx - * lda (sp),y - * tax - * dey - * lda (sp),y - * ldy #$yy + * jsr ldaxysp + * ldy #yy * jsr addeqysp * * and replace it by: @@ -181,7 +200,7 @@ unsigned OptAdd2 (CodeSeg* S) unsigned I = 0; while (I < CS_GetEntryCount (S)) { - CodeEntry* L[7]; + CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); @@ -189,67 +208,155 @@ unsigned OptAdd2 (CodeSeg* S) /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CE_KnownImm (L[0]) && - CS_GetEntries (S, L+1, I+1, 6) && - L[1]->OPC == OP65_LDA && - L[1]->AM == AM65_ZP_INDY && - !CE_HasLabel (L[1]) && - L[2]->OPC == OP65_TAX && - !CE_HasLabel (L[2]) && - L[3]->OPC == OP65_DEY && - !CE_HasLabel (L[3]) && - L[4]->OPC == OP65_LDA && - L[4]->AM == AM65_ZP_INDY && - !CE_HasLabel (L[4]) && - L[5]->OPC == OP65_LDY && - CE_KnownImm (L[5]) && - !CE_HasLabel (L[5]) && - L[6]->OPC == OP65_JSR && - strcmp (L[6]->Arg, "addeqysp") == 0 && - !CE_HasLabel (L[6]) && - (GetRegInfo (S, I+7, REG_AX) & REG_AX) == 0) { - - char Buf [20]; + !CS_RangeHasLabel (S, I+1, 3) && + CS_GetEntries (S, L+1, I+1, 3) && + CE_IsCallTo (L[1], "ldaxysp") && + L[2]->OPC == OP65_LDY && + CE_KnownImm (L[2]) && + CE_IsCallTo (L[3], "addeqysp") && + (GetRegInfo (S, I+4, REG_AX) & REG_AX) == 0) { + + /* Insert new code behind the addeqysp */ + const char* Arg; CodeEntry* X; + /* ldy #xx-1 */ + Arg = MakeHexArg (L[0]->Num-1); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[0]->LI); + CS_InsertEntry (S, X, I+4); - /* Adjust the operand of the first LDY */ - CE_SetNumArg (L[0], L[0]->Num - 1); + /* lda (sp),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); + CS_InsertEntry (S, X, I+5); - /* Load Y with the low offset of the target variable */ - X = NewCodeEntry (OP65_LDY, AM65_IMM, L[5]->Arg, 0, L[1]->LI); - CS_InsertEntry (S, X, I+2); + /* ldy #yy */ + X = NewCodeEntry (OP65_LDY, AM65_IMM, L[2]->Arg, 0, L[2]->LI); + CS_InsertEntry (S, X, I+6); - /* Add the CLC */ - X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI); - CS_InsertEntry (S, X, I+3); + /* clc */ + X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI); + CS_InsertEntry (S, X, I+7); - /* Remove the TAX/DEY sequence */ - CS_DelEntry (S, I+5); /* dey */ - CS_DelEntry (S, I+4); /* tax */ + /* adc (sp),y */ + X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI); + CS_InsertEntry (S, X, I+8); + + /* sta (sp),y */ + X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[3]->LI); + CS_InsertEntry (S, X, I+9); + + /* ldy #xx */ + X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI); + CS_InsertEntry (S, X, I+10); + + /* lda (sp),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); + CS_InsertEntry (S, X, I+11); - /* Addition of the low byte */ - X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[4]->LI); + /* ldy #yy+1 */ + Arg = MakeHexArg (L[2]->Num+1); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[2]->LI); + CS_InsertEntry (S, X, I+12); + + /* adc (sp),y */ + X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI); + CS_InsertEntry (S, X, I+13); + + /* sta (sp),y */ + X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[3]->LI); + CS_InsertEntry (S, X, I+14); + + /* Delete the old code */ + CS_DelEntries (S, I, 4); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +unsigned OptAdd3 (CodeSeg* S) +/* Search for the sequence + * + * jsr pushax + * lda xxx + * ldx yyy + * jsr tosaddax + * + * and replace it by + * + * clc + * adc xxx + * pha + * txa + * adc yyy + * tax + * pla + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* L[4]; + + /* Get next entry */ + L[0] = CS_GetEntry (S, I); + + /* Check for the sequence */ + if (CE_IsCallTo (L[0], "pushax") && + CS_GetEntries (S, L+1, I+1, 3) && + !CS_RangeHasLabel (S, I+1, 3) && + L[1]->OPC == OP65_LDA && + (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP) && + L[2]->OPC == OP65_LDX && + (L[2]->AM == AM65_ABS || L[2]->AM == AM65_ZP) && + CE_IsCallTo (L[3], "tosaddax")) { + + CodeEntry* X; + + /* Insert new code behind the sequence */ + X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+4); - X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[4]->LI); + + /* adc xxx */ + X = NewCodeEntry (OP65_ADC, L[1]->AM, L[1]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+5); - /* LDY */ - xsprintf (Buf, sizeof (Buf), "$%02X", (int) (L[0]->Num+1)); - X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, L[4]->LI); + /* pha */ + X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+6); - /* Addition of the high byte */ - xsprintf (Buf, sizeof (Buf), "$%02X", (int)(L[5]->Num+1)); - X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, L[5]->LI); + /* txa */ + X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[3]->LI); + CS_InsertEntry (S, X, I+7); + + /* adc yyy */ + X = NewCodeEntry (OP65_ADC, L[2]->AM, L[2]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+8); - X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[6]->LI); + + /* tax */ + X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+9); - X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[6]->LI); + + /* pla */ + X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+10); - /* Delete the remaining stuff */ - CS_DelEntry (S, I+12); - CS_DelEntry (S, I+11); + /* Delete the old code */ + CS_DelEntries (S, I, 4); /* Remember, we had changes */ ++Changes; @@ -267,7 +374,60 @@ unsigned OptAdd2 (CodeSeg* S) -unsigned OptAdd3 (CodeSeg* S) +unsigned OptAdd4 (CodeSeg* S) +/* Search for a call to incaxn and replace it by an 8 bit add if the X register + * is not used later. + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* E; + + /* Get next entry */ + E = CS_GetEntry (S, I); + + /* Check for the sequence */ + if (E->OPC == OP65_JSR && + strncmp (E->Arg, "incax", 5) == 0 && + isdigit (E->Arg[5]) && + E->Arg[6] == '\0' && + !RegXUsed (S, I+1)) { + + CodeEntry* X; + const char* Arg; + + /* Insert new code behind the sequence */ + X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, E->LI); + CS_InsertEntry (S, X, I+1); + + Arg = MakeHexArg (E->Arg[5] - '0'); + X = NewCodeEntry (OP65_ADC, AM65_IMM, Arg, 0, E->LI); + CS_InsertEntry (S, X, I+2); + + /* Delete the old code */ + CS_DelEntry (S, I); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +unsigned OptAdd5 (CodeSeg* S) /* Search for the sequence * * adc ... @@ -290,7 +450,7 @@ unsigned OptAdd3 (CodeSeg* S) CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ - if (E->OPC == OP65_ADC && + if (E->OPC == OP65_ADC && CS_GetEntries (S, L, I+1, 3) && (L[0]->OPC == OP65_BCC || L[0]->OPC == OP65_JCC) && L[0]->JumpTo != 0 &&