X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodegen.c;h=6e05351d0d22d1d335214ae46b601f774f0fde6c;hb=d8338efc53e3be70bb17ab6c71f0dd95dff3db12;hp=716d49bbaff407afbeb962174166593e3625a10c;hpb=d1d104d7ffa25e178d4814f8ce4b78766316b4ad;p=cc65 diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 716d49bba..6e05351d0 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -134,7 +134,7 @@ static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs) default: Internal ("Invalid address flags"); } - + /* Return a pointer to the static buffer */ return Buf; } @@ -598,25 +598,25 @@ void g_getimmed (unsigned Flags, unsigned long Val, long Offs) 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); @@ -1131,18 +1131,81 @@ void g_tosint (unsigned flags) -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"); } @@ -1155,7 +1218,7 @@ void g_reglong (unsigned flags) break; default: - typeerror (flags); + typeerror (Flags); } } @@ -1223,9 +1286,14 @@ unsigned g_typecast (unsigned lhs, unsigned rhs) 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 @@ -1574,7 +1642,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs, if (val < 0x100) { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s+1)", lbuf); + AddCodeLine ("ldy #>(%s)", lbuf); if (val == 1) { AddCodeLine ("jsr laddeq1"); } else { @@ -1589,7 +1657,7 @@ void g_addeqstatic (unsigned flags, unsigned long label, long offs, } else { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s+1)", lbuf); + AddCodeLine ("ldy #>(%s)", lbuf); AddCodeLine ("jsr laddeq"); } break; @@ -1809,7 +1877,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs, if (val < 0x100) { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s+1)", lbuf); + AddCodeLine ("ldy #>(%s)", lbuf); AddCodeLine ("lda #$%02X", (unsigned char)val); AddCodeLine ("jsr lsubeqa"); } else { @@ -1820,7 +1888,7 @@ void g_subeqstatic (unsigned flags, unsigned long label, long offs, } else { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); - AddCodeLine ("ldy #>(%s+1)", lbuf); + AddCodeLine ("ldy #>(%s)", lbuf); AddCodeLine ("jsr lsubeq"); } break; @@ -3913,6 +3981,80 @@ void g_zerobytes (unsigned n) +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)); + } +} + + + /*****************************************************************************/ /* Switch statement */ /*****************************************************************************/