#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.
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 ;
0x07, 0x03, 0x01, 0x00};
static int _lastStack = 0;
+static int _pushed = 0;
+static int _spoffset;
#define LSB 0
#define MSB16 1
return aop;
}
+ 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;
+ }
+ }
+
/* 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)
+ emitcode ("ld","iy,#%s ; a", sym->rname);
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] = "xx"; /*_fReturn[i];*/
return;
}
return rs;
case AOP_DIR:
- assert(0);
- emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
+ assert(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);
return rs;
case AOP_STK:
- sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+ if (IS_GB) {
+ /* We cant really optimise this as we cant afford to
+ change the flags.
+ */
+ emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
+ sprintf(s, "(hl)");
+ }
+ else {
+ sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+ }
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
/*-----------------------------------------------------------------*/
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. */
+ assert(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:
+ assert(!IS_GB);
if (!canAssignToPtr(s)) {
emitcode("ld", "a,%s", s);
emitcode("ld", "%d(iy),a", offset);
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";
+ }
+ emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
+ 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:
freeAsmop(IC_RESULT(ic),NULL,ic);
}
+static bool requiresHL(asmop *aop)
+{
+ switch (aop->type) {
+ case AOP_STK:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
/*-----------------------------------------------------------------*/
/* assignResultValue - */
{
int offset = 0;
int size = AOP_SIZE(oper);
+
+ assert(size <= 2);
+
while (size--) {
- aopPut(AOP(oper),fReturn[offset],offset);
+ aopPut(AOP(oper),_fReturn[offset],offset);
offset++;
}
}
+static void fetchHL(asmop *aop)
+{
+ if (IS_GB && requiresHL(aop)) {
+ emitcode("ld", "a,%s", aopGet(aop, 0, FALSE));
+ emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
+ emitcode("ld", "l,a");
+ }
+ else {
+ emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
+ emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
+ }
+}
+
/*-----------------------------------------------------------------*/
/* genIpush - genrate code for pushing this gets a little complex */
/*-----------------------------------------------------------------*/
/* push it on the stack */
if (isPair(AOP(IC_LEFT(ic)))) {
emitcode("push", getPairName(AOP(IC_LEFT(ic))));
+ _pushed += 2;
}
else {
offset = size;
emitcode("ld", "a,%s", l);
emitcode("push", "af");
emitcode("inc", "sp");
+ _pushed++;
}
}
return ;
size = AOP_SIZE(IC_LEFT(ic));
if (isPair(AOP(IC_LEFT(ic)))) {
+ _pushed+=2;
emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
}
else {
if (s) {
emitcode("ld", "hl,%s", s);
emitcode("push", "hl");
+ _pushed+=2;
}
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));
+ fetchHL(AOP(IC_LEFT(ic)));
emitcode("push", "hl");
+ _pushed += 2;
}
goto release;
}
emitcode("ld", "a,%s", l);
emitcode("push", "af");
emitcode("inc", "sp");
+ _pushed++;
}
}
release:
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++;
}
/* adjust the stack for parameters if required */
if (IC_LEFT(ic)->parmBytes) {
int i = IC_LEFT(ic)->parmBytes;
+ _pushed -= i;
if (i>6) {
emitcode("ld", "hl,#%d", i);
emitcode("add", "hl,sp");
/* 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;
emitcode("ld", "hl,#-%d", sym->stack);
emitcode("add", "hl,sp");
emitcode("ld", "sp,hl");
- }
+ }
+ _spoffset = sym->stack;
}
/*-----------------------------------------------------------------*/
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");
+ }
emitcode("pop", "bc");
- emitcode("pop", "de");
emitcode("ret", "");
}
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 (AOP_TYPE(left) == AOP_LIT){
unsigned long lit = (unsigned long)
floatFromVal(AOP(left)->aopu.aop_lit);
- emitcode("ld", "l,#0x%02x",
+ 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", "l,a");
+ 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", "h,#0x%02x",
+ 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", "h,a");
+ emitcode("ld", "%s,a", _fTmp[1]);
fDidXor = TRUE;
}
if (!fDidXor)
if (!sign || size)
MOVA(aopGet(AOP(left),offset,FALSE));
if (sign && size == 0) {
- 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 */
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));
+ fetchHL(AOP(left));
}
/* so iy now contains the address */
freeAsmop(left,NULL,ic);
}
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));
+ fetchHL(AOP(result));
}
}
/* so hl know contains the address */
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) {
+ emitcode("lda", "hl,%d(sp)", sym->stack);
+ emitcode("ld", "d,h");
+ emitcode("ld", "e,l");
+ aopPut(AOP(IC_RESULT(ic)), "e", 0);
+ aopPut(AOP(IC_RESULT(ic)), "d", 1);
+ goto end;
+ }
+ else {
+ emitcode("push", "de");
+ emitcode("push", "ix");
+ emitcode("pop", "hl");
+ emitcode("ld", "de,#%d", sym->stack);
+ emitcode("add", "hl,de");
+ emitcode("pop", "de");
+ }
}
else {
emitcode("ld", "hl,#%s", sym->rname);
}
aopPut(AOP(IC_RESULT(ic)), "l", 0);
aopPut(AOP(IC_RESULT(ic)), "h", 1);
-
+end:
freeAsmop(IC_RESULT(ic),NULL,ic);
}
/* 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);
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);
/* now generate the jump labels */
goto release;
}
+ /* PENDING: should be OK. */
+#if 0
/* if the result is of type pointer */
if (IS_PTR(ctype)) {
assert(0);
}
+#endif
/* so we now know that the size of destination is greater
than the size of the source */
iCode *ic;
int cln = 0;
+ /* HACK */
+ if (IS_GB) {
+ _fReturn = _gbz80_return;
+ _fTmp = _gbz80_return;
+ }
+ else {
+ _fReturn = _z80_return;
+ _fTmp = _z80_return;
+ }
+
lineHead = lineCurr = NULL;
/* if debug information required */
software-hoarding!
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include "SDCCglobl.h"
-#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 "z80.h"
/*-----------------------------------------------------------------*/
/* At this point we start getting processor specific although */
bitVect *funcrUsed = NULL; /* registers used in a function */
int stackExtend = 0;
int dataExtend = 0;
+int _nRegs;
/** Set to help debug register pressure related problems */
#define DEBUG_FAKE_EXTRA_REGS 0
-static regs regsZ80[] =
-{
+static regs _gbz80_regs[] = {
+ { REG_GPR, C_IDX , "b", 1 },
+ { REG_GPR, B_IDX , "c", 1 },
+ { REG_CND, CND_IDX, "c", 1}
+};
+
+static regs _z80_regs[] = {
{ REG_GPR, C_IDX , "c", 1 },
{ REG_GPR, B_IDX , "b", 1 },
{ REG_GPR, E_IDX , "e", 1 },
{ REG_CND, CND_IDX, "c", 1}
};
+regs *regsZ80;
+
/** Number of usable registers (all but C) */
-#define MAX_REGS ((sizeof(regsZ80)/sizeof(regs))-1)
+#define Z80_MAX_REGS ((sizeof(_z80_regs)/sizeof(_z80_regs[0]))-1)
+#define GBZ80_MAX_REGS ((sizeof(_gbz80_regs)/sizeof(_gbz80_regs[0]))-1)
static void spillThis (symbol *);
{
int i;
- for ( i = 0 ; i < MAX_REGS ; i++ ) {
+ for ( i = 0 ; i < _nRegs ; i++ ) {
/* For now we allocate from any free */
if (regsZ80[i].isFree ) {
regsZ80[i].isFree = 0;
{
int i;
- for (i=0;i < MAX_REGS;i++)
+ for (i=0;i < _nRegs;i++)
if (regsZ80[i].rIdx == idx)
return ®sZ80[i];
int i;
int nfr=0;
- for (i = 0 ; i < MAX_REGS; i++ ) {
+ for (i = 0 ; i < _nRegs; i++ ) {
/* For now only one reg type */
if (regsZ80[i].isFree)
nfr++;
{
int i;
assert(sym->nRegs == 2);
- for ( i = 0 ; i < MAX_REGS ; i+=2 ) {
+ for ( i = 0 ; i < _nRegs ; i+=2 ) {
if ((regsZ80[i].isFree)&&(regsZ80[i+1].isFree)) {
regsZ80[i].isFree = 0;
sym->regs[0] = ®sZ80[i];
if (sym->isspilt || !sym->nRegs)
return NULL;
- rumask = newBitVect(MAX_REGS);
+ rumask = newBitVect(_nRegs);
for (j = 0; j < sym->nRegs; j++) {
rumask = bitVectSetBit(rumask,
*/
bitVect *regsUsedIniCode (iCode *ic)
{
- bitVect *rmask = newBitVect(MAX_REGS);
+ bitVect *rmask = newBitVect(_nRegs);
/* do the special cases first */
if (ic->op == IFX ) {
/* now create the register mask for those
registers that are in use : this is a
super set of ic->rUsed */
- ic->rMask = newBitVect(MAX_REGS+1);
+ ic->rMask = newBitVect(_nRegs+1);
/* for all live Ranges alive at this point */
for (j = 1; j < ic->rlive->size; j++ ) {
{
int i;
- for (i=0;i< MAX_REGS;i++ )
+ for (i=0;i< _nRegs;i++ )
regsZ80[i].isFree = 1;
}
packRegsForOneuse (ic,IC_LEFT(ic),ebp);
#endif
- /* if pointer set & left has a size more than
+ if (!IS_GB) {
+ /* if pointer set & left has a size more than
one and right is not in far space */
- if (POINTER_SET(ic) &&
- /* MLH: no such thing.
- !isOperandInFarSpace(IC_RIGHT(ic)) && */
- !OP_SYMBOL(IC_RESULT(ic))->remat &&
- !IS_OP_RUONLY(IC_RIGHT(ic)) &&
- getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
-
- packRegsForOneuse (ic,IC_RESULT(ic),ebp);
-
- /* if pointer get */
- if (POINTER_GET(ic) &&
- /* MLH: dont have far space
- !isOperandInFarSpace(IC_RESULT(ic))&& */
- !OP_SYMBOL(IC_LEFT(ic))->remat &&
- !IS_OP_RUONLY(IC_RESULT(ic)) &&
- getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 )
- packRegsForOneuse (ic,IC_LEFT(ic),ebp);
+ if (POINTER_SET(ic) &&
+ /* MLH: no such thing.
+ !isOperandInFarSpace(IC_RIGHT(ic)) && */
+ !OP_SYMBOL(IC_RESULT(ic))->remat &&
+ !IS_OP_RUONLY(IC_RIGHT(ic)) &&
+ getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
+
+ packRegsForOneuse (ic,IC_RESULT(ic),ebp);
+
+ /* if pointer get */
+ if (POINTER_GET(ic) &&
+ /* MLH: dont have far space
+ !isOperandInFarSpace(IC_RESULT(ic))&& */
+ !OP_SYMBOL(IC_LEFT(ic))->remat &&
+ !IS_OP_RUONLY(IC_RESULT(ic)) &&
+ getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 )
+ packRegsForOneuse (ic,IC_LEFT(ic),ebp);
+ }
/* pack registers for accumulator use, when the result of an
arithmetic or bit wise operation has only one use, that use is
setToNull((void *)&funcrUsed);
ptrRegReq = stackExtend = dataExtend = 0;
+ if (IS_GB) {
+ /* DE is required for the code gen. */
+ _nRegs = GBZ80_MAX_REGS;
+ regsZ80 = _gbz80_regs;
+ }
+ else {
+ _nRegs = Z80_MAX_REGS;
+ regsZ80 = _z80_regs;
+ }
+
/* change assignments this will remove some
live ranges reducing some register pressure */
for (i = 0 ; i < count ;i++ )