/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
break;
default:
- Internal ("Invalid address flags");
+ Internal ("Invalid address flags: %04X", Flags);
}
/* Return a pointer to the static buffer */
/* Identify the compiler version */
AddTextLine (";");
AddTextLine ("; File generated by cc65 v %u.%u.%u",
- VER_MAJOR, VER_MINOR, VER_PATCH);
+ VER_MAJOR, VER_MINOR, VER_PATCH);
AddTextLine (";");
/* Insert some object file options */
AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %u.%u.%u\"",
- VER_MAJOR, VER_MINOR, VER_PATCH);
+ VER_MAJOR, VER_MINOR, VER_PATCH);
/* If we're producing code for some other CPU, switch the command set */
if (CPU == CPU_65C02) {
- AddTextLine ("\t.pc02");
+ AddTextLine ("\t.pc02");
}
/* Allow auto import for runtime library routines */
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.
+void g_importmainargs (void)
+/* Forced import of a special symbol that handles arguments to main */
+{
+ AddTextLine ("\t.forceimport\tinitmainargs");
+}
+
+
+
/*****************************************************************************/
/* Load functions for various registers */
/*****************************************************************************/
/*****************************************************************************/
-/* Register variables */
+/* Register variables */
/*****************************************************************************/
+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;
+ CheckLocalOffs (StackOffs);
+
+ /* Generate code */
+ if (Bytes == 1) {
+
+ if (CodeSizeFactor < 165) {
+ ldyconst (StackOffs);
+ ldxconst (RegOffs);
+ AddCodeLine ("jsr regswap1");
+ } else {
+ ldyconst (StackOffs);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("ldx regbank%+d", RegOffs);
+ AddCodeLine ("sta regbank%+d", RegOffs);
+ AddCodeLine ("txa");
+ AddCodeLine ("sta (sp),y");
+ }
+
+ } else if (Bytes == 2) {
+
+ ldyconst (StackOffs);
+ ldxconst (RegOffs);
+ AddCodeLine ("jsr regswap2");
+
+ } else {
+
+ ldyconst (StackOffs);
+ ldxconst (RegOffs);
+ ldaconst (Bytes);
+ AddCodeLine ("jsr regswap");
+ }
+}
+
+
+
void g_save_regvars (int RegOffs, unsigned Bytes)
/* Save register variables */
{
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;
+ /* 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);
-void g_reglong (unsigned flags)
+void g_regint (unsigned Flags)
+/* Make sure, the value in the primary register an int. Convert if necessary */
+{
+ unsigned L;
+
+ switch (Flags & CF_TYPE) {
+
+ 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);
+ }
+ }
+ /* FALLTHROUGH */
+
+ case CF_INT:
+ case CF_LONG:
+ break;
+
+ default:
+ typeerror (Flags);
+ }
+}
+
+
+
+void g_reglong (unsigned Flags)
/* Make sure, the value in the primary register a long. Convert if necessary */
{
- switch (flags & CF_TYPE) {
+ unsigned L;
+
+ switch (Flags & CF_TYPE) {
case CF_CHAR:
+ if (Flags & CF_FORCECHAR) {
+ /* Conversion is from char */
+ if (Flags & CF_UNSIGNED) {
+ if (CodeSizeFactor >= 200) {
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("stx sreg");
+ AddCodeLine ("stx sreg+1");
+ } else {
+ 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);
+ AddCodeLine ("stx sreg");
+ AddCodeLine ("stx sreg+1");
+ } else {
+ AddCodeLine ("jsr along");
+ }
+ }
+ }
+ /* FALLTHROUGH */
+
case CF_INT:
- if (flags & CF_UNSIGNED) {
+ if (Flags & CF_UNSIGNED) {
if (CodeSizeFactor >= 200) {
ldyconst (0);
AddCodeLine ("sty sreg");
- AddCodeLine ("sty sreg+1");
+ AddCodeLine ("sty sreg+1");
} else {
AddCodeLine ("jsr axulong");
}
break;
default:
- typeerror (flags);
+ typeerror (Flags);
}
}
rtype = rhs & CF_TYPE;
/* 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);
+ 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);
+ }
}
/* Do not need any other action. If the left type is int, and the primary
-void g_zerobytes (unsigned n)
-/* Output n bytes of data initialized with zero */
+void g_zerobytes (unsigned Count)
+/* Output Count bytes of data initialized with zero */
{
- AddDataLine ("\t.res\t%u,$00", n);
+ if (Count > 0) {
+ AddDataLine ("\t.res\t%u,$00", Count);
+ }
+}
+
+
+
+void g_initregister (unsigned Label, unsigned Reg, unsigned Size)
+/* Initialize a register variable from static initialization data */
+{
+ /* Register variables do always have less than 128 bytes */
+ unsigned CodeLabel = GetLocalLabel ();
+ ldxconst (Size-1);
+ g_defcodelabel (CodeLabel);
+ AddCodeLine ("lda %s,x", GetLabelName (CF_STATIC, Label, 0));
+ AddCodeLine ("sta %s,x", GetLabelName (CF_REGVAR, Reg, 0));
+ AddCodeLine ("dex");
+ AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+}
+
+
+
+void g_initauto (unsigned Label, unsigned Size)
+/* Initialize a local variable at stack offset zero from static data */
+{
+ unsigned CodeLabel = GetLocalLabel ();
+
+ CheckLocalOffs (Size);
+ if (Size <= 128) {
+ ldyconst (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 ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("iny");
+ AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+ AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+ }
+}
+
+
+
+void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size)
+/* Initialize a static local variable from static initialization data */
+{
+ if (Size <= 128) {
+ unsigned CodeLabel = GetLocalLabel ();
+ ldyconst (Size-1);
+ g_defcodelabel (CodeLabel);
+ AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
+ AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (CodeLabel));
+ } else if (Size <= 256) {
+ unsigned CodeLabel = GetLocalLabel ();
+ ldyconst (0);
+ 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);
+ AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
+ } else {
+ /* 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));
+ }
}