X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fxa51%2Fgen.c;h=bf86fa619ca685b20ae43a15d41d15e273f5019b;hb=3062f96ccb55d1d05caf9c8782f4961f87b341ce;hp=bbe49199c34ed364aae25676df0cd8ccf89cf8d4;hpb=b1f9b010e519cb7319310c975755d3014534254f;p=fw%2Fsdcc diff --git a/src/xa51/gen.c b/src/xa51/gen.c index bbe49199..bf86fa61 100755 --- a/src/xa51/gen.c +++ b/src/xa51/gen.c @@ -23,9 +23,6 @@ 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) @@ -38,34 +35,11 @@ #include "SDCCglobl.h" #include "newalloc.h" -#ifdef HAVE_SYS_ISA_DEFS_H -#include -#else -#ifdef HAVE_MACHINE_ENDIAN_H -#include -#else -#ifdef HAVE_ENDIAN_H -#include -#else -#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__) -#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN" -#warning "If you running sdcc on an INTEL 80x86 Platform you are okay" -#endif -#endif -#endif -#endif - #include "common.h" #include "SDCCpeeph.h" #include "ralloc.h" #include "gen.h" -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define STRCASECMP stricmp -#else -#define STRCASECMP strcasecmp -#endif - extern int allocInfo; /* this is the down and dirty file with all kinds of @@ -77,14 +51,16 @@ static struct { short inLine; short debugLine; + short stackExtend; short nRegsSaved; + short parmsPushed; set *sendSet; } _G; extern int xa51_ptrRegReq; extern int xa51_nRegs; -extern FILE *codeOutFile; +extern struct dbuf_s *codeOutBuf; static lineNode *lineHead = NULL; static lineNode *lineCurr = NULL; @@ -94,10 +70,15 @@ static lineNode *lineCurr = NULL; #define MSB24 2 #define MSB32 3 +static char *MOV="mov"; static char *MOVB="mov.b"; static char *MOVW="mov.w"; -//static char *MOVCB="movc.b"; -//static char *MOVCW="movc.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); @@ -125,7 +106,7 @@ static void emitcode (char *inst, char *fmt,...) { else vsprintf (lb, fmt, ap); - while (isspace ((int)*lbp)) + while (isspace (*lbp)) lbp++; if (lbp && *lbp) @@ -137,13 +118,23 @@ static void emitcode (char *inst, char *fmt,...) { va_end (ap); } +/*-----------------------------------------------------------------*/ +/* xa51_emitDebuggerSymbol - associate the current code location */ +/* with a debugger symbol */ +/*-----------------------------------------------------------------*/ +void +xa51_emitDebuggerSymbol (char * debugSym) +{ + _G.debugLine = 1; + emitcode ("", "%s ==.", debugSym); + _G.debugLine = 0; +} + + char *getStackOffset(int stack) { static char gsoBuf[1024]; - // dit slaat natuurlijk nergens op, maar ja voor nou - sprintf (gsoBuf, "r7+(%+d+0%+d%+d)", stack, - FUNC_ISISR(currFunc->type) ? - port->stack.isr_overhead : port->stack.call_overhead, - _G.nRegsSaved); + sprintf (gsoBuf, "r7+(%d%+d%+d)", stack, + currFunc->stack, _G.nRegsSaved); return gsoBuf; } @@ -179,7 +170,8 @@ char *aopTypeName(asmop *aop) { /*-----------------------------------------------------------------*/ /* aopForSym - for a true symbol */ /*-----------------------------------------------------------------*/ -static asmop *aopForSym(symbol *sym, bool result, bool cantUsePointer) { +static asmop *aopForSym(symbol *sym, + bool canUsePointer, bool canUseOffset) { int size; asmop *aop; @@ -198,32 +190,31 @@ static asmop *aopForSym(symbol *sym, bool result, bool cantUsePointer) { // if it is on stack if (sym->onStack) { - if (cantUsePointer) { + if (!canUsePointer || !canUseOffset) { aop->type=AOP_REG; switch (size) { case 1: - emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack)); + emitcode ("mov.b", "r0l,[%s] ;aopForSym:stack:1", getStackOffset(sym->stack)); sprintf (aop->name[0], "r0l"); return aop; case 2: - emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack)); + emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack)); sprintf (aop->name[0], "r0"); return aop; case 3: - emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack)); + emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack)); sprintf (aop->name[0], "r0"); - emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2)); + emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2)); sprintf (aop->name[1], "r1l"); return aop; case 4: - emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack)); + emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack)); sprintf (aop->name[0], "r0"); - emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2)); + emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack+2)); sprintf (aop->name[1], "r1"); return aop; } - bailOut("aopForSym: onStack CantUsePointer unknown size"); } aop->type=AOP_STK; sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack)); @@ -235,7 +226,7 @@ static asmop *aopForSym(symbol *sym, bool result, bool cantUsePointer) { // if it has a spillLoc if (sym->usl.spillLoc) { - return aopForSym (sym->usl.spillLoc, result, cantUsePointer); + return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset); } // if in bit space @@ -257,29 +248,90 @@ static asmop *aopForSym(symbol *sym, bool result, bool cantUsePointer) { // if in code space if (IN_CODESPACE(SPEC_OCLS(sym->etype))) { - if (result) { - bailOut("aopForSym: result can not be in code space"); - } - 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]"); + 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, "r0,[r0+]"); + sprintf (aop->name[1], "r0"); + emitcode (MOV, "r1l,[r0+]"); + sprintf (aop->name[0], "r1l"); + return aop; + case 4: + emitcode (MOV, "r0,#%s", sym->rname); + emitcode (MOVC, "r1,[r0+]"); + emitcode (MOVC, "r0,[r0+]"); + emitcode ("xch", "r0,r1"); + sprintf (aop->name[0], "r0"); + sprintf (aop->name[1], "r1"); + 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]"); + } } return aop; } // if in far space if (IN_FARSPACE(SPEC_OCLS(sym->etype))) { - 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]"); + 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.w", "r0,#%s ; aopForSym:far", sym->rname); + sprintf (aop->name[0], "[r0]"); + if (size>2) { + sprintf (aop->name[1], "[r0+2]"); + } + return aop; } - return aop; } - + bailOut("aopForSym"); return NULL; } @@ -312,10 +364,10 @@ static asmop *aopForVal(operand *op) { sprintf (aop->name[1], "#0"); break; case 4: - sprintf (aop->name[0], "#0x%04lx", - SPEC_CVAL(operandType(op)).v_ulong >> 16); + sprintf (aop->name[0], "#0x%04x", + SPEC_CVAL(operandType(op)).v_ulong & 0xffff); sprintf (aop->name[1], "#0x%04x", - SPEC_CVAL(operandType(op)).v_ulong && 0xffff); + SPEC_CVAL(operandType(op)).v_ulong >> 16); break; default: bailOut("aopForVal"); @@ -343,21 +395,35 @@ static asmop *aopForVal(operand *op) { return NULL; } -static void aopOp(operand *op, bool result, bool cantUsePointer) { +static int aopOp(operand *op, + bool canUsePointer, bool canUseOffset) { if (IS_SYMOP(op)) { - op->aop=aopForSym (OP_SYMBOL(op), result, cantUsePointer); - return; + op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset); + return AOP_SIZE(op); } if (IS_VALOP(op)) { - if (result) { - bailOut("aopOp: result can not be a value"); - } op->aop=aopForVal (op); - return; + return AOP_SIZE(op); } 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; +} + +bool aopIsDir(operand *op) { + return AOP_TYPE(op)==AOP_DIR; +} + +bool aopIsBit(operand *op) { + return AOP_TYPE(op)==AOP_BIT; } bool aopIsPtr(operand *op) { @@ -370,7 +436,7 @@ bool aopIsPtr(operand *op) { } } -char *opRegName(operand *op, int offset, char *opName) { +char *opRegName(operand *op, int offset, char *opName, bool decorate) { if (IS_SYMOP(op)) { if (OP_SYMBOL(op)->onStack) { @@ -395,17 +461,21 @@ char *opRegName(operand *op, int offset, char *opName) { } // 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%02x", 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, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float); + sprintf (opName, "#%s%f", decorate?"(float)":"", + SPEC_CVAL(OP_VALUE(op)->type).v_float); break; default: bailOut("opRegName: unexpected noun"); @@ -477,9 +547,9 @@ char * printOp (operand *op) { 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 * "); @@ -496,14 +566,15 @@ char * printOp (operand *op) { 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 { bailOut("printOp: unexpected operand type"); } return line; } -void printIc (char *op, iCode * ic, bool result, bool left, bool right) { +void printIc (bool printToStderr, + char *op, iCode * ic, bool result, bool left, bool right) { char line[132]; sprintf (line, "%s(%d)", op, ic->lineno); @@ -520,18 +591,25 @@ void printIc (char *op, iCode * ic, bool result, bool left, bool right) { strcat (line, printOp (IC_RIGHT(ic))); } emitcode (";", line); + if (printToStderr) { + fprintf (stderr, "%s\n", line); + } } /*-----------------------------------------------------------------*/ /* 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)); - emitcode ("mov", "c,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"; } @@ -596,43 +674,119 @@ static int resultRemat (iCode * ic) { /* genNot - generate code for ! operation */ /*-----------------------------------------------------------------*/ static void genNot (iCode * ic) { - printIc("genNot:", ic, 1,1,0); + printIc (0, "genNot:", ic, 1,1,0); } /*-----------------------------------------------------------------*/ /* genCpl - generate code for complement */ /*-----------------------------------------------------------------*/ static void genCpl (iCode * ic) { - printIc("genCpl", ic, 1,1,0); + printIc (0, "genCpl", ic, 1,1,0); } /*-----------------------------------------------------------------*/ /* genUminus - unary minus code generation */ /*-----------------------------------------------------------------*/ static void genUminus (iCode * ic) { - printIc("genUminus", ic, 1,1,0); + printIc (0, "genUminus", ic, 1,1,0); } /*-----------------------------------------------------------------*/ -/* genIpush - genrate code for pushing this gets a little complex */ +/* genIpush - generate code for pushing */ /*-----------------------------------------------------------------*/ static void genIpush (iCode * ic) { - printIc ("genIpush", ic, 0,1,0); + operand *left=IC_LEFT(ic); + + printIc (0, "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++; + } } /*-----------------------------------------------------------------*/ /* genIpop - recover the registers: can happen only for spilling */ /*-----------------------------------------------------------------*/ static void genIpop (iCode * ic) { - printIc ("genIpop", ic, 0,1,0); + printIc (0, "genIpop", ic, 0,1,0); } /*-----------------------------------------------------------------*/ /* 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"); + } } /*-----------------------------------------------------------------*/ @@ -651,10 +805,11 @@ static void genFunction (iCode * ic) { 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, codeOutBuf); + emitcode ("", "%s:", sym->rname); if (IFFUNC_ISNAKED(type)) @@ -663,10 +818,10 @@ static void genFunction (iCode * ic) { 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); + } } /*-----------------------------------------------------------------*/ @@ -677,13 +832,29 @@ genEndFunction (iCode * ic) { symbol *sym = OP_SYMBOL (IC_LEFT (ic)); - if (IFFUNC_ISNAKED(sym->type)) - { + printIc (0, "genEndFunction", ic, 0,0,0); + + if (IFFUNC_ISNAKED(sym->type)) { emitcode(";", "naked function: no epilogue."); + if (options.debug && currFunc) + debugFile->writeEndFunction (currFunc, ic, 0); 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 (options.debug && currFunc) { + debugFile->writeEndFunction (currFunc, ic, 1); + } + + if (IFFUNC_ISISR(sym->type)) { + emitcode ("reti", ""); + } else { + emitcode ("ret", ""); + } } /*-----------------------------------------------------------------*/ @@ -691,27 +862,32 @@ genEndFunction (iCode * ic) /*-----------------------------------------------------------------*/ static void genRet (iCode * ic) { - printIc ("genRet", ic, 0,1,0); - - aopOp(IC_LEFT(ic),FALSE, FALSE); + if (!IC_LEFT(ic)) { + printIc (0, "genRet", ic, 0, 0, 0); + } else { + printIc (0, "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"); + } + } - 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]); - return; - 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]); - return; - case 1: - emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]); - return; - } - bailOut("genRet"); + emitcode ("jmp", "%05d$", returnLabel->key+100); } /*-----------------------------------------------------------------*/ @@ -722,7 +898,7 @@ static void genLabel (iCode * ic) { 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)); } @@ -730,7 +906,7 @@ static void genLabel (iCode * ic) { /* genGoto - generates a jmp */ /*-----------------------------------------------------------------*/ static void genGoto (iCode * ic) { - emitcode (";", "genGoto %s", IC_LABEL(ic)->name); + emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name); emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100)); } @@ -738,73 +914,160 @@ static void genGoto (iCode * ic) { /* genPlus - generates code for addition */ /*-----------------------------------------------------------------*/ static void genPlus (iCode * ic) { - printIc ("genPlus", ic, 1,1,1); + operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic); + int size; + char *instr; + + printIc (0, "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)); + + // special case for "* = * + char", needs a closer look + // heck, this shouldn't have come here but bug-223113 does + if (size==3 && AOP_SIZE(right)==1) { + emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]); + emitcode ("mov", "r1h,#0"); // ptr arith unsigned???????????? + emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]); + emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]); + emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]); + return; + } + + // special case for "xdata * = xdata * + char", needs a closer look + // heck, this shouldn't have come here but bug-441448 does + if (size==2 && AOP_SIZE(right)==1) { + emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]); + emitcode ("mov", "r1h,#0"); // ptr arith unsigned???????????? + emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]); + emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]); + return; + } + + 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; } /*-----------------------------------------------------------------*/ /* genMinus - generates code for subtraction */ /*-----------------------------------------------------------------*/ static void genMinus (iCode * ic) { - printIc ("genMinus", ic, 1,1,1); -} + operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic); + int size; + char *instr; + + printIc (0, "genMinus", 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 ("clr", 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"); + } + + if (isOperandEqual(result,left)) { + left->aop=result->aop; + } else { + aopOp(left, !aopIsPtr(result), !aopIsDir(result)); + } + aopOp(right, !aopIsPtr(result), !aopIsDir(result)); + + if (size>1) { + instr="sub.w"; + } else { + instr="sub.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 ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]); + } + } + return; +} /*-----------------------------------------------------------------*/ /* genMult - generates code for multiplication */ /*-----------------------------------------------------------------*/ static void genMult (iCode * ic) { - printIc ("genMult", ic, 1,1,1); + printIc (0, "genMult", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genDiv - generates code for division */ /*-----------------------------------------------------------------*/ static void genDiv (iCode * ic) { - printIc ("genDiv", ic, 1,1,1); + printIc (0, "genDiv", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genMod - generates code for division */ /*-----------------------------------------------------------------*/ static void genMod (iCode * ic) { - printIc ("genMod", ic, 1,1,1); -} - -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void genCmpGt (iCode * ic) { - printIc ("genCmpGt", ic, 1,1,1); -} -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void genCmpLe (iCode * ic) { - printIc ("genCmpGt", ic, 1,1,1); -} -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void genCmpGe (iCode * ic) { - printIc ("genCmpGt", ic, 1,1,1); -} -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void genCmpNe (iCode * ic) { - printIc ("genCmpGt", ic, 1,1,1); -} -/*-----------------------------------------------------------------*/ -/* genCmpLt - less than comparisons */ -/*-----------------------------------------------------------------*/ -static void genCmpLt (iCode * ic) { - printIc ("genCmpLt", ic, 1,1,1); -} -/*-----------------------------------------------------------------*/ -/* genCmpEq - generates code for equal to */ -/*-----------------------------------------------------------------*/ -static void genCmpEq (iCode * ic) { - printIc ("genCmpEq", ic, 1,1,1); + printIc (0, "genMod", ic, 1,1,1); } /*-----------------------------------------------------------------*/ @@ -827,6 +1090,89 @@ static iCode *ifxForOp (operand * op, iCode * ic) { return NULL; } +/*-----------------------------------------------------------------*/ +/* genCmp - compares whatever */ +/*-----------------------------------------------------------------*/ +static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) { + iCode *ifx=ifxForOp(IC_RESULT(ic),ic); + operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic); + int size; + bool isTrue; + char *instr; + int jlbl; + + + size=aopOp(left, TRUE, TRUE); + aopOp(right, !aopIsPtr(left), TRUE); + + if (size==1) { + instr="cmp.b"; + } else { + instr="cmp.w"; + } + + if (IC_TRUE(ifx)) { + isTrue=TRUE; + jlbl=IC_TRUE(ifx)->key+100; + } else { + isTrue=FALSE; + jlbl=IC_FALSE(ifx)->key+100; + } + + if (!ifx) { + aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE); + jlbl=newiTempLabel(NULL)->key+100; + emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]); + emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]); + emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl); + emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]); + emitcode("", "%05d$:", jlbl); + } else { + emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]); + emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl); + ifx->generated=1; + } + + if (size>2) { + bailOut("genCmp: size > 2"); + } + +} + +/*-----------------------------------------------------------------*/ +/* genCmpEq :- generates code for equal to */ +/*-----------------------------------------------------------------*/ +static void genCmpEq (iCode * ic) { + printIc (0, "genCmpEq", ic, 0,1,1); + genCmp(ic, "beq", "bne"); // no sign +} + +/*-----------------------------------------------------------------*/ +/* genCmpGt :- greater than comparison */ +/*-----------------------------------------------------------------*/ +static void genCmpGt (iCode * ic) { + printIc (0, "genCmpGt", ic, 0,1,1); + if (SPEC_USIGN(operandType(IC_LEFT(ic))) || + SPEC_USIGN(operandType(IC_RIGHT(ic)))) { + genCmp(ic, "bg", "bl"); // unsigned + } else { + genCmp(ic, "bgt", "ble"); // signed + } +} + +/*-----------------------------------------------------------------*/ +/* genCmpLt - less than comparisons */ +/*-----------------------------------------------------------------*/ +static void genCmpLt (iCode * ic) { + printIc (0, "genCmpLt", ic, 0,1,1); + if (SPEC_USIGN(operandType(IC_LEFT(ic))) || + SPEC_USIGN(operandType(IC_RIGHT(ic)))) { + genCmp(ic, "bcs", "bcc"); // unsigned + } else { + genCmp(ic, "blt", "bge"); // signed + } +} + /*-----------------------------------------------------------------*/ /* hasInc - operand is incremented before any other use */ /*-----------------------------------------------------------------*/ @@ -845,14 +1191,17 @@ static iCode *hasInc (operand *op, iCode *ic, int osize) { while (lic) { /* if operand of the form op = 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) { + if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) { return NULL; } /* if GOTO or IFX */ @@ -866,237 +1215,332 @@ static iCode *hasInc (operand *op, iCode *ic, int osize) { /* genAndOp - for && operation */ /*-----------------------------------------------------------------*/ static void genAndOp (iCode * ic) { - printIc ("genAndOp(&&)", ic, 1,1,1); + printIc (0, "genAndOp(&&)", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genOrOp - for || operation */ /*-----------------------------------------------------------------*/ static void genOrOp (iCode * ic) { - printIc ("genOrOp(||)", ic, 1,1,1); + printIc (0, "genOrOp(||)", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genAnd - code for and */ /*-----------------------------------------------------------------*/ static void genAnd (iCode * ic, iCode * ifx) { - printIc ("genAnd", ic, 1,1,1); + printIc (0, "genAnd", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genOr - code for or */ /*-----------------------------------------------------------------*/ static void genOr (iCode * ic, iCode * ifx) { - printIc ("genOr", ic, 1,1,1); + operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic); + int size; + char *instr; + + printIc (0, "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; } /*-----------------------------------------------------------------*/ /* genXor - code for xclusive or */ /*-----------------------------------------------------------------*/ static void genXor (iCode * ic, iCode * ifx) { - printIc ("genXor", ic, 1,1,1); + printIc (0, "genXor", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genInline - write the inline code out */ /*-----------------------------------------------------------------*/ static void genInline (iCode * ic) { - printIc ("genInline", ic, 0,0,0); + + printIc (0, "genInline", ic, 0,0,0); + + emitcode ("", IC_INLINE(ic)); } /*-----------------------------------------------------------------*/ /* genRRC - rotate right with carry */ /*-----------------------------------------------------------------*/ static void genRRC (iCode * ic) { - printIc ("genRRC", ic, 1,1,0); + printIc (0, "genRRC", ic, 1,1,0); } /*-----------------------------------------------------------------*/ /* genRLC - generate code for rotate left with carry */ /*-----------------------------------------------------------------*/ static void genRLC (iCode * ic) { - printIc ("genRLC", ic, 1,1,0); + printIc (0, "genRLC", ic, 1,1,0); } /*-----------------------------------------------------------------*/ /* genGetHbit - generates code get highest order bit */ /*-----------------------------------------------------------------*/ static void genGetHbit (iCode * ic) { - printIc ("genGetHbit", ic, 1,1,0); + printIc (0, "genGetHbit", ic, 1,1,0); } /*-----------------------------------------------------------------*/ /* genLeftShift - generates code for left shifting */ /*-----------------------------------------------------------------*/ static void genLeftShift (iCode * ic) { - printIc ("genLeftShift", ic, 1,1,1); + printIc (0, "genLeftShift", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genRightShift - generate code for right shifting */ /*-----------------------------------------------------------------*/ static void genRightShift (iCode * ic) { - printIc ("genRightShift", ic, 1,1,1); + printIc (0, "genRightShift", ic, 1,1,1); } /*-----------------------------------------------------------------*/ /* genPointerGet - generate code for pointer get */ /*-----------------------------------------------------------------*/ static void genPointerGet (iCode * ic, iCode *pi) { - printIc ("genPointerGet", ic, 1,1,0); -#if 0 char *instr, *scratchReg; operand *result=IC_RESULT(ic), *left=IC_LEFT(ic); + bool codePointer=IS_CODEPTR(operandType(left)); + int size; + + if (pi) { + printIc (0, "genPointerGet pi", ic, 1,1,0); + } else { + printIc (0, "genPointerGet", ic, 1,1,0); + } if (!IS_PTR(operandType(left))) { 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\t_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 ("beq", "%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: - if (AOP_SIZE(result)==1) { - instr=MOVCB; - } else { - instr=MOVCW; - } - emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]); - if (AOP_SIZE(result) > 2) { - if (AOP_SIZE(result)==3) { - instr=MOVCB; - } else { + case AOP_LIT: + emitcode("mov","r1,%s", AOP_NAME(left)[0]); + sprintf (AOP_NAME(left)[0], "r1"); + // fall through + case AOP_REG: + if (size>1) { + if (codePointer) { instr=MOVCW; - } - emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]); - } - return; - case AOP_FAR: - if (AOP_SIZE(result)==1) { - instr=MOVB; - } else { - instr=MOVW; - } - emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]); - if (AOP_SIZE(result) > 2) { - if (AOP_SIZE(result)==3) { - instr=MOVB; } else { instr=MOVW; } - emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]); - } - return; - case AOP_DIR: - if (AOP_SIZE(result)==1) { - instr=MOVB; + scratchReg=R1; } else { - instr=MOVW; - } - emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]); - if (AOP_SIZE(result) > 2) { - if (AOP_SIZE(result)==3) { - instr=MOVB; + if (codePointer) { + instr=MOVCB; } else { - instr=MOVW; + instr=MOVB; } - emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]); - } - return; - case AOP_REG: - if (AOP_SIZE(result)==1) { - instr=MOVB; - scratchReg=R0L; - } else { - instr=MOVW; - scratchReg=R0; + scratchReg=R1L; } - // if result=onstack if (AOP_TYPE(result)==AOP_STK) { - emitcode (instr, "%s,[%s]", scratchReg, AOP_NAME(left)[0]); - emitcode (instr, "%s,%s", AOP_NAME(result)[0], scratchReg); + emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]); + emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg); } else { - emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]); - } - if (AOP_SIZE(result) > 2) { - // result is generic pointer - sym_link *optype=operandType(left); - sym_link *opetype=getSpec(optype); - if (IS_PTR(optype) && !IS_GENPTR(optype)) { - emitcode (MOVB, "%s,#0x%02x", AOP_NAME(result)[1], - PTR_TYPE(SPEC_OCLS(opetype))); + if (pi) { + emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], + AOP_NAME(left)[0]); + pi->generated=1; } else { - emitcode (MOVB, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]); + 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]); + } } } - return; - case AOP_STK: - // if both on stack - if (AOP_TYPE(result)==AOP_STK) { - if (AOP_SIZE(result)==1) { - emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]); - emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]); - } else { - emitcode ("mov", "r0,%s", AOP_NAME(left)[0]); - emitcode ("mov", "%s,r0", AOP_NAME(result)[0]); - } - } else { - if (AOP_SIZE(result)==1) { - emitcode ("mov.b", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]); - } else { - emitcode ("mov.w", "%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_SIZE(result) > 2) { if (AOP_TYPE(result)==AOP_STK) { - if (AOP_SIZE(result)==3) { - emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]); - emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]); + 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 { - emitcode ("mov", "r0,%s", AOP_NAME(left)[1]); - emitcode ("mov", "%s,r0", AOP_NAME(result)[1]); + if (codePointer) { + emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]); + } else { + emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], + AOP_NAME(left)[0]); + } } - } else { - emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]); } } return; } - bailOut ("genPointerGet: unknown pointer"); -#endif + bailOut ("genPointerGet"); } /*-----------------------------------------------------------------*/ /* genPointerSet - stores the value into a pointer location */ /*-----------------------------------------------------------------*/ static void genPointerSet (iCode * ic, iCode *pi) { - printIc ("genPointerSet", ic, 1,0,1); + char *instr; + operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic); + int size; + + printIc (0, "genPointerSet", ic, 1,0,1); + + if (!IS_PTR(operandType(result))) { + bailOut ("genPointerSet: pointer required"); + } + + aopOp(result,FALSE,FALSE); + size=aopOp(right,FALSE, FALSE); + + if (IS_GENPTR(operandType(result))) { + 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(right)) + { + case AOP_LIT: + case AOP_REG: + 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; + } + bailOut ("genPointerSet"); } /*-----------------------------------------------------------------*/ /* genIfx - generate code for Ifx statement */ /*-----------------------------------------------------------------*/ static void genIfx (iCode * ic, iCode * popIc) { + int size; char *instr; bool trueOrFalse; - symbol *jlbl, *tlbl; + symbol *jlbl, *tlbl=newiTempLabel(NULL); 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,FALSE); + size=aopOp(cond,TRUE,TRUE); if (IC_TRUE(ic)) { trueOrFalse=TRUE; @@ -1109,29 +1553,29 @@ static void genIfx (iCode * ic, iCode * popIc) { switch (AOP_TYPE(cond) ) { case AOP_BIT: - emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", - AOP_NAME(cond)[0], jlbl->key+100); + emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", + AOP_NAME(cond)[0], tlbl->key+100); + emitcode ("jmp", "%05d$", jlbl->key+100); + emitcode ("", "%05d$:", tlbl->key+100); return; case AOP_REG: case AOP_DIR: case AOP_FAR: case AOP_STK: - tlbl=newiTempLabel(NULL); - if (AOP_SIZE(cond)==1) { - instr="cmp.b"; - } else { + 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 (AOP_SIZE(cond) > 2) { - if (AOP_SIZE(cond)==3) { - instr="cmp.b"; + if (size > 2) { + if (size==3) { + // generic pointer, forget the generic part } else { - instr="cmp.w"; + emitcode (instr, "%s,#0", AOP_NAME(cond)[1]); + emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100); } - 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); @@ -1144,18 +1588,19 @@ static void genIfx (iCode * ic, iCode * popIc) { /* genAddrOf - generates code for address of */ /*-----------------------------------------------------------------*/ static void genAddrOf (iCode * ic) { + int size; operand *left=IC_LEFT(ic); - printIc ("genAddrOf", ic, 1,1,0); + printIc (0, "genAddrOf", ic, 1,1,0); - aopOp (IC_RESULT(ic),TRUE, FALSE); + size=aopOp (IC_RESULT(ic), FALSE, TRUE); if (isOperandOnStack(left)) { emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0], getStackOffset(OP_SYMBOL(left)->stack)); - if (AOP_SIZE(IC_RESULT(ic)) > 2) { + if (size > 2) { // this must be a generic pointer - emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER); + emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER); } return; } @@ -1165,7 +1610,7 @@ static void genAddrOf (iCode * ic) { isOperandInCodeSpace(left)) { emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0], OP_SYMBOL(left)->rname); - if (AOP_SIZE(IC_RESULT(ic)) > 2) { + if (size > 2) { // this must be a generic pointer int space=0; // dir space if (isOperandInFarSpace(left)) { @@ -1189,14 +1634,14 @@ static void genAssign (iCode * ic) { int size; char *instr; - printIc ("genAssign", ic, 1,0,1); + printIc (0, "genAssign", ic, 1,0,1); if (!IS_SYMOP(result)) { bailOut("genAssign: result is not a symbol"); } - aopOp(result, TRUE, FALSE); - aopOp(right, FALSE, aopIsPtr(result)); + aopOp(result, TRUE, TRUE); + aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR); size=AOP_SIZE(result); /* if result is a bit */ @@ -1217,24 +1662,23 @@ static void genAssign (iCode * ic) { 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; } + // TODO: if (-8 >= right==lit <= 7) instr=MOVS /* general case */ - if (size==1) { - instr=MOVB; - } else { + if (size>1) { instr=MOVW; + } else { + instr=MOVB; } emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]); - if (AOP_SIZE(result) > 2) { + if (size > 2) { if (size==3) { // generic pointer instr=MOVB; - } else { - instr=MOVW; } emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]); return; @@ -1245,16 +1689,163 @@ static void genAssign (iCode * ic) { /* genJumpTab - genrates code for jump table */ /*-----------------------------------------------------------------*/ static void genJumpTab (iCode * ic) { - printIc ("genJumpTab", ic, 0,0,0); + printIc (0, "genJumpTab", ic, 0,0,0); } /*-----------------------------------------------------------------*/ /* genCast - gen code for casting */ /*-----------------------------------------------------------------*/ static void genCast (iCode * ic) { - printIc ("genCast", ic, 1,1,1); + 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 (0, "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)) { + ptrType=0; // hush the compiler + 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.b", "%s,#0x00", AOP_NAME(result)[1]); + break; + case FPOINTER: + emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]); + break; + case CPOINTER: + emitcode ("mov.b", "%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 0x42: + emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]); + if (signedness) { + emitcode("sext", "%s", AOP_NAME(result)[1]); + } else { + emitcode("mov", "%s,#0", AOP_NAME(result)[1]); + } + return; + case 0x41: + case 0x21: + emitcode("mov", "r1l,%s", AOP_NAME(right)[0]); + if (signedness) { + emitcode("sext", "r1h"); + } else { + emitcode("mov", "r1h,#0"); + } + emitcode("mov", "%s,r1", AOP_NAME(result)[0]); + if (size==2) + return; + // fall through: case 0x41 + if (signedness) { + emitcode("sext", "r1"); + } else { + emitcode("mov", "r1,#0"); + } + emitcode("mov", "%s,r1", AOP_NAME(result)[1]); + return; + case 0x14: + case 0x12: + emitcode("mov", "r1,%s", AOP_NAME(right)[0]); + emitcode("mov", "%s,r1l", AOP_NAME(result)[0]); + return; + } + fprintf(stderr, "genCast: unknown size: %d:%d\n", + AOP_SIZE(result), AOP_SIZE(right)); + bailOut("genCast: unknown size"); } + /*-----------------------------------------------------------------*/ /* genDjnz - generate decrement & jump if not zero instrucion */ /*-----------------------------------------------------------------*/ @@ -1283,13 +1874,13 @@ static bool genDjnz (iCode * ic, iCode * ifx) { if (getSize (operandType (IC_RESULT (ic))) > 2) return 0; - printIc ("genDjnz", ic, 1,1,1); + printIc (0, "genDjnz", ic, 1,1,1); /* otherwise we can save BIG */ lbl = newiTempLabel (NULL); lbl1 = newiTempLabel (NULL); - aopOp (IC_RESULT (ic), TRUE, FALSE); + 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); @@ -1308,7 +1899,18 @@ static bool genDjnz (iCode * ic, iCode * ifx) { /* genReceive - generate code for a receive iCode */ /*-----------------------------------------------------------------*/ static void genReceive (iCode * ic) { - printIc ("genReceive", ic, 1,0,0); + printIc (0, "genReceive", ic, 1,0,0); +} + +/*-----------------------------------------------------------------*/ +/* genDummyRead - generate code for dummy read of volatiles */ +/*-----------------------------------------------------------------*/ +static void +genDummyRead (iCode * ic) +{ + emitcode ("; genDummyRead",""); + + ic = ic; } /*-----------------------------------------------------------------*/ @@ -1317,56 +1919,50 @@ static void genReceive (iCode * ic) { void genXA51Code (iCode * lic) { iCode *ic; int cln = 0; - + lineHead = lineCurr = NULL; - - /* print the allocation information */ - if (allocInfo) - printAllocInfo (currFunc, codeOutFile); /* if debug information required */ if (options.debug && currFunc) { - cdbSymbol (currFunc, cdbFile, FALSE, TRUE); - _G.debugLine = 1; - if (IS_STATIC (currFunc->etype)) - emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name); - else - emitcode ("", "G$%s$0$0 ==.", currFunc->name); - _G.debugLine = 0; + debugFile->writeFunction (currFunc, lic); } - + 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 ==.", - FileBaseName (ic->filename), ic->lineno, - ic->level, ic->block); - _G.debugLine = 0; + debugFile->writeCLine (ic); + } + if (!options.noCcodeInAsm) { + emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, + printCLine(ic->filename, ic->lineno)); } - emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, - printCLine(ic->filename, ic->lineno)); cln = ic->lineno; } + if (options.iCodeInAsm) { + char *iLine = printILine(ic); + emitcode("", ";ic:%d: %s", ic->key, iLine); + dbuf_free(iLine); + } + /* if the result is marked as spilt and rematerializable or code for this has already been generated then do nothing */ if (resultRemat (ic) || ic->generated) continue; - + /* depending on the operation */ switch (ic->op) { case '!': genNot (ic); break; - + case '~': genCpl (ic); break; - + case UNARYMINUS: genUminus (ic); break; @@ -1448,15 +2044,13 @@ void genXA51Code (iCode * lic) { break; case LE_OP: - genCmpLe (ic); - break; - case GE_OP: - genCmpGe (ic); - break; - case NE_OP: - genCmpNe (ic); + + /* 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"); break; case EQ_OP: @@ -1494,7 +2088,7 @@ void genXA51Code (iCode * lic) { case RLC: genRLC (ic); break; - + case GETHBIT: genGetHbit (ic); break; @@ -1508,7 +2102,7 @@ void genXA51Code (iCode * lic) { 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 '=': @@ -1537,23 +2131,27 @@ void genXA51Code (iCode * lic) { case RECEIVE: genReceive (ic); break; - + case SEND: addSet (&_G.sendSet, ic); break; - + + case DUMMY_READ_VOLATILE: + genDummyRead (ic); + break; + default: ic = ic; } } - - + + /* now we are ready to call the peep hole optimizer */ if (!options.nopeep) peepHole (&lineHead); - + /* now do the actual printing */ - printLine (lineHead, codeOutFile); + printLine (lineHead, codeOutBuf); return; }