X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodegen.c;h=a611f4f6a809ec0789c5c975bfc7876104e10b8e;hb=58484449b4842517d09618bc1c5dad59373250ef;hp=060d3a9d4cbc4c1fae6bffad29bb2146442916b3;hpb=40dc3582a9a50be2be845090b2580d3b837450cc;p=cc65 diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 060d3a9d4..a611f4f6a 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* codegen.c */ +/* codegen.c */ /* */ -/* 6502 code generator */ +/* 6502 code generator */ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2013, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -40,10 +40,11 @@ /* common */ #include "check.h" #include "cpu.h" +#include "inttypes.h" #include "strbuf.h" -#include "version.h" #include "xmalloc.h" #include "xsprintf.h" +#include "version.h" /* cc65 */ #include "asmcode.h" @@ -54,6 +55,8 @@ #include "error.h" #include "global.h" #include "segments.h" +#include "stackptr.h" +#include "stdfunc.h" #include "textseg.h" #include "util.h" #include "codegen.h" @@ -61,18 +64,7 @@ /*****************************************************************************/ -/* Data */ -/*****************************************************************************/ - - - -/* Compiler relative stack pointer */ -int oursp = 0; - - - -/*****************************************************************************/ -/* Helpers */ +/* Helpers */ /*****************************************************************************/ @@ -80,7 +72,12 @@ int oursp = 0; 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_TYPEMASK) == CF_FLOAT) { + Fatal ("Floating point type is currently unsupported"); + } else { + Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPEMASK); + } } @@ -89,50 +86,50 @@ static void CheckLocalOffs (unsigned Offs) /* Check the offset into the stack for 8bit range */ { if (Offs >= 256) { - /* Too many local vars */ - Error ("Too many local variables"); + /* Too many local vars */ + Error ("Too many local variables"); } } -static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs) +static const char* GetLabelName (unsigned Flags, uintptr_t Label, long Offs) { - static char Buf [256]; /* Label name */ + static char Buf [256]; /* Label name */ /* Create the correct label name */ switch (Flags & CF_ADDRMASK) { - case CF_STATIC: - /* Static memory cell */ - if (Offs) { - xsprintf (Buf, sizeof (Buf), "%s%+ld", LocalLabelName (Label), Offs); - } else { - xsprintf (Buf, sizeof (Buf), "%s", LocalLabelName (Label)); - } - break; - - case CF_EXTERNAL: - /* External label */ - if (Offs) { - xsprintf (Buf, sizeof (Buf), "_%s%+ld", (char*) Label, Offs); - } else { - xsprintf (Buf, sizeof (Buf), "_%s", (char*) Label); - } - break; - - case CF_ABSOLUTE: - /* Absolute address */ - xsprintf (Buf, sizeof (Buf), "$%04X", (int)((Label+Offs) & 0xFFFF)); - break; - - case CF_REGVAR: - /* Variable in register bank */ - xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF)); - break; - - default: - Internal ("Invalid address flags: %04X", Flags); + case CF_STATIC: + /* Static memory cell */ + if (Offs) { + xsprintf (Buf, sizeof (Buf), "%s%+ld", LocalLabelName (Label), Offs); + } else { + xsprintf (Buf, sizeof (Buf), "%s", LocalLabelName (Label)); + } + break; + + case CF_EXTERNAL: + /* External label */ + if (Offs) { + xsprintf (Buf, sizeof (Buf), "_%s%+ld", (char*) Label, Offs); + } else { + xsprintf (Buf, sizeof (Buf), "_%s", (char*) Label); + } + break; + + case CF_ABSOLUTE: + /* Absolute address */ + xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Label+Offs) & 0xFFFF)); + break; + + case CF_REGVAR: + /* Variable in register bank */ + xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF)); + break; + + default: + Internal ("Invalid address flags: %04X", Flags); } /* Return a pointer to the static buffer */ @@ -142,7 +139,7 @@ static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs) /*****************************************************************************/ -/* Pre- and postamble */ +/* Pre- and postamble */ /*****************************************************************************/ @@ -150,26 +147,23 @@ 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) { case CPU_6502: AddTextLine ("\t.setcpu\t\t\"6502\""); break; + case CPU_6502X: AddTextLine ("\t.setcpu\t\t\"6502X\""); break; case CPU_65SC02: AddTextLine ("\t.setcpu\t\t\"65SC02\""); break; case CPU_65C02: AddTextLine ("\t.setcpu\t\t\"65C02\""); break; case CPU_65816: AddTextLine ("\t.setcpu\t\t\"65816\""); break; + case CPU_HUC6280: AddTextLine ("\t.setcpu\t\t\"HUC6280\""); break; default: Internal ("Unknown CPU: %d", CPU); } @@ -185,8 +179,9 @@ void g_preamble (void) /* Tell the assembler if we want to generate debug info */ AddTextLine ("\t.debuginfo\t%s", (DebugInfo != 0)? "on" : "off"); - /* Import the stack pointer for direct auto variable access */ - AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank, tmp1, ptr1, ptr2"); + /* Import zero page variables */ + AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank"); + AddTextLine ("\t.importzp\ttmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4"); /* Define long branch macros */ AddTextLine ("\t.macpack\tlongbranch"); @@ -198,17 +193,17 @@ void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime) /* If debug info is enabled, place a file info into the source */ { if (DebugInfo) { - /* We have to place this into the global text segment, so it will - * appear before all .dbg line statements. - */ - TS_AddLine (GS->Text, "\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime); + /* We have to place this into the global text segment, so it will + ** appear before all .dbg line statements. + */ + TS_AddLine (GS->Text, "\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime); } } /*****************************************************************************/ -/* Segment support */ +/* Segment support */ /*****************************************************************************/ @@ -243,20 +238,20 @@ void g_segname (segment_t Seg) /* Emit a segment directive for the data style segments */ DataSeg* S; switch (Seg) { - case SEG_RODATA: S = CS->ROData; break; - case SEG_DATA: S = CS->Data; break; - case SEG_BSS: S = CS->BSS; break; - default: S = 0; break; + case SEG_RODATA: S = CS->ROData; break; + case SEG_DATA: S = CS->Data; break; + case SEG_BSS: S = CS->BSS; break; + default: S = 0; break; } if (S) { - DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg)); + DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg)); } } /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -264,24 +259,24 @@ void g_segname (segment_t Seg) unsigned sizeofarg (unsigned flags) /* Return the size of a function argument type that is encoded in flags */ { - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - return (flags & CF_FORCECHAR)? 1 : 2; + case CF_CHAR: + return (flags & CF_FORCECHAR)? 1 : 2; - case CF_INT: - return 2; + case CF_INT: + return 2; - case CF_LONG: - return 4; + case CF_LONG: + return 4; case CF_FLOAT: return 4; - default: - typeerror (flags); - /* NOTREACHED */ - return 2; + default: + typeerror (flags); + /* NOTREACHED */ + return 2; } } @@ -290,7 +285,7 @@ unsigned sizeofarg (unsigned flags) int pop (unsigned flags) /* Pop an argument of the given size */ { - return oursp += sizeofarg (flags); + return StackPtr += sizeofarg (flags); } @@ -298,32 +293,32 @@ int pop (unsigned flags) int push (unsigned flags) /* Push an argument of the given size */ { - return oursp -= sizeofarg (flags); + return StackPtr -= sizeofarg (flags); } static unsigned MakeByteOffs (unsigned Flags, unsigned Offs) /* The value in Offs is an offset to an address in a/x. Make sure, an object - * of the type given in Flags can be loaded or stored into this address by - * adding part of the offset to the address in ax, so that the remaining - * offset fits into an index register. Return the remaining offset. - */ +** of the type given in Flags can be loaded or stored into this address by +** adding part of the offset to the address in ax, so that the remaining +** offset fits into an index register. Return the remaining offset. +*/ { /* If the offset is too large for a byte register, add the high byte - * of the offset to the primary. Beware: We need a special correction - * if the offset in the low byte will overflow in the operation. - */ + ** of the offset to the primary. Beware: We need a special correction + ** if the offset in the low byte will overflow in the operation. + */ unsigned O = Offs & ~0xFFU; if ((Offs & 0xFF) > 256 - sizeofarg (Flags)) { - /* We need to add the low byte also */ - O += Offs & 0xFF; + /* We need to add the low byte also */ + O += Offs & 0xFF; } /* Do the correction if we need one */ if (O != 0) { - g_inc (CF_INT | CF_CONST, O); - Offs -= O; + g_inc (CF_INT | CF_CONST, O); + Offs -= O; } /* Return the new offset */ @@ -333,7 +328,7 @@ static unsigned MakeByteOffs (unsigned Flags, unsigned Offs) /*****************************************************************************/ -/* Functions handling local labels */ +/* Functions handling local labels */ /*****************************************************************************/ @@ -354,8 +349,26 @@ 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 */ +/* Functions handling global labels */ /*****************************************************************************/ @@ -373,9 +386,9 @@ void g_defexport (const char* Name, int ZP) /* Export the given label */ { if (ZP) { - AddTextLine ("\t.exportzp\t_%s", Name); + AddTextLine ("\t.exportzp\t_%s", Name); } else { - AddTextLine ("\t.export\t\t_%s", Name); + AddTextLine ("\t.export\t\t_%s", Name); } } @@ -385,63 +398,41 @@ void g_defimport (const char* Name, int ZP) /* Import the given label */ { if (ZP) { - AddTextLine ("\t.importzp\t_%s", Name); + AddTextLine ("\t.importzp\t_%s", Name); } else { - AddTextLine ("\t.import\t\t_%s", Name); + AddTextLine ("\t.import\t\t_%s", Name); } } -void g_importmainargs (void) -/* Forced import of a special symbol that handles arguments to main */ -{ - AddTextLine ("\t.forceimport\tinitmainargs"); -} - - - -/*****************************************************************************/ -/* 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 */ +void g_importstartup (void) +/* Forced import of the startup module */ { - AddCodeLine ("ldx #$%02X", val & 0xFF); + AddTextLine ("\t.forceimport\t__STARTUP__"); } -static void ldyconst (unsigned val) -/* Load y with a constant */ +void g_importmainargs (void) +/* Forced import of a special symbol that handles arguments to main */ { - AddCodeLine ("ldy #$%02X", val & 0xFF); + AddTextLine ("\t.forceimport\tinitmainargs"); } /*****************************************************************************/ -/* Function entry and exit */ +/* Function entry and exit */ /*****************************************************************************/ /* Remember the argument size of a function. The variable is set by g_enter - * and used by g_leave. If the functions gets its argument size by the caller - * (variable param list or function without prototype), g_enter will set the - * value to -1. - */ +** and used by g_leave. If the function gets its argument size by the caller +** (variable param list or function without prototype), g_enter will set the +** value to -1. +*/ static int funcargs; @@ -449,11 +440,11 @@ void g_enter (unsigned flags, unsigned argsize) /* Function prologue */ { if ((flags & CF_FIXARGC) != 0) { - /* Just remember the argument size for the leave */ - funcargs = argsize; + /* Just remember the argument size for the leave */ + funcargs = argsize; } else { - funcargs = -1; - AddCodeLine ("jsr enter"); + funcargs = -1; + AddCodeLine ("jsr enter"); } } @@ -463,33 +454,30 @@ void g_leave (void) /* Function epilogue */ { /* How many bytes of locals do we have to drop? */ - int k = -oursp; + unsigned ToDrop = (unsigned) -StackPtr; /* If we didn't have a variable argument list, don't call leave */ if (funcargs >= 0) { - /* Drop stackframe if needed */ - k += funcargs; - if (k > 0) { - if (k <= 8) { - AddCodeLine ("jsr incsp%d", k); - } else { - CheckLocalOffs (k); - ldyconst (k); - AddCodeLine ("jsr addysp"); - } - } + /* Drop stackframe if needed */ + g_drop (ToDrop + funcargs); + + } else if (StackPtr != 0) { + + /* We've a stack frame to drop */ + if (ToDrop > 255) { + g_drop (ToDrop); /* Inlines the code */ + AddCodeLine ("jsr leave"); + } else { + AddCodeLine ("ldy #$%02X", ToDrop); + AddCodeLine ("jsr leavey"); + } } else { - if (k == 0) { - /* Nothing to drop */ - AddCodeLine ("jsr leave"); - } else { - /* We've a stack frame to drop */ - ldyconst (k); - AddCodeLine ("jsr leavey"); - } + /* Nothing to drop */ + AddCodeLine ("jsr leave"); + } /* Add the final rts */ @@ -499,7 +487,7 @@ void g_leave (void) /*****************************************************************************/ -/* Register variables */ +/* Register variables */ /*****************************************************************************/ @@ -508,18 +496,17 @@ void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes) /* Swap a register variable with a location on the stack */ { /* Calculate the actual stack offset and check it */ - StackOffs -= oursp; + StackOffs -= StackPtr; CheckLocalOffs (StackOffs); /* Generate code */ + AddCodeLine ("ldy #$%02X", StackOffs & 0xFF); if (Bytes == 1) { - if (CodeSizeFactor < 165) { - ldyconst (StackOffs); - ldxconst (RegOffs); + if (IS_Get (&CodeSizeFactor) < 165) { + 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); @@ -529,15 +516,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"); } } @@ -550,33 +535,33 @@ void g_save_regvars (int RegOffs, unsigned Bytes) /* Don't loop for up to two bytes */ if (Bytes == 1) { - AddCodeLine ("lda regbank%+d", RegOffs); - AddCodeLine ("jsr pusha"); + AddCodeLine ("lda regbank%+d", RegOffs); + AddCodeLine ("jsr pusha"); } else if (Bytes == 2) { - AddCodeLine ("lda regbank%+d", RegOffs); - AddCodeLine ("ldx regbank%+d", RegOffs+1); - AddCodeLine ("jsr pushax"); + AddCodeLine ("lda regbank%+d", RegOffs); + AddCodeLine ("ldx regbank%+d", RegOffs+1); + AddCodeLine ("jsr pushax"); } else { - /* More than two bytes - loop */ - unsigned Label = GetLocalLabel (); - g_space (Bytes); - ldyconst (Bytes - 1); - ldxconst (Bytes); - g_defcodelabel (Label); - AddCodeLine ("lda regbank%+d,x", RegOffs-1); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("dey"); - AddCodeLine ("dex"); - AddCodeLine ("bne %s", LocalLabelName (Label)); + /* More than two bytes - loop */ + unsigned Label = GetLocalLabel (); + g_space (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"); + AddCodeLine ("dey"); + AddCodeLine ("dex"); + AddCodeLine ("bne %s", LocalLabelName (Label)); } /* We pushed stuff, correct the stack pointer */ - oursp -= Bytes; + StackPtr -= Bytes; } @@ -585,67 +570,67 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) /* Restore register variables */ { /* Calculate the actual stack offset and check it */ - StackOffs -= oursp; + StackOffs -= StackPtr; CheckLocalOffs (StackOffs); /* Don't loop for up to two bytes */ if (Bytes == 1) { - ldyconst (StackOffs); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d", RegOffs); + AddCodeLine ("ldy #$%02X", StackOffs); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d", RegOffs); } else if (Bytes == 2) { - ldyconst (StackOffs); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d", RegOffs); - AddCodeLine ("iny"); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d", RegOffs+1); - - } else if (Bytes == 3 && CodeSizeFactor >= 133) { - - ldyconst (StackOffs); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d", RegOffs); - AddCodeLine ("iny"); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d", RegOffs+1); - AddCodeLine ("iny"); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d", RegOffs+2); + AddCodeLine ("ldy #$%02X", StackOffs); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d", RegOffs); + AddCodeLine ("iny"); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d", RegOffs+1); + + } else if (Bytes == 3 && IS_Get (&CodeSizeFactor) >= 133) { + + AddCodeLine ("ldy #$%02X", StackOffs); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d", RegOffs); + AddCodeLine ("iny"); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d", RegOffs+1); + AddCodeLine ("iny"); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d", RegOffs+2); } else if (StackOffs <= RegOffs) { /* More bytes, but the relation between the register offset in the - * register bank and the stack offset allows us to generate short - * code that uses just one index register. - */ - unsigned Label = GetLocalLabel (); - ldyconst (StackOffs); - g_defcodelabel (Label); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d,y", RegOffs - StackOffs); - AddCodeLine ("iny"); - AddCodeLine ("cpy #$%02X", StackOffs + Bytes); - AddCodeLine ("bne %s", LocalLabelName (Label)); + ** register bank and the stack offset allows us to generate short + ** code that uses just one index register. + */ + unsigned Label = GetLocalLabel (); + AddCodeLine ("ldy #$%02X", StackOffs); + g_defcodelabel (Label); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta regbank%+d,y", RegOffs - StackOffs); + AddCodeLine ("iny"); + AddCodeLine ("cpy #$%02X", StackOffs + Bytes); + AddCodeLine ("bne %s", LocalLabelName (Label)); } else { - /* Ok, this is the generic code. We need to save X because the - * caller will only save A. - */ - unsigned Label = GetLocalLabel (); + /* OK, this is the generic code. We need to save X because the + ** caller will only save A. + */ + unsigned Label = GetLocalLabel (); AddCodeLine ("stx tmp1"); - ldyconst (StackOffs + Bytes - 1); - ldxconst (Bytes - 1); - g_defcodelabel (Label); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta regbank%+d,x", RegOffs); - AddCodeLine ("dey"); + 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); + AddCodeLine ("dey"); AddCodeLine ("dex"); - AddCodeLine ("bpl %s", LocalLabelName (Label)); + AddCodeLine ("bpl %s", LocalLabelName (Label)); AddCodeLine ("ldx tmp1"); } @@ -654,7 +639,7 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) /*****************************************************************************/ -/* Fetching memory cells */ +/* Fetching memory cells */ /*****************************************************************************/ @@ -668,277 +653,306 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs) if ((Flags & CF_CONST) != 0) { - /* Numeric constant */ - switch (Flags & CF_TYPE) { - - case CF_CHAR: - if ((Flags & CF_FORCECHAR) != 0) { - ldaconst (Val); - break; - } - /* FALL THROUGH */ - case CF_INT: - ldxconst ((Val >> 8) & 0xFF); - ldaconst (Val & 0xFF); - break; - - case CF_LONG: - /* Split the value into 4 bytes */ - B1 = (unsigned char) (Val >> 0); - B2 = (unsigned char) (Val >> 8); - B3 = (unsigned char) (Val >> 16); - B4 = (unsigned char) (Val >> 24); - - /* Remember which bytes are done */ - Done = 0; - - /* Load the value */ - AddCodeLine ("ldx #$%02X", B2); - Done |= 0x02; - if (B2 == B3) { - AddCodeLine ("stx sreg"); - Done |= 0x04; - } - if (B2 == B4) { - AddCodeLine ("stx sreg+1"); - Done |= 0x08; - } - if ((Done & 0x04) == 0 && B1 != B3) { - AddCodeLine ("lda #$%02X", B3); - AddCodeLine ("sta sreg"); - Done |= 0x04; - } - if ((Done & 0x08) == 0 && B1 != B4) { - AddCodeLine ("lda #$%02X", B4); - AddCodeLine ("sta sreg+1"); - Done |= 0x08; - } - AddCodeLine ("lda #$%02X", B1); - Done |= 0x01; - if ((Done & 0x04) == 0) { - CHECK (B1 == B3); - AddCodeLine ("sta sreg"); - } - if ((Done & 0x08) == 0) { - CHECK (B1 == B4); - AddCodeLine ("sta sreg+1"); - } - break; - - default: - typeerror (Flags); - break; - - } + /* Numeric constant */ + switch (Flags & CF_TYPEMASK) { + + case CF_CHAR: + if ((Flags & CF_FORCECHAR) != 0) { + AddCodeLine ("lda #$%02X", (unsigned char) Val); + break; + } + /* FALL THROUGH */ + case CF_INT: + AddCodeLine ("ldx #$%02X", (unsigned char) (Val >> 8)); + AddCodeLine ("lda #$%02X", (unsigned char) Val); + break; + + case CF_LONG: + /* Split the value into 4 bytes */ + B1 = (unsigned char) (Val >> 0); + B2 = (unsigned char) (Val >> 8); + B3 = (unsigned char) (Val >> 16); + B4 = (unsigned char) (Val >> 24); + + /* Remember which bytes are done */ + Done = 0; + + /* Load the value */ + AddCodeLine ("ldx #$%02X", B2); + Done |= 0x02; + if (B2 == B3) { + AddCodeLine ("stx sreg"); + Done |= 0x04; + } + if (B2 == B4) { + AddCodeLine ("stx sreg+1"); + Done |= 0x08; + } + if ((Done & 0x04) == 0 && B1 != B3) { + AddCodeLine ("lda #$%02X", B3); + AddCodeLine ("sta sreg"); + Done |= 0x04; + } + if ((Done & 0x08) == 0 && B1 != B4) { + AddCodeLine ("lda #$%02X", B4); + AddCodeLine ("sta sreg+1"); + Done |= 0x08; + } + AddCodeLine ("lda #$%02X", B1); + Done |= 0x01; + if ((Done & 0x04) == 0) { + CHECK (B1 == B3); + AddCodeLine ("sta sreg"); + } + if ((Done & 0x08) == 0) { + CHECK (B1 == B4); + AddCodeLine ("sta sreg+1"); + } + break; + + default: + typeerror (Flags); + break; + + } } else { - /* Some sort of label */ - const char* Label = GetLabelName (Flags, Val, Offs); + /* Some sort of label */ + const char* Label = GetLabelName (Flags, Val, Offs); - /* Load the address into the primary */ - AddCodeLine ("lda #<(%s)", Label); - AddCodeLine ("ldx #>(%s)", Label); + /* Load the address into the primary */ + AddCodeLine ("lda #<(%s)", Label); + AddCodeLine ("ldx #>(%s)", Label); } } -void g_getstatic (unsigned flags, unsigned long label, long offs) +void g_getstatic (unsigned flags, uintptr_t label, long offs) /* Fetch an static memory cell into the primary register */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and generate the correct load operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { - AddCodeLine ("lda %s", lbuf); /* load A from the label */ - } else { - ldxconst (0); - AddCodeLine ("lda %s", lbuf); /* load A from the label */ - if (!(flags & CF_UNSIGNED)) { - /* Must sign extend */ - unsigned L = GetLocalLabel (); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - } - break; - - case CF_INT: - AddCodeLine ("lda %s", lbuf); - if (flags & CF_TEST) { - AddCodeLine ("ora %s+1", lbuf); - } else { - AddCodeLine ("ldx %s+1", lbuf); - } - break; - - case CF_LONG: - if (flags & CF_TEST) { - AddCodeLine ("lda %s+3", lbuf); - AddCodeLine ("ora %s+2", lbuf); - AddCodeLine ("ora %s+1", lbuf); - AddCodeLine ("ora %s+0", lbuf); - } else { - AddCodeLine ("lda %s+3", lbuf); - AddCodeLine ("sta sreg+1"); - AddCodeLine ("lda %s+2", lbuf); - AddCodeLine ("sta sreg"); - AddCodeLine ("ldx %s+1", lbuf); - AddCodeLine ("lda %s", lbuf); - } - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { + AddCodeLine ("lda %s", lbuf); /* load A from the label */ + } else { + AddCodeLine ("ldx #$00"); + AddCodeLine ("lda %s", lbuf); /* load A from the label */ + if (!(flags & CF_UNSIGNED)) { + /* Must sign extend */ + unsigned L = GetLocalLabel (); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + } + break; + + case CF_INT: + AddCodeLine ("lda %s", lbuf); + if (flags & CF_TEST) { + AddCodeLine ("ora %s+1", lbuf); + } else { + AddCodeLine ("ldx %s+1", lbuf); + } + break; + + case CF_LONG: + if (flags & CF_TEST) { + AddCodeLine ("lda %s+3", lbuf); + AddCodeLine ("ora %s+2", lbuf); + AddCodeLine ("ora %s+1", lbuf); + AddCodeLine ("ora %s+0", lbuf); + } else { + AddCodeLine ("lda %s+3", lbuf); + AddCodeLine ("sta sreg+1"); + AddCodeLine ("lda %s+2", lbuf); + AddCodeLine ("sta sreg"); + AddCodeLine ("ldx %s+1", lbuf); + AddCodeLine ("lda %s", lbuf); + } + break; + + default: + typeerror (flags); } } -void g_getlocal (unsigned flags, int offs) +void g_getlocal (unsigned Flags, int Offs) /* Fetch specified local object (local var). */ { - offs -= oursp; - CheckLocalOffs (offs); - switch (flags & CF_TYPE) { - - case CF_CHAR: - if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { - ldyconst (offs); - AddCodeLine ("lda (sp),y"); - } else { - ldyconst (offs); - AddCodeLine ("ldx #$00"); - AddCodeLine ("lda (sp),y"); - if ((flags & CF_UNSIGNED) == 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - } - break; - - case CF_INT: - CheckLocalOffs (offs + 1); - if (flags & CF_TEST) { - ldyconst (offs + 1); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("dey"); - AddCodeLine ("ora (sp),y"); - } else { - ldyconst (offs+1); - AddCodeLine ("jsr ldaxysp"); - } - break; - - case CF_LONG: - ldyconst (offs+3); - AddCodeLine ("jsr ldeaxysp"); - break; - - default: - typeerror (flags); + Offs -= StackPtr; + switch (Flags & CF_TYPEMASK) { + + case CF_CHAR: + CheckLocalOffs (Offs); + if ((Flags & CF_FORCECHAR) || (Flags & CF_TEST)) { + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("lda (sp),y"); + } else { + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("ldx #$00"); + AddCodeLine ("lda (sp),y"); + if ((Flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + } + break; + + case CF_INT: + 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 { + AddCodeLine ("jsr ldaxysp"); + } + break; + + case CF_LONG: + CheckLocalOffs (Offs + 3); + AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+3)); + AddCodeLine ("jsr ldeaxysp"); + if (Flags & CF_TEST) { + g_test (Flags); + } + break; + + default: + 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 - */ +** into the primary register +*/ { /* If the offset is greater than 255, add the part that is > 255 to - * the primary. This way we get an easy addition and use the low byte - * as the offset - */ - offs = MakeByteOffs (flags, offs); + ** the primary. This way we get an easy addition and use the low byte + ** as the offset + */ + Offs = MakeByteOffs (Flags, Offs); /* Handle the indirect fetch */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - /* Character sized */ - if (flags & CF_UNSIGNED) { - ldyconst (offs); - AddCodeLine ("jsr ldauidx"); - } else { - ldyconst (offs); - AddCodeLine ("jsr ldaidx"); - } - break; - - case CF_INT: - if (flags & CF_TEST) { - ldyconst (offs); - AddCodeLine ("sta ptr1"); - AddCodeLine ("stx ptr1+1"); - AddCodeLine ("lda (ptr1),y"); - AddCodeLine ("iny"); - AddCodeLine ("ora (ptr1),y"); - } else { - ldyconst (offs+1); - AddCodeLine ("jsr ldaxidx"); - } - break; - - case CF_LONG: - ldyconst (offs+3); - AddCodeLine ("jsr ldeaxidx"); - if (flags & CF_TEST) { - AddCodeLine ("jsr tsteax"); - } - break; - - default: - typeerror (flags); + switch (Flags & CF_TYPEMASK) { + + case CF_CHAR: + /* Character sized */ + AddCodeLine ("ldy #$%02X", Offs); + if (Flags & CF_UNSIGNED) { + AddCodeLine ("jsr ldauidx"); + } else { + AddCodeLine ("jsr ldaidx"); + } + break; + + case CF_INT: + 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 { + AddCodeLine ("ldy #$%02X", Offs+1); + AddCodeLine ("jsr ldaxidx"); + } + break; + + case CF_LONG: + AddCodeLine ("ldy #$%02X", Offs+3); + AddCodeLine ("jsr ldeaxidx"); + if (Flags & CF_TEST) { + g_test (Flags); + } + break; + + default: + 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 -= oursp; + Offs -= StackPtr; - /* For value 0 we do direct code */ - if (offs == 0) { - AddCodeLine ("lda sp"); - AddCodeLine ("ldx sp+1"); + /* 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 (); + 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 { - if (CodeSizeFactor < 300) { - ldaconst (offs); /* Load A with offset value */ - AddCodeLine ("jsr leaasp"); /* Load effective address */ - } else { - 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"); - } - g_defcodelabel (L); - } + /* 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"); } } @@ -946,83 +960,84 @@ void g_leasp (int offs) void g_leavariadic (int Offs) /* Fetch the address of a parameter in a variadic function into the primary - * register - */ +** register +*/ { unsigned ArgSizeOffs; /* Calculate the offset relative to sp */ - Offs -= oursp; + Offs -= StackPtr; /* Get the offset of the parameter which is stored at sp+0 on function - * entry and check if this offset is reachable with a byte offset. - */ - CHECK (oursp <= 0); - ArgSizeOffs = -oursp; + ** entry and check if this offset is reachable with a byte offset. + */ + CHECK (StackPtr <= 0); + ArgSizeOffs = -StackPtr; CheckLocalOffs (ArgSizeOffs); /* Get the size of all parameters. */ - ldyconst (ArgSizeOffs); + AddCodeLine ("ldy #$%02X", ArgSizeOffs); AddCodeLine ("lda (sp),y"); /* Add the value of the stackpointer */ - if (CodeSizeFactor > 250) { - unsigned L = GetLocalLabel(); - AddCodeLine ("ldx sp+1"); - AddCodeLine ("clc"); - AddCodeLine ("adc sp"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); - g_defcodelabel (L); + if (IS_Get (&CodeSizeFactor) > 250) { + unsigned L = GetLocalLabel(); + AddCodeLine ("ldx sp+1"); + AddCodeLine ("clc"); + AddCodeLine ("adc sp"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); + g_defcodelabel (L); } else { - AddCodeLine ("jsr leaasp"); + AddCodeLine ("ldx #$00"); + AddCodeLine ("jsr leaaxsp"); } /* Add the offset to the primary */ if (Offs > 0) { - g_inc (CF_INT | CF_CONST, Offs); + g_inc (CF_INT | CF_CONST, Offs); } else if (Offs < 0) { - g_dec (CF_INT | CF_CONST, -Offs); + g_dec (CF_INT | CF_CONST, -Offs); } } /*****************************************************************************/ -/* Store into memory */ +/* Store into memory */ /*****************************************************************************/ -void g_putstatic (unsigned flags, unsigned long label, long offs) +void g_putstatic (unsigned flags, uintptr_t label, long offs) /* Store the primary register into the specified static memory cell */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and generate the correct store operation */ - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - AddCodeLine ("sta %s", lbuf); - break; + case CF_CHAR: + AddCodeLine ("sta %s", lbuf); + break; - case CF_INT: - AddCodeLine ("sta %s", lbuf); - AddCodeLine ("stx %s+1", lbuf); - break; + case CF_INT: + AddCodeLine ("sta %s", lbuf); + AddCodeLine ("stx %s+1", lbuf); + break; - case CF_LONG: - AddCodeLine ("sta %s", lbuf); - AddCodeLine ("stx %s+1", lbuf); - AddCodeLine ("ldy sreg"); - AddCodeLine ("sty %s+2", lbuf); - AddCodeLine ("ldy sreg+1"); - AddCodeLine ("sty %s+3", lbuf); - break; + case CF_LONG: + AddCodeLine ("sta %s", lbuf); + AddCodeLine ("stx %s+1", lbuf); + AddCodeLine ("ldy sreg"); + AddCodeLine ("sty %s+2", lbuf); + AddCodeLine ("ldy sreg+1"); + AddCodeLine ("sty %s+3", lbuf); + break; - default: - typeerror (flags); + default: + typeerror (flags); } } @@ -1032,60 +1047,59 @@ void g_putstatic (unsigned flags, unsigned long label, long offs) void g_putlocal (unsigned Flags, int Offs, long Val) /* Put data into local object. */ { - Offs -= oursp; + Offs -= StackPtr; CheckLocalOffs (Offs); - switch (Flags & CF_TYPE) { - - case CF_CHAR: - if (Flags & CF_CONST) { - AddCodeLine ("lda #$%02X", (unsigned char) Val); - } - ldyconst (Offs); - AddCodeLine ("sta (sp),y"); - break; - - case CF_INT: - if (Flags & CF_CONST) { - ldyconst (Offs+1); - AddCodeLine ("lda #$%02X", (unsigned char) (Val >> 8)); - AddCodeLine ("sta (sp),y"); - if ((Flags & CF_NOKEEP) == 0) { - /* Place high byte into X */ - AddCodeLine ("tax"); - } - if ((Val & 0xFF) == Offs+1) { - /* The value we need is already in Y */ - AddCodeLine ("tya"); - AddCodeLine ("dey"); - } else { - AddCodeLine ("dey"); - AddCodeLine ("lda #$%02X", (unsigned char) Val); - } - AddCodeLine ("sta (sp),y"); - } else { - if ((Flags & CF_NOKEEP) == 0 || CodeSizeFactor < 160) { - ldyconst (Offs); - AddCodeLine ("jsr staxysp"); - } else { - ldyconst (Offs); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("iny"); - AddCodeLine ("txa"); - AddCodeLine ("sta (sp),y"); - } - } - break; - - case CF_LONG: - if (Flags & CF_CONST) { - g_getimmed (Flags, Val, 0); - } - ldyconst (Offs); - AddCodeLine ("jsr steaxysp"); - break; - - default: - typeerror (Flags); + switch (Flags & CF_TYPEMASK) { + + case CF_CHAR: + if (Flags & CF_CONST) { + AddCodeLine ("lda #$%02X", (unsigned char) Val); + } + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("sta (sp),y"); + break; + + case CF_INT: + if (Flags & CF_CONST) { + AddCodeLine ("ldy #$%02X", Offs+1); + AddCodeLine ("lda #$%02X", (unsigned char) (Val >> 8)); + AddCodeLine ("sta (sp),y"); + if ((Flags & CF_NOKEEP) == 0) { + /* Place high byte into X */ + AddCodeLine ("tax"); + } + if ((Val & 0xFF) == Offs+1) { + /* The value we need is already in Y */ + AddCodeLine ("tya"); + AddCodeLine ("dey"); + } else { + AddCodeLine ("dey"); + AddCodeLine ("lda #$%02X", (unsigned char) Val); + } + AddCodeLine ("sta (sp),y"); + } else { + AddCodeLine ("ldy #$%02X", Offs); + if ((Flags & CF_NOKEEP) == 0 || IS_Get (&CodeSizeFactor) < 160) { + AddCodeLine ("jsr staxysp"); + } else { + AddCodeLine ("sta (sp),y"); + AddCodeLine ("iny"); + AddCodeLine ("txa"); + AddCodeLine ("sta (sp),y"); + } + } + break; + + case CF_LONG: + if (Flags & CF_CONST) { + g_getimmed (Flags, Val, 0); + } + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("jsr steaxysp"); + break; + + default: + typeerror (Flags); } } @@ -1094,67 +1108,65 @@ void g_putlocal (unsigned Flags, int Offs, long Val) void g_putind (unsigned Flags, unsigned Offs) /* Store the specified object type in the primary register at the address - * on the top of the stack - */ +** on the top of the stack +*/ { /* We can handle offsets below $100 directly, larger offsets must be added - * to the address. Since a/x is in use, best code is achieved by adding - * just the high byte. Be sure to check if the low byte will overflow while - * while storing. - */ + ** to the address. Since a/x is in use, best code is achieved by adding + ** just the high byte. Be sure to check if the low byte will overflow while + ** while storing. + */ if ((Offs & 0xFF) > 256 - sizeofarg (Flags | CF_FORCECHAR)) { - /* Overflow - we need to add the low byte also */ - AddCodeLine ("ldy #$00"); - AddCodeLine ("clc"); - AddCodeLine ("pha"); - AddCodeLine ("lda #$%02X", Offs & 0xFF); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("iny"); - AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("pla"); - - /* Complete address is on stack, new offset is zero */ - Offs = 0; + /* Overflow - we need to add the low byte also */ + AddCodeLine ("ldy #$00"); + AddCodeLine ("clc"); + AddCodeLine ("pha"); + AddCodeLine ("lda #$%02X", Offs & 0xFF); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + AddCodeLine ("iny"); + AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + AddCodeLine ("pla"); + + /* Complete address is on stack, new offset is zero */ + Offs = 0; } else if ((Offs & 0xFF00) != 0) { - /* We can just add the high byte */ - AddCodeLine ("ldy #$01"); - AddCodeLine ("clc"); - AddCodeLine ("pha"); - AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("pla"); - - /* Offset is now just the low byte */ - Offs &= 0x00FF; + /* We can just add the high byte */ + AddCodeLine ("ldy #$01"); + AddCodeLine ("clc"); + AddCodeLine ("pha"); + AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + AddCodeLine ("pla"); + + /* Offset is now just the low byte */ + Offs &= 0x00FF; } /* Check the size and determine operation */ - switch (Flags & CF_TYPE) { + AddCodeLine ("ldy #$%02X", Offs); + switch (Flags & CF_TYPEMASK) { - case CF_CHAR: - ldyconst (Offs); - AddCodeLine ("jsr staspidx"); - break; + case CF_CHAR: + AddCodeLine ("jsr staspidx"); + break; - case CF_INT: - ldyconst (Offs); - AddCodeLine ("jsr staxspidx"); - break; + case CF_INT: + AddCodeLine ("jsr staxspidx"); + break; - case CF_LONG: - ldyconst (Offs); - AddCodeLine ("jsr steaxspidx"); - break; + case CF_LONG: + AddCodeLine ("jsr steaxspidx"); + break; - default: - typeerror (Flags); + default: + typeerror (Flags); } @@ -1165,7 +1177,7 @@ void g_putind (unsigned Flags, unsigned Offs) /*****************************************************************************/ -/* type conversion and similiar stuff */ +/* type conversion and similiar stuff */ /*****************************************************************************/ @@ -1173,23 +1185,23 @@ void g_putind (unsigned Flags, unsigned Offs) void g_toslong (unsigned flags) /* Make sure, the value on TOS is a long. Convert if necessary */ { - switch (flags & CF_TYPE) { - - case CF_CHAR: - case CF_INT: - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr tosulong"); - } else { - AddCodeLine ("jsr toslong"); - } - push (CF_INT); - break; - - case CF_LONG: - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + case CF_INT: + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr tosulong"); + } else { + AddCodeLine ("jsr toslong"); + } + push (CF_INT); + break; + + case CF_LONG: + break; + + default: + typeerror (flags); } } @@ -1198,53 +1210,61 @@ void g_toslong (unsigned flags) void g_tosint (unsigned flags) /* Make sure, the value on TOS is an int. Convert if necessary */ { - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - case CF_INT: - break; + case CF_CHAR: + case CF_INT: + break; - case CF_LONG: - AddCodeLine ("jsr tosint"); - pop (CF_INT); - break; + case CF_LONG: + AddCodeLine ("jsr tosint"); + pop (CF_INT); + break; - default: - typeerror (flags); + default: + typeerror (flags); } } -void g_regint (unsigned Flags) -/* Make sure, the value in the primary register an int. Convert if necessary */ +static void g_regchar (unsigned Flags) +/* Make sure, the value in the primary register is in the range of char. Truncate if necessary */ { unsigned L; - switch (Flags & CF_TYPE) { + AddCodeLine ("ldx #$00"); + + if ((Flags & CF_UNSIGNED) == 0) { + /* Sign extend */ + L = GetLocalLabel(); + AddCodeLine ("cmp #$80"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } +} + + + +void g_regint (unsigned Flags) +/* Make sure, the value in the primary register an int. Convert if necessary */ +{ + switch (Flags & CF_TYPEMASK) { - case CF_CHAR: + case CF_CHAR: if (Flags & CF_FORCECHAR) { /* Conversion is from char */ - if (Flags & CF_UNSIGNED) { - AddCodeLine ("ldx #$00"); - } else { - L = GetLocalLabel(); - AddCodeLine ("ldx #$00"); - AddCodeLine ("cmp #$80"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } + g_regchar (Flags); } /* FALLTHROUGH */ - case CF_INT: - case CF_LONG: - break; + case CF_INT: + case CF_LONG: + break; - default: - typeerror (Flags); + default: + typeerror (Flags); } } @@ -1253,15 +1273,13 @@ void g_regint (unsigned Flags) void g_reglong (unsigned Flags) /* Make sure, the value in the primary register a long. Convert if necessary */ { - unsigned L; - - switch (Flags & CF_TYPE) { + switch (Flags & CF_TYPEMASK) { - case CF_CHAR: + case CF_CHAR: if (Flags & CF_FORCECHAR) { /* Conversion is from char */ if (Flags & CF_UNSIGNED) { - if (CodeSizeFactor >= 200) { + if (IS_Get (&CodeSizeFactor) >= 200) { AddCodeLine ("ldx #$00"); AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); @@ -1269,13 +1287,8 @@ void g_reglong (unsigned Flags) AddCodeLine ("jsr aulong"); } } else { - if (CodeSizeFactor >= 366) { - L = GetLocalLabel(); - AddCodeLine ("ldx #$00"); - AddCodeLine ("cmp #$80"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); + if (IS_Get (&CodeSizeFactor) >= 366) { + g_regchar (Flags); AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); } else { @@ -1285,25 +1298,25 @@ void g_reglong (unsigned Flags) } /* FALLTHROUGH */ - case CF_INT: - if (Flags & CF_UNSIGNED) { - if (CodeSizeFactor >= 200) { - ldyconst (0); - AddCodeLine ("sty sreg"); - AddCodeLine ("sty sreg+1"); - } else { - AddCodeLine ("jsr axulong"); - } - } else { - AddCodeLine ("jsr axlong"); - } - break; - - case CF_LONG: - break; - - default: - typeerror (Flags); + case CF_INT: + if (Flags & CF_UNSIGNED) { + if (IS_Get (&CodeSizeFactor) >= 200) { + AddCodeLine ("ldy #$00"); + AddCodeLine ("sty sreg"); + AddCodeLine ("sty sreg+1"); + } else { + AddCodeLine ("jsr axulong"); + } + } else { + AddCodeLine ("jsr axlong"); + } + break; + + case CF_LONG: + break; + + default: + typeerror (Flags); } } @@ -1311,48 +1324,48 @@ void g_reglong (unsigned Flags) unsigned g_typeadjust (unsigned lhs, unsigned rhs) /* Adjust the integer operands before doing a binary operation. lhs is a flags - * value, that corresponds to the value on TOS, rhs corresponds to the value - * in (e)ax. The return value is the the flags value for the resulting type. - */ +** value, that corresponds to the value on TOS, rhs corresponds to the value +** in (e)ax. The return value is the the flags value for the resulting type. +*/ { unsigned ltype, rtype; unsigned result; /* Get the type spec from the flags */ - ltype = lhs & CF_TYPE; - rtype = rhs & CF_TYPE; + ltype = lhs & CF_TYPEMASK; + rtype = rhs & CF_TYPEMASK; /* Check if a conversion is needed */ if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) { - /* We must promote the primary register to long */ - g_reglong (rhs); - /* Get the new rhs type */ - rhs = (rhs & ~CF_TYPE) | CF_LONG; - rtype = CF_LONG; + /* We must promote the primary register to long */ + g_reglong (rhs); + /* Get the new rhs type */ + rhs = (rhs & ~CF_TYPEMASK) | CF_LONG; + rtype = CF_LONG; } else if (ltype != CF_LONG && (lhs & CF_CONST) == 0 && rtype == CF_LONG) { - /* We must promote the lhs to long */ - if (lhs & CF_REG) { - g_reglong (lhs); - } else { - g_toslong (lhs); - } - /* Get the new rhs type */ - lhs = (lhs & ~CF_TYPE) | CF_LONG; - ltype = CF_LONG; + /* We must promote the lhs to long */ + if (lhs & CF_REG) { + g_reglong (lhs); + } else { + g_toslong (lhs); + } + /* Get the new rhs type */ + lhs = (lhs & ~CF_TYPEMASK) | CF_LONG; + ltype = CF_LONG; } /* Determine the result type for the operation: - * - The result is const if both operands are const. - * - The result is unsigned if one of the operands is unsigned. - * - The result is long if one of the operands is long. - * - Otherwise the result is int sized. - */ + ** - The result is const if both operands are const. + ** - The result is unsigned if one of the operands is unsigned. + ** - The result is long if one of the operands is long. + ** - Otherwise the result is int sized. + */ result = (lhs & CF_CONST) & (rhs & CF_CONST); result |= (lhs & CF_UNSIGNED) | (rhs & CF_UNSIGNED); if (rtype == CF_LONG || ltype == CF_LONG) { - result |= CF_LONG; + result |= CF_LONG; } else { - result |= CF_INT; + result |= CF_INT; } return result; } @@ -1361,38 +1374,45 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs) unsigned g_typecast (unsigned lhs, unsigned rhs) /* Cast the value in the primary register to the operand size that is flagged - * by the lhs value. Return the result value. - */ +** by the lhs value. Return the result value. +*/ { - unsigned ltype, rtype; - - /* Get the type spec from the flags */ - ltype = lhs & CF_TYPE; - rtype = rhs & CF_TYPE; - /* Check if a conversion is needed */ if ((rhs & CF_CONST) == 0) { - if (ltype == CF_LONG && rtype != CF_LONG) { - /* We must promote the primary register to long */ - g_reglong (rhs); - } else if (ltype == CF_INT && rtype != CF_INT) { - /* We must promote the primary register to int */ - g_regint (rhs); + switch (lhs & CF_TYPEMASK) { + + case CF_LONG: + /* We must promote the primary register to long */ + g_reglong (rhs); + break; + + case CF_INT: + /* We must promote the primary register to int */ + g_regint (rhs); + break; + + case CF_CHAR: + /* We must truncate the primary register to char */ + g_regchar (lhs); + break; + + default: + typeerror (lhs); } } /* Do not need any other action. If the left type is int, and the primary - * register is long, it will be automagically truncated. If the right hand - * side is const, it is not located in the primary register and handled by - * the expression parser code. - */ + ** register is long, it will be automagically truncated. If the right hand + ** side is const, it is not located in the primary register and handled by + ** the expression parser code. + */ /* Result is const if the right hand side was const */ lhs |= (rhs & CF_CONST); /* The resulting type is that of the left hand side (that's why you called - * this function :-) - */ + ** this function :-) + */ return lhs; } @@ -1400,147 +1420,119 @@ unsigned g_typecast (unsigned lhs, unsigned rhs) void g_scale (unsigned flags, long val) /* Scale the value in the primary register by the given value. If val is positive, - * scale up, is val is negative, scale down. This function is used to scale - * the operands or results of pointer arithmetic by the size of the type, the - * pointer points to. - */ +** scale up, is val is negative, scale down. This function is used to scale +** the operands or results of pointer arithmetic by the size of the type, the +** pointer points to. +*/ { int p2; /* Value may not be zero */ if (val == 0) { - Internal ("Data type has no size"); + Internal ("Data type has no size"); } else if (val > 0) { - /* Scale up */ - if ((p2 = powerof2 (val)) > 0 && p2 <= 4) { - - /* Factor is 2, 4, 8 and 16, use special function */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - while (p2--) { - AddCodeLine ("asl a"); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - if (CodeSizeFactor >= (p2+1)*130U) { - AddCodeLine ("stx tmp1"); - while (p2--) { - AddCodeLine ("asl a"); - AddCodeLine ("rol tmp1"); - } - AddCodeLine ("ldx tmp1"); - } else { - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr shlax%d", p2); - } else { - AddCodeLine ("jsr aslax%d", p2); - } - } - break; - - case CF_LONG: - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr shleax%d", p2); - } else { - AddCodeLine ("jsr asleax%d", p2); - } - break; - - default: - typeerror (flags); - - } - - } else if (val != 1) { - - /* Use a multiplication instead */ - g_mul (flags | CF_CONST, val); - - } + /* Scale up */ + if ((p2 = PowerOf2 (val)) > 0 && p2 <= 4) { + + /* Factor is 2, 4, 8 and 16, use special function */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + while (p2--) { + AddCodeLine ("asl a"); + } + break; + } + /* FALLTHROUGH */ + + case CF_INT: + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shlax%d", p2); + } else { + AddCodeLine ("jsr aslax%d", p2); + } + break; + + case CF_LONG: + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr shleax%d", p2); + } else { + AddCodeLine ("jsr asleax%d", p2); + } + break; + + default: + typeerror (flags); + + } + + } else if (val != 1) { + + /* Use a multiplication instead */ + g_mul (flags | CF_CONST, val); + + } } else { - /* Scale down */ - val = -val; - if ((p2 = powerof2 (val)) > 0 && p2 <= 4) { - - /* Factor is 2, 4, 8 and 16 use special function */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if (flags & CF_UNSIGNED) { - while (p2--) { - AddCodeLine ("lsr a"); - } - break; - } else if (p2 <= 2) { - AddCodeLine ("cmp #$80"); - AddCodeLine ("ror a"); - break; - } - } - /* FALLTHROUGH */ - - case CF_INT: - if (flags & CF_UNSIGNED) { - if (CodeSizeFactor >= (p2+1)*130U) { - AddCodeLine ("stx tmp1"); - while (p2--) { - AddCodeLine ("lsr tmp1"); - AddCodeLine ("ror a"); - } - AddCodeLine ("ldx tmp1"); - } else { - AddCodeLine ("jsr lsrax%d", p2); - } - } else { - if (CodeSizeFactor >= (p2+1)*150U) { - AddCodeLine ("stx tmp1"); - while (p2--) { - AddCodeLine ("cpx #$80"); - AddCodeLine ("ror tmp1"); - AddCodeLine ("ror a"); - } - AddCodeLine ("ldx tmp1"); - } else { - AddCodeLine ("jsr asrax%d", p2); - } - } - break; - - case CF_LONG: - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr lsreax%d", p2); - } else { - AddCodeLine ("jsr asreax%d", p2); - } - break; - - default: - typeerror (flags); - - } - - } else if (val != 1) { - - /* Use a division instead */ - g_div (flags | CF_CONST, val); - - } + /* Scale down */ + val = -val; + if ((p2 = PowerOf2 (val)) > 0 && p2 <= 4) { + + /* Factor is 2, 4, 8 and 16 use special function */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if (flags & CF_UNSIGNED) { + while (p2--) { + AddCodeLine ("lsr a"); + } + break; + } else if (p2 <= 2) { + AddCodeLine ("cmp #$80"); + AddCodeLine ("ror a"); + break; + } + } + /* FALLTHROUGH */ + + case CF_INT: + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr lsrax%d", p2); + } else { + AddCodeLine ("jsr asrax%d", p2); + } + break; + + case CF_LONG: + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr lsreax%d", p2); + } else { + AddCodeLine ("jsr asreax%d", p2); + } + break; + + default: + typeerror (flags); + + } + + } else if (val != 1) { + + /* Use a division instead */ + g_div (flags | CF_CONST, val); + + } } } /*****************************************************************************/ -/* Adds and subs of variables fix a fixed address */ +/* Adds and subs of variables fix a fixed address */ /*****************************************************************************/ @@ -1551,49 +1543,49 @@ void g_addlocal (unsigned flags, int offs) unsigned L; /* Correct the offset and check it */ - offs -= oursp; + offs -= StackPtr; CheckLocalOffs (offs); - switch (flags & CF_TYPE) { - - case CF_CHAR: - L = GetLocalLabel(); - AddCodeLine ("ldy #$%02X", offs & 0xFF); - AddCodeLine ("clc"); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); - g_defcodelabel (L); - break; - - case CF_INT: - AddCodeLine ("ldy #$%02X", offs & 0xFF); - AddCodeLine ("clc"); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("pha"); - AddCodeLine ("txa"); - AddCodeLine ("iny"); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("tax"); - AddCodeLine ("pla"); - break; - - case CF_LONG: - /* Do it the old way */ - g_push (flags, 0); - g_getlocal (flags, offs); - g_add (flags, 0); - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + L = GetLocalLabel(); + AddCodeLine ("ldy #$%02X", offs & 0xFF); + AddCodeLine ("clc"); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); + g_defcodelabel (L); + break; + + case CF_INT: + AddCodeLine ("ldy #$%02X", offs & 0xFF); + AddCodeLine ("clc"); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("pha"); + AddCodeLine ("txa"); + AddCodeLine ("iny"); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("tax"); + AddCodeLine ("pla"); + break; + + case CF_LONG: + /* Do it the old way */ + g_push (flags, 0); + g_getlocal (flags, offs); + g_add (flags, 0); + break; + + default: + typeerror (flags); } } -void g_addstatic (unsigned flags, unsigned long label, long offs) +void g_addstatic (unsigned flags, uintptr_t label, long offs) /* Add a static variable to ax */ { unsigned L; @@ -1601,36 +1593,36 @@ void g_addstatic (unsigned flags, unsigned long label, long offs) /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); - switch (flags & CF_TYPE) { - - case CF_CHAR: - L = GetLocalLabel(); - AddCodeLine ("clc"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); - g_defcodelabel (L); - break; - - case CF_INT: - AddCodeLine ("clc"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("tay"); - AddCodeLine ("txa"); - AddCodeLine ("adc %s+1", lbuf); - AddCodeLine ("tax"); - AddCodeLine ("tya"); - break; - - case CF_LONG: - /* Do it the old way */ - g_push (flags, 0); - g_getstatic (flags, label, offs); - g_add (flags, 0); - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + L = GetLocalLabel(); + AddCodeLine ("clc"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); + g_defcodelabel (L); + break; + + case CF_INT: + AddCodeLine ("clc"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("tay"); + AddCodeLine ("txa"); + AddCodeLine ("adc %s+1", lbuf); + AddCodeLine ("tax"); + AddCodeLine ("tya"); + break; + + case CF_LONG: + /* Do it the old way */ + g_push (flags, 0); + g_getstatic (flags, label, offs); + g_add (flags, 0); + break; + + default: + typeerror (flags); } } @@ -1638,190 +1630,190 @@ void g_addstatic (unsigned flags, unsigned long label, long offs) /*****************************************************************************/ -/* Special op= functions */ +/* Special op= functions */ /*****************************************************************************/ -void g_addeqstatic (unsigned flags, unsigned long label, long offs, - unsigned long val) +void g_addeqstatic (unsigned flags, uintptr_t label, long offs, + unsigned long val) /* Emit += for a static variable */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("ldx #$00"); - if (flags & CF_CONST) { - if (val == 1) { - AddCodeLine ("inc %s", lbuf); - AddCodeLine ("lda %s", lbuf); - } else { - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("clc"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("sta %s", lbuf); - } - } else { - AddCodeLine ("clc"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("sta %s", lbuf); - } - if ((flags & CF_UNSIGNED) == 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - if (flags & CF_CONST) { - if (val == 1) { - unsigned L = GetLocalLabel (); - AddCodeLine ("inc %s", lbuf); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("inc %s+1", lbuf); - g_defcodelabel (L); - AddCodeLine ("lda %s", lbuf); /* Hmmm... */ - AddCodeLine ("ldx %s+1", lbuf); - } else { - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("clc"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("sta %s", lbuf); - if (val < 0x100) { - unsigned L = GetLocalLabel (); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inc %s+1", lbuf); - g_defcodelabel (L); - AddCodeLine ("ldx %s+1", lbuf); - } else { - AddCodeLine ("lda #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("adc %s+1", lbuf); - AddCodeLine ("sta %s+1", lbuf); - AddCodeLine ("tax"); - AddCodeLine ("lda %s", lbuf); - } - } - } else { - AddCodeLine ("clc"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("sta %s", lbuf); - AddCodeLine ("txa"); - AddCodeLine ("adc %s+1", lbuf); - AddCodeLine ("sta %s+1", lbuf); - AddCodeLine ("tax"); - AddCodeLine ("lda %s", lbuf); - } - break; - - case CF_LONG: - if (flags & CF_CONST) { - if (val < 0x100) { - AddCodeLine ("ldy #<(%s)", lbuf); - AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s)", lbuf); - if (val == 1) { - AddCodeLine ("jsr laddeq1"); - } else { - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("jsr laddeqa"); - } - } else { - g_getstatic (flags, label, offs); - g_inc (flags, val); - g_putstatic (flags, label, offs); - } - } else { - AddCodeLine ("ldy #<(%s)", lbuf); - AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s)", lbuf); - AddCodeLine ("jsr laddeq"); - } - break; - - default: - typeerror (flags); - } -} - + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("ldx #$00"); + if (flags & CF_CONST) { + if (val == 1) { + AddCodeLine ("inc %s", lbuf); + AddCodeLine ("lda %s", lbuf); + } else { + AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); + AddCodeLine ("clc"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("sta %s", lbuf); + } + } else { + AddCodeLine ("clc"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("sta %s", lbuf); + } + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + break; + } + /* FALLTHROUGH */ + case CF_INT: + if (flags & CF_CONST) { + if (val == 1) { + unsigned L = GetLocalLabel (); + AddCodeLine ("inc %s", lbuf); + AddCodeLine ("bne %s", LocalLabelName (L)); + AddCodeLine ("inc %s+1", lbuf); + g_defcodelabel (L); + AddCodeLine ("lda %s", lbuf); /* Hmmm... */ + AddCodeLine ("ldx %s+1", lbuf); + } else { + AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); + AddCodeLine ("clc"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("sta %s", lbuf); + if (val < 0x100) { + unsigned L = GetLocalLabel (); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inc %s+1", lbuf); + g_defcodelabel (L); + AddCodeLine ("ldx %s+1", lbuf); + } else { + AddCodeLine ("lda #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("adc %s+1", lbuf); + AddCodeLine ("sta %s+1", lbuf); + AddCodeLine ("tax"); + AddCodeLine ("lda %s", lbuf); + } + } + } else { + AddCodeLine ("clc"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("sta %s", lbuf); + AddCodeLine ("txa"); + AddCodeLine ("adc %s+1", lbuf); + AddCodeLine ("sta %s+1", lbuf); + AddCodeLine ("tax"); + AddCodeLine ("lda %s", lbuf); + } + break; -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 -= oursp; - CheckLocalOffs (offs); + case CF_LONG: + if (flags & CF_CONST) { + if (val < 0x100) { + AddCodeLine ("ldy #<(%s)", lbuf); + AddCodeLine ("sty ptr1"); + AddCodeLine ("ldy #>(%s)", lbuf); + if (val == 1) { + AddCodeLine ("jsr laddeq1"); + } else { + AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); + AddCodeLine ("jsr laddeqa"); + } + } else { + g_getstatic (flags, label, offs); + g_inc (flags, val); + g_putstatic (flags, label, offs); + } + } else { + AddCodeLine ("ldy #<(%s)", lbuf); + AddCodeLine ("sty ptr1"); + AddCodeLine ("ldy #>(%s)", lbuf); + AddCodeLine ("jsr laddeq"); + } + break; + + default: + typeerror (flags); + } +} + + + +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); /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - ldyconst (offs); - AddCodeLine ("ldx #$00"); - if (flags & CF_CONST) { - AddCodeLine ("clc"); - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - } else { - AddCodeLine ("clc"); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - } - if ((flags & CF_UNSIGNED) == 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - ldyconst (offs); - if (flags & CF_CONST) { - if (CodeSizeFactor >= 400) { - AddCodeLine ("clc"); - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("iny"); - AddCodeLine ("lda #$%02X", (int) ((val >> 8) & 0xFF)); - AddCodeLine ("adc (sp),y"); - AddCodeLine ("sta (sp),y"); - AddCodeLine ("tax"); - AddCodeLine ("dey"); - AddCodeLine ("lda (sp),y"); - } else { - g_getimmed (flags, val, 0); - AddCodeLine ("jsr addeqysp"); - } - } else { - AddCodeLine ("jsr addeqysp"); - } - break; - - case CF_LONG: - if (flags & CF_CONST) { - g_getimmed (flags, val, 0); - } - ldyconst (offs); - AddCodeLine ("jsr laddeqysp"); - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("ldx #$00"); + if (flags & CF_CONST) { + AddCodeLine ("clc"); + AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + } else { + AddCodeLine ("clc"); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + } + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + break; + } + /* FALLTHROUGH */ + + case CF_INT: + AddCodeLine ("ldy #$%02X", Offs); + if (flags & CF_CONST) { + if (IS_Get (&CodeSizeFactor) >= 400) { + AddCodeLine ("clc"); + AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + AddCodeLine ("iny"); + AddCodeLine ("lda #$%02X", (int) ((val >> 8) & 0xFF)); + AddCodeLine ("adc (sp),y"); + AddCodeLine ("sta (sp),y"); + AddCodeLine ("tax"); + AddCodeLine ("dey"); + AddCodeLine ("lda (sp),y"); + } else { + g_getimmed (flags, val, 0); + AddCodeLine ("jsr addeqysp"); + } + } else { + AddCodeLine ("jsr addeqysp"); + } + break; + + case CF_LONG: + if (flags & CF_CONST) { + g_getimmed (flags, val, 0); + } + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("jsr laddeqysp"); + break; + + default: + typeerror (flags); } } @@ -1831,211 +1823,193 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val) /* Emit += for the location with address in ax */ { /* If the offset is too large for a byte register, add the high byte - * of the offset to the primary. Beware: We need a special correction - * if the offset in the low byte will overflow in the operation. - */ + ** of the offset to the primary. Beware: We need a special correction + ** if the offset in the low byte will overflow in the operation. + */ offs = MakeByteOffs (flags, offs); /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - AddCodeLine ("sta ptr1"); - AddCodeLine ("stx ptr1+1"); - AddCodeLine ("ldy #$%02X", offs); - AddCodeLine ("ldx #$00"); - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("clc"); - AddCodeLine ("adc (ptr1),y"); - AddCodeLine ("sta (ptr1),y"); - break; - - case CF_INT: - if (CodeSizeFactor >= 200) { - /* Lots of code, use only if size is not important */ - AddCodeLine ("sta ptr1"); - AddCodeLine ("stx ptr1+1"); - AddCodeLine ("ldy #$%02X", offs); - AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); - AddCodeLine ("clc"); - AddCodeLine ("adc (ptr1),y"); - AddCodeLine ("sta (ptr1),y"); - AddCodeLine ("pha"); - AddCodeLine ("iny"); - AddCodeLine ("lda #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("adc (ptr1),y"); - AddCodeLine ("sta (ptr1),y"); - AddCodeLine ("tax"); - AddCodeLine ("pla"); - break; - } - /* FALL THROUGH */ - - case CF_LONG: - AddCodeLine ("jsr pushax"); /* Push the address */ - push (CF_PTR); /* Correct the internal sp */ - g_getind (flags, offs); /* Fetch the value */ - g_inc (flags, val); /* Increment value in primary */ - g_putind (flags, offs); /* Store the value back */ - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + AddCodeLine ("sta ptr1"); + AddCodeLine ("stx ptr1+1"); + AddCodeLine ("ldy #$%02X", offs); + AddCodeLine ("ldx #$00"); + AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); + AddCodeLine ("clc"); + AddCodeLine ("adc (ptr1),y"); + AddCodeLine ("sta (ptr1),y"); + break; + + case CF_INT: + case CF_LONG: + AddCodeLine ("jsr pushax"); /* Push the address */ + push (CF_PTR); /* Correct the internal sp */ + g_getind (flags, offs); /* Fetch the value */ + g_inc (flags, val); /* Increment value in primary */ + g_putind (flags, offs); /* Store the value back */ + break; + + default: + typeerror (flags); } } -void g_subeqstatic (unsigned flags, unsigned long label, long offs, - unsigned long val) +void g_subeqstatic (unsigned flags, uintptr_t label, long offs, + unsigned long val) /* Emit -= for a static variable */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("ldx #$00"); - if (flags & CF_CONST) { - if (val == 1) { - AddCodeLine ("dec %s", lbuf); - AddCodeLine ("lda %s", lbuf); - } else { - AddCodeLine ("sec"); - AddCodeLine ("lda %s", lbuf); - AddCodeLine ("sbc #$%02X", (int)(val & 0xFF)); - AddCodeLine ("sta %s", lbuf); - } - } else { - AddCodeLine ("eor #$FF"); - AddCodeLine ("sec"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("sta %s", lbuf); - } - if ((flags & CF_UNSIGNED) == 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - AddCodeLine ("sec"); - if (flags & CF_CONST) { - AddCodeLine ("lda %s", lbuf); - AddCodeLine ("sbc #$%02X", (unsigned char)val); - AddCodeLine ("sta %s", lbuf); - if (val < 0x100) { - unsigned L = GetLocalLabel (); - AddCodeLine ("bcs %s", LocalLabelName (L)); - AddCodeLine ("dec %s+1", lbuf); - g_defcodelabel (L); - AddCodeLine ("ldx %s+1", lbuf); - } else { - AddCodeLine ("lda %s+1", lbuf); - AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("sta %s+1", lbuf); - AddCodeLine ("tax"); - AddCodeLine ("lda %s", lbuf); - } - } else { - AddCodeLine ("eor #$FF"); - AddCodeLine ("adc %s", lbuf); - AddCodeLine ("sta %s", lbuf); - AddCodeLine ("txa"); - AddCodeLine ("eor #$FF"); - AddCodeLine ("adc %s+1", lbuf); - AddCodeLine ("sta %s+1", lbuf); - AddCodeLine ("tax"); - AddCodeLine ("lda %s", lbuf); - } - break; - - case CF_LONG: - if (flags & CF_CONST) { - if (val < 0x100) { - AddCodeLine ("ldy #<(%s)", lbuf); - AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s)", lbuf); - AddCodeLine ("lda #$%02X", (unsigned char)val); - AddCodeLine ("jsr lsubeqa"); - } else { - g_getstatic (flags, label, offs); - g_dec (flags, val); - g_putstatic (flags, label, offs); - } - } else { - AddCodeLine ("ldy #<(%s)", lbuf); - AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s)", lbuf); - AddCodeLine ("jsr lsubeq"); - } - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("ldx #$00"); + if (flags & CF_CONST) { + if (val == 1) { + AddCodeLine ("dec %s", lbuf); + AddCodeLine ("lda %s", lbuf); + } else { + AddCodeLine ("lda %s", lbuf); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (int)(val & 0xFF)); + AddCodeLine ("sta %s", lbuf); + } + } else { + AddCodeLine ("eor #$FF"); + AddCodeLine ("sec"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("sta %s", lbuf); + } + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + break; + } + /* FALLTHROUGH */ + + case CF_INT: + if (flags & CF_CONST) { + AddCodeLine ("lda %s", lbuf); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char)val); + AddCodeLine ("sta %s", lbuf); + if (val < 0x100) { + unsigned L = GetLocalLabel (); + AddCodeLine ("bcs %s", LocalLabelName (L)); + AddCodeLine ("dec %s+1", lbuf); + g_defcodelabel (L); + AddCodeLine ("ldx %s+1", lbuf); + } else { + AddCodeLine ("lda %s+1", lbuf); + AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("sta %s+1", lbuf); + AddCodeLine ("tax"); + AddCodeLine ("lda %s", lbuf); + } + } else { + AddCodeLine ("eor #$FF"); + AddCodeLine ("sec"); + AddCodeLine ("adc %s", lbuf); + AddCodeLine ("sta %s", lbuf); + AddCodeLine ("txa"); + AddCodeLine ("eor #$FF"); + AddCodeLine ("adc %s+1", lbuf); + AddCodeLine ("sta %s+1", lbuf); + AddCodeLine ("tax"); + AddCodeLine ("lda %s", lbuf); + } + break; + + case CF_LONG: + if (flags & CF_CONST) { + if (val < 0x100) { + AddCodeLine ("ldy #<(%s)", lbuf); + AddCodeLine ("sty ptr1"); + AddCodeLine ("ldy #>(%s)", lbuf); + AddCodeLine ("lda #$%02X", (unsigned char)val); + AddCodeLine ("jsr lsubeqa"); + } else { + g_getstatic (flags, label, offs); + g_dec (flags, val); + g_putstatic (flags, label, offs); + } + } else { + AddCodeLine ("ldy #<(%s)", lbuf); + AddCodeLine ("sty ptr1"); + AddCodeLine ("ldy #>(%s)", lbuf); + AddCodeLine ("jsr lsubeq"); + } + break; + + default: + typeerror (flags); } } -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 -= oursp; - 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 ("ldx #$00"); - AddCodeLine ("sec"); - if (flags & CF_CONST) { - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sbc #$%02X", (unsigned char)val); - } else { - AddCodeLine ("eor #$FF"); - AddCodeLine ("adc (sp),y"); - } - AddCodeLine ("sta (sp),y"); - if ((flags & CF_UNSIGNED) == 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - if (flags & CF_CONST) { - g_getimmed (flags, val, 0); - } - ldyconst (offs); - AddCodeLine ("jsr subeqysp"); - break; - - case CF_LONG: - if (flags & CF_CONST) { - g_getimmed (flags, val, 0); - } - ldyconst (offs); - AddCodeLine ("jsr lsubeqysp"); - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("ldx #$00"); + if (flags & CF_CONST) { + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char)val); + } else { + AddCodeLine ("eor #$FF"); + AddCodeLine ("sec"); + AddCodeLine ("adc (sp),y"); + } + AddCodeLine ("sta (sp),y"); + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + break; + } + /* FALLTHROUGH */ + + case CF_INT: + if (flags & CF_CONST) { + g_getimmed (flags, val, 0); + } + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("jsr subeqysp"); + break; + + case CF_LONG: + if (flags & CF_CONST) { + g_getimmed (flags, val, 0); + } + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("jsr lsubeqysp"); + break; + + default: + typeerror (flags); } } @@ -2045,63 +2019,43 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val) /* Emit -= for the location with address in ax */ { /* If the offset is too large for a byte register, add the high byte - * of the offset to the primary. Beware: We need a special correction - * if the offset in the low byte will overflow in the operation. - */ + ** of the offset to the primary. Beware: We need a special correction + ** if the offset in the low byte will overflow in the operation. + */ offs = MakeByteOffs (flags, offs); /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - AddCodeLine ("sta ptr1"); - AddCodeLine ("stx ptr1+1"); - AddCodeLine ("ldy #$%02X", offs); - AddCodeLine ("ldx #$00"); - AddCodeLine ("lda (ptr1),y"); - AddCodeLine ("sec"); - AddCodeLine ("sbc #$%02X", (unsigned char)val); - AddCodeLine ("sta (ptr1),y"); - break; - - case CF_INT: - if (CodeSizeFactor >= 200) { - /* Lots of code, use only if size is not important */ - AddCodeLine ("sta ptr1"); - AddCodeLine ("stx ptr1+1"); - AddCodeLine ("ldy #$%02X", offs); - AddCodeLine ("lda (ptr1),y"); - AddCodeLine ("sec"); - AddCodeLine ("sbc #$%02X", (unsigned char)val); - AddCodeLine ("sta (ptr1),y"); - AddCodeLine ("pha"); - AddCodeLine ("iny"); - AddCodeLine ("lda (ptr1),y"); - AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("sta (ptr1),y"); - AddCodeLine ("tax"); - AddCodeLine ("pla"); - break; - } - /* FALL THROUGH */ - - case CF_LONG: - AddCodeLine ("jsr pushax"); /* Push the address */ - push (CF_PTR); /* Correct the internal sp */ - g_getind (flags, offs); /* Fetch the value */ - g_dec (flags, val); /* Increment value in primary */ - g_putind (flags, offs); /* Store the value back */ - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + AddCodeLine ("sta ptr1"); + AddCodeLine ("stx ptr1+1"); + AddCodeLine ("ldy #$%02X", offs); + AddCodeLine ("ldx #$00"); + AddCodeLine ("lda (ptr1),y"); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char)val); + AddCodeLine ("sta (ptr1),y"); + break; + + case CF_INT: + case CF_LONG: + AddCodeLine ("jsr pushax"); /* Push the address */ + push (CF_PTR); /* Correct the internal sp */ + g_getind (flags, offs); /* Fetch the value */ + g_dec (flags, val); /* Increment value in primary */ + g_putind (flags, offs); /* Store the value back */ + break; + + default: + typeerror (flags); } } /*****************************************************************************/ -/* Add a variable address to the value in ax */ +/* Add a variable address to the value in ax */ /*****************************************************************************/ @@ -2112,23 +2066,23 @@ void g_addaddr_local (unsigned flags attribute ((unused)), int offs) unsigned L = 0; /* Add the offset */ - offs -= oursp; + offs -= StackPtr; if (offs != 0) { - /* We cannot address more then 256 bytes of locals anyway */ - L = GetLocalLabel(); - CheckLocalOffs (offs); - AddCodeLine ("clc"); - AddCodeLine ("adc #$%02X", offs & 0xFF); - /* Do also skip the CLC insn below */ - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); + /* We cannot address more then 256 bytes of locals anyway */ + L = GetLocalLabel(); + CheckLocalOffs (offs); + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", offs & 0xFF); + /* Do also skip the CLC insn below */ + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); } /* Add the current stackpointer value */ AddCodeLine ("clc"); if (L != 0) { - /* Label was used above */ - g_defcodelabel (L); + /* Label was used above */ + g_defcodelabel (L); } AddCodeLine ("adc sp"); AddCodeLine ("tay"); @@ -2140,7 +2094,7 @@ void g_addaddr_local (unsigned flags attribute ((unused)), int offs) -void g_addaddr_static (unsigned flags, unsigned long label, long offs) +void g_addaddr_static (unsigned flags, uintptr_t label, long offs) /* Add the address of a static variable to ax */ { /* Create the correct label name */ @@ -2159,7 +2113,7 @@ void g_addaddr_static (unsigned flags, unsigned long label, long offs) /*****************************************************************************/ -/* */ +/* */ /*****************************************************************************/ @@ -2168,26 +2122,26 @@ void g_save (unsigned flags) /* Copy primary register to hold register. */ { /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("pha"); - break; - } - /* FALLTHROUGH */ - - case CF_INT: - AddCodeLine ("sta regsave"); - AddCodeLine ("stx regsave+1"); - break; - - case CF_LONG: - AddCodeLine ("jsr saveeax"); - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("pha"); + break; + } + /* FALLTHROUGH */ + + case CF_INT: + AddCodeLine ("sta regsave"); + AddCodeLine ("stx regsave+1"); + break; + + case CF_LONG: + AddCodeLine ("jsr saveeax"); + break; + + default: + typeerror (flags); } } @@ -2197,26 +2151,26 @@ void g_restore (unsigned flags) /* Copy hold register to primary. */ { /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("pla"); - break; - } - /* FALLTHROUGH */ - - case CF_INT: - AddCodeLine ("lda regsave"); - AddCodeLine ("ldx regsave+1"); - break; - - case CF_LONG: - AddCodeLine ("jsr resteax"); - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("pla"); + break; + } + /* FALLTHROUGH */ + + case CF_INT: + AddCodeLine ("lda regsave"); + AddCodeLine ("ldx regsave+1"); + break; + + case CF_LONG: + AddCodeLine ("jsr resteax"); + break; + + default: + typeerror (flags); } } @@ -2224,92 +2178,67 @@ void g_restore (unsigned flags) void g_cmp (unsigned flags, unsigned long val) /* Immidiate compare. The primary register will not be changed, Z flag - * will be set. - */ +** will be set. +*/ { unsigned L; /* Check the size and determine operation */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("cmp #$%02X", (unsigned char)val); - break; - } - /* FALLTHROUGH */ - - case CF_INT: - L = GetLocalLabel(); - AddCodeLine ("cmp #$%02X", (unsigned char)val); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); - g_defcodelabel (L); - break; + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("cmp #$%02X", (unsigned char)val); + break; + } + /* FALLTHROUGH */ + + case CF_INT: + L = GetLocalLabel(); + AddCodeLine ("cmp #$%02X", (unsigned char)val); + AddCodeLine ("bne %s", LocalLabelName (L)); + AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); + g_defcodelabel (L); + break; case CF_LONG: - Internal ("g_cmp: Long compares not implemented"); - break; + Internal ("g_cmp: Long compares not implemented"); + break; - default: - typeerror (flags); + default: + typeerror (flags); } } -static void oper (unsigned flags, unsigned long val, char** subs) -/* Encode a binary operation. subs is a pointer to four groups of three - * strings: - * 0-2 --> Operate on ints - * 3-5 --> Operate on unsigneds - * 6-8 --> Operate on longs - * 9-11 --> Operate on unsigned longs - * - * The first subroutine names in each string group is used to encode an - * operation with a zero constant, the second to encode an operation with - * a 8 bit constant, and the third is used in all other cases. - */ +static void oper (unsigned Flags, unsigned long Val, const char* const* Subs) +/* Encode a binary operation. subs is a pointer to four strings: +** 0 --> Operate on ints +** 1 --> Operate on unsigneds +** 2 --> Operate on longs +** 3 --> Operate on unsigned longs +*/ { - unsigned offs; - /* Determine the offset into the array */ - offs = (flags & CF_UNSIGNED)? 3 : 0; - switch (flags & CF_TYPE) { - case CF_CHAR: - case CF_INT: - break; - - case CF_LONG: - offs += 6; - break; - - default: - typeerror (flags); + if (Flags & CF_UNSIGNED) { + ++Subs; + } + if ((Flags & CF_TYPEMASK) == CF_LONG) { + Subs += 2; } - /* Encode the operation */ - if (flags & CF_CONST) { - /* Constant value given */ - if (val == 0 && subs [offs+0]) { - /* Special case: constant with value zero */ - AddCodeLine ("jsr %s", subs [offs+0]); - } else if (val < 0x100 && subs [offs+1]) { - /* Special case: constant with high byte zero */ - ldaconst (val); /* Load low byte */ - AddCodeLine ("jsr %s", subs [offs+1]); - } else { - /* Others: arbitrary constant value */ - g_getimmed (flags, val, 0); /* Load value */ - AddCodeLine ("jsr %s", subs [offs+2]); - } - } else { - /* Value not constant (is already in (e)ax) */ - AddCodeLine ("jsr %s", subs [offs+2]); + /* Load the value if it is not already in the primary */ + if (Flags & CF_CONST) { + /* Load value */ + g_getimmed (Flags, Val, 0); } + /* Output the operation */ + AddCodeLine ("jsr %s", *Subs); + /* The operation will pop it's argument */ - pop (flags); + pop (Flags); } @@ -2317,30 +2246,30 @@ static void oper (unsigned flags, unsigned long val, char** subs) void g_test (unsigned flags) /* Test the value in the primary and set the condition codes */ { - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("tax"); - break; - } - /* FALLTHROUGH */ - - case CF_INT: - AddCodeLine ("stx tmp1"); - AddCodeLine ("ora tmp1"); - break; - - case CF_LONG: - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr utsteax"); - } else { - AddCodeLine ("jsr tsteax"); - } - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("tax"); + break; + } + /* FALLTHROUGH */ + + case CF_INT: + AddCodeLine ("stx tmp1"); + AddCodeLine ("ora tmp1"); + break; + + case CF_LONG: + if (flags & CF_UNSIGNED) { + AddCodeLine ("jsr utsteax"); + } else { + AddCodeLine ("jsr tsteax"); + } + break; + + default: + typeerror (flags); } } @@ -2350,52 +2279,52 @@ void g_test (unsigned flags) void g_push (unsigned flags, unsigned long val) /* Push the primary register or a constant value onto the stack */ { - if (flags & CF_CONST && (flags & CF_TYPE) != CF_LONG) { + if (flags & CF_CONST && (flags & CF_TYPEMASK) != CF_LONG) { - /* We have a constant 8 or 16 bit value */ - if ((flags & CF_TYPE) == CF_CHAR && (flags & CF_FORCECHAR)) { + /* We have a constant 8 or 16 bit value */ + if ((flags & CF_TYPEMASK) == CF_CHAR && (flags & CF_FORCECHAR)) { - /* Handle as 8 bit value */ - ldaconst (val); - AddCodeLine ("jsr pusha"); + /* Handle as 8 bit value */ + AddCodeLine ("lda #$%02X", (unsigned char) val); + AddCodeLine ("jsr pusha"); - } else { + } else { - /* Handle as 16 bit value */ - g_getimmed (flags, val, 0); - AddCodeLine ("jsr pushax"); - } + /* Handle as 16 bit value */ + g_getimmed (flags, val, 0); + AddCodeLine ("jsr pushax"); + } } else { - /* Value is not 16 bit or not constant */ - if (flags & CF_CONST) { - /* Constant 32 bit value, load into eax */ - g_getimmed (flags, val, 0); - } + /* Value is not 16 bit or not constant */ + if (flags & CF_CONST) { + /* Constant 32 bit value, load into eax */ + g_getimmed (flags, val, 0); + } - /* Push the primary register */ - switch (flags & CF_TYPE) { + /* Push the primary register */ + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - if (flags & CF_FORCECHAR) { - /* Handle as char */ - AddCodeLine ("jsr pusha"); - break; - } - /* FALL THROUGH */ - case CF_INT: - AddCodeLine ("jsr pushax"); - break; + case CF_CHAR: + if (flags & CF_FORCECHAR) { + /* Handle as char */ + AddCodeLine ("jsr pusha"); + break; + } + /* FALL THROUGH */ + case CF_INT: + AddCodeLine ("jsr pushax"); + break; - case CF_LONG: - AddCodeLine ("jsr pusheax"); - break; + case CF_LONG: + AddCodeLine ("jsr pusheax"); + break; - default: - typeerror (flags); + default: + typeerror (flags); - } + } } @@ -2407,22 +2336,22 @@ void g_push (unsigned flags, unsigned long val) void g_swap (unsigned flags) /* Swap the primary register and the top of the stack. flags give the type - * of *both* values (must have same size). - */ +** of *both* values (must have same size). +*/ { - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - case CF_INT: - AddCodeLine ("jsr swapstk"); - break; + case CF_CHAR: + case CF_INT: + AddCodeLine ("jsr swapstk"); + break; - case CF_LONG: - AddCodeLine ("jsr swapestk"); - break; + case CF_LONG: + AddCodeLine ("jsr swapestk"); + break; - default: - typeerror (flags); + default: + typeerror (flags); } } @@ -2433,11 +2362,11 @@ void g_call (unsigned Flags, const char* Label, unsigned ArgSize) /* Call the specified subroutine name */ { if ((Flags & CF_FIXARGC) == 0) { - /* Pass the argument count */ - ldyconst (ArgSize); + /* Pass the argument count */ + AddCodeLine ("ldy #$%02X", ArgSize); } AddCodeLine ("jsr _%s", Label); - oursp += ArgSize; /* callee pops args */ + StackPtr += ArgSize; /* callee pops args */ } @@ -2446,29 +2375,29 @@ void g_callind (unsigned Flags, unsigned ArgSize, int Offs) /* Call subroutine indirect */ { if ((Flags & CF_LOCAL) == 0) { - /* Address is in a/x */ - if ((Flags & CF_FIXARGC) == 0) { - /* Pass arg count */ - ldyconst (ArgSize); - } - AddCodeLine ("jsr callax"); + /* Address is in a/x */ + if ((Flags & CF_FIXARGC) == 0) { + /* Pass arg count */ + AddCodeLine ("ldy #$%02X", ArgSize); + } + AddCodeLine ("jsr callax"); } else { - /* The address is on stack, offset is on Val */ - Offs -= oursp; - CheckLocalOffs (Offs); - AddCodeLine ("pha"); - AddCodeLine ("ldy #$%02X", Offs); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta jmpvec+1"); - AddCodeLine ("iny"); - AddCodeLine ("lda (sp),y"); - AddCodeLine ("sta jmpvec+2"); - AddCodeLine ("pla"); - AddCodeLine ("jsr jmpvec"); + /* The address is on stack, offset is on Val */ + Offs -= StackPtr; + CheckLocalOffs (Offs); + AddCodeLine ("pha"); + AddCodeLine ("ldy #$%02X", Offs); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta jmpvec+1"); + AddCodeLine ("iny"); + AddCodeLine ("lda (sp),y"); + AddCodeLine ("sta jmpvec+2"); + AddCodeLine ("pla"); + AddCodeLine ("jsr jmpvec"); } /* Callee pops args */ - oursp += ArgSize; + StackPtr += ArgSize; } @@ -2496,27 +2425,70 @@ void g_falsejump (unsigned flags attribute ((unused)), unsigned label) } +void g_lateadjustSP (unsigned label) +/* Adjust stack based on non-immediate data */ +{ + AddCodeLine ("pha"); + AddCodeLine ("lda %s", LocalLabelName (label)); + AddCodeLine ("clc"); + AddCodeLine ("adc sp"); + AddCodeLine ("sta sp"); + AddCodeLine ("lda %s+1", LocalLabelName (label)); + AddCodeLine ("adc sp+1"); + AddCodeLine ("sta sp+1"); + AddCodeLine ("pla"); +} -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); } } @@ -2541,16 +2513,13 @@ void g_stackcheck (void) void g_add (unsigned flags, unsigned long val) /* Primary = TOS + Primary */ { - static char* ops [12] = { - 0, "tosadda0", "tosaddax", - 0, "tosadda0", "tosaddax", - 0, 0, "tosaddeax", - 0, 0, "tosaddeax", + static const char* const ops[4] = { + "tosaddax", "tosaddax", "tosaddeax", "tosaddeax" }; if (flags & CF_CONST) { - flags &= ~CF_FORCECHAR; /* Handle chars as ints */ - g_push (flags & ~CF_CONST, 0); + flags &= ~CF_FORCECHAR; /* Handle chars as ints */ + g_push (flags & ~CF_CONST, 0); } oper (flags, val, ops); } @@ -2560,16 +2529,13 @@ void g_add (unsigned flags, unsigned long val) void g_sub (unsigned flags, unsigned long val) /* Primary = TOS - Primary */ { - static char* ops [12] = { - 0, "tossuba0", "tossubax", - 0, "tossuba0", "tossubax", - 0, 0, "tossubeax", - 0, 0, "tossubeax", + static const char* const ops[4] = { + "tossubax", "tossubax", "tossubeax", "tossubeax" }; if (flags & CF_CONST) { - flags &= ~CF_FORCECHAR; /* Handle chars as ints */ - g_push (flags & ~CF_CONST, 0); + flags &= ~CF_FORCECHAR; /* Handle chars as ints */ + g_push (flags & ~CF_CONST, 0); } oper (flags, val, ops); } @@ -2579,11 +2545,8 @@ void g_sub (unsigned flags, unsigned long val) void g_rsub (unsigned flags, unsigned long val) /* Primary = Primary - TOS */ { - static char* ops [12] = { - 0, "tosrsuba0", "tosrsubax", - 0, "tosrsuba0", "tosrsubax", - 0, 0, "tosrsubeax", - 0, 0, "tosrsubeax", + static const char* const ops[4] = { + "tosrsubax", "tosrsubax", "tosrsubeax", "tosrsubeax" }; oper (flags, val, ops); } @@ -2593,104 +2556,101 @@ void g_rsub (unsigned flags, unsigned long val) void g_mul (unsigned flags, unsigned long val) /* Primary = TOS * Primary */ { - static char* ops [12] = { - 0, "tosmula0", "tosmulax", - 0, "tosumula0", "tosumulax", - 0, 0, "tosmuleax", - 0, 0, "tosumuleax", + static const char* const ops[4] = { + "tosmulax", "tosumulax", "tosmuleax", "tosumuleax" }; int p2; /* Do strength reduction if the value is constant and a power of two */ - if (flags & CF_CONST && (p2 = powerof2 (val)) >= 0) { - /* Generate a shift instead */ - g_asl (flags, p2); - return; + if (flags & CF_CONST && (p2 = PowerOf2 (val)) >= 0) { + /* Generate a shift instead */ + g_asl (flags, p2); + return; } /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - /* Handle some special cases */ - switch (val) { - - case 3: - AddCodeLine ("sta tmp1"); - AddCodeLine ("asl a"); - AddCodeLine ("clc"); - AddCodeLine ("adc tmp1"); - return; - - case 5: - AddCodeLine ("sta tmp1"); - AddCodeLine ("asl a"); - AddCodeLine ("asl a"); - AddCodeLine ("clc"); - AddCodeLine ("adc tmp1"); - return; - - case 6: - AddCodeLine ("sta tmp1"); - AddCodeLine ("asl a"); - AddCodeLine ("clc"); - AddCodeLine ("adc tmp1"); - AddCodeLine ("asl a"); - return; - - case 10: - AddCodeLine ("sta tmp1"); - AddCodeLine ("asl a"); - AddCodeLine ("asl a"); - AddCodeLine ("clc"); - AddCodeLine ("adc tmp1"); - AddCodeLine ("asl a"); - return; - } - } - /* FALLTHROUGH */ - - case CF_INT: - switch (val) { - case 3: - AddCodeLine ("jsr mulax3"); - return; - case 5: - AddCodeLine ("jsr mulax5"); - return; - case 6: - AddCodeLine ("jsr mulax6"); - return; - case 7: - AddCodeLine ("jsr mulax7"); - return; - case 9: - AddCodeLine ("jsr mulax9"); - return; - case 10: - AddCodeLine ("jsr mulax10"); - return; - } - break; - - case CF_LONG: - 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. - */ - flags &= ~CF_FORCECHAR; /* Handle chars as ints */ - g_push (flags & ~CF_CONST, 0); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + /* Handle some special cases */ + switch (val) { + + case 3: + AddCodeLine ("sta tmp1"); + AddCodeLine ("asl a"); + AddCodeLine ("clc"); + AddCodeLine ("adc tmp1"); + return; + + case 5: + AddCodeLine ("sta tmp1"); + AddCodeLine ("asl a"); + AddCodeLine ("asl a"); + AddCodeLine ("clc"); + AddCodeLine ("adc tmp1"); + return; + + case 6: + AddCodeLine ("sta tmp1"); + AddCodeLine ("asl a"); + AddCodeLine ("clc"); + AddCodeLine ("adc tmp1"); + AddCodeLine ("asl a"); + return; + + case 10: + AddCodeLine ("sta tmp1"); + AddCodeLine ("asl a"); + AddCodeLine ("asl a"); + AddCodeLine ("clc"); + AddCodeLine ("adc tmp1"); + AddCodeLine ("asl a"); + return; + } + } + /* FALLTHROUGH */ + + case CF_INT: + switch (val) { + case 3: + AddCodeLine ("jsr mulax3"); + return; + case 5: + AddCodeLine ("jsr mulax5"); + return; + case 6: + AddCodeLine ("jsr mulax6"); + return; + case 7: + AddCodeLine ("jsr mulax7"); + return; + case 9: + AddCodeLine ("jsr mulax9"); + return; + case 10: + AddCodeLine ("jsr mulax10"); + return; + } + break; + + case CF_LONG: + 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. + */ + flags &= ~CF_FORCECHAR; /* Handle chars as ints */ + g_push (flags & ~CF_CONST, 0); } @@ -2703,26 +2663,23 @@ void g_mul (unsigned flags, unsigned long val) void g_div (unsigned flags, unsigned long val) /* Primary = TOS / Primary */ { - static char* ops [12] = { - 0, "tosdiva0", "tosdivax", - 0, "tosudiva0", "tosudivax", - 0, 0, "tosdiveax", - 0, 0, "tosudiveax", + static const char* const ops[4] = { + "tosdivax", "tosudivax", "tosdiveax", "tosudiveax" }; /* Do strength reduction if the value is constant and a power of two */ int p2; - if ((flags & CF_CONST) && (p2 = powerof2 (val)) >= 0) { - /* Generate a shift instead */ - g_asr (flags, p2); + if ((flags & CF_CONST) && (p2 = PowerOf2 (val)) >= 0) { + /* Generate a shift instead */ + g_asr (flags, p2); } else { - /* Generate a division */ - if (flags & CF_CONST) { - /* lhs is not on stack */ - flags &= ~CF_FORCECHAR; /* Handle chars as ints */ - g_push (flags & ~CF_CONST, 0); - } - oper (flags, val, ops); + /* Generate a division */ + if (flags & CF_CONST) { + /* lhs is not on stack */ + flags &= ~CF_FORCECHAR; /* Handle chars as ints */ + g_push (flags & ~CF_CONST, 0); + } + oper (flags, val, ops); } } @@ -2731,26 +2688,23 @@ void g_div (unsigned flags, unsigned long val) void g_mod (unsigned flags, unsigned long val) /* Primary = TOS % Primary */ { - static char* ops [12] = { - 0, "tosmoda0", "tosmodax", - 0, "tosumoda0", "tosumodax", - 0, 0, "tosmodeax", - 0, 0, "tosumodeax", + static const char* const ops[4] = { + "tosmodax", "tosumodax", "tosmodeax", "tosumodeax" }; int p2; /* Check if we can do some cost reduction */ - if ((flags & CF_CONST) && (flags & CF_UNSIGNED) && val != 0xFFFFFFFF && (p2 = powerof2 (val)) >= 0) { - /* We can do that with an AND operation */ - g_and (flags, val - 1); + if ((flags & CF_CONST) && (flags & CF_UNSIGNED) && val != 0xFFFFFFFF && (p2 = PowerOf2 (val)) >= 0) { + /* We can do that with an AND operation */ + g_and (flags, val - 1); } else { - /* Do it the hard way... */ - if (flags & CF_CONST) { - /* lhs is not on stack */ - flags &= ~CF_FORCECHAR; /* Handle chars as ints */ - g_push (flags & ~CF_CONST, 0); - } - oper (flags, val, ops); + /* Do it the hard way... */ + if (flags & CF_CONST) { + /* lhs is not on stack */ + flags &= ~CF_FORCECHAR; /* Handle chars as ints */ + g_push (flags & ~CF_CONST, 0); + } + oper (flags, val, ops); } } @@ -2759,63 +2713,65 @@ void g_mod (unsigned flags, unsigned long val) void g_or (unsigned flags, unsigned long val) /* Primary = TOS | Primary */ { - static char* ops [12] = { - 0, "tosora0", "tosorax", - 0, "tosora0", "tosorax", - 0, 0, "tosoreax", - 0, 0, "tosoreax", + static const char* const ops[4] = { + "tosorax", "tosorax", "tosoreax", "tosoreax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if ((val & 0xFF) != 0) { - AddCodeLine ("ora #$%02X", (unsigned char)val); - } - return; - } - /* FALLTHROUGH */ + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if ((val & 0xFF) != 0) { + AddCodeLine ("ora #$%02X", (unsigned char)val); + } + return; + } + /* FALLTHROUGH */ - case CF_INT: - if (val <= 0xFF) { + case CF_INT: + if (val <= 0xFF) { if ((val & 0xFF) != 0) { - AddCodeLine ("ora #$%02X", (unsigned char)val); + AddCodeLine ("ora #$%02X", (unsigned char)val); } - return; - } else if ((val & 0xFF00) == 0xFF00) { + } else if ((val & 0xFF00) == 0xFF00) { if ((val & 0xFF) != 0) { - AddCodeLine ("ora #$%02X", (unsigned char)val); + AddCodeLine ("ora #$%02X", (unsigned char)val); } - ldxconst (0xFF); - return; + AddCodeLine ("ldx #$FF"); + } else if (val != 0) { + AddCodeLine ("ora #$%02X", (unsigned char)val); + AddCodeLine ("pha"); + AddCodeLine ("txa"); + AddCodeLine ("ora #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("tax"); + AddCodeLine ("pla"); } - break; + return; - case CF_LONG: - if (val <= 0xFF) { + case CF_LONG: + if (val <= 0xFF) { if ((val & 0xFF) != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); } - return; - } - 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 - * always work with ints. - */ + return; + } + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -2827,65 +2783,63 @@ void g_or (unsigned flags, unsigned long val) void g_xor (unsigned flags, unsigned long val) /* Primary = TOS ^ Primary */ { - static char* ops [12] = { - 0, "tosxora0", "tosxorax", - 0, "tosxora0", "tosxorax", - 0, 0, "tosxoreax", - 0, 0, "tosxoreax", + static const char* const ops[4] = { + "tosxorax", "tosxorax", "tosxoreax", "tosxoreax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if ((val & 0xFF) != 0) { - AddCodeLine ("eor #$%02X", (unsigned char)val); - } - return; - } - /* FALLTHROUGH */ - - case CF_INT: - if (val <= 0xFF) { - if (val != 0) { - AddCodeLine ("eor #$%02X", (unsigned char)val); - } - return; - } else if ((val & 0xFF) == 0) { - AddCodeLine ("pha"); - AddCodeLine ("txa"); - AddCodeLine ("eor #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("tax"); - AddCodeLine ("pla"); - return; - } - break; - - case CF_LONG: - if (val <= 0xFF) { - if (val != 0) { - AddCodeLine ("eor #$%02X", (unsigned char)val); - } - return; - } - 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 - * always work with ints. - */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if ((val & 0xFF) != 0) { + AddCodeLine ("eor #$%02X", (unsigned char)val); + } + return; + } + /* FALLTHROUGH */ + + case CF_INT: + if (val <= 0xFF) { + if (val != 0) { + AddCodeLine ("eor #$%02X", (unsigned char)val); + } + } else if (val != 0) { + if ((val & 0xFF) != 0) { + AddCodeLine ("eor #$%02X", (unsigned char)val); + } + AddCodeLine ("pha"); + AddCodeLine ("txa"); + AddCodeLine ("eor #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("tax"); + AddCodeLine ("pla"); + } + return; + + case CF_LONG: + if (val <= 0xFF) { + if (val != 0) { + AddCodeLine ("eor #$%02X", (unsigned char)val); + } + return; + } + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -2897,84 +2851,87 @@ void g_xor (unsigned flags, unsigned long val) void g_and (unsigned Flags, unsigned long Val) /* Primary = TOS & Primary */ { - static char* ops [12] = { - 0, "tosanda0", "tosandax", - 0, "tosanda0", "tosandax", - 0, 0, "tosandeax", - 0, 0, "tosandeax", + static const char* const ops[4] = { + "tosandax", "tosandax", "tosandeax", "tosandeax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (Flags & CF_CONST) { - switch (Flags & CF_TYPE) { + switch (Flags & CF_TYPEMASK) { - case CF_CHAR: - if (Flags & CF_FORCECHAR) { - if ((Val & 0xFF) != 0xFF) { + case CF_CHAR: + if (Flags & CF_FORCECHAR) { + if ((Val & 0xFF) == 0x00) { + AddCodeLine ("lda #$00"); + } else if ((Val & 0xFF) != 0xFF) { + AddCodeLine ("and #$%02X", (unsigned char)Val); + } + return; + } + /* FALLTHROUGH */ + case CF_INT: + if ((Val & 0xFFFF) != 0xFFFF) { + if (Val <= 0xFF) { + AddCodeLine ("ldx #$00"); + if (Val == 0) { + AddCodeLine ("lda #$00"); + } else if (Val != 0xFF) { + AddCodeLine ("and #$%02X", (unsigned char)Val); + } + } 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"); + AddCodeLine ("lda #$00"); + } else { + AddCodeLine ("tay"); + AddCodeLine ("txa"); + AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8)); + AddCodeLine ("tax"); + AddCodeLine ("tya"); + 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) { + AddCodeLine ("ldx #$00"); + AddCodeLine ("stx sreg+1"); + AddCodeLine ("stx sreg"); + if ((Val & 0xFF) != 0xFF) { + AddCodeLine ("and #$%02X", (unsigned char)Val); } - return; - } - /* FALLTHROUGH */ - case CF_INT: - if ((Val & 0xFFFF) != 0xFFFF) { - if (Val <= 0xFF) { - ldxconst (0); - if (Val == 0) { - ldaconst (0); - } else if (Val != 0xFF) { - AddCodeLine ("and #$%02X", (unsigned char)Val); - } - } 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); - } else { - AddCodeLine ("tay"); - AddCodeLine ("txa"); - AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8)); - AddCodeLine ("tax"); - AddCodeLine ("tya"); - if ((Val & 0x00FF) != 0x00FF) { - AddCodeLine ("and #$%02X", (unsigned char)Val); - } - } - } - return; - - case CF_LONG: - if (Val <= 0xFF) { - ldxconst (0); - AddCodeLine ("stx sreg+1"); - AddCodeLine ("stx sreg"); - if ((Val & 0xFF) != 0xFF) { - AddCodeLine ("and #$%02X", (unsigned char)Val); - } - return; - } else if (Val == 0xFF00) { - ldaconst (0); - AddCodeLine ("sta sreg+1"); - AddCodeLine ("sta sreg"); - return; - } - 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 - * always work with ints. - */ + return; + } else if (Val == 0xFF00) { + AddCodeLine ("lda #$00"); + AddCodeLine ("sta sreg+1"); + AddCodeLine ("sta sreg"); + return; + } + 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 + ** always work with ints. + */ Flags &= ~CF_FORCECHAR; - g_push (Flags & ~CF_CONST, 0); + g_push (Flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -2986,85 +2943,126 @@ void g_and (unsigned Flags, unsigned long Val) void g_asr (unsigned flags, unsigned long val) /* Primary = TOS >> Primary */ { - static char* ops [12] = { - 0, "tosasra0", "tosasrax", - 0, "tosshra0", "tosshrax", - 0, 0, "tosasreax", - 0, 0, "tosshreax", + static const char* const ops[4] = { + "tosasrax", "tosshrax", "tosasreax", "tosshreax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { - - case CF_CHAR: - case CF_INT: - if (val >= 8 && (flags & CF_UNSIGNED)) { - AddCodeLine ("txa"); - ldxconst (0); - val -= 8; - } - if (val == 0) { - /* Done */ - return; - } else if (val >= 1 && val <= 4) { - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr shrax%ld", val); - } else { - AddCodeLine ("jsr asrax%ld", val); - } - return; - } - break; - - 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); - } - 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 ("ldy #$00"); - AddCodeLine ("ldx sreg+1"); - if ((flags & CF_UNSIGNED) == 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("bpl %s", LocalLabelName (L)); - AddCodeLine ("dey"); - g_defcodelabel (L); - } - AddCodeLine ("lda sreg"); - AddCodeLine ("sty sreg+1"); - AddCodeLine ("sty sreg"); - return; - } - 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 - * always work with ints. - */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + case CF_INT: + 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 >= 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; + + case CF_LONG: + 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); + } + AddCodeLine ("stx sreg"); + AddCodeLine ("stx sreg+1"); + val -= 24; + } + if (val >= 16) { + AddCodeLine ("ldy #$00"); + AddCodeLine ("ldx sreg+1"); + if ((flags & CF_UNSIGNED) == 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("bpl %s", LocalLabelName (L)); + AddCodeLine ("dey"); + g_defcodelabel (L); + } + AddCodeLine ("lda sreg"); + AddCodeLine ("sty sreg+1"); + AddCodeLine ("sty sreg"); + val -= 16; + } + 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); + } + + /* 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3076,78 +3074,94 @@ void g_asr (unsigned flags, unsigned long val) void g_asl (unsigned flags, unsigned long val) /* Primary = TOS << Primary */ { - static char* ops [12] = { - 0, "tosasla0", "tosaslax", - 0, "tosshla0", "tosshlax", - 0, 0, "tosasleax", - 0, 0, "tosshleax", + static const char* const ops[4] = { + "tosaslax", "tosshlax", "tosasleax", "tosshleax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { - - case CF_CHAR: - case CF_INT: - if (val >= 8) { - AddCodeLine ("tax"); - AddCodeLine ("lda #$00"); - val -= 8; - } - if (val == 0) { - /* Done */ - return; - } else if (val >= 1 && val <= 4) { - if (flags & CF_UNSIGNED) { - AddCodeLine ("jsr shlax%ld", val); - } else { - AddCodeLine ("jsr aslax%ld", val); - } - return; - } - break; - - 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"); - AddCodeLine ("lda #$00"); - return; - } else if (val == 16) { - AddCodeLine ("stx sreg+1"); - AddCodeLine ("sta sreg"); - AddCodeLine ("lda #$00"); - AddCodeLine ("tax"); - return; - } - 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 - * always work with ints. - */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + case CF_INT: + val &= 0x0F; + if (val >= 8) { + AddCodeLine ("tax"); + AddCodeLine ("lda #$00"); + val -= 8; + } + 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; + + case CF_LONG: + val &= 0x1F; + if (val >= 24) { + AddCodeLine ("sta sreg+1"); + AddCodeLine ("lda #$00"); + AddCodeLine ("tax"); + AddCodeLine ("sta sreg"); + val -= 24; + } + if (val >= 16) { + AddCodeLine ("stx sreg+1"); + AddCodeLine ("sta sreg"); + AddCodeLine ("lda #$00"); + AddCodeLine ("tax"); + val -= 16; + } + 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); + } + + /* 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3159,9 +3173,9 @@ void g_asl (unsigned flags, unsigned long val) void g_neg (unsigned Flags) /* Primary = -Primary */ { - switch (Flags & CF_TYPE) { + switch (Flags & CF_TYPEMASK) { - case CF_CHAR: + case CF_CHAR: if (Flags & CF_FORCECHAR) { AddCodeLine ("eor #$FF"); AddCodeLine ("clc"); @@ -3170,16 +3184,16 @@ void g_neg (unsigned Flags) } /* FALLTHROUGH */ - case CF_INT: - AddCodeLine ("jsr negax"); - break; + case CF_INT: + AddCodeLine ("jsr negax"); + break; - case CF_LONG: - AddCodeLine ("jsr negeax"); - break; + case CF_LONG: + AddCodeLine ("jsr negeax"); + break; - default: - typeerror (Flags); + default: + typeerror (Flags); } } @@ -3188,22 +3202,22 @@ void g_neg (unsigned Flags) void g_bneg (unsigned flags) /* Primary = !Primary */ { - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - AddCodeLine ("jsr bnega"); - break; + case CF_CHAR: + AddCodeLine ("jsr bnega"); + break; - case CF_INT: - AddCodeLine ("jsr bnegax"); - break; + case CF_INT: + AddCodeLine ("jsr bnegax"); + break; - case CF_LONG: - AddCodeLine ("jsr bnegeax"); - break; + case CF_LONG: + AddCodeLine ("jsr bnegeax"); + break; - default: - typeerror (flags); + default: + typeerror (flags); } } @@ -3212,25 +3226,25 @@ void g_bneg (unsigned flags) void g_com (unsigned Flags) /* Primary = ~Primary */ { - switch (Flags & CF_TYPE) { + switch (Flags & CF_TYPEMASK) { - case CF_CHAR: + case CF_CHAR: if (Flags & CF_FORCECHAR) { AddCodeLine ("eor #$FF"); return; } /* FALLTHROUGH */ - case CF_INT: - AddCodeLine ("jsr complax"); - break; + case CF_INT: + AddCodeLine ("jsr complax"); + break; - case CF_LONG: - AddCodeLine ("jsr compleax"); - break; + case CF_LONG: + AddCodeLine ("jsr compleax"); + break; - default: - typeerror (Flags); + default: + typeerror (Flags); } } @@ -3241,89 +3255,94 @@ void g_inc (unsigned flags, unsigned long val) { /* Don't inc by zero */ if (val == 0) { - return; + return; } /* Generate code for the supported types */ flags &= ~CF_CONST; - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) { - while (val--) { - AddCodeLine ("ina"); - } - } else { - AddCodeLine ("clc"); - AddCodeLine ("adc #$%02X", (unsigned char)val); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val == 1) { - unsigned L = GetLocalLabel(); - AddCodeLine ("ina"); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("inx"); - g_defcodelabel (L); - } else if (CodeSizeFactor < 200) { - /* Use jsr calls */ - if (val <= 8) { - AddCodeLine ("jsr incax%lu", val); - } else if (val <= 255) { - ldyconst (val); - AddCodeLine ("jsr incaxy"); - } else { - g_add (flags | CF_CONST, val); - } - } else { - /* Inline the code */ - if (val <= 0x300) { - if ((val & 0xFF) != 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("clc"); - AddCodeLine ("adc #$%02X", (unsigned char) val); - AddCodeLine ("bcc %s", LocalLabelName (L)); - AddCodeLine ("inx"); - g_defcodelabel (L); - } - if (val >= 0x100) { - AddCodeLine ("inx"); - } - if (val >= 0x200) { - AddCodeLine ("inx"); - } - if (val >= 0x300) { - AddCodeLine ("inx"); - } - } else { - AddCodeLine ("clc"); - if ((val & 0xFF) != 0) { - AddCodeLine ("adc #$%02X", (unsigned char) val); - } - AddCodeLine ("pha"); - AddCodeLine ("txa"); - AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8)); - AddCodeLine ("tax"); - AddCodeLine ("pla"); - } - } - break; - - case CF_LONG: - if (val <= 255) { - ldyconst (val); - AddCodeLine ("jsr inceaxy"); - } else { - g_add (flags | CF_CONST, val); - } - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) { + while (val--) { + AddCodeLine ("ina"); + } + } else { + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", (unsigned char)val); + } + break; + } + /* FALLTHROUGH */ + + case CF_INT: + if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val == 1) { + unsigned L = GetLocalLabel(); + AddCodeLine ("ina"); + AddCodeLine ("bne %s", LocalLabelName (L)); + AddCodeLine ("inx"); + g_defcodelabel (L); + } else if (IS_Get (&CodeSizeFactor) < 200) { + /* Use jsr calls */ + if (val <= 8) { + AddCodeLine ("jsr incax%lu", val); + } else if (val <= 255) { + AddCodeLine ("ldy #$%02X", (unsigned char) val); + AddCodeLine ("jsr incaxy"); + } else { + g_add (flags | CF_CONST, val); + } + } else { + /* Inline the code */ + if (val <= 0x300) { + if ((val & 0xFF) != 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("clc"); + AddCodeLine ("adc #$%02X", (unsigned char) val); + AddCodeLine ("bcc %s", LocalLabelName (L)); + AddCodeLine ("inx"); + g_defcodelabel (L); + } + if (val >= 0x100) { + AddCodeLine ("inx"); + } + if (val >= 0x200) { + AddCodeLine ("inx"); + } + if (val >= 0x300) { + AddCodeLine ("inx"); + } + } else if ((val & 0xFF) != 0) { + AddCodeLine ("clc"); + 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"); + } + } + break; + + case CF_LONG: + if (val <= 255) { + AddCodeLine ("ldy #$%02X", (unsigned char) val); + AddCodeLine ("jsr inceaxy"); + } else { + g_add (flags | CF_CONST, val); + } + break; + + default: + typeerror (flags); } } @@ -3335,80 +3354,87 @@ void g_dec (unsigned flags, unsigned long val) { /* Don't dec by zero */ if (val == 0) { - return; + return; } /* Generate code for the supported types */ flags &= ~CF_CONST; - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) { - while (val--) { - AddCodeLine ("dea"); - } - } else { - AddCodeLine ("sec"); - AddCodeLine ("sbc #$%02X", (unsigned char)val); - } - break; - } - /* FALLTHROUGH */ - - case CF_INT: - if (CodeSizeFactor < 200) { - /* Use subroutines */ - if (val <= 8) { - AddCodeLine ("jsr decax%d", (int) val); - } else if (val <= 255) { - ldyconst (val); - AddCodeLine ("jsr decaxy"); - } else { - g_sub (flags | CF_CONST, val); - } - } else { - /* Inline the code */ - if (val < 0x300) { - if ((val & 0xFF) != 0) { - unsigned L = GetLocalLabel(); - AddCodeLine ("sec"); - AddCodeLine ("sbc #$%02X", (unsigned char) val); - AddCodeLine ("bcs %s", LocalLabelName (L)); - AddCodeLine ("dex"); - g_defcodelabel (L); - } - if (val >= 0x100) { - AddCodeLine ("dex"); - } - if (val >= 0x200) { - AddCodeLine ("dex"); - } - } else { - AddCodeLine ("sec"); - if ((val & 0xFF) != 0) { - AddCodeLine ("sbc #$%02X", (unsigned char) val); - } - AddCodeLine ("pha"); - AddCodeLine ("txa"); - AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8)); - AddCodeLine ("tax"); - AddCodeLine ("pla"); - } - } - break; - - case CF_LONG: - if (val <= 255) { - ldyconst (val); - AddCodeLine ("jsr deceaxy"); - } else { - g_sub (flags | CF_CONST, val); - } - break; - - default: - typeerror (flags); + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) { + while (val--) { + AddCodeLine ("dea"); + } + } else { + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char)val); + } + break; + } + /* FALLTHROUGH */ + + case CF_INT: + if (IS_Get (&CodeSizeFactor) < 200) { + /* Use subroutines */ + if (val <= 8) { + AddCodeLine ("jsr decax%d", (int) val); + } else if (val <= 255) { + AddCodeLine ("ldy #$%02X", (unsigned char) val); + AddCodeLine ("jsr decaxy"); + } else { + g_sub (flags | CF_CONST, val); + } + } else { + /* Inline the code */ + if (val < 0x300) { + if ((val & 0xFF) != 0) { + unsigned L = GetLocalLabel(); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char) val); + AddCodeLine ("bcs %s", LocalLabelName (L)); + AddCodeLine ("dex"); + g_defcodelabel (L); + } + if (val >= 0x100) { + AddCodeLine ("dex"); + } + if (val >= 0x200) { + AddCodeLine ("dex"); + } + } else { + if ((val & 0xFF) != 0) { + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char) val); + AddCodeLine ("pha"); + AddCodeLine ("txa"); + AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8)); + AddCodeLine ("tax"); + AddCodeLine ("pla"); + } else { + AddCodeLine ("pha"); + AddCodeLine ("txa"); + AddCodeLine ("sec"); + AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8)); + AddCodeLine ("tax"); + AddCodeLine ("pla"); + } + } + } + break; + + case CF_LONG: + if (val <= 255) { + AddCodeLine ("ldy #$%02X", (unsigned char) val); + AddCodeLine ("jsr deceaxy"); + } else { + g_sub (flags | CF_CONST, val); + } + break; + + default: + typeerror (flags); } } @@ -3416,62 +3442,59 @@ void g_dec (unsigned flags, unsigned long val) /* - * Following are the conditional operators. They compare the TOS against - * the primary and put a literal 1 in the primary if the condition is - * true, otherwise they clear the primary register - */ +** Following are the conditional operators. They compare the TOS against +** the primary and put a literal 1 in the primary if the condition is +** true, otherwise they clear the primary register +*/ void g_eq (unsigned flags, unsigned long val) /* Test for equal */ { - static char* ops [12] = { - "toseq00", "toseqa0", "toseqax", - "toseq00", "toseqa0", "toseqax", - 0, 0, "toseqeax", - 0, 0, "toseqeax", + static const char* const ops[4] = { + "toseqax", "toseqax", "toseqeax", "toseqeax" }; unsigned L; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("cmp #$%02X", (unsigned char)val); - AddCodeLine ("jsr booleq"); - return; - } - /* FALLTHROUGH */ - - case CF_INT: - L = GetLocalLabel(); - AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("cmp #$%02X", (unsigned char)val); - g_defcodelabel (L); - AddCodeLine ("jsr booleq"); - return; - - case CF_LONG: - 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 - * always work with ints. - */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("cmp #$%02X", (unsigned char)val); + AddCodeLine ("jsr booleq"); + return; + } + /* FALLTHROUGH */ + + case CF_INT: + L = GetLocalLabel(); + AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("bne %s", LocalLabelName (L)); + AddCodeLine ("cmp #$%02X", (unsigned char)val); + g_defcodelabel (L); + AddCodeLine ("jsr booleq"); + return; + + case CF_LONG: + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3483,52 +3506,49 @@ void g_eq (unsigned flags, unsigned long val) void g_ne (unsigned flags, unsigned long val) /* Test for not equal */ { - static char* ops [12] = { - "tosne00", "tosnea0", "tosneax", - "tosne00", "tosnea0", "tosneax", - 0, 0, "tosneeax", - 0, 0, "tosneeax", + static const char* const ops[4] = { + "tosneax", "tosneax", "tosneeax", "tosneeax" }; unsigned L; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - AddCodeLine ("cmp #$%02X", (unsigned char)val); - AddCodeLine ("jsr boolne"); - return; - } - /* FALLTHROUGH */ - - case CF_INT: - L = GetLocalLabel(); - AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); - AddCodeLine ("bne %s", LocalLabelName (L)); - AddCodeLine ("cmp #$%02X", (unsigned char)val); - g_defcodelabel (L); - AddCodeLine ("jsr boolne"); - return; - - case CF_LONG: - 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 - * always work with ints. - */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + AddCodeLine ("cmp #$%02X", (unsigned char)val); + AddCodeLine ("jsr boolne"); + return; + } + /* FALLTHROUGH */ + + case CF_INT: + L = GetLocalLabel(); + AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); + AddCodeLine ("bne %s", LocalLabelName (L)); + AddCodeLine ("cmp #$%02X", (unsigned char)val); + g_defcodelabel (L); + AddCodeLine ("jsr boolne"); + return; + + case CF_LONG: + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3540,22 +3560,21 @@ void g_ne (unsigned flags, unsigned long val) void g_lt (unsigned flags, unsigned long val) /* Test for less than */ { - static char* ops [12] = { - "toslt00", "toslta0", "tosltax", - "tosult00", "tosulta0", "tosultax", - 0, 0, "toslteax", - 0, 0, "tosulteax", + static const char* const ops[4] = { + "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. - */ + ** in the primary register. + */ if (flags & CF_CONST) { /* Because the handling of the overflow flag is too complex for - * inlining, we can handle only unsigned compares, and signed - * compares against zero here. - */ + ** inlining, we can handle only unsigned compares, and signed + ** compares against zero here. + */ if (flags & CF_UNSIGNED) { /* Give a warning in some special cases */ @@ -3566,7 +3585,7 @@ void g_lt (unsigned flags, unsigned long val) } /* Look at the type */ - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { @@ -3606,40 +3625,92 @@ void g_lt (unsigned flags, unsigned long val) } else if (val == 0) { - /* Look at the type */ - switch (flags & CF_TYPE) { + /* A signed compare against zero must only look at the sign bit */ + switch (flags & CF_TYPEMASK) { 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_TYPEMASK) { + + 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 - * into the normal, non-optimized stuff. Note: The standard stuff will - * always work with ints. - */ + /* 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3651,113 +3722,110 @@ void g_lt (unsigned flags, unsigned long val) void g_le (unsigned flags, unsigned long val) /* Test for less than or equal to */ { - static char* ops [12] = { - "tosle00", "toslea0", "tosleax", - "tosule00", "tosulea0", "tosuleax", - 0, 0, "tosleeax", - 0, 0, "tosuleeax", + static const char* const ops[4] = { + "tosleax", "tosuleax", "tosleeax", "tosuleeax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - /* Look at the type */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if (flags & CF_UNSIGNED) { - /* Unsigned compare */ - if (val < 0xFF) { - /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ - g_lt (flags, val+1); - } else { - /* Always true */ - Warning ("Condition is always true"); - AddCodeLine ("jsr return1"); - } - } else { - /* Signed compare */ - if ((long) val < 0x7F) { - /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ - g_lt (flags, val+1); - } else { - /* Always true */ - Warning ("Condition is always true"); - AddCodeLine ("jsr return1"); - } - } - return; - } - /* FALLTHROUGH */ - - case CF_INT: - if (flags & CF_UNSIGNED) { - /* Unsigned compare */ - if (val < 0xFFFF) { - /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ - g_lt (flags, val+1); - } else { - /* Always true */ - Warning ("Condition is always true"); - AddCodeLine ("jsr return1"); - } - } else { - /* Signed compare */ - if ((long) val < 0x7FFF) { - g_lt (flags, val+1); - } else { - /* Always true */ - Warning ("Condition is always true"); - AddCodeLine ("jsr return1"); - } - } - return; - - case CF_LONG: - if (flags & CF_UNSIGNED) { - /* Unsigned compare */ - if (val < 0xFFFFFFFF) { - /* Use < instead of <= because the former gives - * better code on the 6502 than the latter. - */ - g_lt (flags, val+1); - } else { - /* Always true */ - Warning ("Condition is always true"); - AddCodeLine ("jsr return1"); - } - } else { - /* Signed compare */ - if ((long) val < 0x7FFFFFFF) { - g_lt (flags, val+1); - } else { - /* Always true */ - Warning ("Condition is always true"); - AddCodeLine ("jsr return1"); - } - } - return; - - 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 - * always work with ints. - */ + /* Look at the type */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if (flags & CF_UNSIGNED) { + /* Unsigned compare */ + if (val < 0xFF) { + /* Use < instead of <= because the former gives + ** better code on the 6502 than the latter. + */ + g_lt (flags, val+1); + } else { + /* Always true */ + Warning ("Condition is always true"); + AddCodeLine ("jsr return1"); + } + } else { + /* Signed compare */ + if ((long) val < 0x7F) { + /* Use < instead of <= because the former gives + ** better code on the 6502 than the latter. + */ + g_lt (flags, val+1); + } else { + /* Always true */ + Warning ("Condition is always true"); + AddCodeLine ("jsr return1"); + } + } + return; + } + /* FALLTHROUGH */ + + case CF_INT: + if (flags & CF_UNSIGNED) { + /* Unsigned compare */ + if (val < 0xFFFF) { + /* Use < instead of <= because the former gives + ** better code on the 6502 than the latter. + */ + g_lt (flags, val+1); + } else { + /* Always true */ + Warning ("Condition is always true"); + AddCodeLine ("jsr return1"); + } + } else { + /* Signed compare */ + if ((long) val < 0x7FFF) { + g_lt (flags, val+1); + } else { + /* Always true */ + Warning ("Condition is always true"); + AddCodeLine ("jsr return1"); + } + } + return; + + case CF_LONG: + if (flags & CF_UNSIGNED) { + /* Unsigned compare */ + if (val < 0xFFFFFFFF) { + /* Use < instead of <= because the former gives + ** better code on the 6502 than the latter. + */ + g_lt (flags, val+1); + } else { + /* Always true */ + Warning ("Condition is always true"); + AddCodeLine ("jsr return1"); + } + } else { + /* Signed compare */ + if ((long) val < 0x7FFFFFFF) { + g_lt (flags, val+1); + } else { + /* Always true */ + Warning ("Condition is always true"); + AddCodeLine ("jsr return1"); + } + } + return; + + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3769,129 +3837,126 @@ void g_le (unsigned flags, unsigned long val) void g_gt (unsigned flags, unsigned long val) /* Test for greater than */ { - static char* ops [12] = { - "tosgt00", "tosgta0", "tosgtax", - "tosugt00", "tosugta0", "tosugtax", - 0, 0, "tosgteax", - 0, 0, "tosugteax", + static const char* const ops[4] = { + "tosgtax", "tosugtax", "tosgteax", "tosugteax" }; /* If the right hand side is const, the lhs is not on stack but still - * in the primary register. - */ + ** in the primary register. + */ if (flags & CF_CONST) { - /* Look at the type */ - switch (flags & CF_TYPE) { - - case CF_CHAR: - if (flags & CF_FORCECHAR) { - if (flags & CF_UNSIGNED) { - if (val == 0) { - /* If we have a compare > 0, we will replace it by - * != 0 here, since both are identical but the - * latter is easier to optimize. - */ - g_ne (flags, val); - } else if (val < 0xFF) { - /* Use >= instead of > because the former gives - * better code on the 6502 than the latter. - */ - g_ge (flags, val+1); - } else { - /* Never true */ - Warning ("Condition is never true"); - AddCodeLine ("jsr return0"); - } - } else { - if ((long) val < 0x7F) { - /* Use >= instead of > because the former gives - * better code on the 6502 than the latter. - */ - g_ge (flags, val+1); - } else { - /* Never true */ - Warning ("Condition is never true"); - AddCodeLine ("jsr return0"); - } - } - return; - } - /* FALLTHROUGH */ - - case CF_INT: - if (flags & CF_UNSIGNED) { - /* Unsigned compare */ - if (val == 0) { - /* If we have a compare > 0, we will replace it by - * != 0 here, since both are identical but the latter - * is easier to optimize. - */ - g_ne (flags, val); - } else if (val < 0xFFFF) { - /* Use >= instead of > because the former gives better - * code on the 6502 than the latter. - */ - g_ge (flags, val+1); - } else { - /* Never true */ - Warning ("Condition is never true"); - AddCodeLine ("jsr return0"); - } - } else { - /* Signed compare */ - if ((long) val < 0x7FFF) { - g_ge (flags, val+1); - } else { - /* Never true */ - Warning ("Condition is never true"); - AddCodeLine ("jsr return0"); - } - } - return; - - case CF_LONG: - if (flags & CF_UNSIGNED) { - /* Unsigned compare */ - if (val == 0) { - /* If we have a compare > 0, we will replace it by - * != 0 here, since both are identical but the latter - * is easier to optimize. - */ - g_ne (flags, val); - } else if (val < 0xFFFFFFFF) { - /* Use >= instead of > because the former gives better - * code on the 6502 than the latter. - */ - g_ge (flags, val+1); - } else { - /* Never true */ - Warning ("Condition is never true"); - AddCodeLine ("jsr return0"); - } - } else { - /* Signed compare */ - if ((long) val < 0x7FFFFFFF) { - g_ge (flags, val+1); - } else { - /* Never true */ - Warning ("Condition is never true"); - AddCodeLine ("jsr return0"); - } - } - return; - - 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 - * always work with ints. - */ + /* Look at the type */ + switch (flags & CF_TYPEMASK) { + + case CF_CHAR: + if (flags & CF_FORCECHAR) { + if (flags & CF_UNSIGNED) { + if (val == 0) { + /* If we have a compare > 0, we will replace it by + ** != 0 here, since both are identical but the + ** latter is easier to optimize. + */ + g_ne (flags, val); + } else if (val < 0xFF) { + /* Use >= instead of > because the former gives + ** better code on the 6502 than the latter. + */ + g_ge (flags, val+1); + } else { + /* Never true */ + Warning ("Condition is never true"); + AddCodeLine ("jsr return0"); + } + } else { + if ((long) val < 0x7F) { + /* Use >= instead of > because the former gives + ** better code on the 6502 than the latter. + */ + g_ge (flags, val+1); + } else { + /* Never true */ + Warning ("Condition is never true"); + AddCodeLine ("jsr return0"); + } + } + return; + } + /* FALLTHROUGH */ + + case CF_INT: + if (flags & CF_UNSIGNED) { + /* Unsigned compare */ + if (val == 0) { + /* If we have a compare > 0, we will replace it by + ** != 0 here, since both are identical but the latter + ** is easier to optimize. + */ + g_ne (flags, val); + } else if (val < 0xFFFF) { + /* Use >= instead of > because the former gives better + ** code on the 6502 than the latter. + */ + g_ge (flags, val+1); + } else { + /* Never true */ + Warning ("Condition is never true"); + AddCodeLine ("jsr return0"); + } + } else { + /* Signed compare */ + if ((long) val < 0x7FFF) { + g_ge (flags, val+1); + } else { + /* Never true */ + Warning ("Condition is never true"); + AddCodeLine ("jsr return0"); + } + } + return; + + case CF_LONG: + if (flags & CF_UNSIGNED) { + /* Unsigned compare */ + if (val == 0) { + /* If we have a compare > 0, we will replace it by + ** != 0 here, since both are identical but the latter + ** is easier to optimize. + */ + g_ne (flags, val); + } else if (val < 0xFFFFFFFF) { + /* Use >= instead of > because the former gives better + ** code on the 6502 than the latter. + */ + g_ge (flags, val+1); + } else { + /* Never true */ + Warning ("Condition is never true"); + AddCodeLine ("jsr return0"); + } + } else { + /* Signed compare */ + if ((long) val < 0x7FFFFFFF) { + g_ge (flags, val+1); + } else { + /* Never true */ + Warning ("Condition is never true"); + AddCodeLine ("jsr return0"); + } + } + return; + + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -3903,23 +3968,22 @@ void g_gt (unsigned flags, unsigned long val) void g_ge (unsigned flags, unsigned long val) /* Test for greater than or equal to */ { - static char* ops [12] = { - "tosge00", "tosgea0", "tosgeax", - "tosuge00", "tosugea0", "tosugeax", - 0, 0, "tosgeeax", - 0, 0, "tosugeeax", + static const char* const ops[4] = { + "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. - */ + ** in the primary register. + */ if (flags & CF_CONST) { /* Because the handling of the overflow flag is too complex for - * inlining, we can handle only unsigned compares, and signed - * compares against zero here. - */ + ** inlining, we can handle only unsigned compares, and signed + ** compares against zero here. + */ if (flags & CF_UNSIGNED) { /* Give a warning in some special cases */ @@ -3930,30 +3994,31 @@ void g_ge (unsigned flags, unsigned long val) } /* Look at the type */ - switch (flags & CF_TYPE) { + switch (flags & CF_TYPEMASK) { 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)); @@ -3961,7 +4026,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: @@ -3970,8 +4037,8 @@ void g_ge (unsigned flags, unsigned long val) } else if (val == 0) { - /* Look at the type */ - switch (flags & CF_TYPE) { + /* A signed compare against zero must only look at the sign bit */ + switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { @@ -3996,15 +4063,58 @@ void g_ge (unsigned flags, unsigned long val) default: typeerror (flags); } - } + } else { + + /* Signed compare against a constant != zero */ + switch (flags & CF_TYPEMASK) { + + 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; - /* 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 - * always work with ints. - */ + 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 + ** always work with ints. + */ flags &= ~CF_FORCECHAR; - g_push (flags & ~CF_CONST, 0); + g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ @@ -4014,7 +4124,7 @@ void g_ge (unsigned flags, unsigned long val) /*****************************************************************************/ -/* Allocating static storage */ +/* Allocating static storage */ /*****************************************************************************/ @@ -4032,34 +4142,34 @@ void g_defdata (unsigned flags, unsigned long val, long offs) { if (flags & CF_CONST) { - /* Numeric constant */ - switch (flags & CF_TYPE) { + /* Numeric constant */ + switch (flags & CF_TYPEMASK) { - case CF_CHAR: - AddDataLine ("\t.byte\t$%02lX", val & 0xFF); - break; + case CF_CHAR: + AddDataLine ("\t.byte\t$%02lX", val & 0xFF); + break; - case CF_INT: - AddDataLine ("\t.word\t$%04lX", val & 0xFFFF); - break; + case CF_INT: + AddDataLine ("\t.word\t$%04lX", val & 0xFFFF); + break; - case CF_LONG: - AddDataLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF); - break; + case CF_LONG: + AddDataLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF); + break; - default: - typeerror (flags); - break; + default: + typeerror (flags); + break; - } + } } else { - /* Create the correct label name */ - const char* Label = GetLabelName (flags, val, offs); + /* Create the correct label name */ + const char* Label = GetLabelName (flags, val, offs); - /* Labels are always 16 bit */ - AddDataLine ("\t.addr\t%s", Label); + /* Labels are always 16 bit */ + AddDataLine ("\t.addr\t%s", Label); } } @@ -4079,24 +4189,24 @@ void g_defbytes (const void* Bytes, unsigned Count) /* Output the stuff */ while (Count) { - /* How many go into this line? */ - if ((Chunk = Count) > 16) { - Chunk = 16; - } - Count -= Chunk; - - /* Output one line */ - strcpy (Buf, "\t.byte\t"); - B = Buf + 7; - do { - B += sprintf (B, "$%02X", *Data++); - if (--Chunk) { - *B++ = ','; - } - } while (Chunk); - - /* Output the line */ - AddDataLine (Buf); + /* How many go into this line? */ + if ((Chunk = Count) > 16) { + Chunk = 16; + } + Count -= Chunk; + + /* Output one line */ + strcpy (Buf, "\t.byte\t"); + B = Buf + 7; + do { + B += sprintf (B, "$%02X", *Data++); + if (--Chunk) { + *B++ = ','; + } + } while (Chunk); + + /* Output the line */ + AddDataLine ("%s", Buf); } } @@ -4117,7 +4227,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)); @@ -4134,19 +4244,19 @@ void g_initauto (unsigned Label, unsigned Size) CheckLocalOffs (Size); if (Size <= 128) { - ldyconst (Size-1); - g_defcodelabel (CodeLabel); + 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); - g_defcodelabel (CodeLabel); + AddCodeLine ("ldy #$00"); + g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); - AddCodeLine ("cpy #$%02X", (unsigned char) Size); + AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size); AddCodeLine ("bne %s", LocalLabelName (CodeLabel)); } } @@ -4158,7 +4268,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)); @@ -4166,28 +4276,28 @@ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size) AddCodeLine ("bpl %s", LocalLabelName (CodeLabel)); } else if (Size <= 256) { unsigned CodeLabel = GetLocalLabel (); - ldyconst (0); - g_defcodelabel (CodeLabel); + AddCodeLine ("ldy #$00"); + g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0)); AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0)); AddCodeLine ("iny"); - AddCodeLine ("cpy #$%02X", (unsigned char) Size); + AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size); AddCodeLine ("bne %s", LocalLabelName (CodeLabel)); } else { - /* Use the easy way here: memcpy */ + /* Use the easy way here: memcpy() */ g_getimmed (CF_STATIC, VarLabel, 0); AddCodeLine ("jsr pushax"); g_getimmed (CF_STATIC, InitLabel, 0); AddCodeLine ("jsr pushax"); g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, Size, 0); - AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (unsigned long) "memcpy", 0)); + AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (uintptr_t) "memcpy", 0)); } } /*****************************************************************************/ -/* Switch statement */ +/* Switch statement */ /*****************************************************************************/ @@ -4201,61 +4311,61 @@ void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth) /* Setup registers and determine which compare insn to use */ const char* Compare; switch (Depth) { - case 1: - Compare = "cmp #$%02X"; - break; - case 2: - Compare = "cpx #$%02X"; - break; - case 3: - AddCodeLine ("ldy sreg"); - Compare = "cpy #$%02X"; - break; - case 4: - AddCodeLine ("ldy sreg+1"); - Compare = "cpy #$%02X"; - break; - default: - Internal ("Invalid depth in g_switch: %u", Depth); + case 1: + Compare = "cmp #$%02X"; + break; + case 2: + Compare = "cpx #$%02X"; + break; + case 3: + AddCodeLine ("ldy sreg"); + Compare = "cpy #$%02X"; + break; + case 4: + AddCodeLine ("ldy sreg+1"); + Compare = "cpy #$%02X"; + break; + default: + Internal ("Invalid depth in g_switch: %u", Depth); } /* Walk over all nodes */ for (I = 0; I < CollCount (Nodes); ++I) { - /* Get the next case node */ - CaseNode* N = CollAtUnchecked (Nodes, I); + /* Get the next case node */ + CaseNode* N = CollAtUnchecked (Nodes, I); - /* If we have a next label, define it */ - if (NextLabel) { - g_defcodelabel (NextLabel); - NextLabel = 0; - } + /* If we have a next label, define it */ + if (NextLabel) { + g_defcodelabel (NextLabel); + NextLabel = 0; + } - /* Do the compare */ - AddCodeLine (Compare, CN_GetValue (N)); + /* Do the compare */ + AddCodeLine (Compare, CN_GetValue (N)); - /* If this is the last level, jump directly to the case code if found */ - if (Depth == 1) { + /* If this is the last level, jump directly to the case code if found */ + if (Depth == 1) { - /* Branch if equal */ - g_falsejump (0, CN_GetLabel (N)); + /* Branch if equal */ + g_falsejump (0, CN_GetLabel (N)); - } else { + } else { - /* Determine the next label */ - if (I == CollCount (Nodes) - 1) { - /* Last node means not found */ - g_truejump (0, DefaultLabel); - } else { - /* Jump to the next check */ - NextLabel = GetLocalLabel (); - g_truejump (0, NextLabel); - } + /* Determine the next label */ + if (I == CollCount (Nodes) - 1) { + /* Last node means not found */ + g_truejump (0, DefaultLabel); + } else { + /* Jump to the next check */ + NextLabel = GetLocalLabel (); + g_truejump (0, NextLabel); + } - /* Check the next level */ - g_switch (N->Nodes, DefaultLabel, Depth-1); + /* Check the next level */ + g_switch (N->Nodes, DefaultLabel, Depth-1); - } + } } /* If we go here, we haven't found the label */ @@ -4265,7 +4375,7 @@ void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth) /*****************************************************************************/ -/* User supplied assembler code */ +/* User supplied assembler code */ /*****************************************************************************/ @@ -4273,58 +4383,5 @@ 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)); -} - - - -/*****************************************************************************/ -/* Inlined known functions */ -/*****************************************************************************/ - - - -void g_strlen (unsigned flags, unsigned long val, long offs) -/* Inline the strlen() function */ -{ - /* We need a label in both cases */ - unsigned label = GetLocalLabel (); - - /* Two different encodings */ - if (flags & CF_CONST) { - - /* The address of the string is constant. Create the correct label name */ - const char* lbuf = GetLabelName (flags, val, offs); - - /* Generate the strlen code */ - AddCodeLine ("ldy #$FF"); - g_defcodelabel (label); - AddCodeLine ("iny"); - AddCodeLine ("lda %s,y", lbuf); - AddCodeLine ("bne %s", LocalLabelName (label)); - AddCodeLine ("tax"); - AddCodeLine ("tya"); - - } else { - - /* Address not constant but in primary */ - if (CodeSizeFactor < 400) { - /* This is too much code, so call strlen instead of inlining */ - AddCodeLine ("jsr _strlen"); - } else { - /* Inline the function */ - AddCodeLine ("sta ptr1"); - AddCodeLine ("stx ptr1+1"); - AddCodeLine ("ldy #$FF"); - g_defcodelabel (label); - AddCodeLine ("iny"); - AddCodeLine ("lda (ptr1),y"); - AddCodeLine ("bne %s", LocalLabelName (label)); - AddCodeLine ("tax"); - AddCodeLine ("tya"); - } - } + AddCodeLine ("%.*s", (int) SB_GetLen (B), SB_GetConstBuf (B)); } - - -