With loopInduction on Breaks 198B
With all working on 20796 158 196C
Slightly better genCmp(signed) 20597 159 195B
+ Better reg packing, first peephole 20038 163 1873
+ With assign packing 19281 165 1849
+ 5/3/00 17741 185 17B6
Michael Hope <michaelh@earthling.net> 2000
Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "SDCCglobl.h"
#ifdef HAVE_SYS_ISA_DEFS_H
#include <sys/isa_defs.h>
#endif
-#include "SDCCast.h"
-#include "SDCCmem.h"
-#include "SDCCy.h"
-#include "SDCChasht.h"
-#include "SDCCbitv.h"
-#include "SDCCset.h"
-#include "SDCCicode.h"
-#include "SDCClabel.h"
-#include "SDCCBBlock.h"
-#include "SDCCloop.h"
-#include "SDCCcse.h"
-#include "SDCCcflow.h"
-#include "SDCCdflow.h"
-#include "SDCClrange.h"
-#include "ralloc.h"
-#include "gen.h"
+#include "z80.h"
#include "SDCCpeeph.h"
-#include "SDCCglue.h" /* drdani Jan 30 2000 */
+#include "gen.h"
+#include "SDCCglue.h"
/* this is the down and dirty file with all kinds of kludgy & hacky
stuff. This is what it is all about CODE GENERATION for a specific MCU.
Some of the routines may be reusable, will have to see */
+
static char *zero = "#0x00";
static char *one = "#0x01";
static char *spname ;
-static char *fReturn[] = {"l", "h", "e", "d" };
+static char *_z80_return[] = {"l", "h", "e", "d" };
+static char *_gbz80_return[] = { "e", "d", "l", "h" };
+static char **_fReturn;
+static char **_fTmp;
+
static char *accUse[] = {"a" };
short rbank = -1;
short accInUse = 0 ;
extern int nRegs;
extern FILE *codeOutFile;
set *sendSet = NULL;
+const char *_shortJP = "jp";
+
+typedef enum {
+ PAIR_INVALID,
+ PAIR_BC,
+ PAIR_DE,
+ PAIR_HL,
+ PAIR_IY,
+ PAIR_IX,
+ NUM_PAIRS
+} PAIR_ID;
+
+static struct {
+ const char *name;
+ const char *l;
+ const char *h;
+} _pairs[NUM_PAIRS] = {
+ { "??", "?", "?" },
+ { "bc", "c", "b" },
+ { "de", "e", "d" },
+ { "hl", "l", "h" },
+ { "iy", "iy.l?", "iy.h?" },
+ { "ix", "ix.l?", "ix.h?" }
+};
+
#define RESULTONSTACK(x) \
(IC_RESULT(x) && IC_RESULT(x)->aop && \
IC_RESULT(x)->aop->type == AOP_STK )
unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
0x07, 0x03, 0x01, 0x00};
-static int _lastStack = 0;
-
#define LSB 0
#define MSB16 1
#define MSB24 2
#define MSB32 3
/* Stack frame:
-
IX+4 param0 LH
IX+2 ret LH
IX+0 ix LH
IX-2 temp0 LH
*/
+static struct {
+ struct {
+ AOP_TYPE last_type;
+ const char *lit;
+ int offset;
+ } pairs[NUM_PAIRS];
+ struct {
+ int last;
+ int pushed;
+ int offset;
+ } stack;
+ int frameId;
+} _G;
+
+static char *aopGet(asmop *aop, int offset, bool bit16);
+
/*-----------------------------------------------------------------*/
/* emitcode - writes the code into a file : for now it is simple */
/*-----------------------------------------------------------------*/
break;
}
}
- assert(0);
+ wassert(0);
return NULL;
}
-/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
-bool isPair(asmop *aop)
+static PAIR_ID getPairId(asmop *aop)
{
if (aop->size == 2) {
if (aop->type == AOP_REG) {
if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
- return TRUE;
+ return PAIR_BC;
}
if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
- return TRUE;
+ return PAIR_DE;
}
if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
- return TRUE;
+ return PAIR_HL;
}
}
if (aop->type == AOP_STR) {
if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
- return TRUE;
+ return PAIR_BC;
}
if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
- return TRUE;
+ return PAIR_DE;
}
if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
- return TRUE;
+ return PAIR_HL;
}
}
}
- return FALSE;
+ return PAIR_INVALID;
+}
+
+/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
+bool isPair(asmop *aop)
+{
+ return (getPairId(aop) != PAIR_INVALID);
}
+bool isPtrPair(asmop *aop)
+{
+ PAIR_ID pairId = getPairId(aop);
+ switch (pairId) {
+ case PAIR_HL:
+ case PAIR_IY:
+ case PAIR_IX:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
/** Push a register pair onto the stack */
void genPairPush(asmop *aop)
{
emitcode("push", "%s", getPairName(aop));
}
+static char *_strdup(const char *s)
+{
+ char *ret;
+ ALLOC_ATOMIC(ret, strlen(s)+1);
+ strcpy(ret, s);
+ return ret;
+}
+
+
/*-----------------------------------------------------------------*/
/* newAsmop - creates a new asmOp */
/*-----------------------------------------------------------------*/
if (sym->onStack || sym->iaccess) {
sym->aop = aop = newAsmop(AOP_STK);
aop->size = getSize(sym->type);
-
aop->aopu.aop_stk = sym->stack;
return aop;
}
return aop;
}
+#if 0
+ if (IS_GB) {
+ /* if it is in direct space */
+ if (IN_DIRSPACE(space)) {
+ sym->aop = aop = newAsmop (AOP_DIR);
+ aop->aopu.aop_dir = sym->rname ;
+ aop->size = getSize(sym->type);
+ emitcode("", "; AOP_DIR for %s", sym->rname);
+ return aop;
+ }
+ }
+#endif
+
/* only remaining is far space */
/* in which case DPTR gets the address */
- sym->aop = aop = newAsmop(AOP_IY);
- emitcode ("ld","iy,#%s", sym->rname);
+ if (IS_GB) {
+ sym->aop = aop = newAsmop(AOP_HL);
+ }
+ else {
+ sym->aop = aop = newAsmop(AOP_IY);
+ }
aop->size = getSize(sym->type);
aop->aopu.aop_dir = sym->rname;
aop = op->aop = sym->aop = newAsmop(AOP_STR);
aop->size = getSize(sym->type);
for ( i = 0 ; i < 4 ; i++ )
- aop->aopu.aop_str[i] = fReturn[i];
+ aop->aopu.aop_str[i] = _fReturn[i];
return;
}
aop->freed = 1;
- switch (aop->type) {
- case AOP_STK :
- break;
- }
-
dealloc:
/* all other cases just dealloc */
if (op ) {
}
}
-char *aopGetWord(asmop *aop, int offset)
+bool isLitWord(asmop *aop)
+{
+ /* if (aop->size != 2)
+ return FALSE;*/
+ switch (aop->type) {
+ case AOP_IMMD:
+ case AOP_LIT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
{
char *s = buffer ;
char *rs;
- assert(aop->size == 2);
- assert(offset == 0);
+#if 0
+ if (aop->size != 2 && aop->type != AOP_HL)
+ return NULL;
+#endif
+ wassert(offset == 0);
/* depending on type */
switch (aop->type) {
+ case AOP_HL:
+ case AOP_IY:
case AOP_IMMD:
- sprintf (s,"#%s",aop->aopu.aop_immd);
+ sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
-
case AOP_LIT: {
value * val = aop->aopu.aop_lit;
/* if it is a float then it gets tricky */
if (!IS_FLOAT(val->type)) {
unsigned long v = floatFromVal(val);
- sprintf(buffer,"#0x%04lx", v);
+ sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
ALLOC_ATOMIC(rs,strlen(buffer)+1);
return strcpy (rs,buffer);
}
- assert(0);
+ wassert(0);
return NULL;
}
+ default:
+ return NULL;
}
- return NULL;
+}
+
+char *aopGetWord(asmop *aop, int offset)
+{
+ return aopGetLitWordLong(aop, offset, TRUE);
+}
+
+bool isPtr(const char *s)
+{
+ if (!strcmp(s, "hl"))
+ return TRUE;
+ if (!strcmp(s, "ix"))
+ return TRUE;
+ if (!strcmp(s, "iy"))
+ return TRUE;
+ return FALSE;
+}
+
+static void adjustPair(const char *pair, int *pold, int new)
+{
+ wassert(pair);
+
+ while (*pold < new) {
+ emitcode("inc", "%s", pair);
+ (*pold)++;
+ }
+ while (*pold > new) {
+ emitcode("dec", "%s", pair);
+ (*pold)--;
+ }
+}
+
+static void spillPair(PAIR_ID pairId)
+{
+ _G.pairs[pairId].last_type = AOP_INVALID;
+ _G.pairs[pairId].lit = NULL;
+}
+
+static void spillCached(void)
+{
+ spillPair(PAIR_HL);
+ spillPair(PAIR_IY);
+}
+
+static bool requiresHL(asmop *aop)
+{
+ switch (aop->type) {
+ case AOP_HL:
+ case AOP_STK:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
+{
+ const char *l;
+ const char *pair = _pairs[pairId].name;
+ l = aopGetLitWordLong(left, 0, FALSE);
+ wassert(l && pair);
+
+ if (isPtr(pair)) {
+ if (pairId == PAIR_HL || pairId == PAIR_IY) {
+ if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
+ if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
+ adjustPair(pair, &_G.pairs[pairId].offset, offset);
+ return;
+ }
+ if (pairId == PAIR_IY && abs(offset)<127) {
+ return;
+ }
+ }
+ }
+ _G.pairs[pairId].last_type = left->type;
+ _G.pairs[pairId].lit = _strdup(l);
+ _G.pairs[pairId].offset = offset;
+ }
+ /* Both a lit on the right and a true symbol on the left */
+ if (offset)
+ emitcode("ld", "%s,#%s + %d", pair, l, offset);
+ else
+ emitcode("ld", "%s,#%s", pair, l);
+}
+
+static void fetchPair(PAIR_ID pairId, asmop *aop)
+{
+ /* if this is remateriazable */
+ if (isLitWord(aop)) {
+ fetchLitPair(pairId, aop, 0);
+ }
+ else { /* we need to get it byte by byte */
+ if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
+ aopGet(aop, 0, FALSE);
+ emitcode("ld", "a,(hl+)");
+ emitcode("ld", "h,(hl)");
+ emitcode("ld", "l,a");
+ }
+ else {
+ emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, 0, FALSE));
+ emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, 1, FALSE));
+ }
+ /* PENDING: check? */
+ if (pairId == PAIR_HL)
+ spillPair(PAIR_HL);
+ }
+}
+
+static void fetchHL(asmop *aop)
+{
+ fetchPair(PAIR_HL, aop);
+}
+
+static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
+{
+ assert(pairId == PAIR_HL || pairId == PAIR_IY);
+
+ switch (aop->type) {
+ case AOP_IY:
+ case AOP_HL:
+ fetchLitPair(pairId, aop, offset);
+ _G.pairs[pairId].offset = offset;
+ break;
+ case AOP_STK: {
+ /* Doesnt include _G.stack.pushed */
+ int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+ assert(pairId == PAIR_HL);
+ /* In some cases we can still inc or dec hl */
+ if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
+ adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
+ }
+ else {
+ emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _G.stack.pushed, _G.stack.offset);
+ }
+ _G.pairs[pairId].offset = abso;
+ break;
+ }
+ default:
+ wassert(0);
+ }
+ _G.pairs[pairId].last_type = aop->type;
+}
+
+static void emitLabel(int key)
+{
+ emitcode("", LABEL_STR ":", key);
+ spillCached();
}
/*-----------------------------------------------------------------*/
/* aopGet - for fetching value of the aop */
/*-----------------------------------------------------------------*/
-static char *aopGet (asmop *aop, int offset, bool bit16)
+static char *aopGet(asmop *aop, int offset, bool bit16)
{
char *s = buffer ;
char *rs;
/* 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)
return zero;
switch (aop->type) {
case AOP_IMMD:
if (bit16)
- sprintf (s,"#%s",aop->aopu.aop_immd);
+ sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
else
if (offset) {
- assert(offset == 1);
+ wassert(offset == 1);
sprintf(s,"#>%s",
aop->aopu.aop_immd);
}
return rs;
case AOP_DIR:
- assert(0);
- emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
+ wassert(IS_GB);
+ emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
sprintf(s, "a");
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
case AOP_REG:
return aop->aopu.aop_reg[offset]->name;
+ case AOP_HL:
+ wassert(IS_GB);
+ emitcode("", ";3");
+ setupPair(PAIR_HL, aop, offset);
+ sprintf(s, "(hl)");
+ return _strdup("(hl)");
+
case AOP_IY:
+ wassert(IS_Z80);
+ setupPair(PAIR_IY, aop, offset);
sprintf(s,"%d(iy)", offset);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
case AOP_STK:
- sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+ if (IS_GB) {
+ setupPair(PAIR_HL, aop, offset);
+ sprintf(s, "(hl)");
+ }
+ else {
+ sprintf(s,"%d(ix)", aop->aopu.aop_stk+offset);
+ }
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
case AOP_CRY:
- assert(0);
+ wassert(0);
case AOP_ACC:
if (!offset) {
case AOP_STR:
aop->coff = offset;
return aop->aopu.aop_str[offset];
+ default:
+ break;
}
-
- fprintf(stderr, "Type %u\n", aop->type);
-
- werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
- "aopget got unsupported aop->type");
+ wassertl(0, "aopget got unsupported aop->type");
exit(0);
}
return FALSE;
}
-bool isConstant(char *s)
+bool isConstant(const char *s)
{
return (*s == '#');
}
/*-----------------------------------------------------------------*/
static void aopPut (asmop *aop, char *s, int offset)
{
- char *d = buffer ;
-
if (aop->size && offset > ( aop->size - 1)) {
werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
"aopPut got offset > aop->size");
/* depending on where it is ofcourse */
switch (aop->type) {
case AOP_DIR:
- assert(0);
/* Direct. Hmmm. */
+ wassert(IS_GB);
emitcode("ld", "a,%s", s);
- emitcode("ld", "(%s+%d),a", d, offset);
+ emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
break;
case AOP_REG:
break;
case AOP_IY:
+ wassert(!IS_GB);
+ setupPair(PAIR_IY, aop, offset);
if (!canAssignToPtr(s)) {
emitcode("ld", "a,%s", s);
emitcode("ld", "%d(iy),a", offset);
else
emitcode("ld", "%d(iy),%s", offset, s);
break;
-
+
+ case AOP_HL:
+ wassert(IS_GB);
+ if (!strcmp(s, "(hl)")) {
+ emitcode("ld", "a,(hl)");
+ s = "a";
+ }
+ emitcode("", ";2");
+ setupPair(PAIR_HL, aop, offset);
+ emitcode("ld", "(hl),%s", s);
+ break;
+
case AOP_STK:
- if (!canAssignToPtr(s)) {
- emitcode("ld", "a,%s", s);
- emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+ if (IS_GB) {
+ if (!strcmp("(hl)", s)) {
+ emitcode("ld", "a,(hl)");
+ s = "a";
+ }
+ setupPair(PAIR_HL, aop, offset);
+ if (!canAssignToPtr(s)) {
+ emitcode("ld", "a,%s", s);
+ emitcode("ld", "(hl),a");
+ }
+ else
+ emitcode("ld", "(hl),%s", s);
+ }
+ else {
+ if (!canAssignToPtr(s)) {
+ emitcode("ld", "a,%s", s);
+ emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+ }
+ else
+ emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
}
- else
- emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
break;
case AOP_CRY:
emitcode("rla", "");
} else {
/* In bit space but not in C - cant happen */
- assert(0);
+ wassert(0);
}
break;
size = AOP_SIZE(op);
if(size == 3) {
/* pointer */
- assert(0);
+ wassert(0);
}
return size;
}
aopPut(AOP(result),l,offr);
}
else {
- assert(0);
+ wassert(0);
}
}
}
emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
}
else {
- CLRC;
- emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
+ if (AOP(oper)->type != AOP_ACC) {
+ CLRC;
+ emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
+ }
}
}
/* if in bit space then a special case */
if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
- assert(0);
+ wassert(0);
}
/* if type float then do float */
if (IS_FLOAT(optype)) {
- assert(0);
+ wassert(0);
}
toBoolean(IC_LEFT(ic));
a special case */
if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
- assert(0);
+ wassert(0);
}
size = AOP_SIZE(IC_RESULT(ic));
case */
if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
- assert(0);
+ wassert(0);
goto release;
}
/* if float then do float stuff */
if (IS_FLOAT(optype)) {
- assert(0);
+ wassert(0);
goto release;
}
freeAsmop(IC_RESULT(ic),NULL,ic);
}
-
/*-----------------------------------------------------------------*/
/* assignResultValue - */
/*-----------------------------------------------------------------*/
{
int offset = 0;
int size = AOP_SIZE(oper);
+
+ wassert(size <= 2);
+
while (size--) {
- aopPut(AOP(oper),fReturn[offset],offset);
+ aopPut(AOP(oper),_fReturn[offset],offset);
offset++;
}
}
/* push it on the stack */
if (isPair(AOP(IC_LEFT(ic)))) {
emitcode("push", getPairName(AOP(IC_LEFT(ic))));
+ _G.stack.pushed += 2;
}
else {
offset = size;
emitcode("ld", "a,%s", l);
emitcode("push", "af");
emitcode("inc", "sp");
+ _G.stack.pushed++;
}
}
return ;
size = AOP_SIZE(IC_LEFT(ic));
if (isPair(AOP(IC_LEFT(ic)))) {
+ _G.stack.pushed+=2;
emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
}
else {
if (size == 2) {
- char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
- if (s) {
- emitcode("ld", "hl,%s", s);
- emitcode("push", "hl");
- }
- else {
- /* Optimise here - load into HL then push HL */
- emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0, FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1, FALSE));
- emitcode("push", "hl");
- }
+ fetchHL(AOP(IC_LEFT(ic)));
+ emitcode("push", "hl ; 2");
+ spillPair(PAIR_HL);
+ _G.stack.pushed += 2;
goto release;
}
offset = size;
emitcode("ld", "a,%s", l);
emitcode("push", "af");
emitcode("inc", "sp");
+ _G.stack.pushed++;
}
}
release:
while (size--) {
emitcode("dec", "sp");
emitcode("pop", "hl");
+ spillPair(PAIR_HL);
aopPut(AOP(IC_LEFT(ic)), "l", offset--);
}
}
/* if send set is not empty then assign */
if (sendSet) {
iCode *sic ;
-
for (sic = setFirstItem(sendSet) ; sic ;
sic = setNextItem(sendSet)) {
int size, offset = 0;
while (size--) {
char *l = aopGet(AOP(IC_LEFT(sic)),offset,
FALSE);
- if (strcmp(l,fReturn[offset]))
+ if (strcmp(l, _fReturn[offset]))
emitcode("ld","%s,%s",
- fReturn[offset],
+ _fReturn[offset],
l);
offset++;
}
}
if (ispcall) {
- symbol *rlbl = newiTempLabel(NULL);
-
- emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
- emitcode("push", "hl");
-
aopOp(IC_LEFT(ic),ic,FALSE);
- emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
+
+ if (isLitWord(AOP(IC_LEFT(ic)))) {
+ emitcode("", "; Special case where the pCall is to a constant");
+ emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
+ }
+ else {
+ symbol *rlbl = newiTempLabel(NULL);
+ spillPair(PAIR_HL);
+ emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
+ emitcode("push", "hl");
+ _G.stack.pushed += 2;
+
+ fetchHL(AOP(IC_LEFT(ic)));
+ emitcode("jp", "(hl)");
+ emitcode("","%05d$:",(rlbl->key+100));
+ _G.stack.pushed -= 2;
+ }
freeAsmop(IC_LEFT(ic),NULL,ic);
-
- emitcode("jp", "(hl)");
- emitcode("","%05d$:",(rlbl->key+100));
}
else {
/* make the call */
- emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
- OP_SYMBOL(IC_LEFT(ic))->rname :
- OP_SYMBOL(IC_LEFT(ic))->name));
+ char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
+ OP_SYMBOL(IC_LEFT(ic))->rname :
+ OP_SYMBOL(IC_LEFT(ic))->name;
+ emitcode("call", "%s", name);
}
+ spillCached();
/* if we need assign a result value */
if ((IS_ITEMP(IC_RESULT(ic)) &&
/* adjust the stack for parameters if required */
if (IC_LEFT(ic)->parmBytes) {
int i = IC_LEFT(ic)->parmBytes;
- if (i>6) {
- emitcode("ld", "hl,#%d", i);
- emitcode("add", "hl,sp");
- emitcode("ld", "sp,hl");
+ _G.stack.pushed -= i;
+ if (IS_GB) {
+ emitcode("lda", "sp,%d(sp)", i);
}
else {
- while (i>1) {
- emitcode("pop", "hl");
- i-=2;
+ spillCached();
+ if (i>6) {
+ emitcode("ld", "hl,#%d", i);
+ emitcode("add", "hl,sp");
+ emitcode("ld", "sp,hl");
}
- if (i)
- emitcode("inc", "sp");
+ else {
+ while (i>1) {
+ emitcode("pop", "hl");
+ i-=2;
+ }
+ if (i)
+ emitcode("inc", "sp");
+ }
+ spillCached();
}
}
/*-----------------------------------------------------------------*/
static void genFunction (iCode *ic)
{
- symbol *sym;
+ symbol *sym = OP_SYMBOL(IC_LEFT(ic));
link *fetype;
nregssaved = 0;
/* create the function header */
emitcode(";","-----------------------------------------");
- emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
+ emitcode(";"," function %s", sym->name);
emitcode(";","-----------------------------------------");
+ emitcode("", "__%s_start:", sym->rname);
emitcode("","%s:",sym->rname);
+
fetype = getSpec(operandType(IC_LEFT(ic)));
/* if critical function then turn interrupts off */
/* PENDING: callee-save etc */
/* adjust the stack for the function */
- emitcode("push", "de");
emitcode("push", "bc");
- emitcode("push", "ix");
- emitcode("ld", "ix,#0");
- emitcode("add", "ix,sp");
+ if (!IS_GB) {
+ emitcode("push", "de");
+ emitcode("push", "ix");
+ emitcode("ld", "ix,#0");
+ emitcode("add", "ix,sp");
+ }
- _lastStack = sym->stack;
+ _G.stack.last = sym->stack;
if (sym->stack) {
- emitcode("ld", "hl,#-%d", sym->stack);
- emitcode("add", "hl,sp");
- emitcode("ld", "sp,hl");
- }
+ if (IS_GB) {
+ emitcode("lda", "sp,-%d(sp)", sym->stack);
+ }
+ else {
+ emitcode("ld", "hl,#-%d", sym->stack);
+ emitcode("add", "hl,sp");
+ emitcode("ld", "sp,hl");
+ }
+ }
+ _G.stack.offset = sym->stack;
}
/*-----------------------------------------------------------------*/
symbol *sym = OP_SYMBOL(IC_LEFT(ic));
if (IS_ISR(sym->etype)) {
- assert(0);
+ wassert(0);
}
else {
if (SPEC_CRTCL(sym->etype))
emitcode("","XG$%s$0$0 ==.",currFunc->name);
debugLine = 0;
}
- emitcode("ld", "sp,ix");
- emitcode("pop", "ix");
+ if (!IS_GB) {
+ emitcode("ld", "sp,ix");
+ emitcode("pop", "ix");
+ emitcode("pop", "de");
+ }
+ else {
+ if (_G.stack.offset) {
+ emitcode("ld", "hl,#%d", _G.stack.offset);
+ emitcode("add", "hl,sp");
+ emitcode("ld", "sp,hl");
+ }
+ }
emitcode("pop", "bc");
- emitcode("pop", "de");
emitcode("ret", "");
+ emitcode("; Useful for profiling and debugging", "");
+ emitcode(".dw", "%s", sym->rname);
+ emitcode("", "__%s_end:", sym->rname);
}
-
+ _G.stack.pushed = 0;
+ _G.stack.offset = 0;
}
/*-----------------------------------------------------------------*/
size = AOP_SIZE(IC_LEFT(ic));
if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
+ if (IS_GB) {
+ emitcode("ld", "de,%s", l);
+ }
+ else {
emitcode("ld", "hl,%s", l);
+ }
}
else {
while (size--) {
l = aopGet(AOP(IC_LEFT(ic)),offset,
FALSE);
- if (strcmp(fReturn[offset],l))
- emitcode("ld","%s,%s",fReturn[offset++],l);
+ if (strcmp(_fReturn[offset],l))
+ emitcode("ld","%s,%s", _fReturn[offset++],l);
}
}
freeAsmop (IC_LEFT(ic),NULL,ic);
if (IC_LABEL(ic) == entryLabel)
return ;
- emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
+ emitLabel(IC_LABEL(ic)->key+100);
}
/*-----------------------------------------------------------------*/
{
unsigned int icount ;
unsigned int size = getDataSize(IC_RESULT(ic));
-
+ PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
+
/* will try to generate an increment */
/* if the right side is not a literal
we cannot */
if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
return FALSE;
- /* if the literal value of the right hand side
- is greater than 4 then it is not worth it */
- if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
- return FALSE ;
+ emitcode("", "; genPlusIncr");
- /* Inc a pair */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
- isPair(AOP(IC_RESULT(ic)))) {
+ icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+
+ /* If result is a pair */
+ if (resultId != PAIR_INVALID) {
+ if (isLitWord(AOP(IC_LEFT(ic)))) {
+ fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
+ return TRUE;
+ }
+ if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
+ fetchPair(resultId, AOP(IC_RIGHT(ic)));
+ emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
+ return TRUE;
+ }
+ if (icount > 5)
+ return FALSE;
+ /* Inc a pair */
+ if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+ if (icount > 2)
+ return FALSE;
+ movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
+ movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
+ }
while (icount--) {
emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
}
return TRUE;
}
+
+ /* if the literal value of the right hand side
+ is greater than 4 then it is not worth it */
+ if (icount > 4)
+ return FALSE;
+
/* if increment 16 bits in register */
if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
(size > 1) &&
(icount == 1)) {
symbol *tlbl = newiTempLabel(NULL);
emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
- emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
+ emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
if(size == 4) {
- assert(0);
+ wassert(0);
}
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitLabel(tlbl->key+100);
return TRUE;
}
- /* If result is a pair */
- if (isPair(AOP(IC_RESULT(ic)))) {
- movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
- movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
- while (icount--)
- emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
- return TRUE;
- }
-
/* if the sizes are greater than 1 then we cannot */
if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
AOP_SIZE(IC_LEFT(ic)) > 1 )
symbol *tlbl = newiTempLabel(NULL);
/* if the result is a bit */
if (AOP_TYPE(result) == AOP_CRY){
- assert(0);
+ wassert(0);
}
else {
- emitcode("jp","z," LABEL_STR ,tlbl->key+100);
+ emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
emitcode("ld","a,%s",one);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitLabel(tlbl->key+100);
outAcc(result);
}
}
if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
/* Cant happen */
- assert(0);
+ wassert(0);
}
/* if left in bit space & right literal */
if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
/* Can happen I guess */
- assert(0);
+ wassert(0);
}
/* if I can do an increment instead
size = getDataSize(IC_RESULT(ic));
+ /* Special case when left and right are constant */
+ if (isPair(AOP(IC_RESULT(ic)))) {
+ char *left, *right;
+
+ left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
+ right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
+ if (left && right) {
+ /* It's a pair */
+ /* PENDING: fix */
+ char buffer[100];
+ sprintf(buffer, "#(%s + %s)", left, right);
+ emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
+ goto release;
+ }
+ }
+
+ if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
+ /* Fetch into HL then do the add */
+ spillPair(PAIR_HL);
+ fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
+ emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
+ goto release;
+ }
+
while(size--) {
if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
AOP_SIZE(IC_LEFT(ic)) == 3 &&
!sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
- assert(0);
+ wassert(0);
if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
AOP_SIZE(IC_RIGHT(ic)) == 3 &&
!sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
- assert(0);
+ wassert(0);
release:
return FALSE;
size = getDataSize(IC_RESULT(ic));
+
+#if 0
+ /* if increment 16 bits in register */
+ if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+ (size > 1) &&
+ (icount == 1)) {
+ symbol *tlbl = newiTempLabel(NULL);
+ emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
+ emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
+
+ emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
+ if(size == 4) {
+ wassert(0);
+ }
+ emitLabel(tlbl->key+100);
+ return TRUE;
+ }
+#endif
+
/* if decrement 16 bits in register */
if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
(size > 1) && isPair(AOP(IC_RESULT(ic)))) {
/* if both left & right are in bit space */
if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
- assert(0);
+ wassert(0);
goto release ;
}
if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
AOP_SIZE(IC_LEFT(ic)) == 3 &&
!sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
- assert(0);
+ wassert(0);
release:
freeAsmop(IC_LEFT(ic),NULL,ic);
static void genMult (iCode *ic)
{
/* Shouldn't occur - all done through function calls */
- assert(0);
+ wassert(0);
}
/*-----------------------------------------------------------------*/
static void genDiv (iCode *ic)
{
/* Shouldn't occur - all done through function calls */
- assert(0);
+ wassert(0);
}
/*-----------------------------------------------------------------*/
static void genMod (iCode *ic)
{
/* Shouldn't occur - all done through function calls */
- assert(0);
+ wassert(0);
}
/*-----------------------------------------------------------------*/
if (AOP_TYPE(left) == AOP_CRY &&
AOP_TYPE(right) == AOP_CRY ) {
/* Cant happen on the Z80 */
- assert(0);
+ wassert(0);
} else {
/* subtract right from left if at the
end the carry flag is set then we know that
size = max(AOP_SIZE(left),AOP_SIZE(right));
/* if unsigned char cmp with lit, just compare */
- if((size == 1) && !sign &&
+ if((size == 1) &&
(AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
- emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
+ if (sign) {
+ emitcode("xor", "a,#0x80");
+ emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
+ }
+ else
+ emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
}
else {
if(AOP_TYPE(right) == AOP_LIT) {
goto release;
}
}
- CLRC;
+ if (sign) {
+ /* First setup h and l contaning the top most bytes XORed */
+ bool fDidXor = FALSE;
+ if (AOP_TYPE(left) == AOP_LIT){
+ unsigned long lit = (unsigned long)
+ floatFromVal(AOP(left)->aopu.aop_lit);
+ emitcode("ld", "%s,#0x%02x", _fTmp[0],
+ 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+ }
+ else {
+ emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
+ emitcode("xor", "a,#0x80");
+ emitcode("ld", "%s,a", _fTmp[0]);
+ fDidXor = TRUE;
+ }
+ if (AOP_TYPE(right) == AOP_LIT) {
+ unsigned long lit = (unsigned long)
+ floatFromVal(AOP(right)->aopu.aop_lit);
+ emitcode("ld", "%s,#0x%02x", _fTmp[1],
+ 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+ }
+ else {
+ emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
+ emitcode("xor", "a,#0x80");
+ emitcode("ld", "%s,a", _fTmp[1]);
+ fDidXor = TRUE;
+ }
+ if (!fDidXor)
+ CLRC;
+ }
+ else {
+ CLRC;
+ }
while (size--) {
/* Do a long subtract */
- MOVA(aopGet(AOP(left),offset,FALSE));
+ if (!sign || size ) {
+ MOVA(aopGet(AOP(left),offset,FALSE));
+ }
if (sign && size == 0) {
- /* Ugly but hey */
- emitcode("push", "af");
- emitcode("xor", "a,#0x80");
- emitcode("ld", "l,a");
- if (AOP_TYPE(right) == AOP_LIT){
- unsigned long lit = (unsigned long)
- floatFromVal(AOP(right)->aopu.aop_lit);
- emitcode("pop", "af");
- emitcode("ld", "a,l");
- emitcode("sbc","a,#0x%02x",
- 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
- } else {
- emitcode("ld", "a,%s",aopGet(AOP(right),offset++,FALSE));
- emitcode("xor", "a,#0x80");
- emitcode("ld", "h,a");
- emitcode("pop", "af");
- emitcode("ld", "a,l");
- emitcode("sbc", "a,h");
- }
+ emitcode("ld", "a,%s", _fTmp[0]);
+ emitcode("sbc", "a,%s", _fTmp[1]);
}
else {
/* Subtract through, propagating the carry */
- emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
+ emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
}
}
}
/* if the right side is a literal then anything goes */
if (AOP_TYPE(right) == AOP_LIT &&
AOP_TYPE(left) != AOP_DIR ) {
- while (size--) {
- emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
- emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
- emitcode("jp", "nz," LABEL_STR , lbl->key+100);
- offset++;
- }
+ if (lit == 0) {
+ emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
+ if (size > 1) {
+ size--;
+ offset++;
+ while (size--) {
+ emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
+ }
+ }
+ else {
+ emitcode("or", "a,a");
+ }
+ emitcode("jp", "nz," LABEL_STR, lbl->key+100);
+ }
+ else {
+ while (size--) {
+ emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
+ if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
+ emitcode("or", "a,a");
+ else
+ emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
+ emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+ offset++;
+ }
+ }
}
/* if the right side is in a register or in direct space or
if the left is a pointer register & right is not */
/* PENDING */
emitcode("jp","nz," LABEL_STR ,lbl->key+100);
else {
- emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
+ emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
emitcode("jp", "nz," LABEL_STR , lbl->key+100);
}
offset++;
/* right is a pointer reg need both a & b */
/* PENDING: is this required? */
while(size--) {
- char *l = aopGet(AOP(left),offset,FALSE);
MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("cp", "%s", l);
+ emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
emitcode("jr", "nz," LABEL_STR, lbl->key+100);
offset++;
}
/* PENDING: ?? */
emitcode("ld","a,%s",one);
- emitcode("jp", LABEL_STR ,tlbl->key+100);
- emitcode("", LABEL_STR ":",lbl->key+100);
+ emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
+ emitLabel(lbl->key+100);
emitcode("xor","a,a");
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitLabel(tlbl->key+100);
}
/*-----------------------------------------------------------------*/
/* if they are both bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
- assert(0);
+ wassert(0);
} else {
tlbl = newiTempLabel(NULL);
gencjneshort(left, right, tlbl);
if ( IC_TRUE(ifx) ) {
emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitLabel(tlbl->key+100);
} else {
/* PENDING: do this better */
symbol *lbl = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,lbl->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitcode(_shortJP, LABEL_STR ,lbl->key+100);
+ emitLabel(tlbl->key+100);
emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
- emitcode("", LABEL_STR ":",lbl->key+100);
+ emitLabel(lbl->key+100);
}
}
/* mark the icode as generated */
/* if they are both bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
- assert(0);
+ wassert(0);
} else {
gencjne(left,right,newiTempLabel(NULL));
if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
- assert(0);
+ wassert(0);
}
if (ifx) {
genIfxJump(ifx,"a");
/* if both are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
AOP_TYPE(right) == AOP_CRY ) {
- assert(0);
+ wassert(0);
} else {
tlbl = newiTempLabel(NULL);
toBoolean(left);
- emitcode("jp","z," LABEL_STR ,tlbl->key+100);
+ emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
toBoolean(right);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitLabel(tlbl->key+100);
outBitAcc(result);
}
/* if both are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
AOP_TYPE(right) == AOP_CRY ) {
- assert(0);
+ wassert(0);
} else {
tlbl = newiTempLabel(NULL);
toBoolean(left);
- emitcode("jp","nz," LABEL_STR,tlbl->key+100);
+ emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
toBoolean(right);
- emitcode("", LABEL_STR,tlbl->key+100);
+ emitLabel(tlbl->key+100);
outBitAcc(result);
}
return 0;
}
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse - */
+/*-----------------------------------------------------------------*/
+static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+{
+ // ugly but optimized by peephole
+ if(IC_TRUE(ic)){
+ symbol *nlbl = newiTempLabel(NULL);
+ emitcode("jp", LABEL_STR, nlbl->key+100);
+ emitLabel(tlbl->key+100);
+ emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
+ emitLabel(nlbl->key+100);
+ }
+ else{
+ emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
+ emitLabel(tlbl->key+100);
+ }
+ ic->generated = 1;
+}
+
/*-----------------------------------------------------------------*/
/* genAnd - code for and */
/*-----------------------------------------------------------------*/
size = AOP_SIZE(result);
if (AOP_TYPE(left) == AOP_CRY){
- assert(0);
+ wassert(0);
goto release ;
}
MOVA(aopGet(AOP(left),posbit>>3,FALSE));
// bit = left & 2^n
if(size) {
- assert(0);
+ wassert(0);
emitcode("mov","c,acc.%d",posbit&0x07);
}
// if(left & 2^n)
genIfxJump(ifx, buffer);
}
else {
- assert(0);
+ wassert(0);
}
goto release;
}
symbol *tlbl = newiTempLabel(NULL);
int sizel = AOP_SIZE(left);
if(size) {
- assert(0);
+ wassert(0);
emitcode("setb","c");
}
while(sizel--){
MOVA( aopGet(AOP(left),offset,FALSE));
// byte == 2^n ?
if((posbit = isLiteralBit(bytelit)) != 0) {
- assert(0);
+ wassert(0);
emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
}
else{
// if(left & literal)
else{
if(ifx)
-#if 0
jmpTrueOrFalse(ifx, tlbl);
-#else
- assert(0);
-#endif
goto release ;
}
}
} else {
if (AOP_TYPE(left) == AOP_ACC) {
- assert(0);
+ wassert(0);
}
else {
MOVA(aopGet(AOP(right),offset,FALSE));
} else {
// left & result in different registers
if(AOP_TYPE(result) == AOP_CRY){
- assert(0);
+ wassert(0);
} else {
for(;(size--);offset++) {
// normal case
size = AOP_SIZE(result);
if (AOP_TYPE(left) == AOP_CRY){
- assert(0);
+ wassert(0);
goto release ;
}
if((AOP_TYPE(right) == AOP_LIT) &&
(AOP_TYPE(result) == AOP_CRY) &&
(AOP_TYPE(left) != AOP_CRY)){
- assert(0);
+ wassert(0);
goto release ;
}
if(AOP_TYPE(right) == AOP_LIT){
if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
continue;
- else
- emitcode("or","%s,%s; 5",
- aopGet(AOP(left),offset,FALSE),
- aopGet(AOP(right),offset,FALSE));
+ else {
+ MOVA(aopGet(AOP(right),offset,FALSE));
+ emitcode("or","a,%s; 5",
+ aopGet(AOP(left),offset,FALSE));
+ aopPut(AOP(result),"a ; 8", offset);
+ }
} else {
if (AOP_TYPE(left) == AOP_ACC)
emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
MOVA(aopGet(AOP(right),offset,FALSE));
emitcode("or","a,%s ; 7",
aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a ; 8",0);
+ aopPut(AOP(result),"a ; 8", offset);
}
}
}
} else {
// left & result in different registers
if(AOP_TYPE(result) == AOP_CRY){
- assert(0);
+ wassert(0);
} else for(;(size--);offset++){
// normal case
// result = left & right
size = AOP_SIZE(result);
if (AOP_TYPE(left) == AOP_CRY){
- assert(0);
+ wassert(0);
goto release ;
}
if((AOP_TYPE(right) == AOP_LIT) &&
(AOP_TYPE(result) == AOP_CRY) &&
(AOP_TYPE(left) != AOP_CRY)){
- assert(0);
+ wassert(0);
goto release ;
}
} else {
// left & result in different registers
if(AOP_TYPE(result) == AOP_CRY){
- assert(0);
+ wassert(0);
} else for(;(size--);offset++){
// normal case
// result = left & right
/*-----------------------------------------------------------------*/
static void genRRC (iCode *ic)
{
- assert(0);
+ wassert(0);
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static void genRLC (iCode *ic)
{
- assert(0);
+ wassert(0);
}
/*-----------------------------------------------------------------*/
{
if(sameRegs(AOP(result), AOP(left)) &&
((offl + MSB16) == offr)){
- assert(0);
+ wassert(0);
} else {
movLeft2Result(left, offl, result, offr, 0);
movLeft2Result(left, offl+1, result, offr+1, 0);
}
if (sign) {
- assert(0);
+ wassert(0);
}
else {
/* if (AOP(result)->type == AOP_REG) {*/
emitcode("ld","a,#%u+1", shCount);
tlbl = newiTempLabel(NULL);
tlbl1 = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,tlbl1->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
+ emitLabel(tlbl->key+100);
}
emitcode("or", "a,a");
emitcode("rr","%s", l);
}
if (shCount>1) {
- emitcode("", LABEL_STR ":",tlbl1->key+100);
+ emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+ emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
}
}
}
{
if(sameRegs(AOP(result), AOP(left)) &&
((offl + MSB16) == offr)){
- assert(0);
+ wassert(0);
} else {
/* Copy left into result */
movLeft2Result(left, offl, result, offr, 0);
emitcode("ld","a,#%u+1", shCount);
tlbl = newiTempLabel(NULL);
tlbl1 = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,tlbl1->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
+ emitLabel(tlbl->key+100);
}
emitcode("or", "a,a");
emitcode("rl","%s", l);
}
if (shCount>1) {
- emitcode("", LABEL_STR ":",tlbl1->key+100);
+ emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+ emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
}
}
}
{
int size = AOP_SIZE(result);
- assert(size==2);
+ wassert(size==2);
/* if shCount >= 8 */
if (shCount >= 8) {
/* 1 <= shCount <= 7 */
else {
if(size == 1) {
- assert(0);
+ wassert(0);
}
else {
shiftL2Left2Result(left, LSB, result, LSB, shCount);
/* I suppose that the left size >= result size */
if (shCount == 0) {
- assert(0);
+ wassert(0);
}
else if(shCount >= (size * 8))
genlshTwo (result,left,shCount);
break;
case 4:
- assert(0);
+ wassert(0);
break;
default:
- assert(0);
+ wassert(0);
}
}
freeAsmop(left,NULL,ic);
offset = 0 ;
tlbl1 = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,tlbl1->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
+ emitLabel(tlbl->key+100);
l = aopGet(AOP(result),offset,FALSE);
emitcode("or", "a,a");
while (size--) {
l = aopGet(AOP(result),offset++,FALSE);
emitcode("rl","%s", l);
}
- emitcode("", LABEL_STR ":",tlbl1->key+100);
+ emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+ emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
freeAsmop(left,NULL,ic);
freeAsmop(result,NULL,ic);
int size = AOP_SIZE(result);
char *l;
- assert(size==1);
- assert(shCount<8);
+ wassert(size==1);
+ wassert(shCount<8);
l = aopGet(AOP(left),0,FALSE);
if (AOP(result)->type == AOP_REG) {
{
MOVA(aopGet(AOP(left),offl,FALSE));
if (sign) {
- assert(0);
+ wassert(0);
}
else {
AccRsh(shCount);
if (shCount >= 8) {
shCount -= 8 ;
if (shCount) {
- assert(0);
+ wassert(0);
shiftR1Left2Result(left, MSB16, result, LSB,
shCount, sign);
}
/* I suppose that the left size >= result size */
if (shCount == 0) {
- assert(0);
+ wassert(0);
}
else if(shCount >= (size * 8))
genrshTwo(result, left, shCount, FALSE);
break;
case 4:
- assert(0);
+ wassert(0);
break;
default:
- assert(0);
+ wassert(0);
}
}
freeAsmop(left,NULL,ic);
return ;
}
else {
- assert(0);
+ wassert(0);
}
}
{
int size, offset ;
link *retype = getSpec(operandType(result));
+ int pair = PAIR_HL;
+
+ if (IS_GB)
+ pair = PAIR_DE;
aopOp(left,ic,FALSE);
aopOp(result,ic,FALSE);
-
- if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
+
+ if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
/* Just do it */
- emitcode("ld", "a,(%s)", getPairName(AOP(left)));
- aopPut(AOP(result),"a", 0);
+ if (isPtrPair(AOP(left)))
+ {
+ sprintf(buffer, "(%s)", getPairName(AOP(left)));
+ aopPut(AOP(result), buffer, 0);
+ }
+ else {
+ emitcode("ld", "a,(%s)", getPairName(AOP(left)));
+ aopPut(AOP(result),"a", 0);
+ }
freeAsmop(left,NULL,ic);
goto release;
}
/* For now we always load into IY */
/* if this is remateriazable */
- if (AOP_TYPE(left) == AOP_IMMD)
- emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
- else { /* we need to get it byte by byte */
- emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
- }
+ fetchPair(pair, AOP(left));
+
/* so iy now contains the address */
freeAsmop(left,NULL,ic);
/* if bit then unpack */
if (IS_BITVAR(retype)) {
- assert(0);
+ wassert(0);
}
else {
size = AOP_SIZE(result);
while (size--) {
/* PENDING: make this better */
- if (AOP(result)->type == AOP_REG) {
+ if (!IS_GB && AOP(result)->type == AOP_REG) {
aopPut(AOP(result),"(hl)",offset++);
}
else {
- emitcode("ld", "a,(hl)", offset);
+ emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
aopPut(AOP(result),"a",offset++);
}
if (size) {
- emitcode("inc", "hl");
+ emitcode("inc", "%s", _pairs[pair].name);
}
}
}
{
int size, offset ;
link *retype = getSpec(operandType(right));
+ PAIR_ID pairId = PAIR_HL;
aopOp(result,ic,FALSE);
aopOp(right,ic,FALSE);
+ if (IS_GB)
+ pairId = PAIR_DE;
+
/* Handle the exceptions first */
if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
/* Just do it */
char *l = aopGet(AOP(right), 0, FALSE);
- MOVA(l);
- emitcode("ld", "(%s),a", getPairName(AOP(result)));
- freeAsmop(result,NULL,ic);
+ const char *pair = getPairName(AOP(result));
+ if (canAssignToPtr(l) && isPtr(pair)) {
+ emitcode("ld", "(%s),%s", pair, l);
+ }
+ else {
+ MOVA(l);
+ emitcode("ld", "(%s),a ; 1", pair);
+ }
goto release;
}
/* if the operand is already in dptr
then we do nothing else we move the value to dptr */
if (AOP_TYPE(result) != AOP_STR) {
- /* if this is remateriazable */
- if (AOP_TYPE(result) == AOP_IMMD) {
- emitcode("", "; Error 2");
- emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
- }
- else { /* we need to get it byte by byte */
- /* PENDING: do this better */
- emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
- }
+ fetchPair(pairId, AOP(result));
}
/* so hl know contains the address */
freeAsmop(result,NULL,ic);
/* if bit then unpack */
if (IS_BITVAR(retype)) {
- assert(0);
+ wassert(0);
}
else {
size = AOP_SIZE(right);
while (size--) {
char *l = aopGet(AOP(right),offset,FALSE);
-
- if (isRegOrLit(AOP(right))) {
- emitcode("ld", "(hl),%s", l);
+ if (isRegOrLit(AOP(right)) && !IS_GB) {
+ emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
}
else {
MOVA(l);
- emitcode("ld", "(hl),a", offset);
+ emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
}
if (size) {
- emitcode("inc", "hl");
+ emitcode("inc", _pairs[pairId].name);
}
offset++;
}
/* if the operand is on the stack then we
need to get the stack offset of this
variable */
- if (sym->onStack) {
- /* if it has an offset then we need to compute it */
- emitcode("push", "de");
- emitcode("push", "ix");
- emitcode("pop", "hl");
- emitcode("ld", "de,#%d", sym->stack);
- emitcode("add", "hl,de");
- emitcode("pop", "de");
+ if (IS_GB) {
+ if (sym->onStack) {
+ spillCached();
+ emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _G.stack.pushed, _G.stack.offset);
+ emitcode("ld", "d,h");
+ emitcode("ld", "e,l");
+ }
+ else {
+ emitcode("ld", "de,#%s", sym->rname);
+ }
+ aopPut(AOP(IC_RESULT(ic)), "e", 0);
+ aopPut(AOP(IC_RESULT(ic)), "d", 1);
}
else {
- emitcode("ld", "hl,#%s", sym->rname);
+ spillCached();
+ if (sym->onStack) {
+ /* if it has an offset then we need to compute it */
+ emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+ emitcode("add", "hl,sp");
+ }
+ else {
+ emitcode("ld", "hl,#%s", sym->rname);
+ }
+ aopPut(AOP(IC_RESULT(ic)), "l", 0);
+ aopPut(AOP(IC_RESULT(ic)), "h", 1);
}
- aopPut(AOP(IC_RESULT(ic)), "l", 0);
- aopPut(AOP(IC_RESULT(ic)), "h", 1);
-
freeAsmop(IC_RESULT(ic),NULL,ic);
}
/* if the result is a bit */
if (AOP_TYPE(result) == AOP_CRY) {
- assert(0);
+ wassert(0);
}
/* general case */
if(AOP_TYPE(right) == AOP_LIT)
lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
- if((size > 1) &&
+ if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
+ emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
+ }
+ else if((size > 1) &&
(AOP_TYPE(result) != AOP_REG) &&
(AOP_TYPE(right) == AOP_LIT) &&
!IS_FLOAT(operandType(right)) &&
- (lit < 256L)){
- emitcode("xor","a,a");
+ (lit < 256L)) {
+ bool fXored = FALSE;
+ offset = 0;
/* Work from the top down.
Done this way so that we can use the cached copy of 0
in A for a fast clear */
while (size--) {
- if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
- aopPut(AOP(result),"a",size);
+ if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
+ if (!fXored && size>1) {
+ emitcode("xor", "a,a");
+ fXored = TRUE;
+ }
+ if (fXored) {
+ aopPut(AOP(result),"a",offset);
+ }
+ else {
+ aopPut(AOP(result), "#0", offset);
+ }
+ }
else
aopPut(AOP(result),
- aopGet(AOP(right),size,FALSE),
- size);
+ aopGet(AOP(right),offset,FALSE),
+ offset);
+ offset++;
}
+ }
+ else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
+ /* Special case. Load into a and d, then load out. */
+ MOVA(aopGet(AOP(right), 0, FALSE));
+ emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
+ aopPut(AOP(result), "a", 0);
+ aopPut(AOP(result), "e", 1);
} else {
while (size--) {
aopPut(AOP(result),
/* get the condition into accumulator */
l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
MOVA(l);
- emitcode("push", "de");
+ if (!IS_GB)
+ emitcode("push", "de");
emitcode("ld", "e,%s", l);
emitcode("ld", "d,#0");
jtab = newiTempLabel(NULL);
+ spillCached();
emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
emitcode("add", "hl,de");
emitcode("add", "hl,de");
+ emitcode("add", "hl,de");
freeAsmop(IC_JTCOND(ic),NULL,ic);
- emitcode("pop", "de");
+ if (!IS_GB)
+ emitcode("pop", "de");
emitcode("jp", "(hl)");
- emitcode("","%05d$:",jtab->key+100);
+ emitLabel(jtab->key+100);
/* now generate the jump labels */
for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
jtab = setNextItem(IC_JTLABELS(ic)))
/* if the result is a bit */
if (AOP_TYPE(result) == AOP_CRY) {
- assert(0);
+ wassert(0);
}
/* if they are the same size : or less */
goto release;
}
+ /* PENDING: should be OK. */
+#if 0
/* if the result is of type pointer */
if (IS_PTR(ctype)) {
- assert(0);
+ wassert(0);
}
+#endif
/* so we now know that the size of destination is greater
than the size of the source */
if (isOperandInFarSpace(IC_RESULT(ic)) &&
( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
- assert(0);
+ wassert(0);
} else {
accInUse++;
aopOp(IC_RESULT(ic),ic,FALSE);
iCode *ic;
int cln = 0;
+ /* HACK */
+ if (IS_GB) {
+ _fReturn = _gbz80_return;
+ _fTmp = _gbz80_return;
+ _shortJP = "jr";
+ }
+ else {
+ _fReturn = _z80_return;
+ _fTmp = _z80_return;
+ _shortJP = "jp";
+ }
+
lineHead = lineCurr = NULL;
/* if debug information required */
case GETHBIT:
emitcode("", "; genHBIT");
- assert(0);
+ wassert(0);
case LEFT_OP:
emitcode("", "; genLeftShift");
/* now we are ready to call the
peep hole optimizer */
- /* if (!options.nopeep)
- peepHole (&lineHead); */
+ if (!options.nopeep)
+ peepHole (&lineHead);
/* now do the actual printing */
printLine (lineHead,codeOutFile);