X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fxa51%2Fgen.c;h=b466d5dd544f402412cf65cf97c68b495dc4b415;hb=697d97a43ba4c1eb596d7db62f0e53c149861798;hp=fa2823bdb8a87b388a2f06a274eb7ceb2ebf2d69;hpb=5187439e012ebae038b7f75b933129aa725534f4;p=fw%2Fsdcc diff --git a/src/xa51/gen.c b/src/xa51/gen.c index fa2823bd..b466d5dd 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) @@ -77,7 +74,9 @@ static struct { short inLine; short debugLine; + short stackExtend; short nRegsSaved; + short parmsPushed; set *sendSet; } _G; @@ -94,6 +93,21 @@ 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 *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); +} + /*-----------------------------------------------------------------*/ /* emitcode - writes the code into a file : for now it is simple */ /*-----------------------------------------------------------------*/ @@ -127,6 +141,15 @@ static void emitcode (char *inst, char *fmt,...) { va_end (ap); } +char *getStackOffset(int stack) { + static char gsoBuf[1024]; + sprintf (gsoBuf, "r7+(%d%+d%+d%+d)", stack, + FUNC_ISISR(currFunc->type) ? + port->stack.isr_overhead : port->stack.call_overhead, + currFunc->stack, _G.nRegsSaved); + return gsoBuf; +} + /*-----------------------------------------------------------------*/ /* newAsmop - creates a new asmOp */ /*-----------------------------------------------------------------*/ @@ -148,9 +171,10 @@ char *aopTypeName(asmop *aop) { 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"; } @@ -158,40 +182,68 @@ char *aopTypeName(asmop *aop) { /*-----------------------------------------------------------------*/ /* 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; - if (sym->regs[1]) { + sprintf (aop->name[0], sym->regs[0]->name); + if (size > 2) { sprintf (aop->name[1], sym->regs[1]->name); } - sprintf (aop->name[0], sym->regs[0]->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); - 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; } @@ -200,45 +252,99 @@ static asmop *aopForSym(symbol *sym, bool result) { if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) { aop->type=AOP_DIR; sprintf (aop->name[0], sym->rname); - sprintf (aop->name[1], "#0x%02x", POINTER); + 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"); - sprintf (aop->name[1], "#0x%02x", CPOINTER); 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]"); - if (result) { - 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 { - sprintf (aop->name[1], "#0x%02x", FPOINTER); + 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; } - return aop; - } - - // special case for a function - if (IS_FUNC (sym->type)) { - aop->type=AOP_IMMD; - sprintf (aop->name[0], sym->rname); - return aop; } - - fprintf (stderr, "aopForSym (%s): What's up?\n", sym->name); - exit (1); + + bailOut("aopForSym"); + return NULL; } /*-----------------------------------------------------------------*/ @@ -246,25 +352,36 @@ static asmop *aopForSym(symbol *sym, bool result) { /*-----------------------------------------------------------------*/ static asmop *aopForVal(operand *op) { asmop *aop; - long v=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: - fprintf (stderr, "aopForVal (lit): unknown size\n"); - exit (1); + bailOut("aopForVal"); } return aop; } @@ -284,36 +401,57 @@ static asmop *aopForVal(operand *op) { 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; } -char *opRegName(operand *op, int offset, char *opName) { +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) { + 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)) @@ -321,46 +459,48 @@ char *opRegName(operand *op, int offset, char *opName) { 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)) { switch (SPEC_NOUN(OP_VALUE(op)->type)) { + case V_SBIT: 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) { static char line[132]; - bool isPtr = op->isPtr | op->isGptr; + sym_link *optype=operandType(op); + bool isPtr = IS_PTR(optype); if (IS_SYMOP(op)) { symbol *sym=OP_SYMBOL(op); @@ -368,9 +508,24 @@ char * printOp (operand *op) { sym=SYM_SPIL_LOC(sym); } if (isPtr) { - sprintf (line, "[%s]:", sym->name); + sprintf (line, "["); + if (DCL_TYPE(optype)==FPOINTER) + strcat (line, "far * "); + else if (DCL_TYPE(optype)==CPOINTER) + strcat (line, "code * "); + else if (DCL_TYPE(optype)==GPOINTER) + strcat (line, "gen * "); + else if (DCL_TYPE(optype)==POINTER) + strcat (line, "near * "); + else + strcat (line, "unknown * "); + strcat (line, "("); + strcat (line, nounName(sym->etype)); + strcat (line, ")"); + strcat (line, sym->name); + strcat (line, "]:"); } else { - sprintf (line, "%s:", sym->name); + sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name); } if (sym->regs[0]) { strcat (line, sym->regs[0]->name); @@ -381,7 +536,11 @@ char * printOp (operand *op) { return line; } if (sym->onStack) { - sprintf (line+strlen(line), "stack+%d", sym->stack); + 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))) { @@ -399,17 +558,28 @@ 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 * "); + else if (DCL_TYPE(optype)==CPOINTER) + strcat (line, "code * "); + else if (DCL_TYPE(optype)==GPOINTER) + strcat (line, "gen * "); + else if (DCL_TYPE(optype)==POINTER) + strcat (line, "near * "); + else + strcat (line, "unknown * "); + } // forget about static, volatile, ... for now 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; } @@ -417,7 +587,7 @@ char * printOp (operand *op) { void printIc (char *op, iCode * ic, bool result, bool left, bool right) { char line[132]; - sprintf (line, "%s", op); + sprintf (line, "%s(%d)", op, ic->lineno); if (result) { strcat (line, " result="); strcat (line, printOp (IC_RESULT(ic))); @@ -434,19 +604,23 @@ void printIc (char *op, iCode * ic, bool result, bool left, bool right) { } /*-----------------------------------------------------------------*/ -/* 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; } @@ -525,10 +699,51 @@ static void genUminus (iCode * ic) { } /*-----------------------------------------------------------------*/ -/* 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++; + } } /*-----------------------------------------------------------------*/ @@ -542,7 +757,43 @@ static void genIpop (iCode * ic) { /* genCall - generates a call statement */ /*-----------------------------------------------------------------*/ static void genCall (iCode * ic) { - emitcode (";", "genCall %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"); + } } /*-----------------------------------------------------------------*/ @@ -561,10 +812,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, codeOutFile); + emitcode ("", "%s:", sym->rname); if (IFFUNC_ISNAKED(type)) @@ -573,10 +825,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); + } } /*-----------------------------------------------------------------*/ @@ -587,20 +839,53 @@ genEndFunction (iCode * ic) { 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) { - emitcode (";", "genRet"); + + 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); } /*-----------------------------------------------------------------*/ @@ -611,23 +896,73 @@ 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)); } /*-----------------------------------------------------------------*/ -/* 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; } /*-----------------------------------------------------------------*/ @@ -662,19 +997,37 @@ static void genMod (iCode * ic) { /*-----------------------------------------------------------------*/ /* 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); } @@ -716,11 +1069,14 @@ 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) { @@ -758,7 +1114,52 @@ static void genAnd (iCode * ic, iCode * ifx) { /* 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; } /*-----------------------------------------------------------------*/ @@ -772,7 +1173,10 @@ static void genXor (iCode * ic, iCode * ifx) { /* genInline - write the inline code out */ /*-----------------------------------------------------------------*/ static void genInline (iCode * ic) { + printIc ("genInline", ic, 0,0,0); + + emitcode ("", IC_INLINE(ic)); } /*-----------------------------------------------------------------*/ @@ -814,30 +1218,199 @@ static void genRightShift (iCode * ic) { /* genPointerGet - generate code for pointer get */ /*-----------------------------------------------------------------*/ static void genPointerGet (iCode * ic, iCode *pi) { + 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); + + if (!IS_PTR(operandType(left))) { + bailOut ("genPointerGet: pointer required"); + } + + aopOp(left,FALSE,FALSE); + size=aopOp(result,TRUE,aopIsDir(left)); + + if (IS_GENPTR(operandType(left))) { + 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_REG: + 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; + } + bailOut ("genPointerGet"); } /*-----------------------------------------------------------------*/ /* genPointerSet - stores the value into a pointer location */ /*-----------------------------------------------------------------*/ static void genPointerSet (iCode * ic, iCode *pi) { + char *instr; + operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic); + int size; + printIc ("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; 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; @@ -849,31 +1422,77 @@ static void genIfx (iCode * ic, iCode * popIc) { 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_DIR: 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_NAME(cond)[1]) { - 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); return; } + bailOut ("genIfx"); } /*-----------------------------------------------------------------*/ /* genAddrOf - generates code for address of */ /*-----------------------------------------------------------------*/ static void genAddrOf (iCode * ic) { + int size; + operand *left=IC_LEFT(ic); + printIc ("genAddrOf", ic, 1,1,0); + + 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 (size > 2) { + // this must be a generic pointer + emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER); + } + return; + } + + if (isOperandInDirSpace(left) || + isOperandInFarSpace(left) || + isOperandInCodeSpace(left)) { + 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)) { + space=1; + } else if (isOperandInCodeSpace(left)) { + space=2; + } + emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space); + } + return; + } + + bailOut("genAddrOf"); } /*-----------------------------------------------------------------*/ @@ -881,33 +1500,21 @@ static void genAddrOf (iCode * ic) { /*-----------------------------------------------------------------*/ 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_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)) { @@ -918,24 +1525,32 @@ static void genAssign (iCode * ic) { 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 (IS_GENPTR(operandType(result))) { - 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; } - } /*-----------------------------------------------------------------*/ @@ -956,7 +1571,48 @@ static void genCast (iCode * ic) { /* 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; } @@ -974,13 +1630,8 @@ void genXA51Code (iCode * lic) { 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) { @@ -994,7 +1645,7 @@ void genXA51Code (iCode * 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 ==.", @@ -1002,7 +1653,8 @@ void genXA51Code (iCode * lic) { 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 @@ -1096,25 +1748,27 @@ void genXA51Code (iCode * lic) { 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: @@ -1162,7 +1816,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 '=':