-/* The only ops for now are:
- genAssign
- genIfx
- genAddrOf
- genPointerSet
-*/
-
/*-------------------------------------------------------------------------
SDCCgen51.c - source file for code generation for 8051
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
- Notes:
- 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
- Made everything static
-------------------------------------------------------------------------*/
//#define D(x)
{
short inLine;
short debugLine;
+ short stackExtend;
short nRegsSaved;
+ short parmsPushed;
set *sendSet;
}
_G;
#define MSB24 2
#define MSB32 3
+static char *MOV="mov";
+static char *MOVB="mov.b";
+static char *MOVW="mov.w";
+static char *MOVC="movc";
+static char *MOVCB="movc.b";
+static char *MOVCW="movc.w";
+
+static char *R1L="r1l";
+static char *R1="r1";
+
void bailOut (char *mesg) {
fprintf (stderr, "%s: bailing out\n", mesg);
exit (1);
va_end (ap);
}
+char *getStackOffset(int stack) {
+ static char gsoBuf[1024];
+ sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
+ currFunc->stack, _G.nRegsSaved);
+ return gsoBuf;
+}
+
/*-----------------------------------------------------------------*/
/* newAsmop - creates a new asmOp */
/*-----------------------------------------------------------------*/
case AOP_DIR: return "dir";
case AOP_FAR: return "far";
case AOP_CODE: return "code";
+ case AOP_GPTR: return "gptr";
case AOP_STK: return "stack";
case AOP_IMMD: return "imm";
- case AOP_CRY: return "bit";
+ case AOP_BIT: return "bit";
}
return "unknown";
}
/*-----------------------------------------------------------------*/
/* aopForSym - for a true symbol */
/*-----------------------------------------------------------------*/
-static asmop *aopForSym(symbol *sym, bool result) {
+static asmop *aopForSym(symbol *sym,
+ bool canUsePointer, bool canUseOffset) {
+ int size;
asmop *aop;
sym->aop = aop = newAsmop(0);
- aop->size=getSize(sym->type);
+ size=aop->size=getSize(sym->type);
- // if it is in registers
+ // if the sym has registers
if (sym->nRegs && sym->regs[0]) {
aop->type=AOP_REG;
sprintf (aop->name[0], sym->regs[0]->name);
- if (sym->regs[1]) {
+ if (size > 2) {
sprintf (aop->name[1], sym->regs[1]->name);
}
return aop;
// if it is on stack
if (sym->onStack) {
+ if (!canUsePointer || !canUseOffset) {
+ aop->type=AOP_REG;
+ switch (size)
+ {
+ case 1:
+ emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
+ sprintf (aop->name[0], "r0l");
+ return aop;
+ case 2:
+ emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
+ sprintf (aop->name[0], "r0");
+ return aop;
+ case 3:
+ emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
+ sprintf (aop->name[0], "r0");
+ emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
+ sprintf (aop->name[1], "r1l");
+ return aop;
+ case 4:
+ emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
+ sprintf (aop->name[0], "r0");
+ emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
+ sprintf (aop->name[1], "r1");
+ return aop;
+ }
+ }
aop->type=AOP_STK;
- sprintf (aop->name[0], "[r7%+d+0%+d%+d]", sym->stack,
- FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
- if (aop->size > 2) {
- sprintf (aop->name[1], "[r7%+d+2%+d%+d]", sym->stack,
- FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+ sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
+ if (size > 2) {
+ sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
}
return aop;
}
// if it has a spillLoc
if (sym->usl.spillLoc) {
- return aopForSym (sym->usl.spillLoc, result);
+ return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
}
// if in bit space
if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
- aop->type=AOP_CRY;
+ aop->type=AOP_BIT;
sprintf (aop->name[0], sym->rname);
return aop;
}
if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
aop->type=AOP_DIR;
sprintf (aop->name[0], sym->rname);
+ if (size>2) {
+ sprintf (aop->name[1], "%s+2", sym->rname);
+ }
return aop;
}
// if in code space
if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
- if (result) {
- fprintf (stderr, "aopForSym: result can not be in code space\n");
- exit (1);
+ if (!canUsePointer) {
+ aop->type=AOP_REG;
+ switch (size)
+ {
+ case 1:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOVC, "r0l,[r0]");
+ sprintf (aop->name[0], "r0l");
+ return aop;
+ case 2:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOVC, "r0,[r0]");
+ sprintf (aop->name[0], "r0");
+ return aop;
+ case 3:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOVC, "r1l,[r0+2]");
+ sprintf (aop->name[1], "r1l");
+ emitcode (MOV, "r0,[r0]");
+ sprintf (aop->name[0], "r0");
+ return aop;
+ case 4:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOVC, "r1,[r0+2]");
+ sprintf (aop->name[1], "r1");
+ emitcode (MOVC, "r0,[r0]");
+ sprintf (aop->name[0], "r0");
+ return aop;
+ }
+
+ } else {
+ aop->type=AOP_CODE;
+ emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
+ sprintf (aop->name[0], "[r0]");
+ if (size>2) {
+ sprintf (aop->name[1], "[r0+2]");
+ }
}
- aop->type=AOP_CODE;
- emitcode ("mov", "r0,#%s", sym->rname);
- sprintf (aop->name[0], "r0");
return aop;
}
// if in far space
if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
- aop->type=AOP_FAR;
- emitcode ("mov", "r0,#%s", sym->rname);
- sprintf (aop->name[0], "r0");
- return aop;
+ if (!canUsePointer) {
+ aop->type=AOP_REG;
+ switch (size)
+ {
+ case 1:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOV, "r0l,[r0]");
+ sprintf (aop->name[0], "r0l");
+ return aop;
+ case 2:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOV, "r0,[r0]");
+ sprintf (aop->name[0], "r0");
+ return aop;
+ case 3:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOV, "r1l,[r0+2]");
+ sprintf (aop->name[1], "r1l");
+ emitcode (MOV, "r0,[r0]");
+ sprintf (aop->name[0], "r0");
+ return aop;
+ case 4:
+ emitcode (MOV, "r0,#%s", sym->rname);
+ emitcode (MOV, "r1,[r0+2]");
+ sprintf (aop->name[1], "r1");
+ emitcode (MOV, "r0,[r0]");
+ sprintf (aop->name[0], "r0");
+ return aop;
+ }
+ } else {
+ aop->type=AOP_FAR;
+ emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
+ sprintf (aop->name[0], "[r0]");
+ if (size>2) {
+ sprintf (aop->name[1], "[r0+2]");
+ }
+ return aop;
+ }
}
-
- fprintf (stderr, "aopForSym (%s): What's up?\n", sym->name);
- exit (1);
+
+ bailOut("aopForSym");
+ return NULL;
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static asmop *aopForVal(operand *op) {
asmop *aop;
- long v=(long long)floatFromVal(OP_VALUE(op));
if (IS_OP_LITERAL(op)) {
op->aop = aop = newAsmop (AOP_LIT);
switch ((aop->size=getSize(operandType(op))))
{
case 1:
- sprintf (aop->name[0], "#0x%02lx", v);
+ sprintf (aop->name[0], "#0x%02x",
+ SPEC_CVAL(operandType(op)).v_int & 0xff);
+ sprintf (aop->name[1], "#0");
break;
case 2:
- sprintf (aop->name[0], "#0x%04lx", v);
+ sprintf (aop->name[0], "#0x%04x",
+ SPEC_CVAL(operandType(op)).v_int & 0xffff);
+ sprintf (aop->name[1], "#0");
+ break;
+ case 3:
+ // must be a generic pointer, can only be zero
+ // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
+ sprintf (aop->name[0], "#0x%04x",
+ SPEC_CVAL(operandType(op)).v_uint & 0xffff);
+ sprintf (aop->name[1], "#0");
break;
case 4:
- sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
- sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
+ sprintf (aop->name[0], "#0x%04lx",
+ SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
+ sprintf (aop->name[1], "#0x%04lx",
+ SPEC_CVAL(operandType(op)).v_ulong >> 16);
break;
default:
bailOut("aopForVal");
return aop;
}
}
- fprintf (stderr, "aopForVal: unknown type\n");
- exit (1);
+
+ bailOut ("aopForVal: unknown type");
return NULL;
}
-static void aopOp(operand *op, bool result) {
+static int aopOp(operand *op,
+ bool canUsePointer, bool canUseOffset) {
if (IS_SYMOP(op)) {
- op->aop=aopForSym (OP_SYMBOL(op), result);
- return;
+ op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
+ return AOP_SIZE(op);
}
if (IS_VALOP(op)) {
- if (result) {
- fprintf (stderr, "aopOp: result can not be a value\n");
- exit (1);
- }
- aopForVal (op);
- return;
+ op->aop=aopForVal (op);
+ return AOP_SIZE(op);
}
- fprintf (stderr, "aopOp: unexpected operand\n");
- exit (1);
+ bailOut("aopOp: unexpected operand");
+ return 0;
+}
+
+bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
+ if (strcmp(aop1->name[offset], aop2->name[offset])) {
+ return FALSE;
+ }
+ return TRUE;
}
-char *opRegName(operand *op, int offset, char *opName) {
+bool aopIsDir(operand *op) {
+ return AOP_TYPE(op)==AOP_DIR;
+}
+
+bool aopIsBit(operand *op) {
+ return AOP_TYPE(op)==AOP_BIT;
+}
+
+bool aopIsPtr(operand *op) {
+ if (AOP_TYPE(op)==AOP_STK ||
+ AOP_TYPE(op)==AOP_CODE ||
+ AOP_TYPE(op)==AOP_FAR) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+char *opRegName(operand *op, int offset, char *opName, bool decorate) {
if (IS_SYMOP(op)) {
if (OP_SYMBOL(op)->onStack) {
- sprintf (opName, "[r7%+d+0%+d%+d]", OP_SYMBOL(op)->stack,
- FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+ sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
return opName;
}
if (IS_TRUE_SYMOP(op))
else if (OP_SYMBOL(op)->regs[offset])
return OP_SYMBOL(op)->regs[offset]->name;
else
- return "NULL";
+ bailOut("opRegName: unknown regs");
}
if (IS_VALOP(op)) {
case V_BIT:
if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
- fprintf (stderr, "opRegName: invalid bit value (%d)\n",
- SPEC_CVAL(OP_VALUE(op)->type).v_int);
- exit (1);
+ bailOut("opRegName: invalid bit value");
}
// fall through
case V_CHAR:
- sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
+ sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
+ SPEC_CVAL(OP_VALUE(op)->type).v_int);
break;
case V_INT:
if (SPEC_LONG(OP_VALUE(op)->type)) {
- sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
+ sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
+ SPEC_CVAL(OP_VALUE(op)->type).v_long);
} else {
- sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
+ sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
+ SPEC_CVAL(OP_VALUE(op)->type).v_int);
}
break;
case V_FLOAT:
- sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
+ sprintf (opName, "#%s%f", decorate?"(float)":"",
+ SPEC_CVAL(OP_VALUE(op)->type).v_float);
break;
default:
- fprintf (stderr, "opRegName: unexpected noun\n");
- exit (1);
+ bailOut("opRegName: unexpected noun");
}
return opName;
}
- fprintf (stderr, "opRegName: unexpected operand type\n");
- exit (1);
- return NULL; // to keep the compiler happy
+ bailOut("opRegName: unexpected operand type");
+ return NULL;
}
char * printOp (operand *op) {
sprintf (line+strlen(line), "stack%+d", sym->stack);
return line;
}
+ if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
+ strcat (line, "code");
+ return line;
+ }
if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
strcat (line, "far");
return line;
strcat (line, "unknown");
return line;
} else if (IS_VALOP(op)) {
- opRegName(op, 0, line);
+ opRegName(op, 0, line, 1);
} else if (IS_TYPOP(op)) {
- sprintf (line, "[");
+ sprintf (line, "(");
if (isPtr) {
if (DCL_TYPE(optype)==FPOINTER)
strcat (line, "far * ");
if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
if (SPEC_LONG(operandType(op))) strcat (line, "long ");
strcat (line, nounName(operandType(op)));
- strcat (line, "]");
+ strcat (line, ")");
} else {
- fprintf (stderr, "printOp: unexpected operand type\n");
- exit (1);
+ bailOut("printOp: unexpected operand type");
}
return line;
}
}
/*-----------------------------------------------------------------*/
-/* toBoolean - return bit for operand!=0 */
+/* toBoolean - return carry for operand!=0 */
/*-----------------------------------------------------------------*/
static char *toBoolean (operand * op) {
+ symbol *tlbl=newiTempLabel(NULL);
+
switch (AOP_SIZE(op))
{
case 1:
case 2:
- emitcode ("cmp", "%s,#0", AOP_NAME(op));
- return "z";
+ emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
+ "This needs a second thought");
+
+ emitcode ("", "%05d$:", tlbl->key+100);
+ return "c";
}
- fprintf (stderr, "toBoolean: unknown size %d\n", AOP_SIZE(op));
- exit (1);
+ bailOut("toBoolean: unknown size");
return NULL;
}
}
/*-----------------------------------------------------------------*/
-/* genIpush - genrate code for pushing this gets a little complex */
+/* genIpush - generate code for pushing */
/*-----------------------------------------------------------------*/
static void genIpush (iCode * ic) {
+ operand *left=IC_LEFT(ic);
+
printIc ("genIpush", ic, 0,1,0);
+ aopOp(left,FALSE,FALSE);
+
+
+ if (AOP_TYPE(left)==AOP_LIT) {
+ switch (AOP_SIZE(left))
+ {
+ case 1:
+ emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
+ emitcode ("push", "r1l");
+ _G.parmsPushed++;
+ return;
+ case 2:
+ emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
+ emitcode ("push", "r1");
+ _G.parmsPushed++;
+ return;
+ case 3:
+ emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
+ emitcode ("push", "r1l");
+ emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
+ emitcode ("push", "r1");
+ _G.parmsPushed += 2;
+ return;
+ case 4:
+ emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
+ emitcode ("push", "r1");
+ emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
+ emitcode ("push", "r1");
+ _G.parmsPushed += 2;
+ return;
+ }
+ } else {
+ if (AOP_SIZE(left)>2) {
+ emitcode ("push", "%s", AOP_NAME(left)[1]);
+ _G.parmsPushed++;
+ }
+ emitcode ("push", "%s", AOP_NAME(left)[0]);
+ _G.parmsPushed++;
+ }
}
/*-----------------------------------------------------------------*/
/* genCall - generates a call statement */
/*-----------------------------------------------------------------*/
static void genCall (iCode * ic) {
- emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
+ operand *result=IC_RESULT(ic);
+
+ emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
+ OP_SYMBOL(IC_LEFT(ic))->name,
printOp (IC_RESULT(ic)));
+ emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
+
+ /* readjust the stack if we have pushed some parms */
+ if (_G.parmsPushed) {
+ emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
+ _G.parmsPushed=0;
+ }
+
+ /* if we need to assign a result value */
+ if (IS_ITEMP (IC_RESULT(ic)) &&
+ OP_SYMBOL (IC_RESULT (ic))->nRegs) {
+ aopOp(result,FALSE,FALSE);
+ switch (AOP_SIZE(result))
+ {
+ case 1:
+ emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
+ return;
+ case 2:
+ emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
+ return;
+ case 3:
+ // generic pointer
+ emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
+ emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
+ return;
+ case 4:
+ emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
+ emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
+ return;
+ }
+ bailOut("genCall");
+ }
}
/*-----------------------------------------------------------------*/
symbol *sym=OP_SYMBOL(IC_LEFT(ic));
sym_link *type=sym->type;
- emitcode (";", "-----------------------------------------");
- emitcode (";", " function %s", sym->name);
- emitcode (";", "-----------------------------------------");
-
+ emitcode (";", "genFunction %s", sym->rname);
+
+ /* print the allocation information */
+ printAllocInfo (currFunc, codeOutFile);
+
emitcode ("", "%s:", sym->rname);
if (IFFUNC_ISNAKED(type))
return;
}
- /* if critical function then turn interrupts off */
- if (IFFUNC_ISCRITICAL (type))
- emitcode ("clr", "ea");
-
+ /* adjust the stack for locals used in this function */
+ if (sym->stack) {
+ emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
+ }
}
/*-----------------------------------------------------------------*/
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
- if (IFFUNC_ISNAKED(sym->type))
- {
+ printIc ("genEndFunction", ic, 0,0,0);
+
+ if (IFFUNC_ISNAKED(sym->type)) {
emitcode(";", "naked function: no epilogue.");
return;
}
- printIc ("genEndFunction", ic, 0,0,0);
+ /* readjust the stock for locals used in this function */
+ if (sym->stack) {
+ emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
+ }
+
+ if (IFFUNC_ISISR(sym->type)) {
+ emitcode ("reti", "");
+ } else {
+ emitcode ("ret", "");
+ }
}
/*-----------------------------------------------------------------*/
/* genRet - generate code for return statement */
/*-----------------------------------------------------------------*/
static void genRet (iCode * ic) {
+
printIc ("genRet", ic, 0,1,0);
+
+ aopOp(IC_LEFT(ic), TRUE, TRUE);
+
+ switch (AOP_SIZE(IC_LEFT(ic)))
+ {
+ case 4:
+ emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
+ emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
+ break;
+ case 3:
+ emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
+ // fall through
+ case 2:
+ emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
+ break;
+ case 1:
+ emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
+ break;
+ default:
+ bailOut("genRet");
+ }
+ emitcode ("jmp", "%05d$", returnLabel->key+100);
}
/*-----------------------------------------------------------------*/
if (IC_LABEL (ic) == entryLabel)
return;
- emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
+ emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
}
/*-----------------------------------------------------------------*/
-/* genGoto - generates a ljmp */
+/* genGoto - generates a jmp */
/*-----------------------------------------------------------------*/
static void genGoto (iCode * ic) {
- emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
- emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
+ emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
+ emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
}
/*-----------------------------------------------------------------*/
/* genPlus - generates code for addition */
/*-----------------------------------------------------------------*/
static void genPlus (iCode * ic) {
+ operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
+ int size;
+ char *instr;
+
printIc ("genPlus", ic, 1,1,1);
+
+ size=aopOp(result, TRUE, TRUE);
+
+ /* if left is a literal, then exchange them */
+ if (IS_LITERAL(operandType(left))) {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
+
+ if (aopIsBit(result)) {
+ if (IS_LITERAL(operandType(right))) {
+ if (operandLitValue(right)) {
+ emitcode ("setb", AOP_NAME(result)[0]);
+ return;
+ }
+ aopOp(left, TRUE, TRUE);
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
+ return;
+ }
+ bailOut("genPlus: unfinished genPlus bit");
+ }
+
+ aopOp(left, !aopIsPtr(result), !aopIsDir(result));
+ aopOp(right, !aopIsPtr(result), !aopIsDir(result));
+
+ if (size>1) {
+ instr="add.w";
+ } else {
+ instr="add.b";
+ }
+ if (!aopEqual(result->aop, left->aop, 0)) {
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+ }
+ emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ if (size>2) {
+ if (!aopEqual(result->aop, left->aop, 1)) {
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
+ }
+ if (size==3) {
+ // generic pointer
+ } else {
+ emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+ }
+ }
+ return;
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
/* genCmpGt :- greater than comparison */
/*-----------------------------------------------------------------*/
-static void genCmpGt (iCode * ic, iCode * ifx) {
+static void genCmpGt (iCode * ic) {
printIc ("genCmpGt", ic, 1,1,1);
}
/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison */
+/*-----------------------------------------------------------------*/
+static void genCmpLe (iCode * ic) {
+ printIc ("genCmpLe", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison */
+/*-----------------------------------------------------------------*/
+static void genCmpGe (iCode * ic) {
+ printIc ("genCmpGe", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison */
+/*-----------------------------------------------------------------*/
+static void genCmpNe (iCode * ic) {
+ printIc ("genCmpNe", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
/* genCmpLt - less than comparisons */
/*-----------------------------------------------------------------*/
-static void genCmpLt (iCode * ic, iCode * ifx) {
+static void genCmpLt (iCode * ic) {
printIc ("genCmpLt", ic, 1,1,1);
}
/*-----------------------------------------------------------------*/
/* genCmpEq - generates code for equal to */
/*-----------------------------------------------------------------*/
-static void genCmpEq (iCode * ic, iCode * ifx) {
+static void genCmpEq (iCode * ic) {
printIc ("genCmpEq", ic, 1,1,1);
}
while (lic) {
/* if operand of the form op = op + <sizeof *op> */
- if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
- isOperandEqual(IC_RESULT(lic),op) &&
- isOperandLiteral(IC_RIGHT(lic)) &&
- operandLitValue(IC_RIGHT(lic)) == isize) {
- return lic;
+ if (lic->op == '+') {
+ if (isOperandEqual(IC_LEFT(lic),op) &&
+ //isOperandEqual(IC_RESULT(lic),op) &&
+ isOperandLiteral(IC_RIGHT(lic)) &&
+ operandLitValue(IC_RIGHT(lic)) == isize) {
+ emitcode (";", "Found hasInc");
+ return lic;
+ }
}
/* if the operand used or deffed */
if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
/* genOr - code for or */
/*-----------------------------------------------------------------*/
static void genOr (iCode * ic, iCode * ifx) {
+ operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
+ int size;
+ char *instr;
+
printIc ("genOr", ic, 1,1,1);
+
+ size=aopOp(result, TRUE, TRUE);
+
+ /* if left is a literal, then exchange them */
+ if (IS_LITERAL(operandType(left))) {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
+
+ if (aopIsBit(result)) {
+ if (IS_LITERAL(operandType(right))) {
+ if (operandLitValue(right)) {
+ emitcode ("setb", AOP_NAME(result)[0]);
+ return;
+ }
+ aopOp(left, TRUE, TRUE);
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
+ return;
+ }
+ }
+
+ aopOp(left, !aopIsPtr(result), !aopIsDir(result));
+ aopOp(right, !aopIsPtr(result), !aopIsDir(result));
+
+ if (size>1) {
+ instr="or.w";
+ } else {
+ instr="or.b";
+ }
+ if (!aopEqual(result->aop, left->aop, 0)) {
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+ }
+ emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ if (size>2) {
+ if (!aopEqual(result->aop, left->aop, 1)) {
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
+ }
+ emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+ }
+ return;
}
/*-----------------------------------------------------------------*/
/* genInline - write the inline code out */
/*-----------------------------------------------------------------*/
static void genInline (iCode * ic) {
+
printIc ("genInline", ic, 0,0,0);
+
+ emitcode ("", IC_INLINE(ic));
}
/*-----------------------------------------------------------------*/
/* genPointerGet - generate code for pointer get */
/*-----------------------------------------------------------------*/
static void genPointerGet (iCode * ic, iCode *pi) {
- char *instr="mov";
-
+ char *instr, *scratchReg;
operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
+ bool codePointer=IS_CODEPTR(operandType(left));
+ int size;
printIc ("genPointerGet", ic, 1,1,0);
bailOut ("genPointerGet: pointer required");
}
- aopOp(left,FALSE);
- aopOp(result,TRUE);
+ aopOp(left,FALSE,FALSE);
+ size=aopOp(result,TRUE,aopIsDir(left));
if (IS_GENPTR(operandType(left))) {
- emitcode ("INLINE", "_gptrget %s %s= [%s,%s]",
- AOP_NAME(result)[0], AOP_NAME(result)[1],
- AOP_NAME(left)[0], AOP_NAME(left)[1]);
+ symbol *tlbl1=newiTempLabel(NULL);
+ symbol *tlbl2=newiTempLabel(NULL);
+ emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
+ emitcode ("bne", "%05d$", tlbl1->key+100);
+ // far/near pointer
+ if (pi) {
+ emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+ pi->generated=1;
+ } else {
+ emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+ }
+ if (size>2) {
+ if (pi) {
+ emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
+ } else {
+ emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
+ }
+ }
+ emitcode ("br", "%05d$", tlbl2->key+100);
+ emitcode ("", "%05d$:", tlbl1->key+100);
+ // code pointer
+ if (pi) {
+ emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+ pi->generated=1;
+ } else {
+ emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
+ emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
+ }
+ if (size>2) {
+ if (pi) {
+ emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
+ } else {
+ emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
+ }
+ }
+ emitcode ("", "%05d$:", tlbl2->key+100);
return;
}
switch (AOP_TYPE(left))
{
- case AOP_CODE:
- instr="movc";
- // fall through
case AOP_REG:
- case AOP_DIR:
- case AOP_FAR:
- case AOP_STK:
- emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
- if (AOP_SIZE(result) > 2) {
- emitcode (instr, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
+ if (size>1) {
+ if (codePointer) {
+ instr=MOVCW;
+ } else {
+ instr=MOVW;
+ }
+ scratchReg=R1;
+ } else {
+ if (codePointer) {
+ instr=MOVCB;
+ } else {
+ instr=MOVB;
+ }
+ scratchReg=R1L;
+ }
+ if (AOP_TYPE(result)==AOP_STK) {
+ emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
+ emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
+ } else {
+ if (pi) {
+ emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
+ AOP_NAME(left)[0]);
+ pi->generated=1;
+ } else {
+ if (codePointer) {
+ emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
+ emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
+ } else {
+ emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
+ AOP_NAME(left)[0]);
+ }
+ }
+ }
+ if (size > 2) {
+ if (size==3) {
+ if (codePointer) {
+ instr=MOVCB;
+ } else {
+ instr=MOVB;
+ }
+ scratchReg=R1L;
+ }
+ if (AOP_TYPE(result)==AOP_STK) {
+ emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
+ emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
+ } else {
+ if (pi) {
+ emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
+ AOP_NAME(left)[0]);
+ } else {
+ if (codePointer) {
+ emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
+ } else {
+ emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
+ AOP_NAME(left)[0]);
+ }
+ }
+ }
}
return;
- case AOP_GPTR:
}
- bailOut ("genPointerGet: unknown pointer");
+ bailOut ("genPointerGet");
}
/*-----------------------------------------------------------------*/
/* genPointerSet - stores the value into a pointer location */
/*-----------------------------------------------------------------*/
static void genPointerSet (iCode * ic, iCode *pi) {
- char *instr="mov";
-
+ char *instr;
operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
+ int size;
printIc ("genPointerSet", ic, 1,0,1);
bailOut ("genPointerSet: pointer required");
}
- aopOp(right,FALSE);
- aopOp(result,TRUE);
+ aopOp(result,FALSE,FALSE);
+ size=aopOp(right,FALSE, FALSE);
if (IS_GENPTR(operandType(result))) {
- emitcode ("INLINE", "_gptrset %s,%s= [%s,%s]",
+ emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
AOP_NAME(result)[0], AOP_NAME(result)[1],
AOP_NAME(right)[0], AOP_NAME(right)[1]);
return;
}
- switch (AOP_TYPE(result))
+ switch (AOP_TYPE(right))
{
- case AOP_CODE:
- instr="movc";
- // fall through
+ case AOP_LIT:
case AOP_REG:
- case AOP_DIR:
- case AOP_FAR:
- case AOP_STK:
- emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
- if (AOP_SIZE(result) > 2) {
- emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+ if (size>1) {
+ instr=MOVW;
+ } else {
+ instr=MOVB;
+ }
+ if (pi) {
+ emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ pi->generated=1;
+ } else {
+ emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ }
+ if (size > 2) {
+ if (size==3) {
+ instr=MOVB;
+ }
+ if (pi) {
+ emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
+ AOP_NAME(right)[1]);
+ } else {
+ emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
+ AOP_NAME(right)[1]);
+ }
}
return;
- case AOP_GPTR:
}
- bailOut ("genPointerSet: unknown pointer");
+ bailOut ("genPointerSet");
}
/*-----------------------------------------------------------------*/
/* genIfx - generate code for Ifx statement */
/*-----------------------------------------------------------------*/
static void genIfx (iCode * ic, iCode * popIc) {
+ int size;
+ char *instr;
bool trueOrFalse;
symbol *jlbl, *tlbl;
operand *cond=IC_COND(ic);
- emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
- printOp(cond),
+ emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
+ ic->lineno, printOp(cond),
IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
- aopOp(cond,FALSE);
+ size=aopOp(cond,TRUE,TRUE);
if (IC_TRUE(ic)) {
trueOrFalse=TRUE;
switch (AOP_TYPE(cond) )
{
- case AOP_CRY:
- emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
+ case AOP_BIT:
+ emitcode (trueOrFalse ? "jb" : "jnb", "%s,%05d$",
AOP_NAME(cond)[0], jlbl->key+100);
return;
case AOP_REG:
case AOP_FAR:
case AOP_STK:
tlbl=newiTempLabel(NULL);
- emitcode ("cmp", "%s,#0", AOP_NAME(cond)[0]);
- emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
- if (AOP_SIZE(cond) > 2) {
- emitcode ("cmp", "%s,#0", AOP_NAME(cond)[1]);
- emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
+ if (size>1) {
+ instr="cmp.w";
+ } else {
+ instr="cmp.b";
+ }
+ emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
+ emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
+ if (size > 2) {
+ if (size==3) {
+ // generic pointer, forget the generic part
+ } else {
+ emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
+ emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
+ }
}
emitcode ("jmp", "%05d$", jlbl->key+100);
emitcode ("", "%05d$:", tlbl->key+100);
/* genAddrOf - generates code for address of */
/*-----------------------------------------------------------------*/
static void genAddrOf (iCode * ic) {
+ int size;
operand *left=IC_LEFT(ic);
printIc ("genAddrOf", ic, 1,1,0);
- aopOp (IC_RESULT(ic),TRUE);
+ size=aopOp (IC_RESULT(ic), FALSE, TRUE);
if (isOperandOnStack(left)) {
- aopOp (IC_LEFT(ic),FALSE);
emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
- AOP_NAME(IC_LEFT(ic))[0]);
- if (AOP_SIZE(IC_RESULT(ic)) > 2) {
+ getStackOffset(OP_SYMBOL(left)->stack));
+ if (size > 2) {
// this must be a generic pointer
- emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
+ emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
}
return;
}
if (isOperandInDirSpace(left) ||
isOperandInFarSpace(left) ||
isOperandInCodeSpace(left)) {
- emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
- OP_SYMBOL(left));
- if (AOP_SIZE(IC_RESULT(ic)) > 2) {
+ emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
+ OP_SYMBOL(left)->rname);
+ if (size > 2) {
// this must be a generic pointer
int space=0; // dir space
if (isOperandInFarSpace(left)) {
} else if (isOperandInCodeSpace(left)) {
space=2;
}
- emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
+ emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
}
return;
}
/*-----------------------------------------------------------------*/
static void genAssign (iCode * ic) {
operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
+ int size;
+ char *instr;
printIc ("genAssign", ic, 1,0,1);
if (!IS_SYMOP(result)) {
- fprintf (stderr, "genAssign: result is not a symbol\n");
- exit (1);
+ bailOut("genAssign: result is not a symbol");
}
- aopOp(right, FALSE);
- aopOp(result, TRUE);
-
- if (result->aop->type==AOP_REG ||
- right->aop->type==AOP_REG ||
- right->aop->type==AOP_LIT ||
- right->aop->type==AOP_STK ||
- right->aop->type==AOP_IMMD) {
- // everything will do
- } else {
- // they have to match
- if (result->aop->type != right->aop->type) {
- fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
- aopTypeName(result->aop), aopTypeName(right->aop));
- exit (1);
- }
- }
+ aopOp(result, TRUE, TRUE);
+ aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
+ size=AOP_SIZE(result);
/* if result is a bit */
- if (AOP_TYPE(result) == AOP_CRY) {
+ if (AOP_TYPE(result) == AOP_BIT) {
/* if right is literal, we know what the value is */
if (AOP_TYPE(right) == AOP_LIT) {
if (operandLitValue(right)) {
return;
}
/* if right is also a bit */
- if (AOP_TYPE(right) == AOP_CRY) {
+ if (AOP_TYPE(right) == AOP_BIT) {
emitcode ("mov", "c,%s", AOP_NAME(right));
emitcode ("mov", "%s,c", AOP_NAME(result));
return;
}
/* we need to or */
- emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
+ emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
return;
}
/* general case */
- emitcode ("mov", "%s,%s",
- result->aop->name[0], right->aop->name[0]);
- if (AOP_SIZE(result) > 2) {
- emitcode ("mov", "%s,%s",
- result->aop->name[1], right->aop->name[1]);
+ if (size>1) {
+ instr=MOVW;
+ } else {
+ instr=MOVB;
+ }
+ emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+
+ if (size > 2) {
+ if (size==3) {
+ // generic pointer
+ instr=MOVB;
+ }
+ emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+ return;
}
-
}
/*-----------------------------------------------------------------*/
/* genCast - gen code for casting */
/*-----------------------------------------------------------------*/
static void genCast (iCode * ic) {
+ int size;
+ operand *result=IC_RESULT(ic);
+ operand *right=IC_RIGHT(ic);
+ sym_link *ctype=operandType(IC_LEFT(ic));
+ sym_link *rtype=operandType(IC_RIGHT(ic));
+ sym_link *etype=getSpec(rtype);
+ short ptrType, signedness;
+
printIc ("genCast", ic, 1,1,1);
+
+ aopOp(result, TRUE, TRUE);
+ aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
+ size=AOP_SIZE(result);
+
+ /* if result is a bit */
+ if (AOP_TYPE(result) == AOP_BIT) {
+ /* if right is literal, we know what the value is */
+ if (AOP_TYPE(right) == AOP_LIT) {
+ if (operandLitValue(right)) {
+ emitcode ("setb", AOP_NAME(result)[0]);
+ } else {
+ emitcode ("clr", AOP_NAME(result)[0]);
+ }
+ return;
+ }
+ /* if right is also a bit */
+ if (AOP_TYPE(right) == AOP_BIT) {
+ emitcode ("mov", "c,%s", AOP_NAME(right));
+ emitcode ("mov", "%s,c", AOP_NAME(result));
+ return;
+ }
+ /* we need to or */
+ emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
+ return;
+ }
+
+ /* if right is a bit */
+ if (AOP_TYPE(right)==AOP_BIT) {
+ emitcode ("mov", "c,%s", AOP_NAME(right));
+ emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
+ emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
+ if (size>2) {
+ emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
+ }
+ return;
+ }
+
+ /* if the result is of type pointer */
+ if (IS_PTR (ctype)) {
+
+ if (AOP_SIZE(right)>1) {
+ emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ } else {
+ emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
+ emitcode ("sext", "r1h");
+ emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
+ }
+
+ /* if pointer to generic pointer */
+ if (IS_GENPTR (ctype)) {
+
+ if (IS_GENPTR (rtype)) {
+ bailOut("genCast: gptr -> gptr");
+ }
+
+ if (IS_PTR (rtype)) {
+ ptrType = DCL_TYPE (rtype);
+ } else {
+ /* we have to go by the storage class */
+ if (!SPEC_OCLS(etype)) {
+ bailOut("genCast: unknown storage class");
+ } else {
+ ptrType = PTR_TYPE (SPEC_OCLS (etype));
+ }
+ }
+
+ /* the generic part depends on the type */
+ switch (ptrType)
+ {
+ case POINTER:
+ emitcode ("mov", "%s,#0x00", AOP_NAME(result)[1]);
+ break;
+ case FPOINTER:
+ emitcode ("mov", "%s,#0x01", AOP_NAME(result)[1]);
+ break;
+ case CPOINTER:
+ emitcode ("mov", "%s,#0x02", AOP_NAME(result)[1]);
+ break;
+ default:
+ bailOut("genCast: got unknown storage class");
+ }
+ }
+ return;
+ }
+
+ /* do we have to sign extend? */
+ signedness = SPEC_USIGN(rtype);
+
+ /* now depending on the size */
+ switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
+ {
+ case 0x44:
+ case 0x33:
+ emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+ // fall through
+ case 0x24:
+ case 0x22:
+ case 0x11:
+ emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ return;
+ case 0x41:
+ case 0x21:
+ emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
+ if (signedness) {
+ emitcode("sext", "r1h");
+ } else {
+ emitcode("mov", "rlh,#0");
+ }
+ emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
+ if (size==2)
+ return;
+ // fall through: case 0x41
+ emitcode("sext", AOP_NAME(result)[1]);
+ return;
+ case 14:
+ case 12:
+ emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
+ emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
+ return;
+ case 24:
+ emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+ return;
+ }
+ bailOut("genCast: unknown size");
}
+
/*-----------------------------------------------------------------*/
/* genDjnz - generate decrement & jump if not zero instrucion */
/*-----------------------------------------------------------------*/
static bool genDjnz (iCode * ic, iCode * ifx) {
- printIc ("genDjnz", ic, 0,0,0);
+ symbol *lbl, *lbl1;
+
+ if (!ifx)
+ return 0;
+
+ /* if the if condition has a false label
+ then we cannot save */
+ if (IC_FALSE (ifx))
+ return 0;
+
+ /* if the minus is not of the form
+ a = a - 1 */
+ if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
+ !IS_OP_LITERAL (IC_RIGHT (ic)))
+ return 0;
+
+ if (operandLitValue (IC_RIGHT (ic)) != 1)
+ return 0;
+
+ /* if the size of this greater than two then no
+ saving */
+ if (getSize (operandType (IC_RESULT (ic))) > 2)
+ return 0;
+
+ printIc ("genDjnz", ic, 1,1,1);
+
+ /* otherwise we can save BIG */
+ lbl = newiTempLabel (NULL);
+ lbl1 = newiTempLabel (NULL);
+
+ aopOp (IC_RESULT (ic), FALSE, TRUE);
+
+ if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
+ emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
+ emitcode ("br", "%05d$", lbl1->key + 100);
+ emitcode ("", "%05d$:", lbl->key + 100);
+ emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
+ emitcode ("", "%05d$:", lbl1->key + 100);
+ return TRUE;
+ }
+
+ bailOut("genDjnz: aop type");
return FALSE;
}
iCode *ic;
int cln = 0;
- fprintf (stderr, "genXA51Code\n");
lineHead = lineCurr = NULL;
- /* print the allocation information */
- if (allocInfo)
- printAllocInfo (currFunc, codeOutFile);
-
/* if debug information required */
if (options.debug && currFunc)
{
}
for (ic = lic; ic; ic = ic->next) {
- if (cln != ic->lineno) {
+ if (ic->lineno && cln != ic->lineno) {
if (options.debug) {
_G.debugLine = 1;
emitcode ("", "C$%s$%d$%d$%d ==.",
ic->level, ic->block);
_G.debugLine = 0;
}
- emitcode (";", "%s %d", ic->filename, ic->lineno);
+ emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
+ printCLine(ic->filename, ic->lineno));
cln = ic->lineno;
}
/* if the result is marked as
break;
case '>':
- genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+ genCmpGt (ic);
break;
case '<':
- genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
+ genCmpLt (ic);
break;
case LE_OP:
+ genCmpLe (ic);
+ break;
+
case GE_OP:
+ genCmpGe (ic);
+ break;
+
case NE_OP:
-
- /* note these two are xlated by algebraic equivalence
- during parsing SDCC.y */
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "got '>=' or '<=' shouldn't have come here");
+ genCmpNe (ic);
break;
-
+
case EQ_OP:
- genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+ genCmpEq (ic);
break;
case AND_OP:
break;
case GET_VALUE_AT_ADDRESS:
- genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
+ genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
break;
case '=':