diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 3704aebf5..b7ed44fbf 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -790,8 +790,12 @@ void g_getlocal (unsigned flags, int offs) case CF_CHAR: if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { - ldyconst (offs); - AddCodeLine ("\tlda\t(sp),y"); + if (CPU == CPU_65C02 && offs == 0) { + AddCodeLine ("\tlda\t(sp)"); + } else { + ldyconst (offs); + AddCodeLine ("\tlda\t(sp),y"); + } } else { if (offs == 0) { AddCodeLine ("\tldx\t#$00"); @@ -1004,8 +1008,12 @@ void g_putlocal (unsigned flags, int offs) switch (flags & CF_TYPE) { case CF_CHAR: - ldyconst (offs); - AddCodeLine ("\tsta\t(sp),y"); + if (CPU == CPU_65C02 && offs == 0) { + AddCodeLine ("\tsta\t(sp)"); + } else { + ldyconst (offs); + AddCodeLine ("\tsta\t(sp),y"); + } break; case CF_INT: @@ -1275,35 +1283,35 @@ void g_scale (unsigned flags, long val) if (flags & CF_FORCECHAR) { while (p2--) { AddCodeLine ("\tasl\ta"); - } - break; - } - /* FALLTHROUGH */ + } + break; + } + /* FALLTHROUGH */ - case CF_INT: - if (FavourSize || p2 >= 3) { - if (flags & CF_UNSIGNED) { - AddCodeLine ("\tjsr\tshlax%d", p2); - } else { - AddCodeLine ("\tjsr\taslax%d", p2); - } - } else { - AddCodeLine ("\tstx\ttmp1"); - while (p2--) { - AddCodeLine ("\tasl\ta"); - AddCodeLine ("\trol\ttmp1"); - } - AddCodeLine ("\tldx\ttmp1"); - } - break; + case CF_INT: + if (FavourSize || p2 >= 3) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("\tjsr\tshlax%d", p2); + } else { + AddCodeLine ("\tjsr\taslax%d", p2); + } + } else { + AddCodeLine ("\tstx\ttmp1"); + while (p2--) { + AddCodeLine ("\tasl\ta"); + AddCodeLine ("\trol\ttmp1"); + } + AddCodeLine ("\tldx\ttmp1"); + } + break; - case CF_LONG: - if (flags & CF_UNSIGNED) { - AddCodeLine ("\tjsr\tshleax%d", p2); - } else { - AddCodeLine ("\tjsr\tasleax%d", p2); - } - break; + case CF_LONG: + if (flags & CF_UNSIGNED) { + AddCodeLine ("\tjsr\tshleax%d", p2); + } else { + AddCodeLine ("\tjsr\tasleax%d", p2); + } + break; default: typeerror (flags); @@ -1348,7 +1356,7 @@ void g_scale (unsigned flags, long val) } else { AddCodeLine ("\tstx\ttmp1"); while (p2--) { - AddCodeLine ("\tlsr\ttmp1"); + AddCodeLine ("\tlsr\ttmp1"); AddCodeLine ("\tror\ta"); } AddCodeLine ("\tldx\ttmp1"); @@ -1393,7 +1401,7 @@ void g_scale (unsigned flags, long val) /*****************************************************************************/ -/* Adds and subs of variables fix a fixed address */ +/* Adds and subs of variables fix a fixed address */ /*****************************************************************************/ @@ -1528,18 +1536,18 @@ void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs, if (flags & CF_CONST) { if (val == 1) { AddCodeLine ("\tinc\t%s", lbuf); - AddCodeLine ("\tlda\t%s", lbuf); - } else { + AddCodeLine ("\tlda\t%s", lbuf); + } else { AddCodeLine ("\tlda\t#$%02X", val & 0xFF); - AddCodeLine ("\tclc"); - AddCodeLine ("\tadc\t%s", lbuf); - AddCodeLine ("\tsta\t%s", lbuf); - } + AddCodeLine ("\tclc"); + AddCodeLine ("\tadc\t%s", lbuf); + AddCodeLine ("\tsta\t%s", lbuf); + } } else { - AddCodeLine ("\tclc"); - AddCodeLine ("\tadc\t%s", lbuf); - AddCodeLine ("\tsta\t%s", lbuf); - } + AddCodeLine ("\tclc"); + AddCodeLine ("\tadc\t%s", lbuf); + AddCodeLine ("\tsta\t%s", lbuf); + } if ((flags & CF_UNSIGNED) == 0) { AddCodeLine ("\tbpl\t*+3"); AddCodeLine ("\tdex"); @@ -1584,9 +1592,9 @@ void g_addeqstatic (unsigned flags, unsigned long label, unsigned offs, AddCodeLine ("\tsta\t%s", lbuf); AddCodeLine ("\ttxa"); AddCodeLine ("\tadc\t%s+1", lbuf); - AddCodeLine ("\tsta\t%s+1", lbuf); - AddCodeLine ("\ttax"); - AddCodeLine ("\tlda\t%s", lbuf); + AddCodeLine ("\tsta\t%s+1", lbuf); + AddCodeLine ("\ttax"); + AddCodeLine ("\tlda\t%s", lbuf); } break; @@ -1634,38 +1642,38 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val) case CF_CHAR: if (flags & CF_FORCECHAR) { - if (offs == 0) { - AddCodeLine ("\tldx\t#$00"); - if (flags & CF_CONST) { - AddCodeLine ("\tclc"); + if (offs == 0) { + AddCodeLine ("\tldx\t#$00"); + if (flags & CF_CONST) { + AddCodeLine ("\tclc"); AddCodeLine ("\tlda\t#$%02X", val & 0xFF); - AddCodeLine ("\tadc\t(sp,x)"); - AddCodeLine ("\tsta\t(sp,x)"); - } else { - AddCodeLine ("\tclc"); - AddCodeLine ("\tadc\t(sp,x)"); - AddCodeLine ("\tsta\t(sp,x)"); - } - } else { - ldyconst (offs); - AddCodeLine ("\tldx\t#$00"); - if (flags & CF_CONST) { - AddCodeLine ("\tclc"); + AddCodeLine ("\tadc\t(sp,x)"); + AddCodeLine ("\tsta\t(sp,x)"); + } else { + AddCodeLine ("\tclc"); + AddCodeLine ("\tadc\t(sp,x)"); + AddCodeLine ("\tsta\t(sp,x)"); + } + } else { + ldyconst (offs); + AddCodeLine ("\tldx\t#$00"); + if (flags & CF_CONST) { + AddCodeLine ("\tclc"); AddCodeLine ("\tlda\t#$%02X", val & 0xFF); - AddCodeLine ("\tadc\t(sp),y"); - AddCodeLine ("\tsta\t(sp),y"); - } else { + AddCodeLine ("\tadc\t(sp),y"); + AddCodeLine ("\tsta\t(sp),y"); + } else { AddCodeLine ("\tclc"); - AddCodeLine ("\tadc\t(sp),y"); - AddCodeLine ("\tsta\t(sp),y"); - } - } - if ((flags & CF_UNSIGNED) == 0) { - AddCodeLine ("\tbpl\t*+3"); - AddCodeLine ("\tdex"); - AddCodeHint ("x:!"); /* Invalidate X */ - } - break; + AddCodeLine ("\tadc\t(sp),y"); + AddCodeLine ("\tsta\t(sp),y"); + } + } + if ((flags & CF_UNSIGNED) == 0) { + AddCodeLine ("\tbpl\t*+3"); + AddCodeLine ("\tdex"); + AddCodeHint ("x:!"); /* Invalidate X */ + } + break; } /* FALLTHROUGH */ @@ -1674,10 +1682,10 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val) g_getimmed (flags, val, 0); } if (offs == 0) { - AddCodeLine ("\tjsr\taddeq0sp"); + AddCodeLine ("\tjsr\taddeq0sp"); } else { - ldyconst (offs); - AddCodeLine ("\tjsr\taddeqysp"); + ldyconst (offs); + AddCodeLine ("\tjsr\taddeqysp"); } break; @@ -1801,7 +1809,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs, AddCodeLine ("\tbpl\t*+3"); AddCodeLine ("\tdex"); AddCodeHint ("x:!"); /* Invalidate X */ - } + } break; } /* FALLTHROUGH */ @@ -1846,7 +1854,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, unsigned offs, AddCodeLine ("\tsty\tptr1"); AddCodeLine ("\tldy\t#>(%s+1)", lbuf); if (val == 1) { - AddCodeLine ("\tjsr\tlsubeq1"); + AddCodeLine ("\tjsr\tlsubeq1"); } else { AddCodeLine ("\tlda\t#$%02X", val & 0xFF); AddCodeLine ("\tjsr\tlsubeqa"); @@ -1891,7 +1899,7 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val) AddCodeLine ("\tsbc\t#$%02X", val & 0xFF); } else { AddCodeLine ("\tsta\ttmp1"); - AddCodeLine ("\tlda\t(sp),y"); + AddCodeLine ("\tlda\t(sp),y"); AddCodeLine ("\tsbc\ttmp1"); } AddCodeLine ("\tsta\t(sp),y"); @@ -1981,7 +1989,7 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val) AddCodeLine ("\tlda\t(ptr1),y"); AddCodeLine ("\tsbc\t#$%02X", (val >> 8) & 0xFF); AddCodeLine ("\tsta\t(ptr1),y"); - AddCodeLine ("\ttax"); + AddCodeLine ("\ttax"); AddCodeLine ("\tpla"); break; } @@ -2296,7 +2304,7 @@ void g_push (unsigned flags, unsigned long val) break; case CF_LONG: - AddCodeLine ("\tjsr\tpusheax"); + AddCodeLine ("\tjsr\tpusheax"); break; default: @@ -2521,7 +2529,7 @@ void g_mul (unsigned flags, unsigned long val) { static char* ops [12] = { 0, "tosmula0", "tosmulax", - 0, "tosumula0", "tosumulax", + 0, "tosumula0", "tosumulax", 0, 0, "tosmuleax", 0, 0, "tosumuleax", }; @@ -2566,7 +2574,7 @@ void g_mul (unsigned flags, unsigned long val) AddCodeLine ("\tsta\ttmp1"); AddCodeLine ("\tasl\ta"); AddCodeLine ("\tasl\ta"); - AddCodeLine ("\tclc"); + AddCodeLine ("\tclc"); AddCodeLine ("\tadc\ttmp1"); AddCodeLine ("\tasl\ta"); return; @@ -2746,7 +2754,7 @@ void g_xor (unsigned flags, unsigned long val) return; } else if ((val & 0xFF) == 0) { AddCodeLine ("\tpha"); - AddCodeLine ("\ttxa"); + AddCodeLine ("\ttxa"); AddCodeLine ("\teor\t#$%02X", (val >> 8) & 0xFF); AddCodeLine ("\ttax"); AddCodeLine ("\tpla"); @@ -2836,7 +2844,7 @@ void g_and (unsigned flags, unsigned long val) if (val <= 0xFF) { ldxconst (0); AddCodeLine ("\tstx\tsreg+1"); - AddCodeLine ("\tstx\tsreg"); + AddCodeLine ("\tstx\tsreg"); if ((val & 0xFF) != 0xFF) { AddCodeLine ("\tand\t#$%02X", val & 0xFF); } @@ -2926,7 +2934,7 @@ void g_asr (unsigned flags, unsigned long val) AddCodeLine ("\tlda\tsreg"); AddCodeLine ("\tsty\tsreg+1"); AddCodeLine ("\tsty\tsreg"); - return; + return; } break; @@ -2971,7 +2979,7 @@ void g_asl (unsigned flags, unsigned long val) if (flags & CF_UNSIGNED) { AddCodeLine ("\tjsr\tshlax%ld", val); } else { - AddCodeLine ("\tjsr\taslax%ld", val); + AddCodeLine ("\tjsr\taslax%ld", val); } return; } else if (val == 8) { @@ -3106,7 +3114,7 @@ void g_inc (unsigned flags, unsigned long val) while (val--) { AddCodeLine ("\tina"); } - } else { + } else { AddCodeLine ("\tclc"); AddCodeLine ("\tadc\t#$%02X", val & 0xFF); } @@ -3151,7 +3159,7 @@ void g_inc (unsigned flags, unsigned long val) } else { AddCodeLine ("\tclc"); if ((val & 0xFF) != 0) { - AddCodeLine ("\tadc\t#$%02X", (unsigned char) val); + AddCodeLine ("\tadc\t#$%02X", (unsigned char) val); /* Tell the optimizer that the X register may be invalid */ AddCodeHint ("x:!"); } @@ -3196,7 +3204,7 @@ void g_dec (unsigned flags, unsigned long val) } } else { AddCodeLine ("\tsec"); - AddCodeLine ("\tsbc\t#$%02X", val & 0xFF); + AddCodeLine ("\tsbc\t#$%02X", val & 0xFF); } break; } @@ -3376,7 +3384,7 @@ void g_lt (unsigned flags, unsigned long val) } return; } - /* FALLTHROUGH */ + /* FALLTHROUGH */ case CF_INT: if ((flags & CF_UNSIGNED) == 0 && val == 0) { @@ -3511,7 +3519,7 @@ void g_gt (unsigned flags, unsigned long val) AddCodeLine ("\tjsr\tboolne"); } } else { - AddCodeLine ("\tjsr\tboolgt"); + AddCodeLine ("\tjsr\tboolgt"); } return; } @@ -3601,7 +3609,7 @@ void g_ge (unsigned flags, unsigned long val) AddCodeLine ("\tjsr\tbooluge"); return; } - break; + break; case CF_LONG: break; @@ -3646,7 +3654,7 @@ void g_defdata (unsigned flags, unsigned long val, unsigned offs) switch (flags & CF_TYPE) { case CF_CHAR: - AddCodeLine ("\t.byte\t$%02lX", val & 0xFF); + AddCodeLine ("\t.byte\t$%02lX", val & 0xFF); break; case CF_INT: @@ -3715,10 +3723,10 @@ void g_zerobytes (unsigned n) AddCodeLine ("\t.res\t%u,$00", n); } - + /*****************************************************************************/ -/* Inlined known functions */ +/* Inlined known functions */ /*****************************************************************************/ @@ -3741,8 +3749,8 @@ void g_strlen (unsigned flags, unsigned long val, unsigned offs) AddCodeLine ("\tiny"); AddCodeLine ("\tlda\t%s,y", lbuf); AddCodeLine ("\tbne\tL%04X", label); + AddCodeLine ("\ttax"); AddCodeLine ("\ttya"); - AddCodeLine ("\tldx\t#$00"); } else { @@ -3759,8 +3767,8 @@ void g_strlen (unsigned flags, unsigned long val, unsigned offs) AddCodeLine ("\tiny"); AddCodeLine ("\tlda\t(ptr1),y"); AddCodeLine ("\tbne\tL%04X", label); + AddCodeLine ("\ttax"); AddCodeLine ("\ttya"); - AddCodeLine ("\tldx\t#$00"); } } } diff --git a/src/cc65/optimize.c b/src/cc65/optimize.c index 8302ebdc2..dce39dbac 100644 --- a/src/cc65/optimize.c +++ b/src/cc65/optimize.c @@ -1103,7 +1103,7 @@ static unsigned RVUInt2 (Line* L, do { /* Handle jumps to local labels (continue there) */ - if (LineMatch (L, "\tjmp\tL")) { + if (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL")) { /* Get the target of the jump */ L = GetTargetLine (L->Line+5); } @@ -1113,33 +1113,33 @@ static unsigned RVUInt2 (Line* L, /* Bail out if we're done */ if (L == 0 || IsLabel (L)) { - /* Something is wrong */ - return REG_ALL; + /* Something is wrong */ + return REG_ALL; } /* Check if we had this line already. If so, bail out, if not, * add it to the list of known lines. */ if (LCHasLine (LC, L) || !LCAddLine (LC, L)) { - goto ExitPoint; + goto ExitPoint; } - } while (LineMatch (L, "\tjmp\tL")); + } while (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL")); /* Special handling for branches */ if (LineMatchX (L, ShortBranches) >= 0 || LineMatchX (L, LongBranches) >= 0) { const char* Target = L->Line+5; if (Target[0] == 'L') { - /* Jump to local label. Check the register usage starting at - * the branch target and at the code following the branch. - * All registers that are unused in both execution flows are - * returned as unused. - */ - unsigned U1, U2; + /* Jump to local label. Check the register usage starting at + * the branch target and at the code following the branch. + * All registers that are unused in both execution flows are + * returned as unused. + */ + unsigned U1, U2; U2 = RVUInt1 (GetTargetLine (Target), LC, Used, Unused); - U1 = RVUInt1 (L, LC, Used, Unused); - return U1 | U2; /* Used in any of the branches */ + U1 = RVUInt1 (L, LC, Used, Unused); + return U1 | U2; /* Used in any of the branches */ } } @@ -1218,7 +1218,7 @@ static unsigned RegValUsed (Line* Start) * If the end of the lookahead is reached, all registers that are uncertain * are marked as used. * The result of the search is returned. - */ + */ { unsigned R; @@ -1758,7 +1758,7 @@ static void OptRegLoads (void) /* Search for a load of Y and check if the value is used later */ else if (LineMatch (L, "\tldy\t") && - !RegYUsed (L) && + !RegYUsed (L) && !IsCondJump (NextInstruction (L))) { /* Remember to delete this line */ @@ -3867,6 +3867,10 @@ static Line* OptOneBlock (Line* L) } else if (LineFullMatch (L, "\tjsr\tpushax")) { /* We know about this function */ Y = 1; + } else if (LineFullMatch (L, "\tjsr\tpushaysp")) { + /* We know about this function */ + A = -1; + Y = 0; } else if (LineFullMatch (L, "\tjsr\tpushc0")) { /* We know about this function */ A = 0; @@ -4196,6 +4200,26 @@ static void OptJumps (void) } L = NextCodeLine (L); } + + /* Special treatment for jumps on the 65C02 */ + if (CPU == CPU_65C02) { + + Line* L = FirstCode; + while (L) { + if (LineMatch (L, "\tjmp\tL")) { + Line* Target = GetTargetLine (L->Line+5); + unsigned Distance = GetJumpDistance (L, Target); + if (Distance < 123) { /* Safety */ + L->Line [1] = 'b'; /* Make a short branch */ + L->Line [2] = 'r'; + L->Line [3] = 'a'; + L->Size = 2; /* Set new size */ + } + } + L = NextCodeLine (L); + } + + } }