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)
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 ;
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;
-static int _pushed = 0;
-static int _spoffset;
-
#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);
+
+static char *_strdup(const char *s)
+{
+ char *ret;
+ ALLOC_ATOMIC(ret, strlen(s)+1);
+ strcpy(ret, s);
+ return ret;
+}
+
/*-----------------------------------------------------------------*/
/* emitcode - writes the code into a file : for now it is simple */
/*-----------------------------------------------------------------*/
va_end(ap);
}
+typedef struct {
+ const char *szName;
+ const char *szFormat;
+} TOKEN;
+
+static TOKEN _tokens[] = {
+ { "area", ".area %s" },
+ { "global", ".globl %s" },
+ { "labeldef", "%s::" },
+ { "tlabeldef", "%05d$:" },
+ { "fileprelude", "; Generated using the default tokens." },
+ { "functionheader",
+ "; ---------------------------------\n"
+ "; Function %s\n"
+ "; ---------------------------------"
+ },
+ { "functionlabeldef", "%s:" },
+ { "pusha",
+ "\tpush af\n"
+ "\tpush bc\n"
+ "\tpush de\n"
+ "\tpush hl"
+ },
+ { "di", "\tdi" },
+ { "adjustsp", "\tlda sp,-%d(sp)" },
+ { "prelude", "\tpush bc" },
+ { "leave",
+ "\tpop bc\n"
+ "\tret"
+ },
+ { "leavex",
+ "\tlda sp,%d(sp)\n"
+ "\tpop bc\n"
+ "\tret"
+ },
+ { "hli", "(hl+) ; 2" },
+ { "*hl", "(hl) ; 1" },
+ { "ldahlsp", "lda hl,%d(sp)" },
+ { "ldaspsp", "lda sp,%d(sp)" },
+};
+
+/* 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");
+ }
+}
+*/
+
+#define NUM_TOKENS (sizeof(_tokens)/sizeof(_tokens[0]))
+
+static const TOKEN *_findToken(const char *szName)
+{
+ int i;
+ for (i=0; i < NUM_TOKENS; i++) {
+ if (!strcmp(_tokens[i].szName, szName))
+ return _tokens + i;
+ }
+ return NULL;
+}
+
+static va_list _iprintf(char *pInto, const char *szFormat, va_list ap)
+{
+ char *pStart = pInto;
+ char *sz = _strdup(szFormat);
+
+ while (*sz) {
+ if (*sz == '%') {
+ switch (*++sz) {
+ /* See if it's a special emitter */
+ case 'r':
+ wassert(0);
+ break;
+ default:
+ {
+ /* Scan out the arg and pass it on to sprintf */
+ char *p = sz-1, tmp;
+ while (isdigit(*sz))
+ sz++;
+ /* Skip the format */
+ tmp = *++sz;
+ *sz = '\0';
+ vsprintf(pInto, p, ap);
+ /* PENDING: Assume that the arg length was an int */
+ va_arg(ap, int);
+ *sz = tmp;
+ }
+ }
+ pInto = pStart + strlen(pStart);
+ }
+ else {
+ *pInto++ = *sz++;
+ }
+ }
+ *pInto = '\0';
+
+ return ap;
+}
+
+static void vtprintf(char *buffer, const char *szFormat, va_list ap)
+{
+ char *sz = _strdup(szFormat);
+ char *pInto = buffer, *p;
+
+ buffer[0] = '\0';
+
+ while (*sz) {
+ if (*sz == '!') {
+ /* Start of a token. Search until the first
+ [non alplha, *] and call it a token. */
+ char old;
+ const TOKEN *t;
+ p = ++sz;
+ while (isalpha(*sz) || *sz == '*') {
+ sz++;
+ }
+ old = *sz;
+ *sz = '\0';
+ /* Now find the token in the token list */
+ if ((t = _findToken(p))) {
+ ap = _iprintf(pInto, t->szFormat, ap);
+ pInto = buffer + strlen(buffer);
+ }
+ else {
+ printf("Cant find token \"%s\"\n", p);
+ wassert(0);
+ }
+ }
+ else {
+ *pInto++ = *sz++;
+ }
+ }
+ *pInto = '\0';
+}
+
+static void tprintf(char *buffer, const char *szFormat, ...)
+{
+ va_list ap;
+
+ va_start(ap, szFormat);
+ vtprintf(buffer, szFormat, ap);
+}
+
+static void emit2(const char *szFormat, ...)
+{
+ char buffer[256];
+ va_list ap;
+
+ va_start(ap, szFormat);
+
+ vtprintf(buffer, szFormat, ap);
+
+ lineCurr = (lineCurr ?
+ connectLine(lineCurr,newLineNode(buffer)) :
+ (lineHead = newLineNode(buffer)));
+
+ lineCurr->isInline = inLine;
+ lineCurr->isDebug = debugLine;
+}
+
const char *getPairName(asmop *aop)
{
if (aop->type == AOP_REG) {
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));
}
+
/*-----------------------------------------------------------------*/
/* 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)) {
return aop;
}
}
+#endif
/* only remaining is far space */
/* in which case DPTR gets the address */
- sym->aop = aop = newAsmop(AOP_IY);
- if (!IS_GB)
- emitcode ("ld","iy,#%s ; a", 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->freed = 1;
- switch (aop->type) {
- case AOP_STK :
- break;
- }
-
dealloc:
/* all other cases just dealloc */
if (op ) {
}
}
-char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
+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;
- if (aop->size != 2)
+#if 0
+ if (aop->size != 2 && aop->type != AOP_HL)
return NULL;
- assert(offset == 0);
+#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);
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 */
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 aopGetWordLong(aop, offset, TRUE);
+ 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 fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
+{
+ /* if this is remateriazable */
+ if (isLitWord(aop)) {
+ fetchLitPair(pairId, aop, offset);
+ }
+ else { /* we need to get it byte by byte */
+ if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
+ aopGet(aop, offset, FALSE);
+ emit2("ld a,!hli");
+ emit2("ld h,!*hl");
+ emit2("ld l,a");
+ }
+ else {
+ emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
+ emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
+ }
+ /* PENDING: check? */
+ if (pairId == PAIR_HL)
+ spillPair(PAIR_HL);
+ }
+}
+
+static void fetchPair(PAIR_ID pairId, asmop *aop)
+{
+ fetchPairLong(pairId, aop, 0);
+}
+
+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 {
+ emit2("!ldahlsp", 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)
+{
+ emit2("!tlabeldef yeah?", 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(IS_GB);
+ wassert(IS_GB);
emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
sprintf(s, "a");
ALLOC_ATOMIC(rs,strlen(s)+1);
case AOP_REG:
return aop->aopu.aop_reg[offset]->name;
+ case AOP_HL:
+ wassert(IS_GB);
+ emitcode("", ";3");
+ setupPair(PAIR_HL, aop, offset);
+ tprintf(s, "!*hl");
+ return _strdup(s);
+
case AOP_IY:
- sprintf(s,"%d(iy)", offset);
+ wassert(IS_Z80);
+ setupPair(PAIR_IY, aop, offset);
+ tprintf(s,"!*iyx", offset);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
case AOP_STK:
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)");
+ setupPair(PAIR_HL, aop, offset);
+ tprintf(s, "!*hl");
}
else {
- sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+ tprintf(s,"!*ixx", 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 == '#');
}
switch (aop->type) {
case AOP_DIR:
/* Direct. Hmmm. */
- assert(IS_GB);
+ wassert(IS_GB);
emitcode("ld", "a,%s", s);
emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
break;
break;
case AOP_IY:
- assert(!IS_GB);
+ 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 (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);
+ setupPair(PAIR_HL, aop, offset);
if (!canAssignToPtr(s)) {
emitcode("ld", "a,%s", s);
emitcode("ld", "(hl),a");
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);
}
}
}
/* 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);
}
-static bool requiresHL(asmop *aop)
-{
- switch (aop->type) {
- case AOP_STK:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
/*-----------------------------------------------------------------*/
/* assignResultValue - */
/*-----------------------------------------------------------------*/
void assignResultValue(operand * oper)
{
- int offset = 0;
int size = AOP_SIZE(oper);
+ bool topInA = 0;
- assert(size <= 2);
-
- while (size--) {
- aopPut(AOP(oper),_fReturn[offset],offset);
- offset++;
- }
-}
+ wassert(size <= 4);
+ topInA = requiresHL(AOP(oper));
-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");
+ if (!IS_GB)
+ wassert(size <= 2);
+ if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
+ /* We do it the hard way here. */
+ emitcode("push", "hl");
+ _G.stack.pushed += 2;
+ aopPut(AOP(oper), _fReturn[0], 0);
+ aopPut(AOP(oper), _fReturn[1], 1);
+ emitcode("pop", "de");
+ _G.stack.pushed -= 2;
+ aopPut(AOP(oper), _fReturn[0], 2);
+ aopPut(AOP(oper), _fReturn[1], 3);
}
else {
- emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
- emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
+ while (size--) {
+ aopPut(AOP(oper), _fReturn[size], size);
+ }
}
}
/* push it on the stack */
if (isPair(AOP(IC_LEFT(ic)))) {
emitcode("push", getPairName(AOP(IC_LEFT(ic))));
- _pushed += 2;
+ _G.stack.pushed += 2;
}
else {
offset = size;
emitcode("ld", "a,%s", l);
emitcode("push", "af");
emitcode("inc", "sp");
- _pushed++;
+ _G.stack.pushed++;
}
}
return ;
size = AOP_SIZE(IC_LEFT(ic));
if (isPair(AOP(IC_LEFT(ic)))) {
- _pushed+=2;
+ _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");
- _pushed+=2;
- }
- else {
- /* Optimise here - load into HL then push HL */
- fetchHL(AOP(IC_LEFT(ic)));
- emitcode("push", "hl");
- _pushed += 2;
- }
+ 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");
- _pushed++;
+ _G.stack.pushed++;
}
}
release:
while (size--) {
emitcode("dec", "sp");
emitcode("pop", "hl");
+ spillPair(PAIR_HL);
aopPut(AOP(IC_LEFT(ic)), "l", offset--);
}
}
*/
static void emitCall (iCode *ic, bool ispcall)
{
- int isPrintf = 0;
-
/* if caller saves & we have not saved then */
if (!ic->regsSaved) {
/* PENDING */
}
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 */
OP_SYMBOL(IC_LEFT(ic))->rname :
OP_SYMBOL(IC_LEFT(ic))->name;
emitcode("call", "%s", name);
- if (!strcmp(name, "__printf"))
- isPrintf = 1;
-
}
+ 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;
- emitcode("", ";parmBytes = %u\n", i);
- if (isPrintf)
- i+=2;
- _pushed -= i;
- if (i>6) {
- emitcode("ld", "hl,#%d", i);
- emitcode("add", "hl,sp");
- emitcode("ld", "sp,hl");
+ _G.stack.pushed -= i;
+ if (IS_GB) {
+ emit2("!ldaspsp", 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(";","-----------------------------------------");
+ emit2("!functionheader", sym->name);
+ emit2("!functionlabeldef", sym->rname);
- emitcode("","%s:",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");
- }
+ emit2("!prelude");
- _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");
+ emit2("!adjustsp", sym->stack);
}
- _spoffset = sym->stack;
+ _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("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 (_spoffset) {
- emitcode("ld", "hl,#%d", _spoffset);
- emitcode("add", "hl,sp");
- emitcode("ld", "sp,hl");
- }
- }
- emitcode("pop", "bc");
- emitcode("ret", "");
+ if (_G.stack.offset)
+ emit2("!leavex");
+ else
+ emit2("!leave");
}
- _pushed = 0;
- _spoffset = 0;
+ _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 (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
+ fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
+ fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
+ }
+ else {
+ while (size--) {
+ l = aopGet(AOP(IC_LEFT(ic)),offset,
+ FALSE);
+ 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 */
emitcode("", "; genPlusIncr");
icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-
+
/* If result is a pair */
- if (isPair(AOP(IC_RESULT(ic)))) {
- char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
- if (left) {
- /* Both a lit on the right and a true symbol on the left */
- emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
+ 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 ;
+ return FALSE;
- /* Inc a pair */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
- isPair(AOP(IC_RESULT(ic)))) {
- while (icount--) {
- emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
- }
- return TRUE;
- }
/* 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
if (isPair(AOP(IC_RESULT(ic)))) {
char *left, *right;
- left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
- right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
+ 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 */
}
}
+ 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:
emitcode("dec","%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;
}
#endif
/* 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
}
while (size--) {
/* Do a long subtract */
- if (!sign || size)
+ if (!sign || size ) {
MOVA(aopGet(AOP(left),offset,FALSE));
+ }
if (sign && size == 0) {
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 ; 2", aopGet(AOP(left),offset,FALSE));
- if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
+ 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");
- else
- emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
- emitcode("jp", "nz," LABEL_STR , lbl->key+100);
- offset++;
- }
+ }
+ 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 */
/* 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 ; 5", 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);
}
+/*-----------------------------------------------------------------*/
/* genlshTwo - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
static void genrshOne (operand *result,operand *left, int shCount)
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);
/*-----------------------------------------------------------------*/
static void genRightShift (iCode *ic)
{
- operand *left,*right, *result;
+ operand *right, *left, *result;
+ link *retype ;
+ int size, offset, first = 1;
+ char *l;
+ bool is_signed;
+
+ symbol *tlbl, *tlbl1 ;
+
+ /* if signed then we do it the hard way preserve the
+ sign bit moving it inwards */
+ retype = getSpec(operandType(IC_RESULT(ic)));
+
+ is_signed = !SPEC_USIGN(retype);
+
+ /* signed & unsigned types are treated the same : i.e. the
+ signed is NOT propagated inwards : quoting from the
+ ANSI - standard : "for E1 >> E2, is equivalent to division
+ by 2**E2 if unsigned or if it has a non-negative value,
+ otherwise the result is implementation defined ", MY definition
+ is that the sign does not get propagated */
right = IC_RIGHT(ic);
left = IC_LEFT(ic);
/* if the shift count is known then do it
as efficiently as possible */
if (AOP_TYPE(right) == AOP_LIT) {
- genRightShiftLiteral (left,right,result,ic);
- return ;
+ genRightShiftLiteral(left,right,result,ic);
+ return;
}
- else {
- assert(0);
+
+ aopOp(left,ic,FALSE);
+ aopOp(result,ic,FALSE);
+
+ /* now move the left to the result if they are not the
+ same */
+ if (!sameRegs(AOP(left),AOP(result)) &&
+ AOP_SIZE(result) > 1) {
+
+ size = AOP_SIZE(result);
+ offset=0;
+ while (size--) {
+ l = aopGet(AOP(left),offset,FALSE);
+ aopPut(AOP(result),l,offset);
+ offset++;
+ }
+ }
+
+ emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
+ emitcode("inc","a");
+ freeAsmop (right, NULL, ic);
+
+ tlbl = newiTempLabel(NULL);
+ tlbl1= newiTempLabel(NULL);
+ size = AOP_SIZE(result);
+ offset = size - 1;
+
+ emitcode(_shortJP, LABEL_STR, tlbl1->key+100);
+ emitcode("", LABEL_STR ":", tlbl->key+100);
+ while (size--) {
+ l = aopGet(AOP(result),offset--,FALSE);
+ if (first) {
+ if (is_signed)
+ emitcode("sra", "%s", l);
+ else
+ emitcode("srl", "%s", l);
+ first = 0;
+ }
+ else
+ emitcode("rr", "%s", l);
}
+ emitcode("", LABEL_STR ":", tlbl1->key+100);
+ emitcode("dec", "a");
+ emitcode(_shortJP, "nz," LABEL_STR, tlbl->key+100);
+
+ freeAsmop(left,NULL,ic);
+ freeAsmop(result,NULL,ic);
}
/*-----------------------------------------------------------------*/
{
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 */
- fetchHL(AOP(left));
- }
+ 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 */
- fetchHL(AOP(result));
- }
+ 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 */
- if (IS_GB) {
- emitcode("lda", "hl,%d+%d(sp)", sym->stack, _spoffset);
+ if (IS_GB) {
+ if (sym->onStack) {
+ spillCached();
+ emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
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");
+ 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);
-end:
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)) &&
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),
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);
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 */
#if 0
/* if the result is of type pointer */
if (IS_PTR(ctype)) {
- assert(0);
+ wassert(0);
}
#endif
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);
if (IS_GB) {
_fReturn = _gbz80_return;
_fTmp = _gbz80_return;
+ _shortJP = "jr";
}
else {
_fReturn = _z80_return;
_fTmp = _z80_return;
+ _shortJP = "jp";
}
lineHead = lineCurr = NULL;
case GETHBIT:
emitcode("", "; genHBIT");
- assert(0);
+ wassert(0);
case LEFT_OP:
emitcode("", "; genLeftShift");