X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodegen.c;h=577623aa6d941a7cb2d00f6ba234a33841c871f8;hb=77bfcc1ff0a88e0430f077d22b6fad07c7d0c86b;hp=b1a3fc57d228a3e375ec36e6f7ea1516a4c8aad6;hpb=3717443f3bf29ca2d007ee7c177f499b2d1cadf8;p=cc65 diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index b1a3fc57d..577623aa6 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2009 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -41,9 +41,9 @@ #include "check.h" #include "cpu.h" #include "strbuf.h" -#include "version.h" #include "xmalloc.h" #include "xsprintf.h" +#include "version.h" /* cc65 */ #include "asmcode.h" @@ -70,7 +70,12 @@ static void typeerror (unsigned type) /* Print an error message about an invalid operand type */ { - Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPE); + /* Special handling for floats here: */ + if ((type & CF_TYPE) == CF_FLOAT) { + Fatal ("Floating point type is currently unsupported"); + } else { + Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPE); + } } @@ -140,19 +145,14 @@ static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs) void g_preamble (void) /* Generate the assembler code preamble */ { - /* Create a new (global) segment list and remember it */ - PushSegments (0); - GS = CS; - /* Identify the compiler version */ AddTextLine (";"); - AddTextLine ("; File generated by cc65 v %u.%u.%u", - VER_MAJOR, VER_MINOR, VER_PATCH); + AddTextLine ("; File generated by cc65 v %s", GetVersionAsString ()); AddTextLine (";"); /* Insert some object file options */ - AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %u.%u.%u\"", - VER_MAJOR, VER_MINOR, VER_PATCH); + AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %s\"", + GetVersionAsString ()); /* If we're producing code for some other CPU, switch the command set */ switch (CPU) { @@ -346,6 +346,24 @@ void g_defdatalabel (unsigned label) +void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs) +/* Define label as a local alias for baselabel+offs */ +{ + /* We need an intermediate buffer here since LocalLabelName uses a + * static buffer which changes with each call. + */ + StrBuf L = AUTO_STRBUF_INITIALIZER; + SB_AppendStr (&L, LocalLabelName (label)); + SB_Terminate (&L); + AddDataLine ("%s\t:=\t%s+%ld", + SB_GetConstBuf (&L), + LocalLabelName (baselabel), + offs); + SB_Done (&L); +} + + + /*****************************************************************************/ /* Functions handling global labels */ /*****************************************************************************/ @@ -401,36 +419,6 @@ void g_importmainargs (void) -/*****************************************************************************/ -/* Load functions for various registers */ -/*****************************************************************************/ - - - -static void ldaconst (unsigned val) -/* Load a with a constant */ -{ - AddCodeLine ("lda #$%02X", val & 0xFF); -} - - - -static void ldxconst (unsigned val) -/* Load x with a constant */ -{ - AddCodeLine ("ldx #$%02X", val & 0xFF); -} - - - -static void ldyconst (unsigned val) -/* Load y with a constant */ -{ - AddCodeLine ("ldy #$%02X", val & 0xFF); -} - - - /*****************************************************************************/ /* Function entry and exit */ /*****************************************************************************/ @@ -463,39 +451,30 @@ void g_leave (void) /* Function epilogue */ { /* How many bytes of locals do we have to drop? */ - unsigned k = (unsigned) -StackPtr; + unsigned ToDrop = (unsigned) -StackPtr; /* If we didn't have a variable argument list, don't call leave */ if (funcargs >= 0) { - /* Drop stackframe if needed. We can only drop 255 bytes at a time. */ - k += funcargs; - while (k > 0) { - unsigned ToDrop = (k > 255)? 255 : k; - if (ToDrop <= 8) { - AddCodeLine ("jsr incsp%d", k); - } else { - ldyconst (ToDrop); - AddCodeLine ("jsr addysp"); - } - k -= ToDrop; - } + /* Drop stackframe if needed */ + g_drop (ToDrop + funcargs); - } else { + } else if (StackPtr != 0) { - if (k == 0) { - /* Nothing to drop */ + /* We've a stack frame to drop */ + if (ToDrop > 255) { + g_drop (ToDrop); /* Inlines the code */ AddCodeLine ("jsr leave"); } else { - /* We've a stack frame to drop */ - while (k > 255) { - ldyconst (255); - AddCodeLine ("jsr addysp"); - k -= 255; - } - ldyconst (k); + AddCodeLine ("ldy #$%02X", ToDrop); AddCodeLine ("jsr leavey"); } + + } else { + + /* Nothing to drop */ + AddCodeLine ("jsr leave"); + } /* Add the final rts */ @@ -518,14 +497,13 @@ void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes) CheckLocalOffs (StackOffs); /* Generate code */ + AddCodeLine ("ldy #$%02X", StackOffs & 0xFF); if (Bytes == 1) { if (IS_Get (&CodeSizeFactor) < 165) { - ldyconst (StackOffs); - ldxconst (RegOffs); + AddCodeLine ("ldx #$%02X", RegOffs & 0xFF); AddCodeLine ("jsr regswap1"); } else { - ldyconst (StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("ldx regbank%+d", RegOffs); AddCodeLine ("sta regbank%+d", RegOffs); @@ -535,15 +513,13 @@ void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes) } else if (Bytes == 2) { - ldyconst (StackOffs); - ldxconst (RegOffs); + AddCodeLine ("ldx #$%02X", RegOffs & 0xFF); AddCodeLine ("jsr regswap2"); } else { - ldyconst (StackOffs); - ldxconst (RegOffs); - ldaconst (Bytes); + AddCodeLine ("ldx #$%02X", RegOffs & 0xFF); + AddCodeLine ("lda #$%02X", Bytes & 0xFF); AddCodeLine ("jsr regswap"); } } @@ -570,8 +546,8 @@ void g_save_regvars (int RegOffs, unsigned Bytes) /* More than two bytes - loop */ unsigned Label = GetLocalLabel (); g_space (Bytes); - ldyconst (Bytes - 1); - ldxconst (Bytes); + AddCodeLine ("ldy #$%02X", (unsigned char) (Bytes - 1)); + AddCodeLine ("ldx #$%02X", (unsigned char) Bytes); g_defcodelabel (Label); AddCodeLine ("lda regbank%+d,x", RegOffs-1); AddCodeLine ("sta (sp),y"); @@ -597,13 +573,13 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) /* Don't loop for up to two bytes */ if (Bytes == 1) { - ldyconst (StackOffs); + AddCodeLine ("ldy #$%02X", StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs); } else if (Bytes == 2) { - ldyconst (StackOffs); + AddCodeLine ("ldy #$%02X", StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs); AddCodeLine ("iny"); @@ -612,7 +588,7 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) } else if (Bytes == 3 && IS_Get (&CodeSizeFactor) >= 133) { - ldyconst (StackOffs); + AddCodeLine ("ldy #$%02X", StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs); AddCodeLine ("iny"); @@ -629,7 +605,7 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) * code that uses just one index register. */ unsigned Label = GetLocalLabel (); - ldyconst (StackOffs); + AddCodeLine ("ldy #$%02X", StackOffs); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d,y", RegOffs - StackOffs); @@ -644,8 +620,8 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) */ unsigned Label = GetLocalLabel (); AddCodeLine ("stx tmp1"); - ldyconst (StackOffs + Bytes - 1); - ldxconst (Bytes - 1); + AddCodeLine ("ldy #$%02X", (unsigned char) (StackOffs + Bytes - 1)); + AddCodeLine ("ldx #$%02X", (unsigned char) (Bytes - 1)); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d,x", RegOffs); @@ -679,13 +655,13 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs) case CF_CHAR: if ((Flags & CF_FORCECHAR) != 0) { - ldaconst (Val); + AddCodeLine ("lda #$%02X", (unsigned char) Val); break; } /* FALL THROUGH */ case CF_INT: - ldxconst ((Val >> 8) & 0xFF); - ldaconst (Val & 0xFF); + AddCodeLine ("ldx #$%02X", (unsigned char) (Val >> 8)); + AddCodeLine ("lda #$%02X", (unsigned char) Val); break; case CF_LONG: @@ -764,7 +740,7 @@ void g_getstatic (unsigned flags, unsigned long label, long offs) if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { AddCodeLine ("lda %s", lbuf); /* load A from the label */ } else { - ldxconst (0); + AddCodeLine ("ldx #$00"); AddCodeLine ("lda %s", lbuf); /* load A from the label */ if (!(flags & CF_UNSIGNED)) { /* Must sign extend */ @@ -809,22 +785,22 @@ void g_getstatic (unsigned flags, unsigned long label, long offs) -void g_getlocal (unsigned flags, int offs) +void g_getlocal (unsigned Flags, int Offs) /* Fetch specified local object (local var). */ { - offs -= StackPtr; - CheckLocalOffs (offs); - switch (flags & CF_TYPE) { + Offs -= StackPtr; + switch (Flags & CF_TYPE) { case CF_CHAR: - if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { - ldyconst (offs); + CheckLocalOffs (Offs); + if ((Flags & CF_FORCECHAR) || (Flags & CF_TEST)) { + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("lda (sp),y"); } else { - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); AddCodeLine ("lda (sp),y"); - if ((flags & CF_UNSIGNED) == 0) { + if ((Flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); @@ -834,34 +810,34 @@ void g_getlocal (unsigned flags, int offs) break; case CF_INT: - CheckLocalOffs (offs + 1); - if (flags & CF_TEST) { - ldyconst (offs + 1); + CheckLocalOffs (Offs + 1); + AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+1)); + if (Flags & CF_TEST) { AddCodeLine ("lda (sp),y"); AddCodeLine ("dey"); AddCodeLine ("ora (sp),y"); } else { - ldyconst (offs+1); AddCodeLine ("jsr ldaxysp"); } break; case CF_LONG: - ldyconst (offs+3); + CheckLocalOffs (Offs + 3); + AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+3)); AddCodeLine ("jsr ldeaxysp"); - if (flags & CF_TEST) { - g_test (flags); + if (Flags & CF_TEST) { + g_test (Flags); } break; default: - typeerror (flags); + typeerror (Flags); } } -void g_getind (unsigned flags, unsigned offs) +void g_getind (unsigned Flags, unsigned Offs) /* Fetch the specified object type indirect through the primary register * into the primary register */ @@ -870,84 +846,110 @@ void g_getind (unsigned flags, unsigned offs) * the primary. This way we get an easy addition and use the low byte * as the offset */ - offs = MakeByteOffs (flags, offs); + Offs = MakeByteOffs (Flags, Offs); /* Handle the indirect fetch */ - switch (flags & CF_TYPE) { + switch (Flags & CF_TYPE) { case CF_CHAR: /* Character sized */ - if (flags & CF_UNSIGNED) { - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); + if (Flags & CF_UNSIGNED) { AddCodeLine ("jsr ldauidx"); } else { - ldyconst (offs); AddCodeLine ("jsr ldaidx"); } break; case CF_INT: - if (flags & CF_TEST) { - ldyconst (offs); + if (Flags & CF_TEST) { + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); AddCodeLine ("lda (ptr1),y"); AddCodeLine ("iny"); AddCodeLine ("ora (ptr1),y"); } else { - ldyconst (offs+1); + AddCodeLine ("ldy #$%02X", Offs+1); AddCodeLine ("jsr ldaxidx"); } break; case CF_LONG: - ldyconst (offs+3); + AddCodeLine ("ldy #$%02X", Offs+3); AddCodeLine ("jsr ldeaxidx"); - if (flags & CF_TEST) { - g_test (flags); + if (Flags & CF_TEST) { + g_test (Flags); } break; default: - typeerror (flags); + typeerror (Flags); } } -void g_leasp (int offs) +void g_leasp (int Offs) /* Fetch the address of the specified symbol into the primary register */ { + unsigned char Lo, Hi; + /* Calculate the offset relative to sp */ - offs -= StackPtr; + Offs -= StackPtr; - /* For value 0 we do direct code */ - if (offs == 0) { - AddCodeLine ("lda sp"); - AddCodeLine ("ldx sp+1"); - } else { - if (IS_Get (&CodeSizeFactor) < 300) { - ldaconst (offs); /* Load A with offset value */ - AddCodeLine ("jsr leaasp"); /* Load effective address */ + /* Get low and high byte */ + Lo = (unsigned char) Offs; + Hi = (unsigned char) (Offs >> 8); + + /* Generate code */ + if (Lo == 0) { + if (Hi <= 3) { + AddCodeLine ("lda sp"); + AddCodeLine ("ldx sp+1"); + while (Hi--) { + AddCodeLine ("inx"); + } + } else { + AddCodeLine ("lda sp+1"); + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", Hi); + AddCodeLine ("tax"); + AddCodeLine ("lda sp"); + } + } else if (Hi == 0) { + /* 8 bit offset */ + if (IS_Get (&CodeSizeFactor) < 200) { + /* 8 bit offset with subroutine call */ + AddCodeLine ("lda #$%02X", Lo); + AddCodeLine ("jsr leaa0sp"); } else { + /* 8 bit offset inlined */ unsigned L = GetLocalLabel (); - if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && offs == 1) { - AddCodeLine ("lda sp"); - AddCodeLine ("ldx sp+1"); - AddCodeLine ("ina"); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("inx"); - } else { - ldaconst (offs); - AddCodeLine ("clc"); - AddCodeLine ("ldx sp+1"); - AddCodeLine ("adc sp"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); - } + AddCodeLine ("lda sp"); + AddCodeLine ("ldx sp+1"); + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", Lo); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); g_defcodelabel (L); } + } else if (IS_Get (&CodeSizeFactor) < 170) { + /* Full 16 bit offset with subroutine call */ + AddCodeLine ("lda #$%02X", Lo); + AddCodeLine ("ldx #$%02X", Hi); + AddCodeLine ("jsr leaaxsp"); + } else { + /* Full 16 bit offset inlined */ + AddCodeLine ("lda sp"); + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", Lo); + AddCodeLine ("pha"); + AddCodeLine ("lda sp+1"); + AddCodeLine ("adc #$%02X", Hi); + AddCodeLine ("tax"); + AddCodeLine ("pla"); } } @@ -971,7 +973,7 @@ void g_leavariadic (int Offs) CheckLocalOffs (ArgSizeOffs); /* Get the size of all parameters. */ - ldyconst (ArgSizeOffs); + AddCodeLine ("ldy #$%02X", ArgSizeOffs); AddCodeLine ("lda (sp),y"); /* Add the value of the stackpointer */ @@ -984,7 +986,8 @@ void g_leavariadic (int Offs) AddCodeLine ("inx"); g_defcodelabel (L); } else { - AddCodeLine ("jsr leaasp"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("jsr leaaxsp"); } /* Add the offset to the primary */ @@ -1049,13 +1052,13 @@ void g_putlocal (unsigned Flags, int Offs, long Val) if (Flags & CF_CONST) { AddCodeLine ("lda #$%02X", (unsigned char) Val); } - ldyconst (Offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("sta (sp),y"); break; case CF_INT: if (Flags & CF_CONST) { - ldyconst (Offs+1); + AddCodeLine ("ldy #$%02X", Offs+1); AddCodeLine ("lda #$%02X", (unsigned char) (Val >> 8)); AddCodeLine ("sta (sp),y"); if ((Flags & CF_NOKEEP) == 0) { @@ -1072,11 +1075,10 @@ void g_putlocal (unsigned Flags, int Offs, long Val) } AddCodeLine ("sta (sp),y"); } else { + AddCodeLine ("ldy #$%02X", Offs); if ((Flags & CF_NOKEEP) == 0 || IS_Get (&CodeSizeFactor) < 160) { - ldyconst (Offs); AddCodeLine ("jsr staxysp"); } else { - ldyconst (Offs); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCodeLine ("txa"); @@ -1089,7 +1091,7 @@ void g_putlocal (unsigned Flags, int Offs, long Val) if (Flags & CF_CONST) { g_getimmed (Flags, Val, 0); } - ldyconst (Offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr steaxysp"); break; @@ -1145,20 +1147,18 @@ void g_putind (unsigned Flags, unsigned Offs) } /* Check the size and determine operation */ + AddCodeLine ("ldy #$%02X", Offs); switch (Flags & CF_TYPE) { case CF_CHAR: - ldyconst (Offs); AddCodeLine ("jsr staspidx"); break; case CF_INT: - ldyconst (Offs); AddCodeLine ("jsr staxspidx"); break; case CF_LONG: - ldyconst (Offs); AddCodeLine ("jsr steaxspidx"); break; @@ -1297,7 +1297,7 @@ void g_reglong (unsigned Flags) case CF_INT: if (Flags & CF_UNSIGNED) { if (IS_Get (&CodeSizeFactor) >= 200) { - ldyconst (0); + AddCodeLine ("ldy #$00"); AddCodeLine ("sty sreg"); AddCodeLine ("sty sreg+1"); } else { @@ -1735,19 +1735,19 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs, -void g_addeqlocal (unsigned flags, int offs, unsigned long val) +void g_addeqlocal (unsigned flags, int Offs, unsigned long val) /* Emit += for a local variable */ { /* Calculate the true offset, check it, load it into Y */ - offs -= StackPtr; - CheckLocalOffs (offs); + Offs -= StackPtr; + CheckLocalOffs (Offs); /* Check the size and determine operation */ switch (flags & CF_TYPE) { case CF_CHAR: if (flags & CF_FORCECHAR) { - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); if (flags & CF_CONST) { AddCodeLine ("clc"); @@ -1770,7 +1770,7 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val) /* FALLTHROUGH */ case CF_INT: - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); if (flags & CF_CONST) { if (IS_Get (&CodeSizeFactor) >= 400) { AddCodeLine ("clc"); @@ -1797,7 +1797,7 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val) if (flags & CF_CONST) { g_getimmed (flags, val, 0); } - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr laddeqysp"); break; @@ -1967,19 +1967,19 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs, -void g_subeqlocal (unsigned flags, int offs, unsigned long val) +void g_subeqlocal (unsigned flags, int Offs, unsigned long val) /* Emit -= for a local variable */ { /* Calculate the true offset, check it, load it into Y */ - offs -= StackPtr; - CheckLocalOffs (offs); + Offs -= StackPtr; + CheckLocalOffs (Offs); /* Check the size and determine operation */ switch (flags & CF_TYPE) { case CF_CHAR: if (flags & CF_FORCECHAR) { - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); if (flags & CF_CONST) { AddCodeLine ("lda (sp),y"); @@ -2005,7 +2005,7 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val) if (flags & CF_CONST) { g_getimmed (flags, val, 0); } - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr subeqysp"); break; @@ -2013,7 +2013,7 @@ void g_subeqlocal (unsigned flags, int offs, unsigned long val) if (flags & CF_CONST) { g_getimmed (flags, val, 0); } - ldyconst (offs); + AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr lsubeqysp"); break; @@ -2314,7 +2314,7 @@ void g_push (unsigned flags, unsigned long val) if ((flags & CF_TYPE) == CF_CHAR && (flags & CF_FORCECHAR)) { /* Handle as 8 bit value */ - ldaconst (val); + AddCodeLine ("lda #$%02X", (unsigned char) val); AddCodeLine ("jsr pusha"); } else { @@ -2392,7 +2392,7 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize) { if ((Flags & CF_FIXARGC) == 0) { /* Pass the argument count */ - ldyconst (ArgSize); + AddCodeLine ("ldy #$%02X", ArgSize); } AddCodeLine ("jsr _%s", Label); StackPtr += ArgSize; /* callee pops args */ @@ -2407,7 +2407,7 @@ void g_callind (unsigned Flags, unsigned ArgSize, int Offs) /* Address is in a/x */ if ((Flags & CF_FIXARGC) == 0) { /* Pass arg count */ - ldyconst (ArgSize); + AddCodeLine ("ldy #$%02X", ArgSize); } AddCodeLine ("jsr callax"); } else { @@ -2455,26 +2455,56 @@ void g_falsejump (unsigned flags attribute ((unused)), unsigned label) -static void mod_internal (int k, char* verb1, char* verb2) +void g_drop (unsigned Space) +/* Drop space allocated on the stack */ { - if (k <= 8) { - AddCodeLine ("jsr %ssp%c", verb1, k + '0'); - } else { - CheckLocalOffs (k); - ldyconst (k); - AddCodeLine ("jsr %ssp", verb2); + if (Space > 255) { + /* Inline the code since calling addysp repeatedly is quite some + * overhead. + */ + AddCodeLine ("pha"); + AddCodeLine ("lda #$%02X", (unsigned char) Space); + AddCodeLine ("clc"); + AddCodeLine ("adc sp"); + AddCodeLine ("sta sp"); + AddCodeLine ("lda #$%02X", (unsigned char) (Space >> 8)); + AddCodeLine ("adc sp+1"); + AddCodeLine ("sta sp+1"); + AddCodeLine ("pla"); + } else if (Space > 8) { + AddCodeLine ("ldy #$%02X", Space); + AddCodeLine ("jsr addysp"); + } else if (Space != 0) { + AddCodeLine ("jsr incsp%u", Space); } } -void g_space (int space) +void g_space (int Space) /* Create or drop space on the stack */ { - if (space < 0) { - mod_internal (-space, "inc", "addy"); - } else if (space > 0) { - mod_internal (space, "dec", "suby"); + if (Space < 0) { + /* This is actually a drop operation */ + g_drop (-Space); + } else if (Space > 255) { + /* Inline the code since calling subysp repeatedly is quite some + * overhead. + */ + AddCodeLine ("pha"); + AddCodeLine ("lda sp"); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char) Space); + AddCodeLine ("sta sp"); + AddCodeLine ("lda sp+1"); + AddCodeLine ("sbc #$%02X", (unsigned char) (Space >> 8)); + AddCodeLine ("sta sp+1"); + AddCodeLine ("pla"); + } else if (Space > 8) { + AddCodeLine ("ldy #$%02X", Space); + AddCodeLine ("jsr subysp"); + } else if (Space != 0) { + AddCodeLine ("jsr decsp%u", Space); } } @@ -2728,7 +2758,7 @@ void g_or (unsigned flags, unsigned long val) if ((val & 0xFF) != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); } - ldxconst (0xFF); + AddCodeLine ("ldx #$FF"); } else if (val != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); AddCodeLine ("pha"); @@ -2850,7 +2880,9 @@ void g_and (unsigned Flags, unsigned long Val) case CF_CHAR: if (Flags & CF_FORCECHAR) { - if ((Val & 0xFF) != 0xFF) { + if ((Val & 0xFF) == 0x00) { + AddCodeLine ("lda #$00"); + } else if ((Val & 0xFF) != 0xFF) { AddCodeLine ("and #$%02X", (unsigned char)Val); } return; @@ -2859,35 +2891,39 @@ void g_and (unsigned Flags, unsigned long Val) case CF_INT: if ((Val & 0xFFFF) != 0xFFFF) { if (Val <= 0xFF) { - ldxconst (0); + AddCodeLine ("ldx #$00"); if (Val == 0) { - ldaconst (0); + AddCodeLine ("lda #$00"); } else if (Val != 0xFF) { AddCodeLine ("and #$%02X", (unsigned char)Val); } - } else if ((Val & 0xFF00) == 0xFF00) { + } else if ((Val & 0xFFFF) == 0xFF00) { + AddCodeLine ("lda #$00"); + } else if ((Val & 0xFF00) == 0xFF00) { AddCodeLine ("and #$%02X", (unsigned char)Val); } else if ((Val & 0x00FF) == 0x0000) { AddCodeLine ("txa"); AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8)); AddCodeLine ("tax"); - ldaconst (0); + AddCodeLine ("lda #$00"); } else { AddCodeLine ("tay"); AddCodeLine ("txa"); AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8)); AddCodeLine ("tax"); AddCodeLine ("tya"); - if ((Val & 0x00FF) != 0x00FF) { + if ((Val & 0x00FF) == 0x0000) { + AddCodeLine ("lda #$00"); + } else if ((Val & 0x00FF) != 0x00FF) { AddCodeLine ("and #$%02X", (unsigned char)Val); - } + } } } return; case CF_LONG: if (Val <= 0xFF) { - ldxconst (0); + AddCodeLine ("ldx #$00"); AddCodeLine ("stx sreg+1"); AddCodeLine ("stx sreg"); if ((Val & 0xFF) != 0xFF) { @@ -2895,7 +2931,7 @@ void g_and (unsigned Flags, unsigned long Val) } return; } else if (Val == 0xFF00) { - ldaconst (0); + AddCodeLine ("lda #$00"); AddCodeLine ("sta sreg+1"); AddCodeLine ("sta sreg"); return; @@ -2936,44 +2972,55 @@ void g_asr (unsigned flags, unsigned long val) case CF_CHAR: case CF_INT: - if (val >= 8 && (flags & CF_UNSIGNED)) { - AddCodeLine ("txa"); - ldxconst (0); + val &= 0x0F; + if (val >= 8) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("txa"); + AddCodeLine ("ldx #$00"); + } else { + unsigned L = GetLocalLabel(); + AddCodeLine ("cpx #$80"); /* Sign bit into carry */ + AddCodeLine ("txa"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("dex"); /* Make $FF */ + g_defcodelabel (L); + } val -= 8; } - if (val == 0) { - /* Done */ - return; - } else if (val >= 1 && val <= 4) { + if (val >= 4) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shrax4"); + } else { + AddCodeLine ("jsr asrax4"); + } + val -= 4; + } + if (val > 0) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shrax%ld", val); } else { AddCodeLine ("jsr asrax%ld", val); } - return; } - break; + return; case CF_LONG: - if (val == 0) { - /* Nothing to do */ - return; - } else if (val >= 1 && val <= 4) { - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr shreax%ld", val); - } else { - AddCodeLine ("jsr asreax%ld", val); + val &= 0x1F; + if (val >= 24) { + AddCodeLine ("ldx #$00"); + AddCodeLine ("lda sreg+1"); + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); } - return; - } else if (val == 8 && (flags & CF_UNSIGNED)) { - AddCodeLine ("txa"); - AddCodeLine ("ldx sreg"); - AddCodeLine ("ldy sreg+1"); - AddCodeLine ("sty sreg"); - AddCodeLine ("ldy #$00"); - AddCodeLine ("sty sreg+1"); - return; - } else if (val == 16) { + AddCodeLine ("stx sreg"); + AddCodeLine ("stx sreg+1"); + val -= 24; + } + if (val >= 16) { AddCodeLine ("ldy #$00"); AddCodeLine ("ldx sreg+1"); if ((flags & CF_UNSIGNED) == 0) { @@ -2985,9 +3032,42 @@ void g_asr (unsigned flags, unsigned long val) AddCodeLine ("lda sreg"); AddCodeLine ("sty sreg+1"); AddCodeLine ("sty sreg"); - return; + val -= 16; } - break; + if (val >= 8) { + AddCodeLine ("txa"); + AddCodeLine ("ldx sreg"); + AddCodeLine ("ldy sreg+1"); + AddCodeLine ("sty sreg"); + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("cpy #$80"); + AddCodeLine ("ldy #$00"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("dey"); + g_defcodelabel (L); + } else { + AddCodeLine ("ldy #$00"); + } + AddCodeLine ("sty sreg+1"); + val -= 8; + } + if (val >= 4) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shreax4"); + } else { + AddCodeLine ("jsr asreax4"); + } + val -= 4; + } + if (val > 0) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shreax%ld", val); + } else { + AddCodeLine ("jsr asreax%ld", val); + } + } + return; default: typeerror (flags); @@ -3024,50 +3104,69 @@ void g_asl (unsigned flags, unsigned long val) case CF_CHAR: case CF_INT: + val &= 0x0F; if (val >= 8) { AddCodeLine ("tax"); AddCodeLine ("lda #$00"); val -= 8; } - if (val == 0) { - /* Done */ - return; - } else if (val >= 1 && val <= 4) { + if (val >= 4) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shlax4"); + } else { + AddCodeLine ("jsr aslax4"); + } + val -= 4; + } + if (val > 0) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shlax%ld", val); } else { AddCodeLine ("jsr aslax%ld", val); } - return; } - break; + return; case CF_LONG: - if (val == 0) { - /* Nothing to do */ - return; - } else if (val >= 1 && val <= 4) { - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr shleax%ld", val); - } else { - AddCodeLine ("jsr asleax%ld", val); - } - return; - } else if (val == 8) { - AddCodeLine ("ldy sreg"); - AddCodeLine ("sty sreg+1"); - AddCodeLine ("stx sreg"); - AddCodeLine ("tax"); + val &= 0x1F; + if (val >= 24) { + AddCodeLine ("sta sreg+1"); AddCodeLine ("lda #$00"); - return; - } else if (val == 16) { + AddCodeLine ("tax"); + AddCodeLine ("sta sreg"); + val -= 24; + } + if (val >= 16) { AddCodeLine ("stx sreg+1"); AddCodeLine ("sta sreg"); AddCodeLine ("lda #$00"); AddCodeLine ("tax"); - return; + val -= 16; } - break; + if (val >= 8) { + AddCodeLine ("ldy sreg"); + AddCodeLine ("sty sreg+1"); + AddCodeLine ("stx sreg"); + AddCodeLine ("tax"); + AddCodeLine ("lda #$00"); + val -= 8; + } + if (val > 4) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shleax4"); + } else { + AddCodeLine ("jsr asleax4"); + } + val -= 4; + } + if (val > 0) { + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shleax%ld", val); + } else { + AddCodeLine ("jsr asleax%ld", val); + } + } + return; default: typeerror (flags); @@ -3205,7 +3304,7 @@ void g_inc (unsigned flags, unsigned long val) if (val <= 8) { AddCodeLine ("jsr incax%lu", val); } else if (val <= 255) { - ldyconst (val); + AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr incaxy"); } else { g_add (flags | CF_CONST, val); @@ -3230,13 +3329,18 @@ void g_inc (unsigned flags, unsigned long val) if (val >= 0x300) { AddCodeLine ("inx"); } - } else { + } else if ((val & 0xFF) != 0) { AddCodeLine ("clc"); - if ((val & 0xFF) != 0) { - AddCodeLine ("adc #$%02X", (unsigned char) val); - } + AddCodeLine ("adc #$%02X", (unsigned char) val); + AddCodeLine ("pha"); + AddCodeLine ("txa"); + AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8)); + AddCodeLine ("tax"); + AddCodeLine ("pla"); + } else { AddCodeLine ("pha"); AddCodeLine ("txa"); + AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); @@ -3246,7 +3350,7 @@ void g_inc (unsigned flags, unsigned long val) case CF_LONG: if (val <= 255) { - ldyconst (val); + AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr inceaxy"); } else { g_add (flags | CF_CONST, val); @@ -3293,7 +3397,7 @@ void g_dec (unsigned flags, unsigned long val) if (val <= 8) { AddCodeLine ("jsr decax%d", (int) val); } else if (val <= 255) { - ldyconst (val); + AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr decaxy"); } else { g_sub (flags | CF_CONST, val); @@ -3338,7 +3442,7 @@ void g_dec (unsigned flags, unsigned long val) case CF_LONG: if (val <= 255) { - ldyconst (val); + AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr deceaxy"); } else { g_sub (flags | CF_CONST, val); @@ -3476,6 +3580,8 @@ void g_lt (unsigned flags, unsigned long val) "tosltax", "tosultax", "toslteax", "tosulteax", }; + unsigned Label; + /* If the right hand side is const, the lhs is not on stack but still * in the primary register. */ @@ -3535,32 +3641,84 @@ void g_lt (unsigned flags, unsigned long val) } else if (val == 0) { - /* Look at the type */ + /* A signed compare against zero must only look at the sign bit */ switch (flags & CF_TYPE) { case CF_CHAR: if (flags & CF_FORCECHAR) { - AddCodeLine ("tax"); - AddCodeLine ("jsr boollt"); + AddCodeLine ("asl a"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); return; } /* FALLTHROUGH */ case CF_INT: /* Just check the high byte */ - AddCodeLine ("txa"); - AddCodeLine ("jsr boollt"); + AddCodeLine ("cpx #$80"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); return; case CF_LONG: /* Just check the high byte */ AddCodeLine ("lda sreg+1"); - AddCodeLine ("jsr boollt"); + AddCodeLine ("asl a"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); + return; + + default: + typeerror (flags); + } + + } else { + + /* Signed compare against a constant != zero */ + switch (flags & CF_TYPE) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + Label = GetLocalLabel (); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char)val); + AddCodeLine ("bvc %s", LocalLabelName (Label)); + AddCodeLine ("eor #$80"); + g_defcodelabel (Label); + AddCodeLine ("asl a"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); + return; + } + /* FALLTHROUGH */ + + case CF_INT: + /* Do a subtraction */ + Label = GetLocalLabel (); + AddCodeLine ("cmp #$%02X", (unsigned char)val); + AddCodeLine ("txa"); + AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("bvc %s", LocalLabelName (Label)); + AddCodeLine ("eor #$80"); + g_defcodelabel (Label); + AddCodeLine ("asl a"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); return; + case CF_LONG: + /* This one is too costly */ + break; + default: typeerror (flags); } + } /* If we go here, we didn't emit code. Push the lhs on stack and fall @@ -3830,6 +3988,8 @@ void g_ge (unsigned flags, unsigned long val) "tosgeax", "tosugeax", "tosgeeax", "tosugeeax", }; + unsigned Label; + /* If the right hand side is const, the lhs is not on stack but still * in the primary register. @@ -3854,26 +4014,27 @@ void g_ge (unsigned flags, unsigned long val) case CF_CHAR: if (flags & CF_FORCECHAR) { + /* Do a subtraction. Condition is true if carry set */ AddCodeLine ("cmp #$%02X", (unsigned char)val); - AddCodeLine ("jsr booluge"); + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); return; } /* FALLTHROUGH */ case CF_INT: - /* If the low byte is zero, we must only test the high byte */ - AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); - if ((val & 0xFF) != 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("cmp #$%02X", (unsigned char)val); - g_defcodelabel (L); - } - AddCodeLine ("jsr booluge"); + /* Do a subtraction. Condition is true if carry set */ + AddCodeLine ("cmp #$%02X", (unsigned char)val); + AddCodeLine ("txa"); + AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); return; case CF_LONG: - /* Do a subtraction */ + /* Do a subtraction. Condition is true if carry set */ AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); @@ -3881,7 +4042,9 @@ void g_ge (unsigned flags, unsigned long val) AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16)); AddCodeLine ("lda sreg+1"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24)); - AddCodeLine ("jsr booluge"); + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); return; default: @@ -3890,7 +4053,7 @@ void g_ge (unsigned flags, unsigned long val) } else if (val == 0) { - /* Look at the type */ + /* A signed compare against zero must only look at the sign bit */ switch (flags & CF_TYPE) { case CF_CHAR: @@ -3916,8 +4079,51 @@ void g_ge (unsigned flags, unsigned long val) default: typeerror (flags); } - } + } else { + + /* Signed compare against a constant != zero */ + switch (flags & CF_TYPE) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + Label = GetLocalLabel (); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char)val); + AddCodeLine ("bvs %s", LocalLabelName (Label)); + AddCodeLine ("eor #$80"); + g_defcodelabel (Label); + AddCodeLine ("asl a"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); + return; + } + /* FALLTHROUGH */ + + case CF_INT: + /* Do a subtraction */ + Label = GetLocalLabel (); + AddCodeLine ("cmp #$%02X", (unsigned char)val); + AddCodeLine ("txa"); + AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("bvs %s", LocalLabelName (Label)); + AddCodeLine ("eor #$80"); + g_defcodelabel (Label); + AddCodeLine ("asl a"); /* Bit 7 -> carry */ + AddCodeLine ("lda #$00"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("rol a"); + return; + + case CF_LONG: + /* This one is too costly */ + break; + + default: + typeerror (flags); + } + } /* If we go here, we didn't emit code. Push the lhs on stack and fall * into the normal, non-optimized stuff. Note: The standard stuff will @@ -4016,7 +4222,7 @@ void g_defbytes (const void* Bytes, unsigned Count) } while (Chunk); /* Output the line */ - AddDataLine (Buf); + AddDataLine ("%s", Buf); } } @@ -4037,7 +4243,7 @@ void g_initregister (unsigned Label, unsigned Reg, unsigned Size) { /* Register variables do always have less than 128 bytes */ unsigned CodeLabel = GetLocalLabel (); - ldxconst (Size-1); + AddCodeLine ("ldx #$%02X", (unsigned char) (Size - 1)); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,x", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta %s,x", GetLabelName (CF_REGVAR, Reg, 0)); @@ -4054,14 +4260,14 @@ void g_initauto (unsigned Label, unsigned Size) CheckLocalOffs (Size); if (Size <= 128) { - ldyconst (Size-1); + AddCodeLine ("ldy #$%02X", Size-1); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta (sp),y"); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (CodeLabel)); } else if (Size <= 256) { - ldyconst (0); + AddCodeLine ("ldy #$00"); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta (sp),y"); @@ -4078,7 +4284,7 @@ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size) { if (Size <= 128) { unsigned CodeLabel = GetLocalLabel (); - ldyconst (Size-1); + AddCodeLine ("ldy #$%02X", Size-1); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0)); AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0)); @@ -4086,7 +4292,7 @@ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size) AddCodeLine ("bpl %s", LocalLabelName (CodeLabel)); } else if (Size <= 256) { unsigned CodeLabel = GetLocalLabel (); - ldyconst (0); + AddCodeLine ("ldy #$00"); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0)); AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0)); @@ -4193,7 +4399,7 @@ void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth) void g_asmcode (struct StrBuf* B) /* Output one line of assembler code. */ { - AddCodeLine ("%.*s", SB_GetLen (B), SB_GetConstBuf (B)); + AddCodeLine ("%.*s", (int) SB_GetLen (B), SB_GetConstBuf (B)); }