5/3/00 17741 185 17B6
Michael Hope <michaelh@earthling.net> 2000
- Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
- and - Jean-Louis VERN.jlvern@writeme.com (1999)
+ Based on the mcs51 generator -
+ Sandeep Dutta . sandeep.dutta@usa.net (1998)
+ and - Jean-Louis VERN.jlvern@writeme.com (1999)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
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 *_z80_return[] = {"l", "h", "e", "d" };
static char *_gbz80_return[] = { "e", "d", "l", "h" };
static char **_fReturn;
static char **_fTmp;
+/* PENDING: messy */
+static char zero[20];
+
static char *accUse[] = {"a" };
+static char *hlUse[] = { "l", "h" };
short rbank = -1;
short accInUse = 0 ;
short inLine = 0;
extern int nRegs;
extern FILE *codeOutFile;
set *sendSet = NULL;
-const char *_shortJP = "jp";
typedef enum {
PAIR_INVALID,
#define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
#define CLRC emitcode("xor","a,a");
-#define LABEL_STR "%05d$"
-
lineNode *lineHead = NULL;
lineNode *lineCurr = NULL;
-unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
-0xE0, 0xC0, 0x80, 0x00};
-unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
-0x07, 0x03, 0x01, 0x00};
+static const unsigned char SLMask[] =
+{0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
+static const unsigned char SRMask[] =
+{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
#define LSB 0
#define MSB16 1
struct {
int last;
int pushed;
+ int param_offset;
int offset;
+ int pushed_bc;
+ int pushed_de;
} stack;
int frameId;
+ bool flush_statics;
+ bool in_home;
} _G;
static char *aopGet(asmop *aop, int offset, bool bit16);
+static void _tidyUp(char *buf)
+{
+ /* Clean up the line so that it is 'prettier' */
+ if (strchr(buf, ':')) {
+ /* Is a label - cant do anything */
+ return;
+ }
+ /* Change the first (and probably only) ' ' to a tab so
+ everything lines up.
+ */
+ while (*buf) {
+ if (*buf == ' ') {
+ *buf = '\t';
+ return;
+ }
+ buf++;
+ }
+}
+
+static void emit2(const char *szFormat, ...)
+{
+ char buffer[256];
+ va_list ap;
+
+ va_start(ap, szFormat);
+
+ tvsprintf(buffer, szFormat, ap);
+
+ _tidyUp(buffer);
+ lineCurr = (lineCurr ?
+ connectLine(lineCurr,newLineNode(buffer)) :
+ (lineHead = newLineNode(buffer)));
+
+ lineCurr->isInline = inLine;
+ lineCurr->isDebug = debugLine;
+}
+
/*-----------------------------------------------------------------*/
/* emitcode - writes the code into a file : for now it is simple */
/*-----------------------------------------------------------------*/
va_end(ap);
}
+/* Z80:
+ { "adjustsp",
+ "\tld hl,#-%d\n"
+ "\tadd hl,sp\n"
+ "\tld sp,hl"
+ }
+ { "prelude",
+ "push bc"
+ "push de"
+ "push ix"
+ "ld ix,#0"
+ "add ix,sp"
+ { "leave"
+ emitcode("ld", "sp,ix");
+ emitcode("pop", "ix");
+ emitcode("pop", "de");
+ }
+}
+*/
+
const char *getPairName(asmop *aop)
{
if (aop->type == AOP_REG) {
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 */
/*-----------------------------------------------------------------*/
/* aopForSym - for a true symbol */
/*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
{
asmop *aop;
- memmap *space= SPEC_OCLS(sym->etype);
+ memmap *space;
+
+ wassert(ic);
+ wassert(sym);
+ wassert(sym->etype);
+
+ space = SPEC_OCLS(sym->etype);
/* if already has one */
if (sym->aop)
/* Assign depending on the storage class */
if (sym->onStack || sym->iaccess) {
+ emitcode("", "; AOP_STK for %s", sym->rname);
sym->aop = aop = newAsmop(AOP_STK);
aop->size = getSize(sym->type);
aop->aopu.aop_stk = sym->stack;
return aop;
}
-#if 0
if (IS_GB) {
/* if it is in direct space */
- if (IN_DIRSPACE(space)) {
- sym->aop = aop = newAsmop (AOP_DIR);
+ if (IN_REGSP(space) && !requires_a) {
+ sym->aop = aop = newAsmop (AOP_SFR);
aop->aopu.aop_dir = sym->rname ;
aop->size = getSize(sym->type);
- emitcode("", "; AOP_DIR for %s", sym->rname);
+ emitcode("", "; AOP_SFR for %s", sym->rname);
return aop;
}
}
-#endif
/* only remaining is far space */
/* in which case DPTR gets the address */
if (IS_GB) {
+ emitcode("", "; AOP_HL for %s", sym->rname);
sym->aop = aop = newAsmop(AOP_HL);
}
else {
while (1) {
/* if plus or minus print the right hand side */
if (ic->op == '+' || ic->op == '-') {
+ /* PENDING: for re-target */
sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
ic->op );
s += strlen(s);
{
int i;
- if (aop1 == aop2)
- return TRUE ;
+ if (aop1->type == AOP_SFR ||
+ aop2->type == AOP_SFR)
+ return FALSE;
+
+ if (aop1 == aop2)
+ return TRUE;
if (aop1->type != AOP_REG ||
aop2->type != AOP_REG )
- return FALSE ;
+ return FALSE;
if (aop1->size != aop2->size)
return FALSE ;
/*-----------------------------------------------------------------*/
/* aopOp - allocates an asmop for an operand : */
/*-----------------------------------------------------------------*/
-static void aopOp (operand *op, iCode *ic, bool result)
+static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
{
asmop *aop;
symbol *sym;
/* if this is a true symbol */
if (IS_TRUE_SYMOP(op)) {
- op->aop = aopForSym(ic,OP_SYMBOL(op),result);
+ op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
return ;
}
if (sym->accuse) {
int i;
- aop = op->aop = sym->aop = newAsmop(AOP_ACC);
- aop->size = getSize(sym->type);
- for ( i = 0 ; i < 2 ; i++ )
- aop->aopu.aop_str[i] = accUse[i];
- return;
+ if (sym->accuse == ACCUSE_A) {
+ aop = op->aop = sym->aop = newAsmop(AOP_ACC);
+ aop->size = getSize(sym->type);
+ for ( i = 0 ; i < 2 ; i++ )
+ aop->aopu.aop_str[i] = accUse[i];
+ }
+ else if (sym->accuse == ACCUSE_HL) {
+ wassert(!IS_GB);
+ aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
+ aop->size = getSize(sym->type);
+ for ( i = 0 ; i < 2 ; i++ )
+ aop->aopu.aop_str[i] = hlUse[i];
+ }
+ else
+ wassert(0);
+ return;
}
if (sym->ruonly ) {
/* else spill location */
sym->aop = op->aop = aop =
- aopForSym(ic,sym->usl.spillLoc,result);
+ aopForSym(ic,sym->usl.spillLoc,result, requires_a);
aop->size = getSize(sym->type);
return;
}
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%s",with_hash ? "#" : "", aop->aopu.aop_immd);
+ /* PENDING: for re-target */
+ if (with_hash)
+ tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+ else
+ tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
if (!IS_FLOAT(val->type)) {
unsigned long v = floatFromVal(val);
- sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
+ if (offset == 2)
+ v >>= 16;
+
+ if (with_hash)
+ tsprintf(buffer, "!immedword", v);
+ else
+ tsprintf(buffer, "!constword", v);
+ ALLOC_ATOMIC(rs,strlen(buffer)+1);
+ return strcpy (rs,buffer);
+ }
+ else {
+ /* A float */
+ Z80_FLOAT f;
+ convertFloat(&f, floatFromVal(val));
+ if (with_hash)
+ tsprintf(buffer, "!immedword", f.w[offset/2]);
+ else
+ tsprintf(buffer, "!constword", f.w[offset/2]);
ALLOC_ATOMIC(rs,strlen(buffer)+1);
return strcpy (rs,buffer);
}
- wassert(0);
- return NULL;
}
default:
return NULL;
}
}
+static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
+{
+ unsigned long v;
+ value * val = aop->aopu.aop_lit;
+
+ wassert(aop->type == AOP_LIT);
+ wassert(!IS_FLOAT(val->type));
+
+ v = floatFromVal(val);
+
+ if (xor)
+ v ^= 0x8000;
+ if (negate)
+ v = -v;
+ v &= 0xFFFF;
+
+ tsprintf(buffer, "!immedword", v);
+ return gc_strdup(buffer);
+}
+
static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
{
const char *l;
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;
+ if (_G.pairs[pairId].last_type == left->type) {
+ 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].lit = gc_strdup(l);
+ _G.pairs[pairId].offset = offset;
+ }
+ if (IS_GB && pairId == PAIR_DE && 0) {
+ if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
+ if (abs(_G.pairs[pairId].offset - offset) < 3) {
+ adjustPair(pair, &_G.pairs[pairId].offset, offset);
+ return;
+ }
+ }
+ _G.pairs[pairId].last_type = left->type;
+ _G.pairs[pairId].lit = gc_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);
+ emit2("ld %s,!hashedstr + %u", pair, l, offset);
+ else
+ emit2("ld %s,!hashedstr", pair, l);
}
static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
else { /* we need to get it byte by byte */
if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
aopGet(aop, offset, FALSE);
- emitcode("ld", "a,(hl+)");
- emitcode("ld", "h,(hl)");
- emitcode("ld", "l,a");
+ switch (aop->size) {
+ case 1:
+ emit2("ld l,!*hl");
+ emit2("ld h,!immedbyte", 0);
+ break;
+ case 2:
+ emit2("!ldahli");
+ emit2("ld h,!*hl");
+ emit2("ld l,a");
+ break;
+ default:
+ emit2("; WARNING: mlh woosed out. This code is invalid.");
+ }
+ }
+ else if (IS_Z80 && aop->type == AOP_IY) {
+ /* Instead of fetching relative to IY, just grab directly
+ from the address IY refers to */
+ char *l = aopGetLitWordLong(aop, offset, FALSE);
+ wassert(l);
+ emit2("ld %s,(%s)", _pairs[pairId].name, l);
}
else {
emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
switch (aop->type) {
case AOP_IY:
+ fetchLitPair(pairId, aop, 0);
+ break;
case AOP_HL:
fetchLitPair(pairId, aop, offset);
_G.pairs[pairId].offset = offset;
case AOP_STK: {
/* Doesnt include _G.stack.pushed */
int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+ if (aop->aopu.aop_stk > 0) {
+ abso += _G.stack.param_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);
+ emit2("!ldahlsp", abso +_G.stack.pushed);
}
_G.pairs[pairId].offset = abso;
break;
static void emitLabel(int key)
{
- emitcode("", LABEL_STR ":", key);
+ emit2("!tlabeldef", key);
spillCached();
}
/* depending on type */
switch (aop->type) {
case AOP_IMMD:
+ /* PENDING: re-target */
if (bit16)
- sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
+ tsprintf (s,"!immedwords", aop->aopu.aop_immd);
else
- if (offset) {
- wassert(offset == 1);
- sprintf(s,"#>%s",
- aop->aopu.aop_immd);
+ switch (offset) {
+ case 2:
+ tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
+ break;
+ case 1:
+ tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
+ break;
+ case 0:
+ tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
+ break;
+ default:
+ wassert(0);
}
- else
- sprintf(s,"#<%s",
- aop->aopu.aop_immd);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
strcpy(rs,s);
return rs;
+ case AOP_SFR:
+ wassert(IS_GB);
+ emitcode("ldh", "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_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)");
+ tsprintf(s, "!*hl");
+ return gc_strdup(s);
case AOP_IY:
wassert(IS_Z80);
setupPair(PAIR_IY, aop, offset);
- sprintf(s,"%d(iy)", offset);
+ tsprintf(s,"!*iyx", offset);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
case AOP_STK:
if (IS_GB) {
setupPair(PAIR_HL, aop, offset);
- sprintf(s, "(hl)");
+ tsprintf(s, "!*hl");
}
else {
- sprintf(s,"%d(ix)", aop->aopu.aop_stk+offset);
+ tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
}
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
if (!offset) {
return "a";
}
- return "#0x00";
+ return "!zero";
+
+ case AOP_HLREG:
+ wassert(offset < 2);
+ return aop->aopu.aop_str[offset];
case AOP_LIT:
return aopLiteral (aop->aopu.aop_lit,offset);
exit(0);
}
-bool isRegString(char *s)
+bool isRegString(const char *s)
{
if (!strcmp(s, "b") ||
!strcmp(s, "c") ||
bool isConstant(const char *s)
{
- return (*s == '#');
+ /* This is a bit of a hack... */
+ return (*s == '#' || *s == '$');
}
-bool canAssignToPtr(char *s)
+bool canAssignToPtr(const char *s)
{
if (isRegString(s))
return TRUE;
/*-----------------------------------------------------------------*/
/* aopPut - puts a string for a aop */
/*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static void aopPut (asmop *aop, const char *s, int offset)
{
if (aop->size && offset > ( aop->size - 1)) {
werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
case AOP_DIR:
/* Direct. Hmmm. */
wassert(IS_GB);
- emitcode("ld", "a,%s", s);
+ if (strcmp(s, "a"))
+ emitcode("ld", "a,%s", s);
emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
break;
+ case AOP_SFR:
+ wassert(IS_GB);
+ if (strcmp(s, "a"))
+ emitcode("ld", "a,%s", s);
+ emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
+ break;
+
case AOP_REG:
- /* Dont bother if it's a ld x,x */
- if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
- emitcode("ld","%s,%s",
- aop->aopu.aop_reg[offset]->name,s);
- }
+ if (!strcmp(s, "!*hl"))
+ emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
+ else
+ emit2("ld %s,%s",
+ aop->aopu.aop_reg[offset]->name, s);
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);
+ emit2("ld a,%s", s);
+ emit2("ld !*iyx,a", offset);
}
else
- emitcode("ld", "%d(iy),%s", offset, s);
+ emit2("ld !*iyx,%s", offset, s);
break;
case AOP_HL:
wassert(IS_GB);
- if (!strcmp(s, "(hl)")) {
- emitcode("ld", "a,(hl)");
+ /* PENDING: for re-target */
+ if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
+ emit2("ld a,!*hl");
s = "a";
}
- emitcode("", ";2");
setupPair(PAIR_HL, aop, offset);
- emitcode("ld", "(hl),%s", s);
+
+ emit2("ld !*hl,%s", s);
break;
case AOP_STK:
if (IS_GB) {
- if (!strcmp("(hl)", s)) {
- emitcode("ld", "a,(hl)");
+ /* PENDING: re-target */
+ if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
+ emit2("ld a,!*hl");
s = "a";
}
setupPair(PAIR_HL, aop, offset);
if (!canAssignToPtr(s)) {
- emitcode("ld", "a,%s", s);
- emitcode("ld", "(hl),a");
+ emit2("ld a,%s", s);
+ emit2("ld !*hl,a");
}
else
- emitcode("ld", "(hl),%s", s);
+ emit2("ld !*hl,%s", s);
}
else {
if (!canAssignToPtr(s)) {
- emitcode("ld", "a,%s", s);
- emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+ emit2("ld a,%s", s);
+ emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
}
else
- emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
+ emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
}
break;
case AOP_CRY:
/* if bit variable */
if (!aop->aopu.aop_dir) {
- emitcode("ld", "a,#0");
- emitcode("rla", "");
+ emit2("ld a,#0");
+ emit2("rla");
} else {
/* In bit space but not in C - cant happen */
wassert(0);
}
break;
+ case AOP_HLREG:
+ wassert(offset < 2);
+ emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
+ break;
+
default :
werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
"aopPut got unsupported aop->type");
#define AOP_SIZE(op) AOP(op)->size
#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+static void commitPair(asmop *aop, PAIR_ID id)
+{
+ if (id == PAIR_HL && requiresHL(aop)) {
+ emit2("ld a,l");
+ emit2("ld d,h");
+ aopPut(aop, "a", 0);
+ aopPut(aop, "d", 1);
+ }
+ else {
+ aopPut(aop, _pairs[id].l, 0);
+ aopPut(aop, _pairs[id].h, 1);
+ }
+}
+
/*-----------------------------------------------------------------*/
/* getDataSize - get the operand data size */
/*-----------------------------------------------------------------*/
offset = 1;
/* unsigned or positive */
while (size--){
- aopPut(AOP(result),zero,offset++);
+ aopPut(AOP(result), zero, offset++);
}
}
}
/** Take the value in carry and put it into a register
*/
-void outBitC(operand *result)
+void outBitCLong(operand *result, bool swap_sense)
{
/* if the result is bit */
if (AOP_TYPE(result) == AOP_CRY) {
aopPut(AOP(result),"blah",0);
}
else {
- emitcode("ld", "a,#0");
- emitcode("rla", "");
+ emit2("ld a,!zero");
+ emit2("rla");
+ if (swap_sense)
+ emit2("xor a,!immedbyte", 1);
outAcc(result);
}
}
+void outBitC(operand *result)
+{
+ outBitCLong(result, FALSE);
+}
+
/*-----------------------------------------------------------------*/
/* toBoolean - emit code for orl a,operator(sizeop) */
/*-----------------------------------------------------------------*/
link *optype = operandType(IC_LEFT(ic));
/* assign asmOps to operand & result */
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
+ aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
/* if in bit space then a special case */
if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
If A == 0, !A = 1
else A = 0
So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
- emitcode("sub", "a,#0x01");
+ emit2("sub a,!one");
outBitC(IC_RESULT(ic));
/* release the aops */
/* assign asmOps to operand & result */
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+ aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
/* if both are in bit space then
a special case */
link *optype, *rtype;
/* assign asmops */
- aopOp(IC_LEFT(ic),ic,FALSE);
- aopOp(IC_RESULT(ic),ic,TRUE);
+ aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+ aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
/* if both in bit space then special
case */
CLRC ;
while(size--) {
char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
- emitcode("ld", "a,#0");
- emitcode("sbc","a,%s",l);
+ emit2("ld a,!zero");
+ emit2("sbc a,%s",l);
aopPut(AOP(IC_RESULT(ic)),"a",offset++);
}
/* if any remaining bytes in the result */
/* we just need to propagate the sign */
if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
- emitcode("rlc","a");
- emitcode("sbc","a,a");
+ emit2("rlc a");
+ emit2("sbc a,a");
while (size--)
aopPut(AOP(IC_RESULT(ic)),"a",offset++);
}
freeAsmop(IC_RESULT(ic),NULL,ic);
}
+static void _push(PAIR_ID pairId)
+{
+ emit2("push %s", _pairs[pairId].name);
+ _G.stack.pushed += 2;
+}
+
+static void _pop(PAIR_ID pairId)
+{
+ emit2("pop %s", _pairs[pairId].name);
+ _G.stack.pushed -= 2;
+}
+
+
/*-----------------------------------------------------------------*/
/* assignResultValue - */
/*-----------------------------------------------------------------*/
wassert(size <= 4);
topInA = requiresHL(AOP(oper));
+#if 0
if (!IS_GB)
wassert(size <= 2);
+#endif
if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
/* We do it the hard way here. */
- emitcode("push", "hl");
- _G.stack.pushed += 2;
+ _push(PAIR_HL);
aopPut(AOP(oper), _fReturn[0], 0);
aopPut(AOP(oper), _fReturn[1], 1);
emitcode("pop", "de");
int size, offset = 0 ;
char *l;
-
/* if this is not a parm push : ie. it is spill push
and spill push is always done on the local stack */
if (!ic->parmPush) {
if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
return ;
- aopOp(IC_LEFT(ic),ic,FALSE);
+ aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
size = AOP_SIZE(IC_LEFT(ic));
/* push it on the stack */
if (isPair(AOP(IC_LEFT(ic)))) {
else {
offset = size;
while (size--) {
- l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
/* Simple for now - load into A and PUSH AF */
- emitcode("ld", "a,%s", l);
- emitcode("push", "af");
- emitcode("inc", "sp");
+ if (AOP(IC_LEFT(ic))->type == AOP_IY) {
+ char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
+ wassert(l);
+ emit2("ld a,(%s)", l);
+ }
+ else {
+ l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
+ emit2("ld a,%s", l);
+ }
+ emit2("push af");
+ emit2("inc sp");
_G.stack.pushed++;
}
}
at this point? */
/* then do the push */
- aopOp(IC_LEFT(ic),ic,FALSE);
+ aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
size = AOP_SIZE(IC_LEFT(ic));
else {
if (size == 2) {
fetchHL(AOP(IC_LEFT(ic)));
- emitcode("push", "hl ; 2");
+ emitcode("push", "hl");
+ spillPair(PAIR_HL);
+ _G.stack.pushed += 2;
+ goto release;
+ }
+ if (size == 4) {
+ fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
+ emitcode("push", "hl");
+ spillPair(PAIR_HL);
+ _G.stack.pushed += 2;
+ fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
+ emitcode("push", "hl");
spillPair(PAIR_HL);
_G.stack.pushed += 2;
goto release;
}
offset = size;
while (size--) {
- l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
- emitcode("ld", "a,%s", l);
+ if (AOP(IC_LEFT(ic))->type == AOP_IY) {
+ char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
+ wassert(l);
+ emit2("ld a,(%s)", l);
+ }
+ else {
+ l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
+ emit2("ld a,%s", l);
+ }
emitcode("push", "af");
emitcode("inc", "sp");
_G.stack.pushed++;
if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
return ;
- aopOp(IC_LEFT(ic),ic,FALSE);
+ aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
size = AOP_SIZE(IC_LEFT(ic));
offset = (size-1);
if (isPair(AOP(IC_LEFT(ic)))) {
freeAsmop(IC_LEFT(ic),NULL,ic);
}
+static int _isPairUsed(iCode *ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ switch (pairId) {
+ case PAIR_DE:
+ if (bitVectBitValue(ic->rUsed, D_IDX))
+ ret++;
+ if (bitVectBitValue(ic->rUsed, E_IDX))
+ ret++;
+ break;
+ default:
+ wassert(0);
+ }
+ return ret;
+}
+
+static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ asmop *aop;
+ symbol *sym = OP_SYMBOL(op);
+
+ if (sym->isspilt || sym->nRegs == 0)
+ return 0;
+
+ aopOp(op, ic, FALSE, FALSE);
+
+ aop = AOP(op);
+ if (aop->type == AOP_REG) {
+ int i;
+ for (i=0; i < aop->size; i++) {
+ if (pairId == PAIR_DE) {
+ emit2("; name %s", aop->aopu.aop_reg[i]->name);
+ if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
+ ret++;
+ if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
+ ret++;
+ }
+ else {
+ wassert(0);
+ }
+ }
+ }
+
+ freeAsmop(IC_LEFT(ic),NULL,ic);
+ return ret;
+}
+
+/* This is quite unfortunate */
+static void setArea(int inHome)
+{
+ static int lastArea = 0;
+
+ /*
+ if (_G.in_home != inHome) {
+ if (inHome) {
+ const char *sz = port->mem.code_name;
+ port->mem.code_name = "HOME";
+ emit2("!area", CODE_NAME);
+ port->mem.code_name = sz;
+ }
+ else
+ emit2("!area", CODE_NAME);*/
+ _G.in_home = inHome;
+ // }
+}
+
+static bool isInHome(void)
+{
+ return _G.in_home;
+}
+
/** Emit the code for a call statement
*/
-static void emitCall (iCode *ic, bool ispcall)
+static void emitCall(iCode *ic, bool ispcall)
{
+ int pushed_de = 0;
+ link *detype = getSpec(operandType(IC_LEFT(ic)));
+
/* if caller saves & we have not saved then */
if (!ic->regsSaved) {
/* PENDING */
}
-
+
/* if send set is not empty then assign */
if (sendSet) {
- iCode *sic ;
- for (sic = setFirstItem(sendSet) ; sic ;
- sic = setNextItem(sendSet)) {
- int size, offset = 0;
- aopOp(IC_LEFT(sic),sic,FALSE);
- size = AOP_SIZE(IC_LEFT(sic));
- while (size--) {
- char *l = aopGet(AOP(IC_LEFT(sic)),offset,
- FALSE);
- if (strcmp(l, _fReturn[offset]))
- emitcode("ld","%s,%s",
- _fReturn[offset],
- l);
- offset++;
+ iCode *sic;
+ int send = 0;
+ int n = elementsInSet(sendSet);
+ if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
+ /* Only push de if it is used and if it's not used
+ in the return value */
+ /* Panic if partly used */
+ if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
+ emit2("; Warning: de crossover");
+ }
+ else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
+ /* Store away de */
+ _push(PAIR_DE);
+ pushed_de = 1;
}
+ }
+ /* PENDING: HACK */
+ if (IS_Z80 && n == 2 ) {
+ /* Want to load HL first, then DE as HL may = DE */
+ sic = setFirstItem(sendSet);
+ sic = setNextItem(sendSet);
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ send++;
+ freeAsmop (IC_LEFT(sic),NULL,sic);
+ sic = setFirstItem(sendSet);
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+ send++;
freeAsmop (IC_LEFT(sic),NULL,sic);
}
+ else {
+ for (sic = setFirstItem(sendSet) ; sic ;
+ sic = setNextItem(sendSet)) {
+ int size;
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ size = AOP_SIZE(IC_LEFT(sic));
+ wassert(size <= 2);
+ /* Always send in pairs */
+ switch (send) {
+ case 0:
+ if (IS_Z80 && n == 1)
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ else
+ fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+ break;
+ case 1:
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ break;
+ default:
+ /* Send set too big */
+ wassert(0);
+ }
+ send++;
+ freeAsmop (IC_LEFT(sic),NULL,sic);
+ }
+ }
sendSet = NULL;
+ if (pushed_de) {
+ }
}
if (ispcall) {
- aopOp(IC_LEFT(ic),ic,FALSE);
+ if (IS_BANKEDCALL(detype)) {
+ werror(W_INDIR_BANKED);
+ }
+ aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
if (isLitWord(AOP(IC_LEFT(ic)))) {
emitcode("", "; Special case where the pCall is to a constant");
else {
symbol *rlbl = newiTempLabel(NULL);
spillPair(PAIR_HL);
- emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
+ emit2("ld hl,!immed!tlabel", (rlbl->key+100));
emitcode("push", "hl");
_G.stack.pushed += 2;
fetchHL(AOP(IC_LEFT(ic)));
- emitcode("jp", "(hl)");
- emitcode("","%05d$:",(rlbl->key+100));
+ emit2("jp !*hl");
+ emit2("!tlabeldef", (rlbl->key+100));
_G.stack.pushed -= 2;
}
freeAsmop(IC_LEFT(ic),NULL,ic);
}
else {
- /* make the call */
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);
+ if (IS_BANKEDCALL(detype)) {
+ emit2("call banked_call");
+ emit2("!dws", name);
+ emit2("!dw !bankimmeds", name);
+ }
+ else {
+ /* make the call */
+ emit2("call %s", name);
+ }
}
spillCached();
IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
accInUse++;
- aopOp(IC_RESULT(ic),ic,FALSE);
+ aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
accInUse--;
assignResultValue(IC_RESULT(ic));
int i = IC_LEFT(ic)->parmBytes;
_G.stack.pushed -= i;
if (IS_GB) {
- emitcode("lda", "sp,%d(sp)", i);
+ emit2("!ldaspsp", i);
}
else {
spillCached();
spillCached();
}
}
-
+ if (pushed_de)
+ _pop(PAIR_DE);
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static void genCall (iCode *ic)
{
+ link *detype = getSpec(operandType(IC_LEFT(ic)));
emitCall(ic, FALSE);
}
return 0;
}
+extern set *publics;
+
/*-----------------------------------------------------------------*/
/* genFunction - generated code for function entry */
/*-----------------------------------------------------------------*/
link *fetype;
nregssaved = 0;
- /* create the function header */
- emitcode(";","-----------------------------------------");
- emitcode(";"," function %s", sym->name);
- emitcode(";","-----------------------------------------");
+ setArea(IS_NONBANKED(sym->etype));
- emitcode("", "__%s_start:", sym->rname);
- emitcode("","%s:",sym->rname);
+ /* PENDING: hack */
+ if (!IS_STATIC(sym->etype)) {
+ addSetIfnotP(&publics, sym);
+ }
+ /* create the function header */
+ emit2("!functionheader", sym->name);
+ /* PENDING: portability. */
+ emit2("__%s_start:", sym->rname);
+ emit2("!functionlabeldef", sym->rname);
+
fetype = getSpec(operandType(IC_LEFT(ic)));
-
+
/* if critical function then turn interrupts off */
if (SPEC_CRTCL(fetype))
- emitcode("di","");
+ emit2("!di");
/* if this is an interrupt service routine then
save acc, b, dpl, dph */
if (IS_ISR(sym->etype)) {
- emitcode("push", "af");
- emitcode("push", "bc");
- emitcode("push", "de");
- emitcode("push", "hl");
+ emit2("!pusha");
}
/* PENDING: callee-save etc */
- /* adjust the stack for the function */
- emitcode("push", "bc");
- if (!IS_GB) {
- emitcode("push", "de");
- emitcode("push", "ix");
- emitcode("ld", "ix,#0");
- emitcode("add", "ix,sp");
+ /* If BC or DE are used, then push */
+ _G.stack.pushed_bc = 0;
+ _G.stack.pushed_de = 0;
+ _G.stack.param_offset = 0;
+ if (sym->regsUsed) {
+ int i;
+ for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+ if (bitVectBitValue(sym->regsUsed, i)) {
+ switch (i) {
+ case C_IDX:
+ case B_IDX:
+ _G.stack.pushed_bc = 1;
+ break;
+ case D_IDX:
+ case E_IDX:
+ if (IS_Z80)
+ _G.stack.pushed_de = 1;
+ break;
+ }
+ }
+ }
+ if (_G.stack.pushed_bc) {
+ emit2("push bc");
+ _G.stack.param_offset += 2;
+ }
+ if (_G.stack.pushed_de) {
+ emit2("push de");
+ _G.stack.param_offset += 2;
+ }
}
+ /* adjust the stack for the function */
_G.stack.last = sym->stack;
- if (sym->stack) {
- 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");
- }
- }
+ if (sym->stack)
+ emit2("!enterx", sym->stack);
+ else
+ emit2("!enter");
_G.stack.offset = sym->stack;
}
}
else {
if (SPEC_CRTCL(sym->etype))
- emitcode("ei", "");
+ emit2("!ei");
/* PENDING: calleeSave */
emitcode("","XG$%s$0$0 ==.",currFunc->name);
debugLine = 0;
}
- if (!IS_GB) {
- emitcode("ld", "sp,ix");
- emitcode("pop", "ix");
- emitcode("pop", "de");
- }
- else {
- if (_G.stack.offset) {
- emitcode("lda", "sp,%d(sp)", _G.stack.offset);
- }
- }
- emitcode("pop", "bc");
- emitcode("ret", "");
+ if (_G.stack.offset)
+ emit2("!leavex", _G.stack.offset);
+ else
+ emit2("!leave");
+
+ if (_G.stack.pushed_de)
+ emit2("pop de");
+ if (_G.stack.pushed_bc)
+ emit2("pop bc");
+ /* Both baned and non-banked just ret */
+ emit2("ret");
+
+ /* PENDING: portability. */
+ emit2("__%s_end:", sym->rname);
}
+ _G.flush_statics = 1;
_G.stack.pushed = 0;
_G.stack.offset = 0;
}
/* we have something to return then
move the return value into place */
- aopOp(IC_LEFT(ic),ic,FALSE);
+ aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
size = AOP_SIZE(IC_LEFT(ic));
if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
if (!(ic->next && ic->next->op == LABEL &&
IC_LABEL(ic->next) == returnLabel))
- emitcode("jp", LABEL_STR ,(returnLabel->key+100));
+ emit2("jp !tlabel", returnLabel->key+100);
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static void genGoto (iCode *ic)
{
- emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
+ emit2("jp !tlabel", IC_LABEL(ic)->key+100);
}
/*-----------------------------------------------------------------*/
/* 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(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
-
- emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
- if(size == 4) {
- wassert(0);
+ size > 1 &&
+ icount == 1
+ ) {
+ int offset = 0;
+ symbol *tlbl = NULL;
+ tlbl = newiTempLabel(NULL);
+ while (size--) {
+ emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
+ if (size) {
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
+ }
}
emitLabel(tlbl->key+100);
return TRUE;
if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
while (icount--)
emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
-
return TRUE ;
}
wassert(0);
}
else {
- emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
- emitcode("ld","a,%s",one);
+ emit2("!shortjp z,!tlabel", tlbl->key+100);
+ emit2("ld a,!one");
emitLabel(tlbl->key+100);
outAcc(result);
}
/* special cases :- */
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RIGHT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+ aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
+ aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
/* Swap the left and right operands if:
if (genPlusIncr (ic) == TRUE)
goto release;
+ emit2("; genPlusIncr failed");
+
size = getDataSize(IC_RESULT(ic));
/* Special case when left and right are constant */
goto release;
}
+ /* Special case:
+ ld hl,sp+n trashes C so we cant afford to do it during an
+ add with stack based varibles. Worst case is:
+ ld hl,sp+left
+ ld a,(hl)
+ ld hl,sp+right
+ add (hl)
+ ld hl,sp+result
+ ld (hl),a
+ ld hl,sp+left+1
+ ld a,(hl)
+ ld hl,sp+right+1
+ adc (hl)
+ ld hl,sp+result+1
+ ld (hl),a
+ So you cant afford to load up hl if either left, right, or result
+ is on the stack (*sigh*) The alt is:
+ ld hl,sp+left
+ ld de,(hl)
+ ld hl,sp+right
+ ld hl,(hl)
+ add hl,de
+ ld hl,sp+result
+ ld (hl),hl
+ Combinations in here are:
+ * If left or right are in bc then the loss is small - trap later
+ * If the result is in bc then the loss is also small
+ */
+ if (IS_GB) {
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+ if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+ AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+ (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+ AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
+ if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
+ /* Swap left and right */
+ operand *t = IC_RIGHT(ic);
+ IC_RIGHT(ic) = IC_LEFT(ic);
+ IC_LEFT(ic) = t;
+ }
+ if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
+ fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
+ emit2("add hl,bc");
+ }
+ else {
+ fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
+ fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
+ emit2("add hl,de");
+ }
+ commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
+ goto release;
+ }
+ else if (size == 4) {
+ emit2("; WARNING: This add is probably broken.\n");
+ }
+ }
+ }
+
while(size--) {
if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
if(offset == 0)
- emitcode("add","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ emit2("add a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
else
- emitcode("adc","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ emit2("adc a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
} else {
- MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
if(offset == 0)
- emitcode("add","a,%s",
- aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+ emit2("add a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
else
- emitcode("adc","a,%s",
- aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+ emit2("adc a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
}
- aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ aopPut(AOP(IC_RESULT(ic)),"a",offset++);
}
-
- /* Some kind of pointer arith. */
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_LEFT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
- wassert(0);
-
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_RIGHT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
- wassert(0);
-
release:
freeAsmop(IC_LEFT(ic),NULL,ic);
int size, offset = 0;
unsigned long lit = 0L;
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RIGHT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+ aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
+ aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
/* special cases :- */
/* if both left & right are in bit space */
lit = - (long)lit;
}
-
+ /* Same logic as genPlus */
+ if (IS_GB) {
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
+ AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+ if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+ AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+ (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+ AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
+ PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
+ PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
+
+ if (left == PAIR_INVALID && right == PAIR_INVALID) {
+ left = PAIR_DE;
+ right = PAIR_HL;
+ }
+ else if (right == PAIR_INVALID)
+ right = PAIR_DE;
+ else if (left == PAIR_INVALID)
+ left = PAIR_DE;
+
+ fetchPair(left, AOP(IC_LEFT(ic)));
+ /* Order is important. Right may be HL */
+ fetchPair(right, AOP(IC_RIGHT(ic)));
+
+ emit2("ld a,%s", _pairs[left].l);
+ emit2("sub a,%s", _pairs[right].l);
+ emit2("ld e,a");
+ emit2("ld a,%s", _pairs[left].h);
+ emit2("sbc a,%s", _pairs[right].h);
+
+ aopPut(AOP(IC_RESULT(ic)), "a", 1);
+ aopPut(AOP(IC_RESULT(ic)), "e", 0);
+ goto release;
+ }
+ else if (size == 4) {
+ emit2("; WARNING: This sub is probably broken.\n");
+ }
+ }
+ }
+
/* if literal, add a,#-lit, else normal subb */
while (size--) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
else{
/* first add without previous c */
if (!offset)
- emitcode("add","a,#0x%02x",
- (unsigned int)(lit & 0x0FFL));
+ emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
else
- emitcode("adc","a,#0x%02x",
- (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+ emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
}
aopPut(AOP(IC_RESULT(ic)),"a",offset++);
}
/* if true label then we jump if condition
supplied is true */
- if ( IC_TRUE(ic) ) {
+ if (IC_TRUE(ic)) {
jlbl = IC_TRUE(ic);
if (!strcmp(jval, "a")) {
inst = "nz";
else if (!strcmp(jval, "c")) {
inst = "c";
}
+ else if (!strcmp(jval, "nc")) {
+ inst = "nc";
+ }
else {
/* The buffer contains the bit on A that we should test */
inst = "nz";
else if (!strcmp(jval, "c")) {
inst = "nc";
}
+ else if (!strcmp(jval, "nc")) {
+ inst = "c";
+ }
else {
/* The buffer contains the bit on A that we should test */
inst = "z";
}
else if (!strcmp(jval, "c")) {
}
+ else if (!strcmp(jval, "nc")) {
+ }
else {
emitcode("bit", "%s,a", jval);
}
- emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
+ emit2("jp %s,!tlabel", inst, jlbl->key+100);
/* mark the icode as generated */
ic->generated = 1;
}
+const char *getPairIdName(PAIR_ID id)
+{
+ return _pairs[id].name;
+}
+
/** Generic compare for > or <
*/
static void genCmp (operand *left,operand *right,
{
int size, offset = 0 ;
unsigned long lit = 0L;
+ bool swap_sense = FALSE;
/* if left & right are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
(AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
if (sign) {
- emitcode("xor", "a,#0x80");
- emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
+ emit2("xor a,!immedbyte", 0x80);
+ emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
}
else
- emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
+ emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
}
else {
+ /* Special cases:
+ On the GB:
+ If the left or the right is a lit:
+ Load -lit into HL, add to right via, check sense.
+ */
+ if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
+ asmop *lit = AOP(right);
+ asmop *op = AOP(left);
+ swap_sense = TRUE;
+ if (AOP_TYPE(left) == AOP_LIT) {
+ swap_sense = FALSE;
+ lit = AOP(left);
+ op = AOP(right);
+ }
+ if (sign) {
+ emit2("ld e,%s", aopGet(op, 0, 0));
+ emit2("ld a,%s", aopGet(op, 1, 0));
+ emit2("xor a,!immedbyte", 0x80);
+ emit2("ld d,a");
+ }
+ emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
+ emit2("add hl,de");
+ goto release;
+ }
if(AOP_TYPE(right) == AOP_LIT) {
lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
/* optimize if(x < 0) or if(x >= 0) */
if (AOP_TYPE(left) == AOP_LIT){
unsigned long lit = (unsigned long)
floatFromVal(AOP(left)->aopu.aop_lit);
- emitcode("ld", "%s,#0x%02x", _fTmp[0],
+ emit2("ld %s,!immedbyte", _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");
+ emit2("xor a,!immedbyte", 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],
+ emit2("ld %s,!immedbyte", _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");
+ emit2("xor a,!immedbyte", 0x80);
emitcode("ld", "%s,a", _fTmp[1]);
fDidXor = TRUE;
}
release:
if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
- outBitC(result);
+ outBitCLong(result, swap_sense);
} else {
/* if the result is used in the next
ifx conditional branch then generate
code a little differently */
- if (ifx )
- genIfxJump (ifx,"c");
+ if (ifx)
+ genIfxJump(ifx, swap_sense ? "nc" : "c");
else
- outBitC(result);
+ outBitCLong(result, swap_sense);
/* leave the result in acc */
}
}
retype =getSpec(operandType(right));
sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
/* assign the amsops */
- aopOp (left,ic,FALSE);
- aopOp (right,ic,FALSE);
- aopOp (result,ic,TRUE);
+ aopOp (left,ic,FALSE, FALSE);
+ aopOp (right,ic,FALSE, FALSE);
+ aopOp (result,ic,TRUE, FALSE);
genCmp(right, left, result, ifx, sign);
sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
/* assign the amsops */
- aopOp (left,ic,FALSE);
- aopOp (right,ic,FALSE);
- aopOp (result,ic,TRUE);
+ aopOp (left,ic,FALSE, FALSE);
+ aopOp (right,ic,FALSE, FALSE);
+ aopOp (result,ic,TRUE, FALSE);
genCmp(left, right, result, ifx, sign);
else {
emitcode("or", "a,a");
}
- emitcode("jp", "nz," LABEL_STR, lbl->key+100);
+ emit2("jp nz,!tlabel", lbl->key+100);
}
else {
while (size--) {
emitcode("or", "a,a");
else
emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
- emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+ emit2("jp nz,!tlabel", lbl->key+100);
offset++;
}
}
if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
/* PENDING */
- emitcode("jp","nz," LABEL_STR ,lbl->key+100);
+ emit2("jp nz,!tlabel", lbl->key+100);
else {
emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
- emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+ emit2("jp nz,!tlabel", lbl->key+100);
}
offset++;
}
while(size--) {
MOVA(aopGet(AOP(right),offset,FALSE));
emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
- emitcode("jr", "nz," LABEL_STR, lbl->key+100);
+ emit2("!shortjp nz,!tlabel", lbl->key+100);
offset++;
}
}
gencjneshort(left, right, lbl);
/* PENDING: ?? */
- emitcode("ld","a,%s",one);
- emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
+ emit2("ld a,!one");
+ emit2("!shortjp !tlabel", tlbl->key+100);
emitLabel(lbl->key+100);
emitcode("xor","a,a");
emitLabel(tlbl->key+100);
{
operand *left, *right, *result;
- aopOp((left=IC_LEFT(ic)),ic,FALSE);
- aopOp((right=IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
+ aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
+ aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
/* Swap operands if it makes the operation easier. ie if:
1. Left is a literal.
tlbl = newiTempLabel(NULL);
gencjneshort(left, right, tlbl);
if ( IC_TRUE(ifx) ) {
- emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
+ emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
emitLabel(tlbl->key+100);
} else {
/* PENDING: do this better */
symbol *lbl = newiTempLabel(NULL);
- emitcode(_shortJP, LABEL_STR ,lbl->key+100);
- emitLabel(tlbl->key+100);
- emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
+ emit2("!shortjp !tlabel", lbl->key+100);
+ emitLabel(tlbl->key+100);
+ emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
emitLabel(lbl->key+100);
}
}
/* note here that && operations that are in an if statement are
taken away by backPatchLabels only those used in arthmetic
operations remain */
- aopOp((left=IC_LEFT(ic)),ic,FALSE);
- aopOp((right=IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,FALSE);
+ aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
+ aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+ aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
/* if both are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
} else {
tlbl = newiTempLabel(NULL);
toBoolean(left);
- emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
+ emit2("!shortjp z,!tlabel", tlbl->key+100);
toBoolean(right);
emitLabel(tlbl->key+100);
outBitAcc(result);
/* note here that || operations that are in an
if statement are taken away by backPatchLabels
only those used in arthmetic operations remain */
- aopOp((left=IC_LEFT(ic)),ic,FALSE);
- aopOp((right=IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,FALSE);
+ aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
+ aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+ aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
/* if both are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
} else {
tlbl = newiTempLabel(NULL);
toBoolean(left);
- emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
toBoolean(right);
emitLabel(tlbl->key+100);
outBitAcc(result);
// ugly but optimized by peephole
if(IC_TRUE(ic)){
symbol *nlbl = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR, nlbl->key+100);
+ emit2("jp !tlabel", nlbl->key+100);
emitLabel(tlbl->key+100);
- emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
+ emit2("jp !tlabel", IC_TRUE(ic)->key+100);
emitLabel(nlbl->key+100);
}
else{
- emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
+ emit2("jp !tlabel", IC_FALSE(ic)->key+100);
emitLabel(tlbl->key+100);
}
ic->generated = 1;
unsigned long lit = 0L;
int bytelit = 0;
- aopOp((left = IC_LEFT(ic)),ic,FALSE);
- aopOp((right= IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+ aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
+ aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
#ifdef DEBUG_TYPE
emitcode("","; Type res[%d] = l[%d]&r[%d]",
if(bytelit != 0x0FFL)
emitcode("and","a,%s",
aopGet(AOP(right),offset,FALSE));
- emitcode("jr","nz, %05d$",tlbl->key+100);
+ else
+ /* For the flags */
+ emit2("or a,a");
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
}
}
offset++;
// bit = left & literal
if (size){
emitcode("clr","c");
- emitcode("","%05d$:",tlbl->key+100);
+ emit2("!tlabeldef", tlbl->key+100);
}
// if(left & literal)
else{
MOVA(aopGet(AOP(left),offset,FALSE));
emitcode("and","a,%s",
aopGet(AOP(right),offset,FALSE));
- emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
+ aopPut(AOP(left), "a", offset);
}
}
wassert(0);
}
else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("and","%s,a",
- aopGet(AOP(left),offset,FALSE));
+ MOVA(aopGet(AOP(left),offset,FALSE));
+ emitcode("and","a,%s",
+ aopGet(AOP(right),offset,FALSE));
+ aopPut(AOP(left), "a", offset);
}
}
}
if (AOP_TYPE(left) == AOP_ACC)
emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
else {
- MOVA(aopGet(AOP(right),offset,FALSE));
+ MOVA(aopGet(AOP(left),offset,FALSE));
emitcode("and","a,%s",
- aopGet(AOP(left),offset,FALSE));
+ aopGet(AOP(right),offset,FALSE));
}
aopPut(AOP(result),"a",offset);
}
int size, offset=0;
unsigned long lit = 0L;
- aopOp((left = IC_LEFT(ic)),ic,FALSE);
- aopOp((right= IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+ aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
+ aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
#if 1
emitcode("","; Type res[%d] = l[%d]&r[%d]",
if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
continue;
else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("or","a,%s; 5",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a ; 8", offset);
+ MOVA(aopGet(AOP(left),offset,FALSE));
+ emitcode("or","a,%s",
+ aopGet(AOP(right),offset,FALSE));
+ aopPut(AOP(result),"a", offset);
}
} else {
if (AOP_TYPE(left) == AOP_ACC)
- emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
+ emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("or","a,%s ; 7",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a ; 8", offset);
+ MOVA(aopGet(AOP(left),offset,FALSE));
+ emitcode("or","a,%s",
+ aopGet(AOP(right),offset,FALSE));
+ aopPut(AOP(result),"a", offset);
}
}
}
if (AOP_TYPE(left) == AOP_ACC)
emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
else {
- MOVA(aopGet(AOP(right),offset,FALSE));
+ MOVA(aopGet(AOP(left),offset,FALSE));
emitcode("or","a,%s",
- aopGet(AOP(left),offset,FALSE));
+ aopGet(AOP(right),offset,FALSE));
}
aopPut(AOP(result),"a",offset);
/* PENDING: something weird is going on here. Add exception. */
int size, offset=0;
unsigned long lit = 0L;
- aopOp((left = IC_LEFT(ic)),ic,FALSE);
- aopOp((right= IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+ aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
+ aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
/* if left is a literal & right is not then exchange them */
if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
operand *result, int offr,
int shCount, int sign)
{
- if(sameRegs(AOP(result), AOP(left)) &&
- ((offl + MSB16) == offr)){
- wassert(0);
- } else {
- movLeft2Result(left, offl, result, offr, 0);
- movLeft2Result(left, offl+1, result, offr+1, 0);
- }
+ movLeft2Result(left, offl, result, offr, 0);
+ movLeft2Result(left, offl+1, result, offr+1, 0);
if (sign) {
wassert(0);
symbol *tlbl , *tlbl1;
char *l;
+ tlbl = newiTempLabel(NULL);
+ tlbl1 = newiTempLabel(NULL);
+
/* Left is already in result - so now do the shift */
if (shCount>1) {
- emitcode("ld","a,#%u+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
- emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
+ emit2("ld a,!immedbyte+1", shCount);
+ emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
}
if (shCount>1) {
emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
}
}
}
symbol *tlbl , *tlbl1;
char *l;
+ tlbl = newiTempLabel(NULL);
+ tlbl1 = newiTempLabel(NULL);
+
/* Left is already in result - so now do the shift */
if (shCount>1) {
- emitcode("ld","a,#%u+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
- emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
+ emit2("ld a,!immedbyte+1", shCount);
+ emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
}
if (shCount>1) {
emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
}
}
}
/*-----------------------------------------------------------------*/
static void AccLsh (int shCount)
{
- if(shCount != 0){
- if(shCount == 1)
- emitcode("add","a,a");
- else
- if(shCount == 2) {
- emitcode("add","a,a");
+ if(shCount != 0) {
+ if(shCount == 1) {
emitcode("add","a,a");
- } else {
- /* rotate left accumulator */
- AccRol(shCount);
- /* and kill the lower order bits */
- emitcode("and","a,#0x%02x", SLMask[shCount]);
- }
+ }
+ else if(shCount == 2) {
+ emitcode("add","a,a");
+ emitcode("add","a,a");
+ } else {
+ /* rotate left accumulator */
+ AccRol(shCount);
+ /* and kill the lower order bits */
+ emit2("and a,!immedbyte", SLMask[shCount]);
+ }
}
}
/* if shCount >= 8 */
if (shCount >= 8) {
shCount -= 8 ;
-
if (size > 1){
if (shCount) {
movLeft2Result(left, LSB, result, MSB16, 0);
aopPut(AOP(result),zero, 0);
- shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+ shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
}
else {
movLeft2Result(left, LSB, result, MSB16, 0);
aopPut(AOP(result),zero, 0);
}
}
- aopPut(AOP(result),zero,LSB);
+ else {
+ aopPut(AOP(result),zero,LSB);
+ }
}
/* 1 <= shCount <= 7 */
else {
freeAsmop(right,NULL,ic);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ aopOp(left,ic,FALSE, FALSE);
+ aopOp(result,ic,FALSE, FALSE);
size = getSize(operandType(result));
left = IC_LEFT(ic);
result = IC_RESULT(ic);
- aopOp(right,ic,FALSE);
+ aopOp(right,ic,FALSE, FALSE);
/* if the shift count is known then do it
as efficiently as possible */
emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
emitcode("inc","a");
freeAsmop (right,NULL,ic);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ aopOp(left,ic,FALSE, FALSE);
+ aopOp(result,ic,FALSE, FALSE);
/* now move the left to the result if they are not the
same */
offset = 0 ;
tlbl1 = newiTempLabel(NULL);
- emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
+ emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
l = aopGet(AOP(result),offset,FALSE);
emitcode("or", "a,a");
}
emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
freeAsmop(left,NULL,ic);
freeAsmop(result,NULL,ic);
}
/*-----------------------------------------------------------------*/
-/* genlshTwo - left shift two bytes by known amount != 0 */
+/* genrshOne - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
static void genrshOne (operand *result,operand *left, int shCount)
{
static void AccRsh (int shCount)
{
if(shCount != 0){
- if(shCount == 1){
- CLRC;
- emitcode("rr","a");
- } else {
- /* rotate right accumulator */
- AccRol(8 - shCount);
- /* and kill the higher order bits */
- emitcode("and","a,#0x%02x", SRMask[shCount]);
- }
+ /* rotate right accumulator */
+ AccRol(8 - shCount);
+ /* and kill the higher order bits */
+ emit2("and a,!immedbyte", SRMask[shCount]);
}
}
{
/* if shCount >= 8 */
if (shCount >= 8) {
- shCount -= 8 ;
+ shCount -= 8;
if (shCount) {
- wassert(0);
shiftR1Left2Result(left, MSB16, result, LSB,
shCount, sign);
}
else {
movLeft2Result(left, MSB16, result, LSB, sign);
- aopPut(AOP(result),zero,1);
}
+ aopPut(AOP(result),zero,1);
}
/* 1 <= shCount <= 7 */
else {
freeAsmop(right,NULL,ic);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ aopOp(left,ic,FALSE, FALSE);
+ aopOp(result,ic,FALSE, FALSE);
size = getSize(operandType(result));
left = IC_LEFT(ic);
result = IC_RESULT(ic);
- aopOp(right,ic,FALSE);
+ aopOp(right,ic,FALSE, FALSE);
/* if the shift count is known then do it
as efficiently as possible */
return;
}
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ aopOp(left,ic,FALSE, FALSE);
+ aopOp(result,ic,FALSE, FALSE);
/* now move the left to the result if they are not the
same */
size = AOP_SIZE(result);
offset = size - 1;
- emitcode(_shortJP, LABEL_STR, tlbl1->key+100);
- emitcode("", LABEL_STR ":", tlbl->key+100);
+ emit2("!shortjp !tlabel", tlbl1->key+100);
+ emitLabel(tlbl->key+100);
while (size--) {
l = aopGet(AOP(result),offset--,FALSE);
if (first) {
else
emitcode("rr", "%s", l);
}
- emitcode("", LABEL_STR ":", tlbl1->key+100);
+ emitLabel(tlbl1->key+100);
emitcode("dec", "a");
- emitcode(_shortJP, "nz," LABEL_STR, tlbl->key+100);
+ emit2("!shortjp nz,!tlabel", tlbl->key+100);
freeAsmop(left,NULL,ic);
freeAsmop(result,NULL,ic);
}
/*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space */
+/* genGenPointerGet - get value from generic pointer space */
/*-----------------------------------------------------------------*/
static void genGenPointerGet (operand *left,
operand *result, iCode *ic)
if (IS_GB)
pair = PAIR_DE;
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ aopOp(left,ic,FALSE, FALSE);
+ aopOp(result,ic,FALSE, FALSE);
if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
/* Just do it */
if (isPtrPair(AOP(left)))
{
- sprintf(buffer, "(%s)", getPairName(AOP(left)));
+ tsprintf(buffer, "!*pair", getPairName(AOP(left)));
aopPut(AOP(result), buffer, 0);
}
else {
- emitcode("ld", "a,(%s)", getPairName(AOP(left)));
+ emit2("ld a,!*pair", getPairName(AOP(left)));
aopPut(AOP(result),"a", 0);
}
freeAsmop(left,NULL,ic);
while (size--) {
/* PENDING: make this better */
if (!IS_GB && AOP(result)->type == AOP_REG) {
- aopPut(AOP(result),"(hl)",offset++);
+ aopPut(AOP(result), "!*hl", offset++);
}
else {
- emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
+ emit2("ld a,!*pair", _pairs[pair].name);
aopPut(AOP(result),"a",offset++);
}
if (size) {
- emitcode("inc", "%s", _pairs[pair].name);
+ emit2("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
}
}
}
link *retype = getSpec(operandType(right));
PAIR_ID pairId = PAIR_HL;
- aopOp(result,ic,FALSE);
- aopOp(right,ic,FALSE);
+ aopOp(result,ic,FALSE, FALSE);
+ aopOp(right,ic,FALSE, FALSE);
if (IS_GB)
pairId = PAIR_DE;
char *l = aopGet(AOP(right), 0, FALSE);
const char *pair = getPairName(AOP(result));
if (canAssignToPtr(l) && isPtr(pair)) {
- emitcode("ld", "(%s),%s", pair, l);
+ emit2("ld !*pair,%s", pair, l);
}
else {
MOVA(l);
- emitcode("ld", "(%s),a ; 1", pair);
+ emit2("ld !*pair,a", pair);
}
goto release;
}
while (size--) {
char *l = aopGet(AOP(right),offset,FALSE);
if (isRegOrLit(AOP(right)) && !IS_GB) {
- emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
+ emit2("ld !*pair,%s", _pairs[pairId].name, l);
}
else {
MOVA(l);
- emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
+ emit2("ld !*pair,a", _pairs[pairId].name);
}
if (size) {
emitcode("inc", _pairs[pairId].name);
+ _G.pairs[pairId].offset++;
}
offset++;
}
operand *cond = IC_COND(ic);
int isbit =0;
- aopOp(cond,ic,FALSE);
+ aopOp(cond,ic,FALSE, TRUE);
/* get the value into acc */
if (AOP_TYPE(cond) != AOP_CRY)
{
symbol *sym = OP_SYMBOL(IC_LEFT(ic));
- aopOp(IC_RESULT(ic),ic,FALSE);
+ aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
/* if the operand is on the stack then we
need to get the stack offset of this
if (IS_GB) {
if (sym->onStack) {
spillCached();
- emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _G.stack.pushed, _G.stack.offset);
+ if (sym->stack <= 0) {
+ emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+ }
+ else {
+ emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+ }
emitcode("ld", "d,h");
emitcode("ld", "e,l");
}
else {
- emitcode("ld", "de,#%s", sym->rname);
+ emit2("ld de,!hashedstr", sym->rname);
}
aopPut(AOP(IC_RESULT(ic)), "e", 0);
aopPut(AOP(IC_RESULT(ic)), "d", 1);
}
#endif
- aopOp(right,ic,FALSE);
- aopOp(result,ic,TRUE);
+ aopOp(right,ic,FALSE, FALSE);
+ aopOp(result,ic,TRUE, FALSE);
/* if they are the same registers */
if (sameRegs(AOP(right),AOP(result))) {
if(AOP_TYPE(right) == AOP_LIT)
lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
- if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
- emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
+ if (isPair(AOP(result))) {
+ fetchPair(getPairId(AOP(result)), AOP(right));
}
else if((size > 1) &&
(AOP_TYPE(result) != AOP_REG) &&
aopPut(AOP(result),"a",offset);
}
else {
- aopPut(AOP(result), "#0", offset);
+ aopPut(AOP(result), zero, offset);
}
}
else
offset++;
}
}
- else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
+ else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
/* 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), "e", 1);
} else {
while (size--) {
- aopPut(AOP(result),
- aopGet(AOP(right),offset,FALSE),
- offset);
+ /* PENDING: do this check better */
+ if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
+ MOVA(aopGet(AOP(right), offset, FALSE));
+ aopPut(AOP(result), "a", offset);
+ }
+ else
+ aopPut(AOP(result),
+ aopGet(AOP(right),offset,FALSE),
+ offset);
offset++;
}
}
symbol *jtab;
char *l;
- aopOp(IC_JTCOND(ic),ic,FALSE);
+ aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
/* get the condition into accumulator */
l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
- MOVA(l);
if (!IS_GB)
emitcode("push", "de");
emitcode("ld", "e,%s", l);
- emitcode("ld", "d,#0");
+ emit2("ld d,!zero");
jtab = newiTempLabel(NULL);
spillCached();
- emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
+ emit2("ld hl,!immed!tlabel", jtab->key+100);
emitcode("add", "hl,de");
emitcode("add", "hl,de");
emitcode("add", "hl,de");
freeAsmop(IC_JTCOND(ic),NULL,ic);
if (!IS_GB)
emitcode("pop", "de");
- emitcode("jp", "(hl)");
+ emit2("jp !*hl");
emitLabel(jtab->key+100);
/* now generate the jump labels */
for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
jtab = setNextItem(IC_JTLABELS(ic)))
- emitcode("jp", LABEL_STR, jtab->key+100);
+ emit2("jp !tlabel", jtab->key+100);
}
/*-----------------------------------------------------------------*/
if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
return ;
- aopOp(right,ic,FALSE) ;
- aopOp(result,ic,FALSE);
+ aopOp(right,ic,FALSE, FALSE);
+ aopOp(result,ic,FALSE, FALSE);
/* if the result is a bit */
if (AOP_TYPE(result) == AOP_CRY) {
wassert(0);
} else {
accInUse++;
- aopOp(IC_RESULT(ic),ic,FALSE);
+ aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
accInUse--;
assignResultValue(IC_RESULT(ic));
}
if (IS_GB) {
_fReturn = _gbz80_return;
_fTmp = _gbz80_return;
- _shortJP = "jr";
}
else {
_fReturn = _z80_return;
_fTmp = _z80_return;
- _shortJP = "jp";
}
+ tsprintf(zero, "!zero");
lineHead = lineCurr = NULL;
if (!options.nopeep)
peepHole (&lineHead);
+ /* This is unfortunate */
/* now do the actual printing */
- printLine (lineHead,codeOutFile);
- return;
+ {
+ FILE *fp = codeOutFile;
+ if (isInHome() && codeOutFile == code->oFile)
+ codeOutFile = home->oFile;
+ printLine (lineHead, codeOutFile);
+ if (_G.flush_statics) {
+ flushStatics();
+ _G.flush_statics = 0;
+ }
+ codeOutFile = fp;
+ }
}