#define STRCASECMP strcasecmp
#endif
-#ifdef HAVE_SYS_ISA_DEFS_H
-#include <sys/isa_defs.h>
-#endif
-
#include "z80.h"
#include "SDCCglobl.h"
#include "SDCCpeeph.h"
int pushedDE;
} calleeSaves;
+ bool omitFramePtr;
int frameId;
int receiveOffset;
bool flushStatics;
bool in_home;
const char *lastFunctionName;
-
+ iCode *current_iCode;
+ bool preserveCarry;
+
set *sendSet;
struct
lineNode *head;
lineNode *current;
int isInline;
+ int isDebug;
allocTrace trace;
} lines;
"AOP_HLREG",
"AOP_SIMPLELIT",
"AOP_EXSTK",
- "AOP_PAIRPT"
+ "AOP_PAIRPT",
+ "AOP_DUMMY"
};
static bool
static void
_vemit2 (const char *szFormat, va_list ap)
{
- char buffer[256];
+ char buffer[INITIAL_INLINEASM];
- tvsprintf (buffer, szFormat, ap);
+ tvsprintf (buffer, sizeof(buffer), szFormat, ap);
_tidyUp (buffer);
_G.lines.current = (_G.lines.current ?
(_G.lines.head = _newLineNode (buffer)));
_G.lines.current->isInline = _G.lines.isInline;
+ _G.lines.current->isDebug = _G.lines.isDebug;
+ _G.lines.current->ic = _G.current_iCode;
}
static void
if (!DISABLE_DEBUG)
{
va_list ap;
-
+
va_start (ap, szFormat);
-
+
_vemit2 (szFormat, ap);
-
+
va_end (ap);
}
}
+/*-----------------------------------------------------------------*/
+/* z80_emitDebuggerSymbol - associate the current code location */
+/* with a debugger symbol */
+/*-----------------------------------------------------------------*/
+void
+z80_emitDebuggerSymbol (char * debugSym)
+{
+ _G.lines.isDebug = 1;
+ emit2 ("%s !equ .", debugSym);
+ emit2 ("!global", debugSym);
+ _G.lines.isDebug = 0;
+}
+
/*-----------------------------------------------------------------*/
/* emit2 - writes the code into a file : for now it is simple */
/*-----------------------------------------------------------------*/
{
va_list ap;
char lb[INITIAL_INLINEASM];
- char *lbp = lb;
+ unsigned char *lbp = lb;
va_start (ap, fmt);
(_G.lines.head = _newLineNode (lb)));
}
_G.lines.current->isInline = _G.lines.isInline;
+ _G.lines.current->ic = _G.current_iCode;
va_end (ap);
}
void
aopDump(const char *plabel, asmop *aop)
{
+ int i;
+ char regbuf[9];
+ char *rbp = regbuf;
+
emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size);
switch (aop->type)
{
+ case AOP_EXSTK:
case AOP_STK:
emitDebug("; aop_stk %d", aop->aopu.aop_stk);
break;
+ case AOP_REG:
+ for (i=aop->size-1;i>=0;i--)
+ *rbp++ = *(aop->aopu.aop_reg[i]->name);
+ *rbp = '\0';
+ emitDebug("; reg = %s", regbuf);
+ break;
+ case AOP_PAIRPTR:
+ emitDebug("; pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name);
+
default:
/* No information. */
break;
return (getPairId (aop) != PAIR_INVALID);
}
+/** Returns TRUE if the registers used in aop cannot be split into high
+ and low halves */
+bool
+isUnsplitable (asmop * aop)
+{
+ switch (getPairId (aop))
+ {
+ case PAIR_IX:
+ case PAIR_IY:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ return FALSE;
+}
+
bool
isPtrPair (asmop * aop)
{
_G.pairs[pairId].base = NULL;
}
+/* Given a register name, spill the pair (if any) the register is part of */
+static void
+spillPairReg (const char *regname)
+{
+ if (strlen(regname)==1)
+ {
+ switch (*regname)
+ {
+ case 'h':
+ case 'l':
+ spillPair(PAIR_HL);
+ break;
+ case 'd':
+ case 'e':
+ spillPair(PAIR_DE);
+ break;
+ case 'b':
+ case 'c':
+ spillPair(PAIR_BC);
+ break;
+ }
+ }
+}
+
/** Push a register pair onto the stack */
void
genPairPush (asmop * aop)
spillPair (pairId);
}
+void
+genMovePairPair (PAIR_ID srcPair, PAIR_ID dstPair)
+{
+ switch (dstPair)
+ {
+ case PAIR_IX:
+ case PAIR_IY:
+ case PAIR_AF:
+ _push(srcPair);
+ _pop(dstPair);
+ break;
+ case PAIR_BC:
+ case PAIR_DE:
+ case PAIR_HL:
+ if (srcPair == PAIR_IX || srcPair == PAIR_IY)
+ {
+ _push(srcPair);
+ _pop(dstPair);
+ }
+ else
+ {
+ emit2("ld %s,%s",_pairs[dstPair].l,_pairs[srcPair].l);
+ emit2("ld %s,%s",_pairs[dstPair].h,_pairs[srcPair].h);
+ }
+ default:
+ wassertl (0, "Tried to move a nonphysical pair");
+ }
+ _G.pairs[dstPair].last_type = _G.pairs[srcPair].last_type;
+ _G.pairs[dstPair].base = _G.pairs[srcPair].base;
+ _G.pairs[dstPair].offset = _G.pairs[srcPair].offset;
+}
+
+
/*-----------------------------------------------------------------*/
/* newAsmop - creates a new asmOp */
/*-----------------------------------------------------------------*/
Normally everything is AOP_STK, but for offsets of < -128 or
> 127 on the Z80 an extended stack pointer is used.
*/
- if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
+ if (IS_Z80 && (_G.omitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
{
emitDebug ("; AOP_EXSTK for %s", sym->rname);
sym->aop = aop = newAsmop (AOP_EXSTK);
return aop;
}
- if (IS_GB)
+ if( IN_REGSP( space ))
+ { /*.p.t.20030716 minor restructure to add SFR support to the Z80 */
+ if (IS_GB)
{
/* if it is in direct space */
- if (IN_REGSP (space) && !requires_a)
- {
- sym->aop = aop = newAsmop (AOP_SFR);
- aop->aopu.aop_dir = sym->rname;
- aop->size = getSize (sym->type);
+ if( !requires_a )
+ {
+ sym->aop = aop = newAsmop (AOP_SFR);
+ aop->aopu.aop_dir = sym->rname;
+ aop->size = getSize (sym->type);
emitDebug ("; AOP_SFR for %s", sym->rname);
- return aop;
- }
+ return aop;
+ }
+ }
+ else
+ { /*.p.t.20030716 adding SFR support to the Z80 port */
+ aop = newAsmop (AOP_SFR);
+ sym->aop = aop;
+ aop->aopu.aop_dir = sym->rname;
+ aop->size = getSize( sym->type );
+ aop->paged = FUNC_REGBANK(sym->type);
+ aop->bcInUse = isPairInUse( PAIR_BC, ic );
+ aop->deInUse = isPairInUse( PAIR_DE, ic );
+ emitDebug( ";Z80 AOP_SFR for %s banked:%d bc:%d de:%d", sym->rname, FUNC_REGBANK(sym->type), aop->bcInUse, aop->deInUse );
+
+ return( aop );
}
+ }
/* only remaining is far space */
/* in which case DPTR gets the address */
if (sym1 == sym2)
return 1;
- if (strcmp (sym1->rname, sym2->rname) == 0)
+ if (sym1->rname[0] && sym2->rname[0]
+ && strcmp (sym1->rname, sym2->rname) == 0)
return 2;
-
/* if left is a tmp & right is not */
if (IS_ITEMP (op1) &&
!IS_ITEMP (op2) &&
/* if already has a asmop then continue */
if (op->aop)
{
+ if (op->aop->type == AOP_SFR)
+ {
+ op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
+ op->aop->deInUse = isPairInUse( PAIR_DE, ic );
+ }
return;
}
if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
{
op->aop = OP_SYMBOL (op)->aop;
+ if (op->aop->type == AOP_SFR)
+ {
+ op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
+ op->aop->deInUse = isPairInUse( PAIR_DE, ic );
+ }
return;
}
return;
}
- /* else spill location */
- if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
- /* force a new aop if sizes differ */
- sym->usl.spillLoc->aop = NULL;
- }
- sym->aop = op->aop = aop =
- aopForSym (ic, sym->usl.spillLoc, result, requires_a);
- wassertl (aop->size >= getSize (sym->type), "Operand doesn't fit in the spill location");
+ if (sym->usl.spillLoc)
+ {
+ if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+ {
+ /* force a new aop if sizes differ */
+ sym->usl.spillLoc->aop = NULL;
+ }
+ sym->aop = op->aop = aop =
+ aopForSym (ic, sym->usl.spillLoc, result, requires_a);
+ aop->size = getSize (sym->type);
+ return;
+ }
+
+ /* else must be a dummy iTemp */
+ sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
aop->size = getSize (sym->type);
return;
}
char *
aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
{
- char *s = buffer;
-
/* depending on type */
switch (aop->type)
{
/* PENDING: for re-target */
if (with_hash)
{
- tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+ tsprintf (buffer, sizeof(buffer),
+ "!hashedstr + %d", aop->aopu.aop_immd, offset);
}
else if (offset == 0)
{
- tsprintf (s, "%s", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer),
+ "%s", aop->aopu.aop_immd);
}
else
{
- tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
+ tsprintf (buffer, sizeof(buffer),
+ "%s + %d", aop->aopu.aop_immd, offset);
}
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_LIT:
{
}
if (with_hash)
- tsprintf (buffer, "!immedword", v);
+ tsprintf (buffer, sizeof(buffer), "!immedword", v);
else
- tsprintf (buffer, "!constword", v);
+ tsprintf (buffer, sizeof(buffer), "!constword", v);
return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
/* it is type float */
fl.f = (float) floatFromVal (val);
-#ifdef _BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
#else
i = fl.c[offset] | (fl.c[offset+1]<<8);
#endif
if (with_hash)
- tsprintf (buffer, "!immedword", i);
+ tsprintf (buffer, sizeof(buffer), "!immedword", i);
else
- tsprintf (buffer, "!constword", i);
+ tsprintf (buffer, sizeof(buffer), "!constword", i);
return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
_pop (id);
}
}
+ else if (isUnsplitable(aop))
+ {
+ emit2("push %s", _pairs[getPairId(aop)].name);
+ emit2("pop %s", _pairs[pairId].name);
+ }
else
{
emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
{
wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
+ if (_G.preserveCarry)
+ {
+ _push (PAIR_AF);
+ offset += 2;
+ }
+
if (offset < INT8MIN || offset > INT8MAX)
{
emit2 ("ld hl,!immedword", offset);
}
else
{
- emit2 ("!ldahlsp", offset);
+ emit2 ("!ldahlsp", offset);
+ }
+
+ if (_G.preserveCarry)
+ {
+ _pop (PAIR_AF);
+ offset -= 2;
}
}
else
{
/* PENDING: Do this better. */
+ if (_G.preserveCarry)
+ _push (PAIR_AF);
sprintf (buffer, "%d", offset + _G.stack.pushed);
emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
emit2 ("add %s,sp", _pairs[pairId].name);
_G.pairs[pairId].last_type = aop->type;
_G.pairs[pairId].offset = offset;
+ if (_G.preserveCarry)
+ _pop (PAIR_AF);
}
}
break;
}
case AOP_PAIRPTR:
+ if (pairId != aop->aopu.aop_pairId)
+ genMovePairPair(aop->aopu.aop_pairId, pairId);
adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
break;
static const char *
aopGet (asmop * aop, int offset, bool bit16)
{
- char *s = buffer;
+ // char *s = buffer;
/* offset is greater than size then zero */
/* PENDING: this seems a bit screwed in some pointer cases. */
if (offset > (aop->size - 1) &&
aop->type != AOP_LIT)
{
- tsprintf (s, "!zero");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ tsprintf (buffer, sizeof(buffer), "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
/* depending on type */
switch (aop->type)
{
+ case AOP_DUMMY:
+ tsprintf (buffer, sizeof(buffer), "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+
case AOP_IMMD:
/* PENDING: re-target */
if (bit16)
- tsprintf (s, "!immedwords", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
else
switch (offset)
{
case 2:
- tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
break;
case 1:
- tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
break;
case 0:
- tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
+ tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
break;
default:
wassertl (0, "Fetching from beyond the limits of an immediate value.");
}
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_DIR:
wassert (IS_GB);
emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
- sprintf (s, "a");
+ SNPRINTF (buffer, sizeof(buffer), "a");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_SFR:
- wassert (IS_GB);
- emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
- sprintf (s, "a");
+ if( IS_GB )
+ {
+ // wassert (IS_GB);
+ emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
+ SNPRINTF (buffer, sizeof(buffer), "a");
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+ }
+ else
+ { /*.p.t.20030716 handling for i/o port read access for Z80 */
+ if( aop->paged )
+ { /* banked mode */
+ /* reg A goes to address bits 15-8 during "in a,(x)" instruction */
+ emit2( "ld a,!msbimmeds", aop->aopu.aop_dir);
+ emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir);
+ }
+ else if( z80_opts.port_mode == 180 )
+ { /* z180 in0/out0 mode */
+ emit2( "in0 a,(%s)", aop->aopu.aop_dir );
+ }
+ else
+ { /* 8 bit mode */
+ emit2( "in a,(%s)", aop->aopu.aop_dir );
+ }
+
+ SNPRINTF (buffer, sizeof(buffer), "a");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+ }
case AOP_REG:
return aop->aopu.aop_reg[offset]->name;
case AOP_HL:
wassert (IS_GB);
setupPair (PAIR_HL, aop, offset);
- tsprintf (s, "!*hl");
+ tsprintf (buffer, sizeof(buffer), "!*hl");
- return traceAlloc(&_G.trace.aops, Safe_strdup (s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
case AOP_IY:
wassert (IS_Z80);
setupPair (PAIR_IY, aop, offset);
- tsprintf (s, "!*iyx", offset);
+ tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_EXSTK:
wassert (IS_Z80);
setupPair (PAIR_IY, aop, offset);
- tsprintf (s, "!*iyx", offset, offset);
+ tsprintf (buffer, sizeof(buffer), "!*iyx", offset, offset);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_STK:
if (IS_GB)
{
setupPair (PAIR_HL, aop, offset);
- tsprintf (s, "!*hl");
+ tsprintf (buffer, sizeof(buffer), "!*hl");
}
else
{
if (aop->aopu.aop_stk >= 0)
offset += _G.stack.param_offset;
- tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
+ tsprintf (buffer, sizeof(buffer),
+ "!*ixx", aop->aopu.aop_stk + offset);
}
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
case AOP_CRY:
wassertl (0, "Tried to fetch from a bit variable");
}
else
{
- tsprintf(s, "!zero");
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ tsprintf(buffer, sizeof(buffer), "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
case AOP_HLREG:
unsigned long v = aop->aopu.aop_simplelit;
v >>= (offset * 8);
- tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
+ tsprintf (buffer, sizeof(buffer),
+ "!immedbyte", (unsigned int) v & 0xff);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
}
case AOP_STR:
aop->coff = offset;
case AOP_PAIRPTR:
setupPair (aop->aopu.aop_pairId, aop, offset);
- sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name);
+ if (aop->aopu.aop_pairId==PAIR_IX)
+ SNPRINTF (buffer, sizeof(buffer),
+ "!*ixx", 0);
+ else if (aop->aopu.aop_pairId==PAIR_IY)
+ SNPRINTF (buffer, sizeof(buffer),
+ "!*iyx", 0);
+ else
+ SNPRINTF (buffer, sizeof(buffer),
+ "(%s)", _pairs[aop->aopu.aop_pairId].name);
- return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
default:
break;
}
// PENDING
- tsprintf(buffer2, s);
+ tsprintf(buffer2, sizeof(buffer2), s);
s = buffer2;
/* will assign value to value */
/* depending on where it is ofcourse */
switch (aop->type)
{
+ case AOP_DUMMY:
+ _moveA (s); /* in case s is volatile */
+ break;
+
case AOP_DIR:
/* Direct. Hmmm. */
wassert (IS_GB);
break;
case AOP_SFR:
- wassert (IS_GB);
- if (strcmp (s, "a"))
- emit2 ("ld a,%s", s);
- emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+ if( IS_GB )
+ {
+ // wassert (IS_GB);
+ if (strcmp (s, "a"))
+ emit2 ("ld a,%s", s);
+ emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+ }
+ else
+ { /*.p.t.20030716 handling for i/o port read access for Z80 */
+ if (aop->paged)
+ { /* banked mode */
+ if (aop->bcInUse)
+ emit2( "push bc" );
+
+ if (strlen(s) != 1
+ || (s[0] != 'a' && s[0] != 'd' && s[0] != 'e'
+ && s[0] != 'h' && s[0] != 'l'))
+ {
+ emit2( "ld a,%s", s );
+ s = "a";
+ }
+
+ emit2( "ld bc,#%s", aop->aopu.aop_dir );
+ emit2( "out (c),%s", s );
+
+ if( aop->bcInUse )
+ emit2( "pop bc" );
+ else
+ spillPair (PAIR_BC);
+ }
+ else if( z80_opts.port_mode == 180 )
+ { /* z180 in0/out0 mode */
+ emit2( "ld a,%s", s );
+ emit2( "out0 (%s),a", aop->aopu.aop_dir );
+ }
+ else
+ { /* 8 bit mode */
+ emit2( "ld a,%s", s );
+ emit2( "out (%s),a", aop->aopu.aop_dir );
+ }
+ }
break;
case AOP_REG:
else
emit2 ("ld %s,%s",
aop->aopu.aop_reg[offset]->name, s);
+ spillPairReg(aop->aopu.aop_reg[offset]->name);
break;
case AOP_IY:
{
emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
}
+ spillPairReg(aop->aopu.aop_str[offset]);
break;
case AOP_ACC:
else
{
if (strcmp (aop->aopu.aop_str[offset], s))
- emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+ {
+ emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+ spillPairReg(aop->aopu.aop_str[offset]);
+ }
}
break;
case AOP_HLREG:
wassert (offset < 2);
emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+ spillPairReg(aop->aopu.aop_str[offset]);
break;
case AOP_PAIRPTR:
setupPair (aop->aopu.aop_pairId, aop, offset);
- emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
+ if (aop->aopu.aop_pairId==PAIR_IX)
+ emit2 ("ld !*ixx,%s", 0, s);
+ else if (aop->aopu.aop_pairId==PAIR_IY)
+ emit2 ("ld !*ixy,%s", 0, s);
+ else
+ emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
break;
default:
#define AOP(op) op->aop
#define AOP_TYPE(op) AOP(op)->type
#define AOP_SIZE(op) AOP(op)->size
-#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+#define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
static void
commitPair (asmop * aop, PAIR_ID id)
}
}
-/*-----------------------------------------------------------------*/
-/* genNotFloat - generates not for float operations */
-/*-----------------------------------------------------------------*/
-static void
-genNotFloat (operand * op, operand * res)
-{
- int size, offset;
- symbol *tlbl;
-
- emitDebug ("; genNotFloat");
-
- /* we will put 127 in the first byte of
- the result */
- aopPut (AOP (res), "!immedbyte", 0x7F);
- size = AOP_SIZE (op) - 1;
- offset = 1;
-
- _moveA (aopGet (op->aop, offset++, FALSE));
-
- while (size--)
- {
- emit2 ("or a,%s", aopGet (op->aop, offset++, FALSE));
- }
-
- tlbl = newiTempLabel (NULL);
- aopPut (res->aop, "!one", 1);
- emit2 ("!shortjp z !tlabel", tlbl->key + 100);
- aopPut (res->aop, "!zero", 1);
-
- emitLabel(tlbl->key + 100);
-
- size = res->aop->size - 2;
- offset = 2;
- /* put zeros in the rest */
- while (size--)
- aopPut (res->aop, "!zero", offset++);
-}
/*-----------------------------------------------------------------*/
/* genNot - generate code for ! operation */
static void
genNot (iCode * ic)
{
- sym_link *optype = operandType (IC_LEFT (ic));
/* assign asmOps to operand & result */
aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
wassertl (0, "Tried to negate a bit");
}
- /* if type float then do float */
- if (IS_FLOAT (optype))
- {
- genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
- goto release;
- }
-
_toBoolean (IC_LEFT (ic));
/* Not of A:
emit2 ("sub a,!one");
outBitC (IC_RESULT (ic));
- release:
/* release the aops */
freeAsmop (IC_LEFT (ic), NULL, ic);
freeAsmop (IC_RESULT (ic), NULL, ic);
emitDebug("; genUminusFloat");
/* for this we just need to flip the
- first it then copy the rest in place */
+ first bit then copy the rest in place */
size = AOP_SIZE (op) - 1;
_moveA(aopGet (AOP (op), MSB32, FALSE));
bool bcInRet = FALSE, deInRet = FALSE;
bitVect *rInUse;
- rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+ rInUse = bitVectCplAnd (bitVectCopy (ic->rMask),
+ z80_rUmaskForOp (IC_RESULT(ic)));
deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
static void
emitCall (iCode * ic, bool ispcall)
{
+ bool bInRet, cInRet, dInRet, eInRet;
sym_link *dtype = operandType (IC_LEFT (ic));
/* if caller saves & we have not saved then */
}
spillCached ();
- /* Mark the regsiters as restored. */
+ /* Mark the registers as restored. */
_G.saves.saved = FALSE;
/* if we need assign a result value */
}
spillCached ();
+ if (IC_RESULT (ic))
+ {
+ bitVect *result = z80_rUmaskForOp (IC_RESULT (ic));
+ bInRet = bitVectBitValue(result, B_IDX);
+ cInRet = bitVectBitValue(result, C_IDX);
+ dInRet = bitVectBitValue(result, D_IDX);
+ eInRet = bitVectBitValue(result, E_IDX);
+ }
+ else
+ {
+ bInRet = FALSE;
+ cInRet = FALSE;
+ dInRet = FALSE;
+ eInRet = FALSE;
+ }
if (_G.stack.pushedDE)
{
- bool dInRet = bitVectBitValue(ic->rUsed, D_IDX);
- bool eInRet = bitVectBitValue(ic->rUsed, E_IDX);
-
if (dInRet && eInRet)
{
wassertl (0, "Shouldn't push DE if it's wiped out by the return");
if (_G.stack.pushedBC)
{
- bool bInRet = bitVectBitValue(ic->rUsed, B_IDX);
- bool cInRet = bitVectBitValue(ic->rUsed, C_IDX);
-
if (bInRet && cInRet)
{
wassertl (0, "Shouldn't push BC if it's wiped out by the return");
static void
genFunction (iCode * ic)
{
+ bool stackParm;
+
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
sym_link *ftype;
/* Create the function header */
emit2 ("!functionheader", sym->name);
- sprintf (buffer, "%s_start", sym->rname);
- emit2 ("!labeldef", buffer);
+ if (!IS_STATIC(sym->etype))
+ {
+ sprintf (buffer, "%s_start", sym->rname);
+ emit2 ("!labeldef", buffer);
+ }
emit2 ("!functionlabeldef", sym->rname);
if (options.profile)
ftype = operandType (IC_LEFT (ic));
- /* if critical function then turn interrupts off */
- if (IFFUNC_ISCRITICAL (ftype))
- emit2 ("!di");
-
/* if this is an interrupt service routine then save all potentially used registers. */
if (IFFUNC_ISISR (sym->type))
{
- emit2 ("!pusha");
+ if (!FUNC_ISNAKED( sym->type ))
+ {
+ emit2 ("!pusha");
+ }
+ }
+ else
+ {
+ /* if critical function then turn interrupts off */
+ if (IFFUNC_ISCRITICAL (sym->type))
+ {
+ emit2 ("!di");
+ }
}
/* PENDING: callee-save etc */
/* adjust the stack for the function */
_G.stack.last = sym->stack;
-
- if (sym->stack && IS_GB && sym->stack > -INT8MIN)
+
+ stackParm = FALSE;
+ for (sym = setFirstItem (istack->syms); sym;
+ sym = setNextItem (istack->syms))
+ {
+ if (sym->_isparm && !IS_REGPARM (sym->etype))
+ {
+ stackParm = TRUE;
+ break;
+ }
+ }
+ sym = OP_SYMBOL (IC_LEFT (ic));
+
+ _G.omitFramePtr = options.ommitFramePtr;
+ if (IS_Z80 && !stackParm && !sym->stack)
+ {
+ /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */
+ /* the above !sym->stack condition can be removed. -- EEP */
+ if (sym->stack)
+ emit2 ("!ldaspsp", -sym->stack);
+ _G.omitFramePtr = TRUE;
+ }
+ else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
emit2 ("!enterxl", sym->stack);
else if (sym->stack)
emit2 ("!enterx", sym->stack);
- else
+ else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
emit2 ("!enter");
+
_G.stack.offset = sym->stack;
}
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
- if (IFFUNC_ISISR (sym->type))
+
+ /* PENDING: calleeSave */
+ if (IS_Z80 && _G.omitFramePtr)
{
- wassertl (0, "Tried to close an interrupt support function");
+ if (_G.stack.offset)
+ emit2 ("!ldaspsp", _G.stack.offset);
}
- else
+ else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
{
- if (IFFUNC_ISCRITICAL (sym->type))
- emit2 ("!ei");
-
- /* PENDING: calleeSave */
-
- if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
- {
- emit2 ("!leavexl", _G.stack.offset);
- }
- else if (_G.stack.offset)
- {
- emit2 ("!leavex", _G.stack.offset);
- }
- else
- {
- emit2 ("!leave");
- }
+ emit2 ("!leavexl", _G.stack.offset);
+ }
+ else if (_G.stack.offset)
+ {
+ emit2 ("!leavex", _G.stack.offset);
+ }
+ else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
+ {
+ emit2 ("!leave");
+ }
+
+ if (_G.calleeSaves.pushedDE)
+ {
+ emit2 ("pop de");
+ _G.calleeSaves.pushedDE = FALSE;
+ }
- if (_G.calleeSaves.pushedDE)
- {
- emit2 ("pop de");
- _G.calleeSaves.pushedDE = FALSE;
- }
+ if (_G.calleeSaves.pushedBC)
+ {
+ emit2 ("pop bc");
+ _G.calleeSaves.pushedBC = FALSE;
+ }
- if (_G.calleeSaves.pushedBC)
- {
- emit2 ("pop bc");
- _G.calleeSaves.pushedBC = FALSE;
- }
+ if (options.profile)
+ {
+ emit2 ("!profileexit");
+ }
- if (options.profile)
+ /* if this is an interrupt service routine then restore all potentially used registers. */
+ if (IFFUNC_ISISR (sym->type))
+ {
+ if (!FUNC_ISNAKED( sym->type ))
{
- emit2 ("!profileexit");
+ emit2 ("!popa");
}
+ }
+ else
+ {
+ /* if critical function then turn interrupts back on */
+ if (IFFUNC_ISCRITICAL (sym->type))
+ emit2 ("!ei");
+ }
-
- /* Both baned and non-banked just ret */
+ if (options.debug && currFunc)
+ {
+ debugFile->writeEndFunction (currFunc, ic, 1);
+ }
+
+ if (IFFUNC_ISISR (sym->type))
+ {
+ /* "critical interrupt" is used to imply NMI handler */
+ if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type))
+ emit2 ("retn");
+ else
+ emit2 ("reti");
+ }
+ else
+ {
+ /* Both banked and non-banked just ret */
emit2 ("ret");
-
+ }
+
+ if (!IS_STATIC(sym->etype))
+ {
sprintf (buffer, "%s_end", sym->rname);
emit2 ("!labeldef", buffer);
}
+
_G.flushStatics = 1;
_G.stack.pushed = 0;
_G.stack.offset = 0;
aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
size = AOP_SIZE (IC_LEFT (ic));
+ aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
+
+ #if 0
if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
{
if (IS_GB)
emit2 ("ld hl,%s", l);
}
}
+ #endif
+ if (size==2)
+ {
+ fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic)));
+ }
else
{
if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
l = aopGet (AOP (IC_LEFT (ic)), offset,
FALSE);
if (strcmp (_fReturn[offset], l))
- emit2 ("ld %s,%s", _fReturn[offset++], l);
+ emit2 ("ld %s,%s", _fReturn[offset], l);
+ offset++;
}
}
}
if (couldDestroyCarry (right) && couldDestroyCarry (result))
{
shiftIntoPair (0, right);
- shiftIntoPair (1, result);
+ /* check result again, in case right == result */
+ if (couldDestroyCarry (result))
+ shiftIntoPair (1, result);
}
else if (couldDestroyCarry (right))
{
- shiftIntoPair (0, right);
+ if (getPairId (result) == PAIR_HL)
+ _G.preserveCarry = TRUE;
+ else
+ shiftIntoPair (0, right);
}
else if (couldDestroyCarry (result))
{
in ACC */
if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
- (AOP_NEEDSACC (IC_LEFT (ic))) ||
+ (AOP_NEEDSACC (IC_RIGHT (ic))) ||
AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
{
operand *t = IC_RIGHT (ic);
goto release;
}
}
-
+
setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
while (size--)
}
release:
+ _G.preserveCarry = FALSE;
freeAsmop (IC_LEFT (ic), NULL, ic);
freeAsmop (IC_RIGHT (ic), NULL, ic);
freeAsmop (IC_RESULT (ic), NULL, ic);
}
release:
+ _G.preserveCarry = FALSE;
freeAsmop (IC_LEFT (ic), NULL, ic);
freeAsmop (IC_RIGHT (ic), NULL, ic);
freeAsmop (IC_RESULT (ic), NULL, ic);
int count, i;
/* If true then the final operation should be a subtract */
bool active = FALSE;
+ bool byteResult;
/* Shouldn't occur - all done through function calls */
aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+ byteResult = (AOP_SIZE (IC_RESULT (ic)) == 1);
if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
AOP_SIZE (IC_RIGHT (ic)) > 2 ||
if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
{
emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
- emit2 ("ld a,e");
- emit2 ("rlc a");
- emit2 ("sbc a,a");
- emit2 ("ld d,a");
+ if (!byteResult)
+ {
+ emit2 ("ld a,e");
+ emit2 ("rlc a");
+ emit2 ("sbc a,a");
+ emit2 ("ld d,a");
+ }
}
else
{
if (active == FALSE)
{
emit2 ("ld l,e");
- emit2 ("ld h,d");
+ if (!byteResult)
+ emit2 ("ld h,d");
}
else
{
_G.stack.pushedDE = FALSE;
}
- commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
+ if (byteResult)
+ aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
+ else
+ commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
freeAsmop (IC_LEFT (ic), NULL, ic);
freeAsmop (IC_RIGHT (ic), NULL, ic);
/* if left is a literal & right is not then exchange them */
if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
- AOP_NEEDSACC (left))
+ (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
{
operand *tmp = right;
right = left;
/* if left is a literal & right is not then exchange them */
if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
- AOP_NEEDSACC (left))
+ (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
{
operand *tmp = right;
right = left;
/* if left is a literal & right is not then exchange them */
if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
- AOP_NEEDSACC (left))
+ (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
{
operand *tmp = right;
right = left;
continue;
else
{
- _moveA (aopGet (AOP (right), offset, FALSE));
+ _moveA (aopGet (AOP (left), offset, FALSE));
emit2 ("xor a,%s",
- aopGet (AOP (left), offset, FALSE));
+ aopGet (AOP (right), offset, FALSE));
aopPut (AOP (result), "a", offset);
}
}
}
else
{
- _moveA (aopGet (AOP (right), offset, FALSE));
+ _moveA (aopGet (AOP (left), offset, FALSE));
emit2 ("xor a,%s",
- aopGet (AOP (left), offset, FALSE));
- aopPut (AOP (result), "a", 0);
+ aopGet (AOP (right), offset, FALSE));
+ aopPut (AOP (result), "a", offset);
}
}
}
}
else
{
- _moveA (aopGet (AOP (right), offset, FALSE));
+ _moveA (aopGet (AOP (left), offset, FALSE));
emit2 ("xor a,%s",
- aopGet (AOP (left), offset, FALSE));
+ aopGet (AOP (right), offset, FALSE));
}
aopPut (AOP (result), "a", offset);
}
{
shCount &= 0x0007; // shCount : 0..7
+#if 0
switch (shCount)
{
case 0:
emit2 ("srl a");
break;
}
+#else
+ switch (shCount)
+ {
+ case 0:
+ break;
+ case 1:
+ emit2 ("rlca");
+ break;
+ case 2:
+ emit2 ("rlca");
+ emit2 ("rlca");
+ break;
+ case 3:
+ emit2 ("rlca");
+ emit2 ("rlca");
+ emit2 ("rlca");
+ break;
+ case 4:
+ emit2 ("rlca");
+ emit2 ("rlca");
+ emit2 ("rlca");
+ emit2 ("rlca");
+ break;
+ case 5:
+ emit2 ("rrca");
+ emit2 ("rrca");
+ emit2 ("rrca");
+ break;
+ case 6:
+ emit2 ("rrca");
+ emit2 ("rrca");
+ break;
+ case 7:
+ emit2 ("rrca");
+ break;
+ }
+#endif
}
/*-----------------------------------------------------------------*/
aopOp (left, ic, FALSE, FALSE);
aopOp (result, ic, FALSE, FALSE);
+ if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+ _push (PAIR_AF);
+
/* now move the left to the result if they are not the
same */
offset = 0;
tlbl1 = newiTempLabel (NULL);
+ if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+ _pop (PAIR_AF);
+
emit2 ("!shortjp !tlabel", tlbl1->key + 100);
emitLabel (tlbl->key + 100);
l = aopGet (AOP (result), offset, FALSE);
wassert (0);
}
- else if (shCount >= (size * 8))
+ else if (shCount >= (size * 8)) {
+ const char *s;
+ if (!SPEC_USIGN(getSpec(operandType(left)))) {
+ _moveA(aopGet (AOP (left), 0, FALSE));
+ emit2 ("rlc a");
+ emit2 ("sbc a,a");
+ s=ACC_NAME;
+ } else {
+ s="!zero";
+ }
while (size--)
- aopPut (AOP (result), "!zero", size);
+ aopPut (AOP (result), s, size);
+ }
else
{
switch (size)
return;
}
+ emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+ emit2 ("inc a");
+ freeAsmop (right, NULL, ic);
+
aopOp (left, ic, FALSE, FALSE);
aopOp (result, ic, FALSE, FALSE);
+ if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+ _push (PAIR_AF);
+
/* now move the left to the result if they are not the
same */
- if (!sameRegs (AOP (left), AOP (result)) &&
- AOP_SIZE (result) > 1)
+ if (!sameRegs (AOP (left), AOP (result)))
{
size = AOP_SIZE (result);
}
}
- emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
- emit2 ("inc a");
- freeAsmop (right, NULL, ic);
-
tlbl = newiTempLabel (NULL);
tlbl1 = newiTempLabel (NULL);
size = AOP_SIZE (result);
offset = size - 1;
+
+ if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+ _pop (PAIR_AF);
emit2 ("!shortjp !tlabel", tlbl1->key + 100);
emitLabel (tlbl->key + 100);
freeAsmop (result, NULL, ic);
}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits */
+/*-----------------------------------------------------------------*/
+static void
+genUnpackBits (operand * result, int pair)
+{
+ int offset = 0; /* result byte offset */
+ int rsize; /* result size */
+ int rlen = 0; /* remaining bitfield length */
+ sym_link *etype; /* bitfield type information */
+ int blen; /* bitfield length */
+ int bstr; /* bitfield starting bit within byte */
+
+ emitDebug ("; genUnpackBits");
+
+ etype = getSpec (operandType (result));
+ rsize = getSize (operandType (result));
+ blen = SPEC_BLEN (etype);
+ bstr = SPEC_BSTR (etype);
+
+ /* If the bitfield length is less than a byte */
+ if (blen < 8)
+ {
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ AccRsh (bstr);
+ emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
+ aopPut (AOP (result), "a", offset++);
+ goto finish;
+ }
+
+ /* TODO: what if pair == PAIR_DE ? */
+ if (getPairId (AOP (result)) == PAIR_HL)
+ {
+ wassertl (rsize == 2, "HL must be of size 2");
+ emit2 ("ld a,!*hl");
+ emit2 ("inc hl");
+ emit2 ("ld h,!*hl");
+ emit2 ("ld l,a");
+ emit2 ("ld a,h");
+ emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
+ emit2 ("ld h,a");
+ spillPair (PAIR_HL);
+ return;
+ }
+
+ /* Bit field did not fit in a byte. Copy all
+ but the partial byte at the end. */
+ for (rlen=blen;rlen>=8;rlen-=8)
+ {
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ aopPut (AOP (result), "a", offset++);
+ if (rlen>8)
+ {
+ emit2 ("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
+ }
+ }
+
+ /* Handle the partial byte at the end */
+ if (rlen)
+ {
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
+ aopPut (AOP (result), "a", offset++);
+ }
+
+finish:
+ if (offset < rsize)
+ {
+ rsize -= offset;
+ while (rsize--)
+ aopPut (AOP (result), "!zero", offset++);
+ }
+}
+
/*-----------------------------------------------------------------*/
/* genGenPointerGet - get value from generic pointer space */
/*-----------------------------------------------------------------*/
size = AOP_SIZE (result);
- if (isPair (AOP (left)) && size == 1)
+ if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
{
/* Just do it */
if (isPtrPair (AOP (left)))
{
- tsprintf (buffer, "!*pair", getPairName (AOP (left)));
+ tsprintf (buffer, sizeof(buffer),
+ "!*pair", getPairName (AOP (left)));
aopPut (AOP (result), buffer, 0);
}
else
goto release;
}
- if (getPairId (AOP (left)) == PAIR_IY)
+ if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
{
/* Just do it */
offset = 0;
while (size--)
{
char at[20];
- tsprintf (at, "!*iyx", offset);
+ tsprintf (at, sizeof(at), "!*iyx", offset);
aopPut (AOP (result), at, offset);
offset++;
}
/* if bit then unpack */
if (IS_BITVAR (retype))
{
- wassert (0);
+ genUnpackBits (result, pair);
+ freeAsmop (left, NULL, ic);
+ goto release;
+ //wassert (0);
}
else if (getPairId (AOP (result)) == PAIR_HL)
{
return FALSE;
}
+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage */
+/*-----------------------------------------------------------------*/
+static void
+genPackBits (sym_link * etype,
+ operand * right,
+ int pair,
+ iCode *ic)
+{
+ int offset = 0; /* source byte offset */
+ int rlen = 0; /* remaining bitfield length */
+ int blen; /* bitfield length */
+ int bstr; /* bitfield starting bit within byte */
+ int litval; /* source literal value (if AOP_LIT) */
+ unsigned char mask; /* bitmask within current byte */
+ int extraPair; /* a tempory register */
+ bool needPopExtra=0; /* need to restore original value of temp reg */
+
+ emitDebug ("; genPackBits","");
+
+ blen = SPEC_BLEN (etype);
+ bstr = SPEC_BSTR (etype);
+
+ /* If the bitfield length is less than a byte */
+ if (blen < 8)
+ {
+ mask = ((unsigned char) (0xFF << (blen + bstr)) |
+ (unsigned char) (0xFF >> (8 - bstr)));
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Case with a bitfield length <8 and literal source
+ */
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval <<= bstr;
+ litval &= (~mask) & 0xff;
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ if ((mask|litval)!=0xff)
+ emit2 ("and a,!immedbyte", mask);
+ if (litval)
+ emit2 ("or a,!immedbyte", litval);
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ return;
+ }
+ else
+ {
+ /* Case with a bitfield length <8 and arbitrary source
+ */
+ _moveA (aopGet (AOP (right), 0, FALSE));
+ /* shift and mask source value */
+ AccLsh (bstr);
+ emit2 ("and a,!immedbyte", (~mask) & 0xff);
+
+ extraPair = getFreePairId(ic);
+ if (extraPair == PAIR_INVALID)
+ {
+ extraPair = PAIR_BC;
+ if (getPairId (AOP (right)) != PAIR_BC
+ || !isLastUse (ic, right))
+ {
+ _push (extraPair);
+ needPopExtra = 1;
+ }
+ }
+ emit2 ("ld %s,a", _pairs[extraPair].l);
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+
+ emit2 ("and a,!immedbyte", mask);
+ emit2 ("or a,%s", _pairs[extraPair].l);
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ if (needPopExtra)
+ _pop (extraPair);
+ return;
+ }
+ }
+
+ /* Bit length is greater than 7 bits. In this case, copy */
+ /* all except the partial byte at the end */
+ for (rlen=blen;rlen>=8;rlen-=8)
+ {
+ emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ if (rlen>8)
+ {
+ emit2 ("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
+ }
+ }
+
+ /* If there was a partial byte at the end */
+ if (rlen)
+ {
+ mask = (((unsigned char) -1 << rlen) & 0xff);
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Case with partial byte and literal source
+ */
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval >>= (blen-rlen);
+ litval &= (~mask) & 0xff;
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ if ((mask|litval)!=0xff)
+ emit2 ("and a,!immedbyte", mask);
+ if (litval)
+ emit2 ("or a,!immedbyte", litval);
+ }
+ else
+ {
+ /* Case with partial byte and arbitrary source
+ */
+ _moveA (aopGet (AOP (right), offset++, FALSE));
+ emit2 ("and a,!immedbyte", (~mask) & 0xff);
+
+ extraPair = getFreePairId(ic);
+ if (extraPair == PAIR_INVALID)
+ {
+ extraPair = getPairId (AOP (right));
+ if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
+ extraPair = PAIR_BC;
+
+ if (getPairId (AOP (right)) != PAIR_BC
+ || !isLastUse (ic, right))
+ {
+ _push (extraPair);
+ needPopExtra = 1;
+ }
+ }
+ emit2 ("ld %s,a", _pairs[extraPair].l);
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+
+ emit2 ("and a,!immedbyte", mask);
+ emit2 ("or a,%s", _pairs[extraPair].l);
+ if (needPopExtra)
+ _pop (extraPair);
+
+ }
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ }
+}
+
+
/*-----------------------------------------------------------------*/
/* genGenPointerSet - stores the value into a pointer location */
/*-----------------------------------------------------------------*/
{
int size, offset;
sym_link *retype = getSpec (operandType (right));
+ sym_link *letype = getSpec (operandType (result));
PAIR_ID pairId = PAIR_HL;
+ bool isBitvar;
aopOp (result, ic, FALSE, FALSE);
aopOp (right, ic, FALSE, FALSE);
size = AOP_SIZE (right);
+ isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
+ emitDebug("; isBitvar = %d", isBitvar);
+
/* Handle the exceptions first */
- if (isPair (AOP (result)) && size == 1)
+ if (isPair (AOP (result)) && size == 1 && !isBitvar)
{
/* Just do it */
const char *l = aopGet (AOP (right), 0, FALSE);
goto release;
}
- if ( getPairId( AOP (result)) == PAIR_IY)
+ if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
{
/* Just do it */
const char *l = aopGet (AOP (right), 0, FALSE);
}
goto release;
}
- else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result))
+ else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
+ && !isBitvar)
{
offset = 0;
{
fetchPair (pairId, AOP (result));
}
- /* so hl know contains the address */
+ /* so hl now contains the address */
freeAsmop (result, NULL, ic);
/* if bit then unpack */
- if (IS_BITVAR (retype))
+ if (isBitvar)
{
- wassert (0);
+ genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
+ goto release;
+ //wassert (0);
}
else
{
/* now depending on the sign of the destination */
size = AOP_SIZE (result) - AOP_SIZE (right);
/* Unsigned or not an integral type - right fill with zeros */
- if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
+ if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
{
while (size--)
aopPut (AOP (result), "!zero", offset++);
freeAsmop (IC_RESULT (ic), NULL, ic);
}
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+ operand *op;
+ int size, offset;
+
+ op = IC_RIGHT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ aopOp (op, ic, FALSE, FALSE);
+
+ /* general case */
+ size = AOP_SIZE (op);
+ offset = 0;
+
+ while (size--)
+ {
+ _moveA (aopGet (AOP (op), offset, FALSE));
+ offset++;
+ }
+
+ freeAsmop (op, NULL, ic);
+ }
+
+ op = IC_LEFT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ aopOp (op, ic, FALSE, FALSE);
+
+ /* general case */
+ size = AOP_SIZE (op);
+ offset = 0;
+
+ while (size--)
+ {
+ _moveA (aopGet (AOP (op), offset, FALSE));
+ offset++;
+ }
+
+ freeAsmop (op, NULL, ic);
+ }
+}
+
enum
{
/** Maximum number of bytes to emit per line. */
chunks.
*/
static void
-_rleAppend(RLECTX *self, int c)
+_rleAppend(RLECTX *self, unsigned c)
{
int i;
if (type && type->next)
{
- elementSize = getSize(type->next);
+ if (IS_SPEC(type->next) || IS_PTR(type->next))
+ {
+ elementSize = getSize(type->next);
+ }
+ else if (IS_ARRAY(type->next) && type->next->next)
+ {
+ elementSize = getSize(type->next->next);
+ }
+ else
+ {
+ printTypeChainRaw (type, NULL);
+ wassertl (0, "Can't determine element size in genArrayInit.");
+ }
}
else
{
wassertl (0, "Can't determine element size in genArrayInit.");
}
+ wassertl ((elementSize > 0) && (elementSize <= 4), "Illegal element size in genArrayInit.");
+
iLoop = IC_ARRAYILIST(ic);
lastVal = (unsigned)-1;
{
ix = iLoop->count;
- if (ix != 0)
+ for (i = 0; i < ix; i++)
{
- for (i = 0; i < ix; i++)
+ for (eIndex = 0; eIndex < elementSize; eIndex++)
{
- for (eIndex = 0; eIndex < elementSize; eIndex++)
- {
- val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
- _rleAppend(&rle, val);
- }
+ val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
+ _rleAppend(&rle, val);
}
- }
+ }
iLoop = iLoop->next;
}
}
_G.lines.head = _G.lines.current = NULL;
+
+ /* if debug information required */
+ if (options.debug && currFunc)
+ {
+ debugFile->writeFunction (currFunc, lic);
+ }
for (ic = lic; ic; ic = ic->next)
{
+ _G.current_iCode = ic;
- if (cln != ic->lineno)
+ if (ic->lineno && cln != ic->lineno)
{
- emit2 ("; %s %d", ic->filename, ic->lineno);
+ if (options.debug)
+ {
+ debugFile->writeCLine (ic);
+ }
+ if (!options.noCcodeInAsm) {
+ emit2 (";%s:%d: %s", ic->filename, ic->lineno,
+ printCLine(ic->filename, ic->lineno));
+ }
cln = ic->lineno;
}
+ if (options.iCodeInAsm) {
+ emit2 (";ic:%d: %s", ic->key, printILine(ic));
+ }
/* if the result is marked as
spilt and rematerializable or code for
this has already been generated then
emitDebug ("; genArrayInit");
genArrayInit(ic);
break;
-
+
+ case DUMMY_READ_VOLATILE:
+ emitDebug ("; genDummyRead");
+ genDummyRead (ic);
+ break;
+
default:
ic = ic;
}
v = 0-v;
v &= 0xFFFF;
- tsprintf (buffer, "!immedword", v);
+ tsprintf (buffer, sizeof(buffer), "!immedword", v);
return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
}