X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fhc08%2Fgen.c;h=8c93b380c85b1083471488e31910cd8b5eb77e86;hb=3062f96ccb55d1d05caf9c8782f4961f87b341ce;hp=0487f96660767fdd6b72f8164bf513eb3a2528bd;hpb=8d326ee2d53edf7e720d694f73d29b8b1a27d87d;p=fw%2Fsdcc diff --git a/src/hc08/gen.c b/src/hc08/gen.c index 0487f966..8c93b380 100644 --- a/src/hc08/gen.c +++ b/src/hc08/gen.c @@ -27,8 +27,12 @@ -------------------------------------------------------------------------*/ -#define D(x) -//#define D(x) x +/* Use the D macro for basic (unobtrusive) debugging messages */ +//#define D(x) +#define D(x) x +/* Use the DD macro for detailed debugging messages */ +#define DD(x) +//#define DD(x) x #include #include @@ -47,6 +51,7 @@ char *aopLiteralLong (value * val, int offset, int size); extern int allocInfo; static int pushReg (regs *reg, bool freereg); static void pullReg (regs *reg); +static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs); static char *zero = "#0x00"; static char *one = "#0x01"; @@ -78,7 +83,7 @@ static asmop *hc08_aop_pass[4]; extern int hc08_ptrRegReq; extern int hc08_nRegs; -extern FILE *codeOutFile; +extern struct dbuf_s *codeOutBuf; //static void saveRBank (int, iCode *, bool); static bool operandsEqu (operand * op1, operand * op2); static void loadRegFromConst (regs *reg, char *c); @@ -162,7 +167,7 @@ emitcode (char *inst, char *fmt,...) else vsprintf (lb, fmt, ap); - while (isspace (*lbp)) + while (isspace ((unsigned char)*lbp)) lbp++; if (lbp && *lbp) @@ -172,6 +177,7 @@ emitcode (char *inst, char *fmt,...) lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; lineCurr->ic = _G.current_iCode; + lineCurr->isComment = (*lbp==';'); //printf("%s\n", lb); va_end (ap); @@ -187,6 +193,7 @@ static void emitLabel (symbol *tlbl) { emitcode ("", "%05d$:", (tlbl->key +100)); + lineCurr->isLabel = 1; } /*-----------------------------------------------------------------*/ @@ -226,7 +233,7 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) return; } - D(emitcode ("", "; transferRegReg(%s,%s)", + DD(emitcode ("", "; transferRegReg(%s,%s)", sreg->name, dreg->name)); srcidx = sreg->rIdx; @@ -410,18 +417,18 @@ pullReg (regs *reg) updateCFA(); break; case HX_IDX: - emitcode ("pulx", ""); + emitcode ("pulh", ""); _G.stackPushes--; updateCFA(); - emitcode ("pulh", ""); + emitcode ("pulx", ""); _G.stackPushes--; updateCFA(); break; case XA_IDX: - emitcode ("pula", ""); + emitcode ("pulx", ""); _G.stackPushes--; updateCFA(); - emitcode ("pulx", ""); + emitcode ("pula", ""); _G.stackPushes--; updateCFA(); break; @@ -597,7 +604,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) printf(" reg missing operand link\n"); #endif - D(emitcode ("", "; loadRegFromAop (%s, %s, %d)", + DD(emitcode ("", "; loadRegFromAop (%s, %s, %d)", reg->name, aopName (aop), loffset)); /* If operand is volatile, we cannot optimize. */ @@ -612,7 +619,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) && (reg->aopofs == loffset)) { hc08_useReg(reg); - D(emitcode ("","; already had correct value for %s", reg->name)); + DD(emitcode ("","; already had correct value for %s", reg->name)); return; } @@ -622,7 +629,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) && operandsEqu(hc08_reg_h->aop->op,aop->op) && (hc08_reg_h->aopofs == loffset)) { - D(emitcode ("","; found correct value for %s in h", reg->name)); + DD(emitcode ("","; found correct value for %s in h", reg->name)); transferRegReg (hc08_reg_h, reg, FALSE); hc08_useReg (reg); return; @@ -633,7 +640,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) && operandsEqu(hc08_reg_x->aop->op,aop->op) && (hc08_reg_x->aopofs == loffset)) { - D(emitcode ("","; found correct value for %s in x", reg->name)); + DD(emitcode ("","; found correct value for %s in x", reg->name)); transferRegReg (hc08_reg_x, reg, FALSE); hc08_useReg (reg); return; @@ -643,7 +650,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) && operandsEqu(hc08_reg_a->aop->op,aop->op) && (hc08_reg_a->aopofs == loffset)) { - D(emitcode ("","; found correct value for %s in a", reg->name)); + DD(emitcode ("","; found correct value for %s in a", reg->name)); transferRegReg (hc08_reg_a, reg, FALSE); hc08_useReg (reg); return; @@ -662,7 +669,13 @@ forceload: emitcode ("clra", ""); /* TODO: handle sign extension */ } else - emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE)); + { + char * l = aopAdrStr (aop, loffset, FALSE); + if (!strcmp (l, zero)) + emitcode ("clra", ""); + else + emitcode ("lda", "%s", l); + } break; case X_IDX: if (aop->type == AOP_REG) @@ -673,9 +686,23 @@ forceload: emitcode ("clrx", ""); /* TODO: handle sign extension */ } else - emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE)); + { + char * l = aopAdrStr (aop, loffset, FALSE); + if (!strcmp (l, zero)) + emitcode ("clrx", ""); + else + emitcode ("ldx", "%s", l); + } break; case H_IDX: + { + char * l = aopAdrStr (aop, loffset, FALSE); + if (!strcmp (l, zero)) + { + emitcode ("clrh", ""); + break; + } + } if (hc08_reg_a->isFree) { loadRegFromAop (hc08_reg_a, aop, loffset); @@ -747,25 +774,51 @@ forceload: /*--------------------------------------------------------------------------*/ /* forceStackedAop - Reserve space on the stack for asmop aop; when */ /* freeAsmop is called with aop, the stacked data will */ -/* be copied to the original aop location and */ +/* be copied to the original aop location. */ /*--------------------------------------------------------------------------*/ static asmop * -forceStackedAop (asmop *aop) +forceStackedAop (asmop *aop, bool copyOrig) { + regs *reg; int loffset; asmop *newaop = newAsmop (aop->type); memcpy (newaop, aop, sizeof(*newaop)); - D(emitcode("", "; forcedStackAop %s", aopName(aop))); + DD(emitcode("", "; forcedStackAop %s", aopName(aop))); + + if (copyOrig && hc08_reg_a->isFree) + reg = hc08_reg_a; + else if (copyOrig && hc08_reg_x->isFree) + reg = hc08_reg_x; + else + reg = NULL; + for (loffset=0; loffset < newaop->size; loffset++) { asmop *aopsof = newAsmop (AOP_SOF); aopsof->size = 1; - aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE); + if (copyOrig && reg) + { + loadRegFromAop (reg, aop, loffset); + aopsof->aopu.aop_stk = pushReg (reg, FALSE); + } + else + { + aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE); + } aopsof->op = aop->op; newaop->stk_aop[loffset] = aopsof; } newaop->stacked = 1; + + if (!reg && copyOrig) + { + for (loffset=0; loffset < newaop->size; loffset++) + { + transferAopAop (aop, loffset, newaop, loffset); + } + } + return newaop; } @@ -782,7 +835,7 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) int otheridx; #endif - D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d", + DD(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d", reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr)); if ((reg->rIdx == HX_IDX) && aop->stacked @@ -818,7 +871,10 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) if (aop->type == AOP_DUMMY) return; - + + if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */ + return; /* away, so just toss the result */ + switch (regidx) { case A_IDX: @@ -899,19 +955,19 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) && operandsEqu(otherreg->aop->op,aop->op) && (otherreg->aopofs == loffset)) { - D(emitcode("","; marking %s stale", otherreg->name)); + DD(emitcode("","; marking %s stale", otherreg->name)); otherreg->aop=NULL; } } if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop) { hc08_reg_hx->aop = NULL; - D(emitcode("","; marking hx stale")); + DD(emitcode("","; marking hx stale")); } if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop) { hc08_reg_xa->aop = NULL; - D(emitcode("","; marking xa stale")); + DD(emitcode("","; marking xa stale")); } reg->aop = aop; @@ -1110,7 +1166,7 @@ storeRegToFullAop (regs *reg, asmop *aop, bool isSigned) /*--------------------------------------------------------------------------*/ /* transferAopAop - Transfer the value at logical offset srcofs of asmop */ -/* srcaop to logical offset dstofs of asmop dstofs. */ +/* srcaop to logical offset dstofs of asmop dstaop. */ /*--------------------------------------------------------------------------*/ static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) @@ -1123,7 +1179,8 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) /* ignore transfers at the same byte, unless its volatile */ if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE) && dstaop->op && !isOperandVolatile (dstaop->op, FALSE) - && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs) + && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs + && dstaop->type == srcaop->type) return; if (srcaop->stacked && srcaop->stk_aop[srcofs]) @@ -1138,10 +1195,10 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) return; } -// D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)", +// DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)", // aopName (srcaop), srcofs, aopName (dstaop), dstofs)); -// D(emitcode ("", "; srcaop->type = %d", srcaop->type)); -// D(emitcode ("", "; dstaop->type = %d", dstaop->type)); +// DD(emitcode ("", "; srcaop->type = %d", srcaop->type)); +// DD(emitcode ("", "; dstaop->type = %d", dstaop->type)); if (dstofs >= dstaop->size) return; @@ -1152,7 +1209,7 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) if (srcaop->type == AOP_LIT) { unsigned long lit; - unsigned char bytemask; + unsigned long bytemask; lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit); bytemask = (lit >> (srcofs*8)) & 0xff; @@ -1316,10 +1373,10 @@ rmwWithAop (char *rmwop, asmop *aop, int loffset) break; case AOP_EXT: needpula = pushRegIfUsed (hc08_reg_a); - loadRegFromAop (hc08_reg_a, aop, loffset); + loadRegFromAop (hc08_reg_a, aop, loffset); rmwWithReg (rmwop, hc08_reg_a); if (strcmp ("tst", rmwop)) - storeRegToAop (hc08_reg_a, aop, loffset); + storeRegToAop (hc08_reg_a, aop, loffset); pullOrFreeReg (hc08_reg_a, needpula); break; case AOP_DUMMY: @@ -1777,14 +1834,22 @@ aopOp (operand * op, iCode * ic, bool result) /* else spill location */ if (sym->usl.spillLoc) { + asmop *oldAsmOp = NULL; + if (sym->usl.spillLoc->aop && sym->usl.spillLoc->aop->size != getSize (sym->type)) { /* force a new aop if sizes differ */ + oldAsmOp = sym->usl.spillLoc->aop; sym->usl.spillLoc->aop = NULL; //printf ("forcing new aop\n"); } sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result); + if (sym->usl.spillLoc->aop->size != getSize (sym->type)) + { + /* Don't reuse the new aop, go with the last one */ + sym->usl.spillLoc->aop = oldAsmOp; + } aop->size = getSize (sym->type); aop->op = op; aop->isaddr = op->isaddr; @@ -1836,7 +1901,7 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop) int stackAdjust; int loffset; - D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop))); + DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop))); aop->stacked = 0; stackAdjust = 0; for (loffset=0; loffsetsize; loffset++) @@ -1878,7 +1943,7 @@ aopDerefAop (asmop *aop) sym_link *type, *etype; int p_type; - D(emitcode ("", "; aopDerefAop(%s)", aopName(aop))); + DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop))); if (aop->op) { @@ -2064,67 +2129,6 @@ getDataSize (operand * op) return size; } -/*-----------------------------------------------------------------*/ -/* outAcc - output Acc */ -/*-----------------------------------------------------------------*/ -static void -outAcc (operand * result) -{ - int size, offset; - size = getDataSize (result); - if (size) - { - storeRegToAop (hc08_reg_a, AOP (result), 0); - size--; - offset = 1; - /* unsigned or positive */ - while (size--) - { - storeConstToAop (zero, AOP (result), offset++); - } - } -} - -/*-----------------------------------------------------------------*/ -/* outBitC - output a bit C */ -/*-----------------------------------------------------------------*/ -static void -outBitC (operand * result) -{ - -#if 0 - /* if the result is bit */ - if (AOP_TYPE (result) == AOP_CRY) - aopPut (AOP (result), "c", 0); - else -#endif - { - emitcode ("clra", ""); - emitcode ("rola", ""); - outAcc (result); - } -} - -/*-----------------------------------------------------------------*/ -/* outBitNV - output a bit N^V */ -/*-----------------------------------------------------------------*/ -static void -outBitNV (operand * result) -{ - symbol *tlbl, *tlbl1; - - tlbl = newiTempLabel (NULL); - tlbl1 = newiTempLabel (NULL); - - emitBranch ("blt", tlbl); - loadRegFromConst (hc08_reg_a, zero); - emitBranch ("bra", tlbl1); - emitLabel (tlbl); - loadRegFromConst (hc08_reg_a, one); - emitLabel (tlbl1); - outAcc (result); -} - /*-----------------------------------------------------------------*/ /* asmopToBool - Emit code to convert an asmop to a boolean. */ @@ -2184,7 +2188,7 @@ asmopToBool (asmop *aop, bool resultInA) emitcode ("tsta", ""); emitcode ("bne", "%05d$", (tlbl->key + 100)); emitcode ("tstx", ""); - emitcode ("", "%05d$:", (tlbl->key + 100)); + emitLabel (tlbl); } else { @@ -2209,6 +2213,14 @@ asmopToBool (asmop *aop, bool resultInA) flagsonly = FALSE; } break; + case AOP_LIT: + /* Higher levels should optimize this case away but let's be safe */ + if ((unsigned long) floatFromVal (aop->aopu.aop_lit)) + loadRegFromConst (hc08_reg_a, one); + else + loadRegFromConst (hc08_reg_a, zero); + hc08_freeReg(hc08_reg_a); + break; default: if (size==1) { @@ -2237,7 +2249,7 @@ asmopToBool (asmop *aop, bool resultInA) emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE)); emitcode ("bne", "%05d$", (tlbl->key + 100)); emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE)); - emitcode ("", "%05d$:", (tlbl->key + 100)); + emitLabel (tlbl); break; } } @@ -2414,7 +2426,7 @@ genUminus (iCode * ic) else { if (IS_AOP_XA (AOP (IC_RESULT (ic)))) - result = forceStackedAop (AOP (IC_RESULT (ic))); + result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE); else result = AOP (IC_RESULT (ic)); @@ -2645,7 +2657,7 @@ static void genSend(set *sendSet) iCode *sic; for (sic = setFirstItem (sendSet); sic; - sic = setNextItem (sendSet)) { + sic = setNextItem (sendSet)) { int size, offset = 0; aopOp (IC_LEFT (sic), sic, FALSE); size = AOP_SIZE (IC_LEFT (sic)); @@ -2675,7 +2687,7 @@ genCall (iCode * ic) D(emitcode("; genCall","")); dtype = operandType (IC_LEFT (ic)); - /* if send set is not empty the assign */ + /* if send set is not empty then assign */ if (_G.sendSet) { if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */ @@ -2755,6 +2767,8 @@ genPcall (iCode * ic) emitBranch ("bsr", tlbl); emitBranch ("bra", rlbl); emitLabel (tlbl); + _G.stackPushes += 2; /* account for the bsr return address now on stack */ + updateCFA(); /* Push the function's address */ aopOp (IC_LEFT (ic), ic, FALSE); @@ -2773,6 +2787,8 @@ genPcall (iCode * ic) emitcode ("rts", ""); emitLabel (rlbl); + _G.stackPushes -= 4; /* account for rts here & in called function */ + updateCFA(); /* if we need assign a result value */ @@ -2823,12 +2839,6 @@ resultRemat (iCode * ic) return 0; } -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define STRCASECMP stricmp -#else -#define STRCASECMP strcasecmp -#endif - /*-----------------------------------------------------------------*/ /* inExcludeList - return 1 if the string is in exclude Reg list */ /*-----------------------------------------------------------------*/ @@ -2856,18 +2866,21 @@ inExcludeList (char *s) static void genFunction (iCode * ic) { - symbol *sym; + symbol *sym = OP_SYMBOL (IC_LEFT (ic)); sym_link *ftype; - int calleesaves_saved_register = -1; + iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL; + int stackAdjust = sym->stack; + int accIsFree = sym->recvSize == 0; _G.nRegsSaved = 0; _G.stackPushes = 0; /* create the function header */ emitcode (";", "-----------------------------------------"); - emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name); + emitcode (";", " function %s", sym->name); emitcode (";", "-----------------------------------------"); emitcode ("", "%s:", sym->rname); + lineCurr->isLabel = 1; ftype = operandType (IC_LEFT (ic)); _G.stackOfs = 0; @@ -2880,8 +2893,6 @@ genFunction (iCode * ic) return; } - - /* if this is an interrupt service routine then save h */ if (IFFUNC_ISISR (sym->type)) @@ -2890,47 +2901,52 @@ genFunction (iCode * ic) if (!inExcludeList ("h")) pushReg (hc08_reg_h, FALSE); } - else + + /* For some cases it is worthwhile to perform a RECEIVE iCode */ + /* before setting up the stack frame completely. */ + while (ric && ric->next && ric->next->op == RECEIVE) + ric = ric->next; + while (ric && IC_RESULT (ric)) { - /* if callee-save to be used for this function - then save the registers being used in this function */ - if (IFFUNC_CALLEESAVES(sym->type)) - { - int i; + symbol * rsym = OP_SYMBOL (IC_RESULT (ric)); + int rsymSize = rsym ? getSize(rsym->type) : 0; - /* if any registers used */ - if (sym->regsUsed) - { - /* save the registers used */ - for (i = 0; i < sym->regsUsed->size; i++) - { - if (bitVectBitValue (sym->regsUsed, i)) - { - /* remember one saved register for later usage */ - if (calleesaves_saved_register < 0) - calleesaves_saved_register = i; - pushReg (hc08_regWithIdx (i), FALSE); - _G.nRegsSaved++; - } - } - } - } - } + if (rsym->isitmp) + { + if (rsym && rsym->regType == REG_CND) + rsym = NULL; + if (rsym && (rsym->accuse || rsym->ruonly)) + rsym = NULL; + if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc) + rsym = rsym->usl.spillLoc; + } - if (IFFUNC_ISREENT (sym->type) || options.stackAuto) - { + /* If the RECEIVE operand immediately spills to the first entry on the */ + /* stack, we can push it directly rather than use an sp relative store. */ + if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize) + { + int ofs; + _G.current_iCode = ric; + D(emitcode ("; genReceive","")); + for (ofs=0; ofs < rsymSize; ofs++) + { + regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0]; + pushReg (reg, TRUE); + if (reg->rIdx == A_IDX) + accIsFree = 1; + stackAdjust--; + } + _G.current_iCode = ic; + ric->generated = 1; + } + ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL; } /* adjust the stack for the function */ - if (sym->stack) + if (stackAdjust) { - - int i = sym->stack; -// if (i > 256) -// werror (W_STACK_OVERFLOW, sym->name); - - adjustStack (-i); + adjustStack (-stackAdjust); } _G.stackOfs = sym->stack; _G.stackPushes = 0; @@ -2938,7 +2954,7 @@ genFunction (iCode * ic) /* if critical function then turn interrupts off */ if (IFFUNC_ISCRITICAL (ftype)) { - if (IFFUNC_ARGS (ftype)) + if (!accIsFree) { /* Function was passed parameters, so make sure A is preserved */ pushReg (hc08_reg_a, FALSE); @@ -3145,7 +3161,7 @@ genLabel (iCode * ic) debugFile->writeLabel(IC_LABEL (ic), ic); - emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100)); + emitLabel (IC_LABEL (ic)); } @@ -3205,7 +3221,7 @@ genPlusIncr (iCode * ic) bool needpulh; bool needpula; unsigned int size = getDataSize (IC_RESULT (ic)); - int offset; + unsigned int offset; symbol *tlbl = NULL; left = IC_LEFT (ic); @@ -3219,7 +3235,7 @@ genPlusIncr (iCode * ic) icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); - D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)))); + DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)))); if ((IS_AOP_HX (AOP (left)) || ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) ) @@ -3245,7 +3261,7 @@ genPlusIncr (iCode * ic) return TRUE; } - D(emitcode ("", "; icount = %d, sameRegs=%d", icount, + DD(emitcode ("", "; icount = %d, sameRegs=%d", icount, sameRegs (AOP (left), AOP (result)))); if ((icount > 255) || (icount<0)) @@ -3330,9 +3346,9 @@ genPlus (iCode * ic) if (genPlusIncr (ic) == TRUE) goto release; - D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)))); - D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)))); - D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)))); + DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)))); + DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)))); + DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)))); size = getDataSize (IC_RESULT (ic)); @@ -3360,7 +3376,7 @@ release: } /*-----------------------------------------------------------------*/ -/* genMinusDec :- does subtraction with deccrement if possible */ +/* genMinusDec :- does subtraction with decrement if possible */ /*-----------------------------------------------------------------*/ static bool genMinusDec (iCode * ic) @@ -3475,13 +3491,22 @@ genMinus (iCode * ic) leftOp = AOP(IC_LEFT(ic)); rightOp = AOP(IC_RIGHT(ic)); - sub = "sub"; offset = 0; + + if (IS_AOP_A (rightOp)) + { + loadRegFromAop ( hc08_reg_a, rightOp, offset); + accopWithAop (sub, leftOp, offset); + accopWithMisc ("nega", ""); + storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++); + goto release; + } + while (size--) { loadRegFromAop ( hc08_reg_a, leftOp, offset); - accopWithAop(sub, rightOp, offset); + accopWithAop (sub, rightOp, offset); storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++); sub = "sbc"; } @@ -3554,7 +3579,7 @@ genMultOneByte (operand * left, || (lUnsigned && rUnsigned)) { // just an unsigned 8*8=8/16 multiply - //D(emitcode (";","unsigned")); + //DD(emitcode (";","unsigned")); loadRegFromAop (hc08_reg_a, AOP (left), 0); loadRegFromAop (hc08_reg_x, AOP (right), 0); @@ -3572,7 +3597,7 @@ genMultOneByte (operand * left, /* left unsigned, right signed literal -- literal determines sign handling */ if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned) { - signed char val=floatFromVal (AOP (right)->aopu.aop_lit); + signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit); loadRegFromAop (hc08_reg_a, AOP (left), 0); if (val < 0) @@ -3616,7 +3641,7 @@ genMultOneByte (operand * left, if (AOP_TYPE(right)==AOP_LIT && !rUnsigned) { - signed char val=floatFromVal (AOP (right)->aopu.aop_lit); + signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit); /* AND literal negative */ if (val < 0) { emitcode ("ldx", "#0x%02x", -val); @@ -3948,11 +3973,10 @@ genModOneByte (operand * left, loadRegFromAop (hc08_reg_h, AOP (left), 1); loadRegFromAop (hc08_reg_a, AOP (left), 0); emitcode ("div", ""); - hc08_dirtyReg (hc08_reg_a, FALSE); - hc08_dirtyReg (hc08_reg_h, FALSE); - storeRegToFullAop (hc08_reg_h, AOP (result), FALSE); hc08_freeReg (hc08_reg_a); hc08_freeReg (hc08_reg_x); + hc08_dirtyReg (hc08_reg_h, FALSE); + storeRegToFullAop (hc08_reg_h, AOP (result), FALSE); hc08_freeReg (hc08_reg_h); return; } @@ -4022,8 +4046,8 @@ genModOneByte (operand * left, loadRegFromConst (hc08_reg_h, zero); emitcode ("div", ""); - hc08_dirtyReg (hc08_reg_x, FALSE); - hc08_dirtyReg (hc08_reg_a, FALSE); + hc08_freeReg (hc08_reg_a); + hc08_freeReg (hc08_reg_x); hc08_dirtyReg (hc08_reg_h, FALSE); if (runtimeSign || compiletimeSign) @@ -4148,108 +4172,146 @@ genIfxJump (iCode * ic, char *jval) ic->generated = 1; } + /*-----------------------------------------------------------------*/ -/* genCmp :- greater or less than comparison */ +/* exchangedCmp : returns the opcode need if the two operands are */ +/* exchanged in a comparison */ /*-----------------------------------------------------------------*/ -static void -genCmp (operand * left, operand * right, - operand * result, iCode * ifx, int sign, iCode *ic) -{ - int size, offset = 0; - unsigned long lit = 0L; - char *sub; - bool needpula = FALSE; - - D(emitcode ("; genCmp","")); - - /* subtract right from left if at the - end the carry flag is set then we know that - left is greater than right */ - size = max (AOP_SIZE (left), AOP_SIZE (right)); - - if (AOP_TYPE (right) == AOP_LIT) - { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - /* optimize if(x < 0) or if(x >= 0) */ - if (lit == 0L) - { - if (!sign) - { - CLRC; - } - else - { - loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1); - emitcode ("rola", ""); - hc08_useReg (hc08_reg_a); - } - sign = 0; - goto release; - } +static int +exchangedCmp (int opcode) +{ + switch (opcode) + { + case '<': + return '>'; + case '>': + return '<'; + case LE_OP: + return GE_OP; + case GE_OP: + return LE_OP; + case NE_OP: + return NE_OP; + case EQ_OP: + return EQ_OP; + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "opcode not a comparison"); } + return EQ_OP; /* shouldn't happen, but need to return something */ +} - if ((size==2) - && ((AOP_TYPE (right) == AOP_LIT) || - ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) ) - && hc08_reg_hx->isFree) - { - loadRegFromAop (hc08_reg_hx, AOP (left), 0); - emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE)); - hc08_freeReg (hc08_reg_hx); - goto release; +/*------------------------------------------------------------------*/ +/* negatedCmp : returns the equivalent opcode for when a comparison */ +/* if not true */ +/*------------------------------------------------------------------*/ +static int +negatedCmp (int opcode) +{ + switch (opcode) + { + case '<': + return GE_OP; + case '>': + return LE_OP; + case LE_OP: + return '>'; + case GE_OP: + return '<'; + case NE_OP: + return EQ_OP; + case EQ_OP: + return NE_OP; + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "opcode not a comparison"); } + return EQ_OP; /* shouldn't happen, but need to return something */ +} - offset = 0; - if (size==1) - sub="cmp"; - else - sub="sub"; - while (size--) - { - loadRegFromAop (hc08_reg_a, AOP (left), offset); - accopWithAop (sub, AOP (right), offset); - hc08_freeReg (hc08_reg_a); - offset++; - sub="sbc"; +/* compile only if the debugging macro D is enabled */ +#if (D(1) -0) +static char * +nameCmp (int opcode) +{ + switch (opcode) + { + case '<': + return "<"; + case '>': + return ">"; + case LE_OP: + return "<="; + case GE_OP: + return ">="; + case NE_OP: + return "!="; + case EQ_OP: + return "=="; + default: + return "invalid"; } +} +#endif -release: - freeAsmop (right, NULL, ic, TRUE); - freeAsmop (left, NULL, ic, TRUE); - if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) - { - outBitC (result); - } - else +/*------------------------------------------------------------------*/ +/* branchInstCmp : returns the conditional branch instruction that */ +/* will branch if the comparison is true */ +/*------------------------------------------------------------------*/ +static char * +branchInstCmp (int opcode, int sign) +{ + switch (opcode) { - /* if the result is used in the next - ifx conditional branch then generate - code a little differently */ - if (ifx) - { - pullOrFreeReg(hc08_reg_a,needpula); - genIfxJump (ifx, sign ? "s" : "c"); - } + case '<': + if (sign) + return "blt"; + else + return "bcs"; /* same as blo */ + case '>': + if (sign) + return "bgt"; else - if (!sign) - outBitC (result); - else - outBitNV (result); - pullOrFreeReg(hc08_reg_a,needpula); + return "bhi"; + case LE_OP: + if (sign) + return "ble"; + else + return "bls"; + case GE_OP: + if (sign) + return "bge"; + else + return "bcc"; /* same as bhs */ + case NE_OP: + return "bne"; + case EQ_OP: + return "beq"; + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "opcode not a comparison"); } + return "brn"; } -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ + +/*------------------------------------------------------------------*/ +/* genCmp :- greater or less than (and maybe with equal) comparison */ +/*------------------------------------------------------------------*/ static void -genCmpGt (iCode * ic, iCode * ifx) -{ +genCmp (iCode * ic, iCode * ifx) +{ operand *left, *right, *result; sym_link *letype, *retype; - int sign; + int sign, opcode; + int size, offset = 0; + unsigned long lit = 0L; + char *sub; + symbol *jlbl = NULL; + + opcode = ic->op; - D(emitcode ("; genCmpGt","")); + D(emitcode ("; genCmp", "(%s)",nameCmp (opcode))); result = IC_RESULT (ic); left = IC_LEFT (ic); @@ -4263,22 +4325,136 @@ genCmpGt (iCode * ic, iCode * ifx) aopOp (right, ic, FALSE); aopOp (result, ic, TRUE); - genCmp (right, left, result, ifx, sign,ic); + /* need register operand on left, prefer literal operand on right */ + if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT) + { + operand *temp = left; + left = right; + right = temp; + opcode = exchangedCmp (opcode); + } - freeAsmop (result, NULL, ic, TRUE); + if (ifx) + { + if (IC_TRUE (ifx)) + { + jlbl = IC_TRUE (ifx); + opcode = negatedCmp (opcode); + } + else + { + /* false label is present */ + jlbl = IC_FALSE (ifx); + } + } + + size = max (AOP_SIZE (left), AOP_SIZE (right)); + + if ((size == 2) + && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2)) + && ((AOP_TYPE (right) == AOP_LIT) || + ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) ) + && hc08_reg_hx->isFree) + { + loadRegFromAop (hc08_reg_hx, AOP (left), 0); + emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE)); + hc08_freeReg (hc08_reg_hx); + } + else + { + offset = 0; + if (size == 1) + sub = "cmp"; + else + { + sub = "sub"; + + /* These conditions depend on the Z flag bit, but Z is */ + /* only valid for the last byte of the comparison, not */ + /* the whole value. So exchange the operands to get a */ + /* comparison that doesn't depend on Z. (This is safe */ + /* to do here since ralloc won't assign multi-byte */ + /* operands to registers for comparisons) */ + if ((opcode == '>') || (opcode == LE_OP)) + { + operand *temp = left; + left = right; + right = temp; + opcode = exchangedCmp (opcode); + } + + if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE)) + { + lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0)) + { + offset++; + size--; + } + } + } + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop (sub, AOP (right), offset); + hc08_freeReg (hc08_reg_a); + offset++; + sub = "sbc"; + } + } + freeAsmop (right, NULL, ic, FALSE); + freeAsmop (left, NULL, ic, FALSE); + + if (ifx) + { + symbol *tlbl = newiTempLabel (NULL); + char *inst; + + freeAsmop (result, NULL, ic, TRUE); + + inst = branchInstCmp (opcode, sign); + emitBranch (inst, tlbl); + emitBranch ("jmp", jlbl); + emitLabel (tlbl); + + /* mark the icode as generated */ + ifx->generated = 1; + } + else + { + symbol *tlbl1 = newiTempLabel (NULL); + symbol *tlbl2 = newiTempLabel (NULL); + + emitBranch (branchInstCmp (opcode, sign), tlbl1); + loadRegFromConst (hc08_reg_a, zero); + emitBranch ("bra", tlbl2); + emitLabel (tlbl1); + loadRegFromConst (hc08_reg_a, one); + emitLabel (tlbl2); + storeRegToFullAop (hc08_reg_a, AOP(result), FALSE); + freeAsmop (result, NULL, ic, TRUE); + } + } /*-----------------------------------------------------------------*/ -/* genCmpLt - less than comparisons */ +/* genCmpEQorNE - equal or not equal comparison */ /*-----------------------------------------------------------------*/ static void -genCmpLt (iCode * ic, iCode * ifx) -{ +genCmpEQorNE (iCode * ic, iCode * ifx) +{ operand *left, *right, *result; sym_link *letype, *retype; - int sign; + int sign, opcode; + int size, offset = 0; + char *sub; + symbol *jlbl = NULL; + symbol *tlbl_NE = NULL; + symbol *tlbl_EQ = NULL; + + opcode = ic->op; - D(emitcode ("; genCmpLt","")); + D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode))); result = IC_RESULT (ic); left = IC_LEFT (ic); @@ -4287,141 +4463,128 @@ genCmpLt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - /* assign the amsops */ aopOp (left, ic, FALSE); aopOp (right, ic, FALSE); aopOp (result, ic, TRUE); - - genCmp (left, right, result, ifx, sign,ic); - - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* - compare and branch if not equal */ -/*-----------------------------------------------------------------*/ -static void -gencbneshort (operand * left, operand * right, symbol * lbl) -{ - int size = max (AOP_SIZE (left), AOP_SIZE (right)); - int offset = 0; - unsigned long lit = 0L; - - /* if the left side is a literal or - if the right is in a pointer register and left - is not */ - if (AOP_TYPE (left) == AOP_LIT) + + /* need register operand on left, prefer literal operand on right */ + if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT) { - operand *t = right; - right = left; - left = t; + operand *temp = left; + left = right; + right = temp; + opcode = exchangedCmp (opcode); } - if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - while (size--) + if (ifx) { - loadRegFromAop (hc08_reg_a, AOP (left), offset); - accopWithAop ("cmp", AOP (right), offset); - hc08_useReg (hc08_reg_a); - hc08_freeReg (hc08_reg_a); - emitBranch ("bne", lbl); - offset++; + if (IC_TRUE (ifx)) + { + jlbl = IC_TRUE (ifx); + opcode = negatedCmp (opcode); + } + else + { + /* false label is present */ + jlbl = IC_FALSE (ifx); + } } - -} - -/*-----------------------------------------------------------------*/ -/* gencjne - compare and jump if not equal */ -/*-----------------------------------------------------------------*/ -static void -gencjne (operand * left, operand * right, symbol * lbl) -{ - symbol *tlbl = newiTempLabel (NULL); - - gencbneshort (left, right, lbl); - - loadRegFromConst (hc08_reg_a, one); - emitBranch ("bra", tlbl); - emitLabel (lbl); - loadRegFromConst (hc08_reg_a, zero); - emitLabel (tlbl); - - hc08_useReg(hc08_reg_a); - hc08_freeReg(hc08_reg_a); -} - -/*-----------------------------------------------------------------*/ -/* genCmpEq - generates code for equal to */ -/*-----------------------------------------------------------------*/ -static void -genCmpEq (iCode * ic, iCode * ifx) -{ - operand *left, *right, *result; - - D(emitcode ("; genCmpEq","")); - - aopOp ((left = IC_LEFT (ic)), ic, FALSE); - aopOp ((right = IC_RIGHT (ic)), ic, FALSE); - aopOp ((result = IC_RESULT (ic)), ic, TRUE); - - /* if literal, literal on the right or - if the right is in a pointer register and left - is not */ - if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) + + size = max (AOP_SIZE (left), AOP_SIZE (right)); + + if ((size == 2) + && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2)) + && ((AOP_TYPE (right) == AOP_LIT) || + ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) ) + && hc08_reg_hx->isFree) { - operand *t = IC_RIGHT (ic); - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = t; + loadRegFromAop (hc08_reg_hx, AOP (left), 0); + emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE)); + hc08_freeReg (hc08_reg_hx); + } + else + { + offset = 0; + sub = "cmp"; + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop (sub, AOP (right), offset); + if (size) + { + if (!tlbl_NE) + tlbl_NE = newiTempLabel (NULL); + emitBranch ("bne", tlbl_NE); + } + hc08_freeReg (hc08_reg_a); + offset++; + } } + freeAsmop (right, NULL, ic, FALSE); + freeAsmop (left, NULL, ic, FALSE); - if (ifx && !AOP_SIZE (result)) + if (ifx) { - symbol *tlbl; - tlbl = newiTempLabel (NULL); - gencbneshort (left, right, tlbl); - if (IC_TRUE (ifx)) + freeAsmop (result, NULL, ic, TRUE); + + if (opcode == EQ_OP) { - emitBranch ("jmp", IC_TRUE (ifx)); - emitLabel (tlbl); + if (!tlbl_EQ) + tlbl_EQ = newiTempLabel (NULL); + emitBranch ("beq", tlbl_EQ); + if (tlbl_NE) + emitLabel (tlbl_NE); + emitBranch ("jmp", jlbl); + emitLabel (tlbl_EQ); } else - { - symbol *lbl = newiTempLabel (NULL); - emitBranch ("bra", lbl); - emitLabel (tlbl); - emitBranch ("jmp", IC_FALSE (ifx)); - emitLabel (lbl); - } - + { + if (!tlbl_NE) + tlbl_NE = newiTempLabel (NULL); + emitBranch ("bne", tlbl_NE); + emitBranch ("jmp", jlbl); + emitLabel (tlbl_NE); + } + /* mark the icode as generated */ ifx->generated = 1; - goto release; - } - - gencjne (left, right, newiTempLabel (NULL)); - if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) - { - storeRegToAop (hc08_reg_a, AOP (result), 0); - goto release; } - if (ifx) + else { - genIfxJump (ifx, "a"); - goto release; + symbol *tlbl = newiTempLabel (NULL); + + if (opcode == EQ_OP) + { + if (!tlbl_EQ) + tlbl_EQ = newiTempLabel (NULL); + emitBranch ("beq", tlbl_EQ); + if (tlbl_NE) + emitLabel (tlbl_NE); + loadRegFromConst (hc08_reg_a, zero); + emitBranch ("bra", tlbl); + emitLabel (tlbl_EQ); + loadRegFromConst (hc08_reg_a, one); + } + else + { + if (!tlbl_NE) + tlbl_NE = newiTempLabel (NULL); + emitBranch ("bne", tlbl_NE); + loadRegFromConst (hc08_reg_a, zero); + emitBranch ("bra", tlbl); + emitLabel (tlbl_NE); + loadRegFromConst (hc08_reg_a, one); + } + + emitLabel (tlbl); + storeRegToFullAop (hc08_reg_a, AOP(result), FALSE); + freeAsmop (result, NULL, ic, TRUE); } - /* if the result is used in an arithmetic operation - then put the result in place */ - if (AOP_TYPE (result) != AOP_CRY) - outAcc (result); - -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); + } + /*-----------------------------------------------------------------*/ /* ifxForOp - returns the icode containing the ifx for operand */ /*-----------------------------------------------------------------*/ @@ -4449,24 +4612,24 @@ genPointerGetSetOfs (iCode *ic) { iCode *lic = ic->next; bool pset, pget; - int offset, size; + int size; symbol *sym; asmop *derefaop; /* Make sure we have a next iCode */ - D(emitcode("","; checking lic")); + DD(emitcode("","; checking lic")); if (!lic) return FALSE; /* Make sure the result of the addition is an iCode */ - D(emitcode("","; checking IS_ITEMP")); + DD(emitcode("","; checking IS_ITEMP")); if (!IS_ITEMP (IC_RESULT (ic))) return FALSE; /* Make sure the next iCode is a pointer set or get */ pset = POINTER_SET(lic); pget = POINTER_GET(lic); - D(emitcode("","; pset=%d, pget=%d",pset,pget)); + DD(emitcode("","; pset=%d, pget=%d",pset,pget)); if (!pset && !pget) return FALSE; @@ -4474,25 +4637,25 @@ genPointerGetSetOfs (iCode *ic) if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1) return FALSE; - D(emitcode("", "; checking pset operandsEqu")); + DD(emitcode("", "; checking pset operandsEqu")); if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic))) return FALSE; - D(emitcode("", "; checking pget operandsEqu")); + DD(emitcode("", "; checking pget operandsEqu")); if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic))) return FALSE; - D(emitcode("", "; checking IS_SYMOP")); + DD(emitcode("", "; checking IS_SYMOP")); if (!IS_SYMOP (IC_LEFT (ic))) return FALSE; - D(emitcode("", "; checking !IS_TRUE_SYMOP")); + DD(emitcode("", "; checking !IS_TRUE_SYMOP")); if (IS_TRUE_SYMOP (IC_LEFT (ic))) return FALSE; sym = OP_SYMBOL (IC_LEFT (ic)); - D(emitcode("", "; checking remat")); + DD(emitcode("", "; checking remat")); if (!sym->remat) return FALSE; @@ -4529,14 +4692,13 @@ genPointerGetSetOfs (iCode *ic) loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0); size = AOP_SIZE (IC_RESULT(lic)); derefaop->size = size; - offset=0; while (size--) { emitcode ("lda", "%s,x", - aopAdrStr (derefaop, offset, TRUE)); + aopAdrStr (derefaop, size, TRUE)); hc08_useReg (hc08_reg_a); - storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++); + storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size); hc08_freeReg (hc08_reg_a); } @@ -4582,15 +4744,13 @@ genPointerGetSetOfs (iCode *ic) loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0); size = AOP_SIZE (IC_RIGHT(lic)); derefaop->size = size; - offset=0; while (size--) { - loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset); + loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size); emitcode ("sta", "%s,x", - aopAdrStr (derefaop, offset, TRUE)); + aopAdrStr (derefaop, size, TRUE)); hc08_freeReg (hc08_reg_a); - offset++; } lic->generated = 1; @@ -4634,7 +4794,7 @@ hasInc (operand *op, iCode *ic,int osize) 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 */ @@ -4820,10 +4980,10 @@ genAnd (iCode * ic, iCode * ifx) aopOp ((result = IC_RESULT (ic)), ic, TRUE); #ifdef DEBUG_TYPE - D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", + DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", AOP_TYPE (result), AOP_TYPE (left), AOP_TYPE (right))); - D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", + DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", AOP_SIZE (result), AOP_SIZE (left), AOP_SIZE (right))); #endif @@ -4847,12 +5007,37 @@ genAnd (iCode * ic, iCode * ifx) if (AOP_TYPE (right) == AOP_LIT) lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right); + + if (AOP_TYPE (result) == AOP_CRY + && size > 1 + && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE))) + { + /* this generates ugly code, but meets volatility requirements */ + loadRegFromConst (hc08_reg_a, zero); + pushReg (hc08_reg_a, TRUE); + + offset = 0; + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop ("and", AOP (right), offset); + emitcode ("ora", "1,s"); + emitcode ("sta", "1,s"); + offset++; + } + + pullReg (hc08_reg_a); + emitcode ("tsta", ""); + genIfxJump (ifx, "a"); + goto release; + } + if (AOP_TYPE (result) == AOP_CRY) { symbol *tlbl = NULL; wassertl (ifx, "AOP_CRY result without ifx"); - size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right); offset = 0; while (size--) { @@ -4860,11 +5045,7 @@ genAnd (iCode * ic, iCode * ifx) if (AOP_TYPE (right) == AOP_LIT && bytemask == 0) { - if (isOperandVolatile (left, FALSE)) - { - loadRegFromAop (hc08_reg_a, AOP (left), offset); - hc08_freeReg( hc08_reg_a); - } + /* do nothing */ } else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff) { @@ -4893,6 +5074,7 @@ genAnd (iCode * ic, iCode * ifx) if (tlbl) emitLabel (tlbl); genIfxJump (ifx, "a"); + goto release; } size = AOP_SIZE (result); @@ -4962,10 +5144,10 @@ genOr (iCode * ic, iCode * ifx) aopOp ((result = IC_RESULT (ic)), ic, TRUE); #ifdef DEBUG_TYPE - D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", + DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", AOP_TYPE (result), AOP_TYPE (left), AOP_TYPE (right))); - D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", + DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", AOP_SIZE (result), AOP_SIZE (left), AOP_SIZE (right))); #endif @@ -4989,12 +5171,37 @@ genOr (iCode * ic, iCode * ifx) if (AOP_TYPE (right) == AOP_LIT) lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right); + + if (AOP_TYPE (result) == AOP_CRY + && size > 1 + && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE))) + { + /* this generates ugly code, but meets volatility requirements */ + loadRegFromConst (hc08_reg_a, zero); + pushReg (hc08_reg_a, TRUE); + + offset = 0; + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop ("ora", AOP (right), offset); + emitcode ("ora", "1,s"); + emitcode ("sta", "1,s"); + offset++; + } + + pullReg (hc08_reg_a); + emitcode ("tsta", ""); + genIfxJump (ifx, "a"); + goto release; + } + if (AOP_TYPE (result) == AOP_CRY) { symbol *tlbl = NULL; wassertl (ifx, "AOP_CRY result without ifx"); - size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right); offset = 0; while (size--) { @@ -5096,10 +5303,10 @@ genXor (iCode * ic, iCode * ifx) aopOp ((result = IC_RESULT (ic)), ic, TRUE); #ifdef DEBUG_TYPE - D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", + DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", AOP_TYPE (result), AOP_TYPE (left), AOP_TYPE (right))); - D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", + DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", AOP_SIZE (result), AOP_SIZE (left), AOP_SIZE (right))); #endif @@ -5184,7 +5391,7 @@ emitinline (iCode * ic, char *inlin) if (*inlin == '_') { symname = ++inlin; - while (isalnum(*inlin) || (*inlin == '_')) + while (isalnum((unsigned char)*inlin) || (*inlin == '_')) inlin++; c = *inlin; *inlin = '\0'; @@ -5205,7 +5412,7 @@ emitinline (iCode * ic, char *inlin) if (*l=='#') l++; sym->isref = 1; - if (!sym->allocreq && !sym->ismyparm) + if (sym->level && !sym->allocreq && !sym->ismyparm) { werror (E_ID_UNDEF, sym->name); werror (W_CONTINUE, @@ -5580,11 +5787,15 @@ AccLsh (int shCount) switch (shCount) { case 4: + if (optimize.codeSpeed) + break; accopWithMisc ("nsa", ""); accopWithMisc ("and", "#0xf0"); /* total: 5 cycles, 3 bytes */ return; case 5: + if (optimize.codeSpeed) + break; accopWithMisc ("nsa", ""); accopWithMisc ("and", "#0xf0"); accopWithMisc ("lsla", ""); @@ -5657,11 +5868,15 @@ AccRsh (int shCount, bool sign) switch (shCount) { case 4: + if (optimize.codeSpeed) + break; accopWithMisc ("nsa", ""); accopWithMisc ("and", "#0x0f"); /* total: 5 cycles, 3 bytes */ return; case 5: + if (optimize.codeSpeed) + break; accopWithMisc ("nsa", ""); accopWithMisc ("and", "#0x0f"); accopWithMisc ("lsra", ""); @@ -5801,7 +6016,7 @@ XAccSRsh (int shCount) ; } - /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */ + /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */ /* the fastest and shortest. */ for (i=0;ikey + 100); - emitcode ("", "%05d$:", tlbl->key + 100); + emitBranch ("beq", tlbl1); + emitLabel (tlbl); + shift= sign ? "asr" : "lsr"; for (offset=size-1;offset>=0;offset--) { @@ -6716,11 +6962,11 @@ genRightShift (iCode * ic) shift="ror"; } rmwWithReg ("dec", hc08_reg_x); - emitcode ("bne","%05d$", tlbl->key + 100); - emitcode ("", "%05d$:", tlbl1->key + 100); + emitBranch ("bne", tlbl); + emitLabel (tlbl1); + hc08_freeReg (hc08_reg_x); freeAsmop (result, NULL, ic, TRUE); - freeAsmop (left, NULL, ic, TRUE); freeAsmop (right, NULL, ic, TRUE); } @@ -6745,22 +6991,38 @@ genUnpackBits (operand * result, iCode *ifx) blen = SPEC_BLEN (etype); bstr = SPEC_BSTR (etype); - /* If the bitfield length is less than a byte */ - if (blen < 8) + if (ifx && blen <= 8) { emitcode ("lda", ",x"); hc08_dirtyReg (hc08_reg_a, FALSE); - if (!ifx) - { - AccRsh (bstr, FALSE); - emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen)); - storeRegToAop (hc08_reg_a, AOP (result), offset++); - } - else + if (blen < 8) { emitcode ("and", "#0x%02x", (((unsigned char) -1) >> (8 - blen)) << bstr); } + genIfxJump (ifx, "a"); + return; + } + wassert (!ifx); + + /* If the bitfield length is less than a byte */ + if (blen < 8) + { + emitcode ("lda", ",x"); + hc08_dirtyReg (hc08_reg_a, FALSE); + AccRsh (bstr, FALSE); + emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emitcode ("bit", "#0x%02x", 1<<(blen - 1)); + emitcode ("beq", "%05d$", tlbl->key + 100); + emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen)); + emitLabel (tlbl); + } + storeRegToAop (hc08_reg_a, AOP (result), offset++); goto finish; } @@ -6770,8 +7032,7 @@ genUnpackBits (operand * result, iCode *ifx) { emitcode ("lda", ",x"); hc08_dirtyReg (hc08_reg_a, FALSE); - if (!ifx) - storeRegToAop (hc08_reg_a, AOP (result), offset); + storeRegToAop (hc08_reg_a, AOP (result), offset); offset++; if (rlen>8) emitcode ("aix", "#1"); @@ -6782,6 +7043,16 @@ genUnpackBits (operand * result, iCode *ifx) { emitcode ("lda", ",x"); emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emitcode ("bit", "#0x%02x", 1<<(rlen - 1)); + emitcode ("beq", "%05d$", tlbl->key + 100); + emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen)); + emitLabel (tlbl); + } storeRegToAop (hc08_reg_a, AOP (result), offset++); } @@ -6789,13 +7060,21 @@ finish: if (offset < rsize) { rsize -= offset; - while (rsize--) - storeConstToAop (zero, AOP (result), offset++); - } + if (SPEC_USIGN (etype)) + { + while (rsize--) + storeConstToAop (zero, AOP (result), offset++); + } + else + { + /* signed bitfield: sign extension with 0x00 or 0xff */ + emitcode ("rola", ""); + emitcode ("clra", ""); + emitcode ("sbc", zero); - if (ifx && !ifx->generated) - { - genIfxJump (ifx, "a"); + while (rsize--) + storeRegToAop (hc08_reg_a, AOP (result), offset++); + } } } @@ -6843,7 +7122,10 @@ genUnpackBitsImmed (operand * left, emitcode ("brclr", "#%d,%s,%05d$", bstr, aopAdrStr (derefaop, 0, FALSE), (tlbl->key + 100)); - rmwWithReg ("inc", hc08_reg_a); + if (SPEC_USIGN (etype)) + rmwWithReg ("inc", hc08_reg_a); + else + rmwWithReg ("dec", hc08_reg_a); emitLabel (tlbl); storeRegToAop (hc08_reg_a, AOP (result), offset); hc08_freeReg (hc08_reg_a); @@ -6886,6 +7168,16 @@ genUnpackBitsImmed (operand * left, AccRsh (bstr, FALSE); emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen)); hc08_dirtyReg (hc08_reg_a, FALSE); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emitcode ("bit", "#0x%02x", 1<<(blen - 1)); + emitcode ("beq", "%05d$", tlbl->key + 100); + emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen)); + emitLabel (tlbl); + } storeRegToAop (hc08_reg_a, AOP (result), offset); } else @@ -6915,6 +7207,16 @@ genUnpackBitsImmed (operand * left, { loadRegFromAop (hc08_reg_a, derefaop, size-offset-1); emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen)); + if (!SPEC_USIGN (etype)) + { + /* signed bitfield */ + symbol *tlbl = newiTempLabel (NULL); + + emitcode ("bit", "#0x%02x", 1<<(rlen - 1)); + emitcode ("beq", "%05d$", tlbl->key + 100); + emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen)); + emitLabel (tlbl); + } storeRegToAop (hc08_reg_a, AOP (result), offset++); } @@ -6922,8 +7224,21 @@ finish: if (offset < rsize) { rsize -= offset; - while (rsize--) - storeConstToAop (zero, AOP (result), offset++); + if (SPEC_USIGN (etype)) + { + while (rsize--) + storeConstToAop (zero, AOP (result), offset++); + } + else + { + /* signed bitfield: sign extension with 0x00 or 0xff */ + emitcode ("rola", ""); + emitcode ("clra", ""); + emitcode ("sbc", zero); + + while (rsize--) + storeRegToAop (hc08_reg_a, AOP (result), offset++); + } } freeAsmop (NULL, derefaop, ic, TRUE); @@ -6945,7 +7260,7 @@ genDataPointerGet (operand * left, iCode * ic, iCode * ifx) { - int size, offset = 0; + int size; asmop *derefaop; D(emitcode ("; genDataPointerGet","")); @@ -6960,10 +7275,9 @@ genDataPointerGet (operand * left, while (size--) { if (!ifx) - transferAopAop (derefaop, offset, AOP (result), offset); + transferAopAop (derefaop, size, AOP (result), size); else - loadRegFromAop (hc08_reg_a, derefaop, offset); - offset++; + loadRegFromAop (hc08_reg_a, derefaop, size); } freeAsmop (NULL, derefaop, ic, TRUE); @@ -7347,7 +7661,7 @@ genDataPointerSet (operand * right, operand * result, iCode * ic) { - int size, offset = 0; + int size; asmop *derefaop; D(emitcode ("; genDataPointerSet","")); @@ -7361,8 +7675,7 @@ genDataPointerSet (operand * right, while (size--) { - transferAopAop (AOP (right), offset, derefaop, offset); - offset++; + transferAopAop (AOP (right), size, derefaop, size); } freeAsmop (right, NULL, ic, TRUE); @@ -7461,6 +7774,30 @@ genIfx (iCode * ic, iCode * popIc) aopOp (cond, ic, FALSE); + /* If the condition is a literal, we can just do an unconditional */ + /* branch or no branch */ + if (AOP_TYPE (cond) == AOP_LIT) + { + unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit); + freeAsmop (cond, NULL, ic, TRUE); + + /* if there was something to be popped then do it */ + if (popIc) + genIpop (popIc); + if (lit) + { + if (IC_TRUE (ic)) + emitBranch ("jmp", IC_TRUE (ic)); + } + else + { + if (IC_FALSE (ic)) + emitBranch ("jmp", IC_FALSE (ic)); + } + ic->generated = 1; + return; + } + /* get the value into acc */ if (AOP_TYPE (cond) != AOP_CRY) asmopToBool (AOP (cond), FALSE); @@ -7503,11 +7840,21 @@ genAddrOf (iCode * ic) variable */ if (sym->onStack) { - /* if it has an offset then we need to compute - it */ + /* if it has an offset then we need to compute it */ + offset = _G.stackOfs + _G.stackPushes + sym->stack; hc08_useReg (hc08_reg_hx); emitcode ("tsx", ""); - emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack); + while (offset > 127) + { + emitcode ("aix", "#127"); + offset -= 127; + } + while (offset < -128) + { + emitcode ("aix", "#-128"); + offset += 128; + } + emitcode ("aix", "#%d", offset); storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE); hc08_freeReg (hc08_reg_hx); @@ -7548,7 +7895,7 @@ static void genAssign (iCode * ic) { operand *result, *right; - int size, offset; + int size; // unsigned long lit = 0L; D(emitcode("; genAssign","")); @@ -7577,12 +7924,9 @@ genAssign (iCode * ic) /* general case */ size = AOP_SIZE (result); - offset = 0; - while (size--) { - transferAopAop (AOP (right), offset, AOP (result), offset); - offset++; + transferAopAop (AOP (right), size, AOP (result), size); } release: @@ -7591,38 +7935,65 @@ release: } /*-----------------------------------------------------------------*/ -/* genJumpTab - genrates code for jump table */ +/* genJumpTab - generates code for jump table */ /*-----------------------------------------------------------------*/ static void genJumpTab (iCode * ic) { symbol *jtab; -// char *l; - + symbol *jtablo = newiTempLabel (NULL); + symbol *jtabhi = newiTempLabel (NULL); + D(emitcode ("; genJumpTab","")); aopOp (IC_JTCOND (ic), ic, FALSE); - /* get the condition into accumulator */ - loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0); - freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE); - /* multiply by three */ - pushReg (hc08_reg_a, FALSE); - emitcode ("lsla", ""); - emitcode ("add","1,s"); - transferRegReg (hc08_reg_a, hc08_reg_x, TRUE); - loadRegFromConst (hc08_reg_h, zero); - pullReg (hc08_reg_a); + + if (hc08_reg_x->isFree && hc08_reg_x->isFree) + { + /* get the condition into x */ + loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0); + freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE); + loadRegFromConst (hc08_reg_h, zero); + + emitcode ("lda", "%05d$,x", jtabhi->key + 100); + emitcode ("ldx", "%05d$,x", jtablo->key + 100); + transferRegReg (hc08_reg_a, hc08_reg_h, TRUE); + emitcode ("jmp", ",x"); + + hc08_dirtyReg (hc08_reg_a, TRUE); + hc08_dirtyReg (hc08_reg_hx, TRUE); + } + else + { + adjustStack(-2); + pushReg(hc08_reg_hx, TRUE); + + /* get the condition into x */ + loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0); + freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE); + loadRegFromConst (hc08_reg_h, zero); + + emitcode ("lda", "%05d$,x", jtabhi->key + 100); + emitcode ("sta", "3,s"); + emitcode ("lda", "%05d$,x", jtablo->key + 100); + emitcode ("sta", "4,s"); + + pullReg(hc08_reg_hx); + emitcode ("rts", ""); + _G.stackPushes += 2; + updateCFA(); + } - jtab = newiTempLabel (NULL); - emitcode ("jmp", "%05d$,x", jtab->key + 100); - emitcode ("", "%05d$:", jtab->key + 100); /* now generate the jump labels */ + emitLabel (jtablo); + for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; + jtab = setNextItem (IC_JTLABELS (ic))) + emitcode (".db", "%05d$", jtab->key + 100); + emitLabel (jtabhi); for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; jtab = setNextItem (IC_JTLABELS (ic))) - emitcode ("jmp", "%05d$", jtab->key + 100); + emitcode (".db", ">%05d$", jtab->key + 100); - hc08_dirtyReg (hc08_reg_a, TRUE); - hc08_dirtyReg (hc08_reg_hx, TRUE); } /*-----------------------------------------------------------------*/ @@ -7713,7 +8084,7 @@ genCast (iCode * ic) exit(1); } - sprintf(gpValStr, "#0x%d", gpVal); + sprintf(gpValStr, "#0x%x", gpVal); aopPut (AOP (result), gpValStr, GPTRSIZE - 1); } #endif @@ -7969,7 +8340,7 @@ genhc08Code (iCode * lic) /* print the allocation information */ if (allocInfo && currFunc) - printAllocInfo (currFunc, codeOutFile); + printAllocInfo (currFunc, codeOutBuf); /* if debug information required */ if (options.debug && currFunc) { @@ -8041,13 +8412,16 @@ genhc08Code (iCode * lic) if (options.iCodeInAsm) { char regsInUse[80]; int i; + char *iLine; for (i=0; i<6; i++) { sprintf (®sInUse[i], "%c", ic->riu & (1<seq, printILine(ic)); + dbuf_free(iLine); } /* if the result is marked as spilt and rematerializable or code for @@ -8186,26 +8560,16 @@ genhc08Code (iCode * lic) break; case '>': - genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - case '<': - genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - case LE_OP: case GE_OP: - 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"); - break; + genCmp (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + case NE_OP: case EQ_OP: - genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic)); - break; + genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic)); + break; case AND_OP: genAndOp (ic); @@ -8310,15 +8674,15 @@ genhc08Code (iCode * lic) } if (!hc08_reg_a->isFree) - D(emitcode("","; forgot to free a")); + DD(emitcode("","; forgot to free a")); if (!hc08_reg_x->isFree) - D(emitcode("","; forgot to free x")); + DD(emitcode("","; forgot to free x")); if (!hc08_reg_h->isFree) - D(emitcode("","; forgot to free h")); + DD(emitcode("","; forgot to free h")); if (!hc08_reg_hx->isFree) - D(emitcode("","; forgot to free hx")); + DD(emitcode("","; forgot to free hx")); if (!hc08_reg_xa->isFree) - D(emitcode("","; forgot to free xa")); + DD(emitcode("","; forgot to free xa")); } debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */ @@ -8330,6 +8694,6 @@ genhc08Code (iCode * lic) peepHole (&lineHead); /* now do the actual printing */ - printLine (lineHead, codeOutFile); + printLine (lineHead, codeOutBuf); return; }