X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fhc08%2Fgen.c;h=a656eb5bf238c16ad47c5b619737a460edaadc46;hb=04a66f4aa0c6a3cf27d0b5339a74ed8e4f92f1a6;hp=9c94f3559b73891c3037ce99b0dc5e295720476e;hpb=0694926e60ec83b31f87590e601f7e0d8f86c512;p=fw%2Fsdcc diff --git a/src/hc08/gen.c b/src/hc08/gen.c index 9c94f355..a656eb5b 100644 --- a/src/hc08/gen.c +++ b/src/hc08/gen.c @@ -27,8 +27,11 @@ -------------------------------------------------------------------------*/ -//#define D(x) -#define D(x) x +/* Use the D macro for basic (unobtrusive) debugging messages */ +#define D(x) do if (options.verboseAsm) {x;} while(0) +/* Use the DD macro for detailed debugging messages */ +#define DD(x) +//#define DD(x) x #include #include @@ -45,6 +48,9 @@ char *aopLiteral (value * val, int offset); 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"; @@ -52,7 +58,7 @@ static char *spname; char *fReturnhc08[] = {"a", "x", "_ret2", "_ret3"}; -unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */ +unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */ char **fReturn2 = fReturnhc08; @@ -68,6 +74,7 @@ static struct int stackPushes; short regsinuse; set *sendSet; + iCode *current_iCode; } _G; @@ -75,7 +82,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); @@ -110,7 +117,7 @@ static char * aopAdrStr (asmop * aop, int loffset, bool bit16); (((x)->type == AOP_REG) \ && ((x)->aopu.aop_reg[0] == hc08_reg_h) \ && ((x)->size == 1) ) - + #define CLRC emitcode("clc","") static lineNode *lineHead = NULL; @@ -151,23 +158,25 @@ emitcode (char *inst, char *fmt,...) if (inst && *inst) { if (fmt && *fmt) - sprintf (lb, "%s\t", inst); + sprintf (lb, "%s\t", inst); else - sprintf (lb, "%s", inst); + sprintf (lb, "%s", inst); vsprintf (lb + (strlen (lb)), fmt, ap); } else vsprintf (lb, fmt, ap); - while (isspace (*lbp)) + while (isspace ((unsigned char)*lbp)) lbp++; if (lbp && *lbp) lineCurr = (lineCurr ? - connectLine (lineCurr, newLineNode (lb)) : - (lineHead = newLineNode (lb))); + connectLine (lineCurr, newLineNode (lb)) : + (lineHead = newLineNode (lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->ic = _G.current_iCode; + lineCurr->isComment = (*lbp==';'); //printf("%s\n", lb); va_end (ap); @@ -183,8 +192,20 @@ static void emitLabel (symbol *tlbl) { emitcode ("", "%05d$:", (tlbl->key +100)); + lineCurr->isLabel = 1; } +/*-----------------------------------------------------------------*/ +/* hc08_emitDebuggerSymbol - associate the current code location */ +/* with a debugger symbol */ +/*-----------------------------------------------------------------*/ +void +hc08_emitDebuggerSymbol (char * debugSym) +{ + _G.debugLine = 1; + emitcode ("", "%s ==.", debugSym); + _G.debugLine = 0; +} /*--------------------------------------------------------------------------*/ @@ -207,27 +228,27 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) if (!sreg) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "NULL sreg in transferRegReg"); + "NULL sreg in transferRegReg"); return; } - emitcode ("", "; transferRegReg(%s,%s)", - sreg->name, dreg->name); + DD(emitcode ("", "; transferRegReg(%s,%s)", + sreg->name, dreg->name)); srcidx = sreg->rIdx; dstidx = dreg->rIdx; - + if (srcidx==dstidx) return; - + switch (dstidx) { case A_IDX: switch (srcidx) { case H_IDX: /* H to A */ - emitcode ("pshh", ""); - emitcode ("pula", ""); + pushReg (hc08_reg_h, FALSE); + pullReg (hc08_reg_a); break; case X_IDX: /* X to A */ emitcode ("txa", ""); @@ -240,12 +261,12 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) switch (srcidx) { case A_IDX: /* A to H */ - emitcode ("psha", ""); - emitcode ("pulh", ""); + pushReg (hc08_reg_a, FALSE); + pullReg (hc08_reg_h); break; case X_IDX: /* X to H */ - emitcode ("pshx", ""); - emitcode ("pulh", ""); + pushReg (hc08_reg_x, FALSE); + pullReg (hc08_reg_h); break; default: error=1; @@ -258,8 +279,8 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) emitcode ("tax", ""); break; case H_IDX: /* H to X */ - emitcode ("pshh", ""); - emitcode ("pulx", ""); + pushReg (hc08_reg_h, FALSE); + pullReg (hc08_reg_x); break; default: error=1; @@ -269,8 +290,8 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) switch (srcidx) { case XA_IDX: /* XA to HX */ - emitcode ("pshx", ""); - emitcode ("pulh", ""); + pushReg (hc08_reg_x, FALSE); + pullReg (hc08_reg_h); emitcode ("tax", ""); break; default: @@ -282,8 +303,8 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) { case HX_IDX: /* HX to XA */ emitcode ("txa", ""); - emitcode ("pshh", ""); - emitcode ("pulx", ""); + pushReg (hc08_reg_h, FALSE); + pullReg (hc08_reg_x); break; default: error=1; @@ -304,6 +325,21 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc) hc08_useReg(dreg); } +/*--------------------------------------------------------------------------*/ +/* updateCFA - update the debugger information to reflect the current */ +/* connonical frame address relative to the stack pointer */ +/*--------------------------------------------------------------------------*/ +static void +updateCFA(void) +{ + /* there is no frame unless there is a function */ + if (!currFunc) + return; + + debugFile->writeFrameAddress (NULL, hc08_reg_sp, + 1 + _G.stackOfs + _G.stackPushes); +} + /*--------------------------------------------------------------------------*/ /* pushReg - Push register reg onto the stack. If freereg is true, reg is */ /* marked free and available for reuse. */ @@ -312,30 +348,39 @@ static int pushReg (regs *reg, bool freereg) { int regidx = reg->rIdx; - + switch (regidx) { case A_IDX: emitcode ("psha", ""); _G.stackPushes++; + updateCFA(); break; case X_IDX: emitcode ("pshx", ""); _G.stackPushes++; + updateCFA(); break; case H_IDX: emitcode ("pshh", ""); _G.stackPushes++; + updateCFA(); break; case HX_IDX: emitcode ("pshx", ""); + _G.stackPushes++; + updateCFA(); emitcode ("pshh", ""); - _G.stackPushes += 2; + _G.stackPushes++; + updateCFA(); break; case XA_IDX: emitcode ("psha", ""); + updateCFA(); + _G.stackPushes++; emitcode ("pshx", ""); - _G.stackPushes += 2; + updateCFA(); + _G.stackPushes++; break; default: break; @@ -352,30 +397,39 @@ static void pullReg (regs *reg) { int regidx = reg->rIdx; - + switch (regidx) { case A_IDX: emitcode ("pula", ""); _G.stackPushes--; + updateCFA(); break; case X_IDX: emitcode ("pulx", ""); _G.stackPushes--; + updateCFA(); break; case H_IDX: emitcode ("pulh", ""); _G.stackPushes--; + updateCFA(); break; case HX_IDX: - emitcode ("pulx", ""); emitcode ("pulh", ""); - _G.stackPushes -= 2; + _G.stackPushes--; + updateCFA(); + emitcode ("pulx", ""); + _G.stackPushes--; + updateCFA(); break; case XA_IDX: - emitcode ("pula", ""); emitcode ("pulx", ""); - _G.stackPushes -= 2; + _G.stackPushes--; + updateCFA(); + emitcode ("pula", ""); + _G.stackPushes--; + updateCFA(); break; default: break; @@ -394,6 +448,7 @@ pullNull (int n) { emitcode("ais","#%d",n); _G.stackPushes -= n; + updateCFA(); } } @@ -432,25 +487,30 @@ pullOrFreeReg (regs *reg, bool needpull) static void adjustStack (int n) { - _G.stackPushes -= n; while (n) { if (n>127) { emitcode ("ais","#127"); n -= 127; + _G.stackPushes -= 127; + updateCFA(); } else if (n<-128) { emitcode ("ais","#-128"); n += 128; + _G.stackPushes += 128; + updateCFA(); } else { emitcode ("ais", "#%d", n); + _G.stackPushes -= n; n = 0; + updateCFA(); } - } + } } @@ -462,7 +522,7 @@ aopName (asmop *aop) { static char buffer[256]; char *buf = buffer; - + if (!aop) return "(asmop*)NULL"; @@ -543,14 +603,14 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) printf(" reg missing operand link\n"); #endif - emitcode ("", "; loadRegFromAop (%s, %s, %d)", - reg->name, aopName (aop), loffset); - + DD(emitcode ("", "; loadRegFromAop (%s, %s, %d)", + reg->name, aopName (aop), loffset)); + /* If operand is volatile, we cannot optimize. */ if (!aop->op || isOperandVolatile (aop->op, FALSE)) goto forceload; - + /* If this register already has this offset of the operand then we need only mark it as in use. */ if (reg->aop && reg->aop->op && aop->op @@ -558,7 +618,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) && (reg->aopofs == loffset)) { hc08_useReg(reg); - emitcode ("","; already had correct value for %s", reg->name); + DD(emitcode ("","; already had correct value for %s", reg->name)); return; } @@ -568,28 +628,28 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset) && operandsEqu(hc08_reg_h->aop->op,aop->op) && (hc08_reg_h->aopofs == loffset)) { - 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; } - + if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op && operandsEqu(hc08_reg_x->aop->op,aop->op) && (hc08_reg_x->aopofs == loffset)) { - 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; } - + if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op && operandsEqu(hc08_reg_a->aop->op,aop->op) && (hc08_reg_a->aopofs == loffset)) { - 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; @@ -608,7 +668,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) @@ -619,9 +685,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); @@ -680,7 +760,7 @@ forceload: loadRegFromAop (hc08_reg_x, aop, loffset+1); } break; - } + } // ignore caching for now #if 0 @@ -693,25 +773,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)); - - 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; } @@ -728,8 +834,8 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) int otheridx; #endif - emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d", - reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr); + 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 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1])) @@ -762,7 +868,13 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) return; } - switch (regidx) + 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: if ((aop->type == AOP_REG) && (loffset < aop->size)) @@ -827,7 +939,7 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) storeRegToAop (hc08_reg_x, aop, loffset+1); } break; - } + } /* Disable the register tracking for now */ #if 0 @@ -842,21 +954,21 @@ storeRegToAop (regs *reg, asmop *aop, int loffset) && operandsEqu(otherreg->aop->op,aop->op) && (otherreg->aopofs == loffset)) { - 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; - 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; - emitcode("","; marking xa stale"); + DD(emitcode("","; marking xa stale")); } - + reg->aop = aop; reg->aopofs = loffset; } @@ -913,8 +1025,8 @@ loadRegFromConst (regs *reg, char *c) break; default: werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "Bad rIdx in loadRegFromConst"); - return; + "Bad rIdx in loadRegFromConst"); + return; } hc08_useReg (reg); } @@ -945,6 +1057,8 @@ storeConstToAop (char *c, asmop *aop, int loffset) break; loadRegFromConst (aop->aopu.aop_reg[loffset], c); break; + case AOP_DUMMY: + break; default: if (hc08_reg_a->isFree) { @@ -981,10 +1095,10 @@ storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned) { // int regidx = reg->rIdx; int size = aop->size; - + if (size<=loffset) return; - + if (!isSigned) { /* Unsigned case */ @@ -1051,7 +1165,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) @@ -1061,6 +1175,13 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) int regIdx; bool keepreg = FALSE; + /* 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 + && dstaop->type == srcaop->type) + return; + if (srcaop->stacked && srcaop->stk_aop[srcofs]) { transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs); @@ -1073,17 +1194,32 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) return; } -// emitcode ("", "; transferAopAop (%s, %d, %s, %d)", -// aopName (srcaop), srcofs, aopName (dstaop), dstofs); -// emitcode ("", "; srcaop->type = %d", srcaop->type); -// emitcode ("", "; dstaop->type = %d", dstaop->type); - +// DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)", +// aopName (srcaop), srcofs, aopName (dstaop), dstofs)); +// DD(emitcode ("", "; srcaop->type = %d", srcaop->type)); +// DD(emitcode ("", "; dstaop->type = %d", dstaop->type)); + if (dstofs >= dstaop->size) return; if ((dstaop->type == AOP_DIR) && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) ) { + if (srcaop->type == AOP_LIT) + { + unsigned long lit; + unsigned long bytemask; + + lit = ulFromVal (srcaop->aopu.aop_lit); + bytemask = (lit >> (srcofs*8)) & 0xff; + + if (bytemask == 0) + { + emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE)); + return; + } + } + emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE), aopAdrStr(dstaop, dstofs, FALSE)); return; @@ -1114,7 +1250,7 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) if (hc08_reg_a->isFree) reg = hc08_reg_a; else if (hc08_reg_x->isFree) - reg = hc08_reg_x; + reg = hc08_reg_x; else { pushReg (hc08_reg_a, TRUE); @@ -1122,10 +1258,10 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs) reg = hc08_reg_a; } } - + loadRegFromAop (reg, srcaop, srcofs); storeRegToAop (reg, dstaop, dstofs); - + if (!keepreg) pullOrFreeReg (hc08_reg_a, needpula); } @@ -1155,7 +1291,10 @@ accopWithAop (char *accop, asmop *aop, int loffset) accopWithAop (accop, aop->stk_aop[loffset], 0); return; } - + + if (aop->type == AOP_DUMMY) + return; + if (aop->type == AOP_REG) { pushReg (aop->aopu.aop_reg[loffset], FALSE); @@ -1213,7 +1352,7 @@ rmwWithReg (char *rmwop, regs *reg) /*--------------------------------------------------------------------------*/ /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */ /* logical offset loffset of asmop aop. */ -/* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */ +/* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */ /*--------------------------------------------------------------------------*/ static void rmwWithAop (char *rmwop, asmop *aop, int loffset) @@ -1225,7 +1364,7 @@ rmwWithAop (char *rmwop, asmop *aop, int loffset) rmwWithAop (rmwop, aop->stk_aop[loffset], 0); return; } - + switch (aop->type) { case AOP_REG: @@ -1233,15 +1372,18 @@ 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); - storeRegToAop (hc08_reg_a, aop, loffset); + if (strcmp ("tst", rmwop)) + storeRegToAop (hc08_reg_a, aop, loffset); pullOrFreeReg (hc08_reg_a, needpula); break; + case AOP_DUMMY: + break; default: emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE)); } - + } @@ -1330,14 +1472,14 @@ aopForSym (iCode * ic, symbol * sym, bool result) aop->aopu.aop_stk = sym->stack; return aop; } - + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopForSym should never reach here"); + "aopForSym should never reach here"); exit(1); - + /* if it is in code space */ if (IN_CODESPACE (space)) aop->code = 1; @@ -1346,33 +1488,34 @@ aopForSym (iCode * ic, symbol * sym, bool result) } /*-----------------------------------------------------------------*/ -/* aopForRemat - rematerialzes an object */ +/* aopForRemat - rematerializes an object */ /*-----------------------------------------------------------------*/ static asmop * aopForRemat (symbol * sym) { iCode *ic = sym->rematiCode; asmop *aop = NULL; - int ptr_type=0; + int ptr_type = 0; int val = 0; for (;;) { if (ic->op == '+') - val += (int) operandLitValue (IC_RIGHT (ic)); + val += (int) operandLitValue (IC_RIGHT (ic)); else if (ic->op == '-') - val -= (int) operandLitValue (IC_RIGHT (ic)); - else if (IS_CAST_ICODE(ic)) { - sym_link *from_type = operandType(IC_RIGHT(ic)); - aop->aopu.aop_immd.from_cast_remat = 1; - ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode; - ptr_type = DCL_TYPE(from_type); - if (ptr_type == IPOINTER) { - // bug #481053 - ptr_type = POINTER; - } - continue ; - } else break; + val -= (int) operandLitValue (IC_RIGHT (ic)); + else if (IS_CAST_ICODE(ic)) + { + sym_link *from_type = operandType(IC_RIGHT(ic)); + ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode; + ptr_type = DCL_TYPE(from_type); + if (ptr_type == IPOINTER) + {// bug #481053 + ptr_type = POINTER; + } + continue ; + } + else break; ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; } @@ -1380,37 +1523,35 @@ aopForRemat (symbol * sym) if (ic->op == ADDRESS_OF) { if (val) - sprintf (buffer, "(%s %c 0x%04x)", - OP_SYMBOL (IC_LEFT (ic))->rname, - val >= 0 ? '+' : '-', - abs (val) & 0xffff); + { + SNPRINTF (buffer, sizeof(buffer), + "(%s %c 0x%04x)", + OP_SYMBOL (IC_LEFT (ic))->rname, + val >= 0 ? '+' : '-', + abs (val) & 0xffff); + } else - strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname); + { + strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer)); + } aop = newAsmop (AOP_IMMD); - aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1); - strcpy (aop->aopu.aop_immd.aop_immd1, buffer); + aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer); /* set immd2 field if required */ - if (aop->aopu.aop_immd.from_cast_remat) - { - sprintf(buffer,"#0x%02x",ptr_type); - aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1); - strcpy (aop->aopu.aop_immd.aop_immd2, buffer); - } } else if (ic->op == '=') { val += (int) operandLitValue (IC_RIGHT (ic)); val &= 0xffff; - sprintf (buffer, "0x%04x", val); + SNPRINTF (buffer, sizeof(buffer), "0x%04x", val); aop = newAsmop (AOP_LIT); aop->aopu.aop_lit = constVal (buffer); } else - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "unexpected rematerialization"); - - + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unexpected rematerialization"); + } return aop; } @@ -1438,16 +1579,16 @@ regsInCommon (operand * op1, operand * op2) { int j; if (!sym1->regs[i]) - continue; + continue; for (j = 0; j < sym2->nRegs; j++) - { - if (!sym2->regs[j]) - continue; + { + if (!sym2->regs[j]) + continue; - if (sym2->regs[j] == sym1->regs[i]) - return TRUE; - } + if (sym2->regs[j] == sym1->regs[i]) + return TRUE; + } } return FALSE; @@ -1478,10 +1619,11 @@ operandsEqu (operand * op1, operand * op2) if (sym1 == sym2) return TRUE; - if (strcmp (sym1->rname, sym2->rname) == 0) + /* if they have the same rname */ + if (sym1->rname[0] && sym2->rname[0] + && strcmp (sym1->rname, sym2->rname) == 0) return TRUE; - /* if left is a tmp & right is not */ if (IS_ITEMP (op1) && !IS_ITEMP (op2) && @@ -1567,7 +1709,7 @@ aopOp (operand * op, iCode * ic, bool result) // printf("checking pre-existing\n"); /* if already has a asmop then continue */ - if (op->aop ) + if (op->aop) { op->aop->op = op; op->aop->isaddr = op->isaddr; @@ -1584,7 +1726,7 @@ aopOp (operand * op, iCode * ic, bool result) aop->size = getSize( operandType (op)); //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name); //printf (" with size = %d\n", aop->size); - + aop->op = op; aop->isaddr = op->isaddr; /* if (aop->isaddr & IS_ITEMP (op)) @@ -1608,7 +1750,7 @@ aopOp (operand * op, iCode * ic, bool result) } /* this is a temporary : this has - only four choices : + only five choices : a) register b) spillocation c) rematerialize @@ -1621,7 +1763,7 @@ aopOp (operand * op, iCode * ic, bool result) /* if the type is a conditional */ if (sym->regType == REG_CND) { - aop = op->aop = sym->aop = newAsmop (AOP_CRY); + sym->aop = op->aop = aop = newAsmop (AOP_CRY); aop->size = 0; aop->op = op; aop->isaddr = op->isaddr; @@ -1638,10 +1780,9 @@ aopOp (operand * op, iCode * ic, bool result) // printf("checking remat\n"); /* rematerialize it NOW */ if (sym->remat) - { - sym->aop = op->aop = aop = - aopForRemat (sym); - aop->size = getSize (sym->type); + { + sym->aop = op->aop = aop = aopForRemat (sym); + aop->size = getSize (sym->type); aop->op = op; aop->isaddr = op->isaddr; /* if (aop->isaddr & IS_ITEMP (op)) @@ -1649,67 +1790,75 @@ aopOp (operand * op, iCode * ic, bool result) aop->psize=aop->size; aop->size = getSize( operandType (op)->next); } */ - return; - } + return; + } // printf("checking accuse\n"); if (sym->accuse) - { - aop = op->aop = sym->aop = newAsmop (AOP_REG); - aop->size = getSize (sym->type); - switch (sym->accuse) - { - case ACCUSE_XA: + { + sym->aop = op->aop = aop = newAsmop (AOP_REG); + aop->size = getSize (sym->type); + switch (sym->accuse) + { + case ACCUSE_XA: aop->aopu.aop_reg[0] = hc08_reg_a; aop->aopu.aop_reg[1] = hc08_reg_x; break; - case ACCUSE_HX: + case ACCUSE_HX: aop->aopu.aop_reg[0] = hc08_reg_x; aop->aopu.aop_reg[1] = hc08_reg_h; break; } aop->op = op; aop->isaddr = op->isaddr; - return; - } + return; + } // printf("checking ruonly\n"); #if 1 if (sym->ruonly) - { - unsigned i; + { + unsigned i; - aop = op->aop = sym->aop = newAsmop (AOP_STR); - aop->size = getSize (sym->type); - for (i = 0; i < fReturnSizeHC08; i++) - aop->aopu.aop_str[i] = fReturn2[i]; + sym->aop = op->aop = aop = newAsmop (AOP_STR); + aop->size = getSize (sym->type); + for (i = 0; i < fReturnSizeHC08; i++) + aop->aopu.aop_str[i] = fReturn2[i]; aop->op = op; aop->isaddr = op->isaddr; - return; - } + return; + } #endif /* else spill location */ -// printf("checking spill loc\n"); -// if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) { - if (sym->usl.spillLoc && sym->usl.spillLoc->aop - && sym->usl.spillLoc->aop->size != getSize (sym->type)) + if (sym->usl.spillLoc) { - /* force a new aop if sizes differ */ - sym->usl.spillLoc->aop = NULL; - //printf ("forcing new aop\n"); + 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; + //printf ("spill symbol %s\n", OP_SYMBOL (op)->name); + //printf (" with size = %d\n", aop->size); + return; } - sym->aop = op->aop = aop = - aopForSym (ic, sym->usl.spillLoc, result); + + /* else must be a dummy iTemp */ + sym->aop = op->aop = aop = newAsmop (AOP_DUMMY); aop->size = getSize (sym->type); - aop->op = op; - aop->isaddr = op->isaddr; - //printf ("spill symbol %s\n", OP_SYMBOL (op)->name); - //printf (" with size = %d\n", aop->size); - /* if (aop->isaddr & IS_ITEMP (op)) - { - aop->psize=aop->size; - aop->size = getSize( operandType (op)->next); - } */ return; } @@ -1750,7 +1899,7 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop) int stackAdjust; int loffset; - 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++) @@ -1761,19 +1910,19 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop) } pullNull (stackAdjust); } - + dealloc: /* all other cases just dealloc */ if (op) { op->aop = NULL; if (IS_SYMOP (op)) - { - OP_SYMBOL (op)->aop = NULL; - /* if the symbol has a spill */ - if (SPIL_LOC (op)) - SPIL_LOC (op)->aop = NULL; - } + { + OP_SYMBOL (op)->aop = NULL; + /* if the symbol has a spill */ + if (SPIL_LOC (op)) + SPIL_LOC (op)->aop = NULL; + } } } @@ -1791,11 +1940,11 @@ aopDerefAop (asmop *aop) asmop *newaop = NULL; sym_link *type, *etype; int p_type; - - emitcode ("", "; aopDerefAop(%s)", aopName(aop)); + + DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop))); if (aop->op) { - + type = operandType (aop->op); etype = getSpec (type); /* if op is of type of pointer then it is simple */ @@ -1809,7 +1958,7 @@ aopDerefAop (asmop *aop) } else p_type = UPOINTER; - + switch (aop->type) { case AOP_IMMD: @@ -1820,7 +1969,7 @@ aopDerefAop (asmop *aop) newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1; break; case AOP_LIT: - adr = (int) floatFromVal (aop->aopu.aop_lit); + adr = (int) ulFromVal (aop->aopu.aop_lit); if (p_type == POINTER) adr &= 0xff; @@ -1844,7 +1993,7 @@ aopDerefAop (asmop *aop) return NULL; } - + return newaop; } @@ -1859,7 +2008,7 @@ aopAdrStr (asmop * aop, int loffset, bool bit16) char *s = buffer; char *rs; int offset = aop->size - 1 - loffset; - + /* offset is greater than size then zero */ @@ -1871,46 +2020,53 @@ aopAdrStr (asmop * aop, int loffset, bool bit16) switch (aop->type) { + case AOP_DUMMY: + return zero; + case AOP_IMMD: - if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) { - sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2); - } else if (bit16) - sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1); + if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) + { + sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2); + } + else if (bit16) + { + sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1); + } else if (loffset) { if (loffset!=1) - sprintf (s, "#(%s >> %d)", - aop->aopu.aop_immd.aop_immd1, - loffset * 8); - else - sprintf (s, "#>%s", - aop->aopu.aop_immd.aop_immd1); + sprintf (s, "#(%s >> %d)", + aop->aopu.aop_immd.aop_immd1, + loffset * 8); + else + sprintf (s, "#>%s", + aop->aopu.aop_immd.aop_immd1); } else - sprintf (s, "#%s", - aop->aopu.aop_immd.aop_immd1); + sprintf (s, "#%s", + aop->aopu.aop_immd.aop_immd1); rs = Safe_calloc (1, strlen (s) + 1); strcpy (rs, s); return rs; case AOP_DIR: if (offset) - sprintf (s, "*(%s + %d)", - aop->aopu.aop_dir, - offset); + sprintf (s, "*(%s + %d)", + aop->aopu.aop_dir, + offset); else - sprintf (s, "*%s", aop->aopu.aop_dir); + sprintf (s, "*%s", aop->aopu.aop_dir); rs = Safe_calloc (1, strlen (s) + 1); strcpy (rs, s); return rs; case AOP_EXT: if (offset) - sprintf (s, "(%s + %d)", - aop->aopu.aop_dir, - offset); + sprintf (s, "(%s + %d)", + aop->aopu.aop_dir, + offset); else - sprintf (s, "%s", aop->aopu.aop_dir); + sprintf (s, "%s", aop->aopu.aop_dir); rs = Safe_calloc (1, strlen (s) + 1); strcpy (rs, s); return rs; @@ -1929,8 +2085,8 @@ aopAdrStr (asmop * aop, int loffset, bool bit16) return aop->aopu.aop_str[loffset]; case AOP_SOF: - sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk - + offset + 1); + sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk + + offset + 1); rs = Safe_calloc (1, strlen (s) + 1); strcpy (rs, s); return rs; @@ -1938,7 +2094,7 @@ aopAdrStr (asmop * aop, int loffset, bool bit16) } werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopAdrStr got unsupported aop->type"); + "aopAdrStr got unsupported aop->type"); exit (1); } @@ -1975,67 +2131,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. */ @@ -2054,7 +2149,7 @@ asmopToBool (asmop *aop, bool resultInA) if (resultInA) hc08_freeReg(hc08_reg_a); - + switch (aop->type) { case AOP_REG: @@ -2095,7 +2190,7 @@ asmopToBool (asmop *aop, bool resultInA) emitcode ("tsta", ""); emitcode ("bne", "%05d$", (tlbl->key + 100)); emitcode ("tstx", ""); - emitcode ("", "%05d$:", (tlbl->key + 100)); + emitLabel (tlbl); } else { @@ -2120,6 +2215,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 (ulFromVal (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) { @@ -2148,7 +2251,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; } } @@ -2208,7 +2311,7 @@ genNot (iCode * ic) asmopToBool ( AOP (IC_LEFT (ic)), TRUE); emitcode ("eor", one); storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE); - + freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); } @@ -2223,8 +2326,6 @@ genCpl (iCode * ic) int offset = 0; int size; regs* reg = hc08_reg_a; - -// symbol *tlbl; D(emitcode ("; genCpl","")); @@ -2240,6 +2341,7 @@ genCpl (iCode * ic) hc08_useReg (reg); storeRegToAop (reg, AOP (IC_RESULT (ic)), offset); hc08_freeReg (reg); + offset++; } /* release the aops */ @@ -2264,20 +2366,16 @@ genUminusFloat (operand * op, operand * result) while (size--) { - if (!size) - { - needpula = pushRegIfUsed (hc08_reg_a); - loadRegFromAop (hc08_reg_a, AOP (op), offset); - emitcode ("eor", "#0x80"); - hc08_useReg (hc08_reg_a); - storeRegToAop (hc08_reg_a, AOP (result), offset); - pullOrFreeReg (hc08_reg_a, needpula); - } - else - transferAopAop (AOP (op), offset, AOP (result), offset); + transferAopAop (AOP (op), offset, AOP (result), offset); offset++; } + needpula = pushRegIfUsed (hc08_reg_a); + loadRegFromAop (hc08_reg_a, AOP (op), offset); + emitcode ("eor", "#0x80"); + hc08_useReg (hc08_reg_a); + storeRegToAop (hc08_reg_a, AOP (result), offset); + pullOrFreeReg (hc08_reg_a, needpula); } /*-----------------------------------------------------------------*/ @@ -2290,6 +2388,7 @@ genUminus (iCode * ic) sym_link *optype, *rtype; char *sub; bool needpula; + asmop *result; D(emitcode ("; genUminus","")); @@ -2313,28 +2412,39 @@ genUminus (iCode * ic) if (size == 1) { - needpula = pushRegIfUsed (hc08_reg_a); + if (!IS_AOP_A (AOP (IC_LEFT (ic)))) + needpula = pushRegIfUsed (hc08_reg_a); + else + needpula = FALSE; loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0); emitcode ("nega", ""); hc08_freeReg (hc08_reg_a); - storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)), + storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)), SPEC_USIGN (operandType (IC_LEFT (ic)))); pullOrFreeReg (hc08_reg_a, needpula); } else { + if (IS_AOP_XA (AOP (IC_RESULT (ic)))) + result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE); + else + result = AOP (IC_RESULT (ic)); + needpula = pushRegIfUsed (hc08_reg_a); sub="sub"; while (size--) { loadRegFromConst (hc08_reg_a, zero); accopWithAop (sub, AOP( IC_LEFT (ic)), offset); - storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++); + storeRegToAop (hc08_reg_a, result, offset++); sub = "sbc"; } - storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset, + storeRegSignToUpperAop (hc08_reg_a, result, offset, SPEC_USIGN (operandType (IC_LEFT (ic)))); pullOrFreeReg (hc08_reg_a, needpula); + + if (IS_AOP_XA (AOP (IC_RESULT (ic)))) + freeAsmop (NULL, result, ic, TRUE); } @@ -2342,7 +2452,7 @@ genUminus (iCode * ic) release: /* release the aops */ freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + freeAsmop (IC_LEFT (ic), NULL, ic, FALSE); } /*-----------------------------------------------------------------*/ @@ -2374,11 +2484,11 @@ saveRegisters (iCode * lic) (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))) return; - + /* safe the registers in use at this time but skip the ones for the result */ - rsave = bitVectCplAnd (bitVectCopy (ic->rMask), - hc08_rUmaskForOp (IC_RESULT(ic))); + rsave = bitVectCplAnd (bitVectCopy (ic->rMask), + hc08_rUmaskForOp (IC_RESULT(ic))); ic->regsSaved = 1; for (i = 0; i < hc08_nRegs; i++) @@ -2399,8 +2509,8 @@ unsaveRegisters (iCode * ic) /* restore the registers in use at this time but skip the ones for the result */ - rsave = bitVectCplAnd (bitVectCopy (ic->rMask), - hc08_rUmaskForOp (IC_RESULT(ic))); + rsave = bitVectCplAnd (bitVectCopy (ic->rMask), + hc08_rUmaskForOp (IC_RESULT(ic))); for (i = hc08_nRegs; i >= 0; i--) { @@ -2412,17 +2522,22 @@ unsaveRegisters (iCode * ic) /*-----------------------------------------------------------------*/ -/* pushSide - */ +/* pushSide - */ /*-----------------------------------------------------------------*/ static void -pushSide (operand * oper, int size) +pushSide (operand * oper, int size, iCode * ic) { int offset = 0; + + aopOp (oper, ic, FALSE); + while (size--) { loadRegFromAop (hc08_reg_a, AOP (oper), offset++); pushReg ( hc08_reg_a, TRUE); } + + freeAsmop (oper, NULL, ic, TRUE); } /*-----------------------------------------------------------------*/ @@ -2451,7 +2566,6 @@ static void genIpush (iCode * ic) { int size, offset = 0; -// char *l; D(emitcode ("; genIpush","")); @@ -2462,7 +2576,7 @@ genIpush (iCode * ic) /* and the item is spilt then do nothing */ if (OP_SYMBOL (IC_LEFT (ic))->isspilt) - return; + return; aopOp (IC_LEFT (ic), ic, FALSE); size = AOP_SIZE (IC_LEFT (ic)); @@ -2540,27 +2654,27 @@ genIpop (iCode * ic) /*-----------------------------------------------------------------*/ -/* genSend - gen code for SEND */ +/* genSend - gen code for SEND */ /*-----------------------------------------------------------------*/ static void genSend(set *sendSet) { iCode *sic; - for (sic = setFirstItem (_G.sendSet); sic; - sic = setNextItem (_G.sendSet)) { - int size, offset = 0; - aopOp (IC_LEFT (sic), sic, FALSE); - size = AOP_SIZE (IC_LEFT (sic)); - - if (sic->argreg) { - offset = size-1; - while (size--) { - transferAopAop( AOP (IC_LEFT (sic)), offset, - hc08_aop_pass[offset+(sic->argreg-1)], 0); - offset--; - } - } - freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); + for (sic = setFirstItem (sendSet); sic; + sic = setNextItem (sendSet)) { + int size, offset = 0; + aopOp (IC_LEFT (sic), sic, FALSE); + size = AOP_SIZE (IC_LEFT (sic)); + + if (sic->argreg) { + offset = size-1; + while (size--) { + transferAopAop( AOP (IC_LEFT (sic)), offset, + hc08_aop_pass[offset+(sic->argreg-1)], 0); + offset--; + } + } + freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); } } @@ -2577,14 +2691,14 @@ 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 */ - genSend(reverseSet(_G.sendSet)); - } else { - genSend(_G.sendSet); - } + if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */ + genSend(reverseSet(_G.sendSet)); + } else { + genSend(_G.sendSet); + } _G.sendSet = NULL; } @@ -2596,15 +2710,15 @@ genCall (iCode * ic) /* make the call */ emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ? - OP_SYMBOL (IC_LEFT (ic))->rname : - OP_SYMBOL (IC_LEFT (ic))->name)); + OP_SYMBOL (IC_LEFT (ic))->rname : + OP_SYMBOL (IC_LEFT (ic))->name)); /* if we need assign a result value */ if ((IS_ITEMP (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->accuse || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || + OP_SYMBOL (IC_RESULT (ic))->accuse || + OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic))) { @@ -2642,7 +2756,7 @@ genPcall (iCode * ic) // bool restoreBank=FALSE; // bool swapBanks = FALSE; - D(emitcode("; genPCall","")); + D (emitcode (";", "genPcall")); /* if caller saves & we have not saved then */ if (!ic->regsSaved) @@ -2653,21 +2767,21 @@ genPcall (iCode * ic) destination registers on the stack */ dtype = operandType (IC_LEFT (ic))->next; - /* now push the calling address */ + /* push the return address on to the stack */ 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); - pushSide (IC_LEFT (ic), FPTRSIZE); - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + /* now push the function address */ + pushSide (IC_LEFT (ic), FPTRSIZE, ic); - /* if send set is not empty the assign */ + /* if send set is not empty then assign */ if (_G.sendSet) { - genSend(reverseSet(_G.sendSet)); - _G.sendSet = NULL; + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; } @@ -2675,12 +2789,14 @@ 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 */ if ((IS_ITEMP (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || + OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic))) { @@ -2719,18 +2835,12 @@ resultRemat (iCode * ic) { symbol *sym = OP_SYMBOL (IC_RESULT (ic)); if (sym->remat && !POINTER_SET (ic)) - return 1; + return 1; } 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 */ /*-----------------------------------------------------------------*/ @@ -2758,85 +2868,95 @@ 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; + _G.stackPushes = 0; + debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0); + if (IFFUNC_ISNAKED(ftype)) { emitcode(";", "naked function: no prologue."); return; } - - /* if this is an interrupt service routine then save h */ if (IFFUNC_ISISR (sym->type)) { if (!inExcludeList ("h")) - emitcode ("pshh", ""); - } - else - { - /* 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; - - /* 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++; - } - } - } - } + pushReg (hc08_reg_h, FALSE); } - if (IFFUNC_ISREENT (sym->type) || options.stackAuto) + /* 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)) { + symbol * rsym = OP_SYMBOL (IC_RESULT (ric)); + int rsymSize = rsym ? getSize(rsym->type) : 0; + + 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 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; - + /* 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); @@ -2868,6 +2988,8 @@ genEndFunction (iCode * ic) if (IFFUNC_ISNAKED(sym->type)) { emitcode(";", "naked function: no epilogue."); + if (options.debug && currFunc) + debugFile->writeEndFunction (currFunc, ic, 0); return; } @@ -2909,58 +3031,42 @@ genEndFunction (iCode * ic) { if (!inExcludeList ("h")) - emitcode ("pulh", ""); + pullReg (hc08_reg_h); /* if debug then send end of function */ if (options.debug && currFunc) - { - _G.debugLine = 1; - emitcode ("", "C$%s$%d$%d$%d ==.", - FileBaseName (ic->filename), currFunc->lastLine, - ic->level, ic->block); - if (IS_STATIC (currFunc->etype)) - emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name); - else - emitcode ("", "XG$%s$0$0 ==.", currFunc->name); - _G.debugLine = 0; - } - + { + debugFile->writeEndFunction (currFunc, ic, 1); + } + emitcode ("rti", ""); } else { if (IFFUNC_CALLEESAVES(sym->type)) - { - int i; - - /* if any registers used */ - if (sym->regsUsed) - { - /* save the registers used */ - for (i = sym->regsUsed->size; i >= 0; i--) - { - if (bitVectBitValue (sym->regsUsed, i) || - (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX))) - emitcode ("pop", "%s", hc08_regWithIdx (i)->dname); - } - } - - } + { + int i; + + /* if any registers used */ + if (sym->regsUsed) + { + /* save the registers used */ + for (i = sym->regsUsed->size; i >= 0; i--) + { + if (bitVectBitValue (sym->regsUsed, i) || + (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX))) + emitcode ("pop", "%s", hc08_regWithIdx (i)->name); + } + } + + } /* if debug then send end of function */ if (options.debug && currFunc) - { - _G.debugLine = 1; - emitcode ("", "C$%s$%d$%d$%d ==.", - FileBaseName (ic->filename), currFunc->lastLine, - ic->level, ic->block); - if (IS_STATIC (currFunc->etype)) - emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name); - else - emitcode ("", "XG$%s$0$0 ==.", currFunc->name); - _G.debugLine = 0; - } + { + debugFile->writeEndFunction (currFunc, ic, 1); + } emitcode ("rts", ""); } @@ -3027,7 +3133,7 @@ jumpret: /* generate a jump to the return label if the next is not the return statement */ if (!(ic->next && ic->next->op == LABEL && - IC_LABEL (ic->next) == returnLabel)) + IC_LABEL (ic->next) == returnLabel)) emitcode ("jmp", "%05d$", (returnLabel->key + 100)); @@ -3041,7 +3147,7 @@ genLabel (iCode * ic) { int i; regs *reg; - + /* For the high level labels we cannot depend on any */ /* register's contents. Amnesia time. */ for (i=A_IDX;i<=XA_IDX;i++) @@ -3055,7 +3161,9 @@ genLabel (iCode * ic) if (IC_LABEL (ic) == entryLabel) return; - emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100)); + debugFile->writeLabel(IC_LABEL (ic), ic); + + emitLabel (IC_LABEL (ic)); } @@ -3086,16 +3194,16 @@ findLabelBackwards (iCode * ic, int key) count++; /* If we have any pushes or pops, we cannot predict the distance. - I don't like this at all, this should be dealt with in the - back-end */ + I don't like this at all, this should be dealt with in the + back-end */ if (ic->op == IPUSH || ic->op == IPOP) { - return 0; + return 0; } if (ic->op == LABEL && IC_LABEL (ic)->key == key) - { - return count; - } + { + return count; + } } return 0; @@ -3115,9 +3223,9 @@ 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); result = IC_RESULT (ic); @@ -3127,17 +3235,25 @@ genPlusIncr (iCode * ic) if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) return FALSE; - icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + + DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)))); - 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) ) ) && (icount>=-128) && (icount<=127) && (size==2)) { - needpulx = pushRegIfUsed (hc08_reg_x); - needpulh = pushRegIfUsed (hc08_reg_h); + if (!IS_AOP_HX (AOP (left))) + { + needpulx = pushRegIfUsed (hc08_reg_x); + needpulh = pushRegIfUsed (hc08_reg_h); + } + else + { + needpulx = FALSE; + needpulh = FALSE; + } loadRegFromAop (hc08_reg_hx, AOP(left), 0); emitcode ("aix","#%d", icount); hc08_dirtyReg (hc08_reg_hx, FALSE); @@ -3147,9 +3263,9 @@ genPlusIncr (iCode * ic) return TRUE; } - emitcode ("", "; icount = %d, sameRegs=%d", icount, - sameRegs (AOP (left), AOP (result))); - + DD(emitcode ("", "; icount = %d, sameRegs=%d", icount, + sameRegs (AOP (left), AOP (result)))); + if ((icount > 255) || (icount<0)) return FALSE; @@ -3170,7 +3286,10 @@ genPlusIncr (iCode * ic) } else { - needpula = pushRegIfUsed (hc08_reg_a); + if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result))) + needpula = pushRegIfUsed (hc08_reg_a); + else + needpula = FALSE; loadRegFromAop (hc08_reg_a, AOP (result), 0); accopWithAop ("add", AOP (IC_RIGHT (ic)), 0); hc08_useReg (hc08_reg_a); @@ -3188,9 +3307,9 @@ genPlusIncr (iCode * ic) if (size>1) emitLabel (tlbl); - + pullOrFreeReg (hc08_reg_a, needpula); - + return TRUE; } @@ -3229,10 +3348,10 @@ genPlus (iCode * ic) if (genPlusIncr (ic) == TRUE) goto release; - emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))); - emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))); - 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)); leftOp = AOP(IC_LEFT(ic)); @@ -3259,7 +3378,7 @@ release: } /*-----------------------------------------------------------------*/ -/* genMinusDec :- does subtraction with deccrement if possible */ +/* genMinusDec :- does subtraction with decrement if possible */ /*-----------------------------------------------------------------*/ static bool genMinusDec (iCode * ic) @@ -3272,7 +3391,7 @@ genMinusDec (iCode * ic) unsigned int size = getDataSize (IC_RESULT (ic)); // int offset; // symbol *tlbl; - + left = IC_LEFT (ic); result = IC_RESULT (ic); @@ -3282,22 +3401,30 @@ genMinusDec (iCode * ic) if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) return FALSE; - icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) && (icount>=-127) && (icount<=128) && (size==2)) { - needpulx = pushRegIfUsed (hc08_reg_x); - needpulh = pushRegIfUsed (hc08_reg_h); + if (!IS_AOP_HX (AOP (left))) + { + needpulx = pushRegIfUsed (hc08_reg_x); + needpulh = pushRegIfUsed (hc08_reg_h); + } + else + { + needpulx = FALSE; + needpulh = FALSE; + } loadRegFromAop (hc08_reg_hx, AOP(left), 0); - emitcode ("aix","#%d", -icount); + emitcode ("aix","#%d", -(int) icount); hc08_dirtyReg (hc08_reg_hx, FALSE); storeRegToAop (hc08_reg_hx, AOP(result), 0); pullOrFreeReg (hc08_reg_h, needpulh); pullOrFreeReg (hc08_reg_x, needpulx); return TRUE; } - + if ((icount > 1) || (icount<0)) return FALSE; @@ -3310,7 +3437,7 @@ genMinusDec (iCode * ic) D(emitcode ("; genMinusDec","")); rmwWithAop ("dec", AOP (result), 0); - + return TRUE; } @@ -3324,16 +3451,16 @@ addSign (operand * result, int offset, int sign) if (size > 0) { if (sign) - { - emitcode ("rola", ""); - emitcode ("clra", ""); - emitcode ("sbc", zero); - while (size--) - storeRegToAop (hc08_reg_a, AOP (result), offset++); - } + { + emitcode ("rola", ""); + emitcode ("clra", ""); + emitcode ("sbc", zero); + while (size--) + storeRegToAop (hc08_reg_a, AOP (result), offset++); + } else - while (size--) - storeConstToAop (zero, AOP (result), offset++); + while (size--) + storeConstToAop (zero, AOP (result), offset++); } } @@ -3346,7 +3473,7 @@ genMinus (iCode * ic) { char *sub; int size, offset = 0; - + asmop *leftOp, *rightOp; D(emitcode ("; genMinus","")); @@ -3366,18 +3493,27 @@ 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"; } - - + + // adjustArithmeticResult (ic); release: @@ -3393,20 +3529,21 @@ release: /*-----------------------------------------------------------------*/ static void genMultOneByte (operand * left, - operand * right, - operand * result) + operand * right, + operand * result) { - sym_link *opetype = operandType (result); + /* sym_link *opetype = operandType (result); */ symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4; int size=AOP_SIZE(result); bool negLiteral = FALSE; + bool lUnsigned, rUnsigned; D(emitcode ("; genMultOneByte","")); if (size<1 || size>2) { // this should never happen - fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", - AOP_SIZE(result), __FILE__, lineno); + fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", + AOP_SIZE(result), __FILE__, lineno); exit (1); } @@ -3417,13 +3554,34 @@ genMultOneByte (operand * left, operand *t = right; right = left; left = t; - //emitcode (";", "swapped left and right"); } + /* if an operand is in A, make sure it is on the left */ + if (IS_AOP_A (AOP (right))) + { + operand *t = right; + right = left; + left = t; + } + + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); - if (SPEC_USIGN(opetype)) + /* lUnsigned rUnsigned negLiteral negate case */ + /* false false false odd 3 */ + /* false false true even 3 */ + /* false true false odd 3 */ + /* false true true impossible */ + /* true false false odd 3 */ + /* true false true always 2 */ + /* true true false never 1 */ + /* true true true impossible */ + + /* case 1 */ + if (size == 1 + || (lUnsigned && rUnsigned)) { // just an unsigned 8*8=8/16 multiply - //emitcode (";","unsigned"); + //DD(emitcode (";","unsigned")); loadRegFromAop (hc08_reg_a, AOP (left), 0); loadRegFromAop (hc08_reg_x, AOP (right), 0); @@ -3431,28 +3589,61 @@ genMultOneByte (operand * left, hc08_dirtyReg (hc08_reg_xa, FALSE); storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE); hc08_freeReg (hc08_reg_xa); - + return; } // we have to do a signed multiply + /* case 2 */ + /* left unsigned, right signed literal -- literal determines sign handling */ + if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned) + { + signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit); + + loadRegFromAop (hc08_reg_a, AOP (left), 0); + if (val < 0) + emitcode ("ldx", "#0x%02x", -val); + else + emitcode ("ldx", "#0x%02x", val); + + emitcode ("mul", ""); + + if (val < 0) + { + rmwWithReg ("neg", hc08_reg_a); + tlbl4 = newiTempLabel (NULL); + emitBranch ("bcc", tlbl4); + rmwWithReg ("inc", hc08_reg_x); + emitLabel (tlbl4); + rmwWithReg ("neg", hc08_reg_x); + } + + hc08_dirtyReg (hc08_reg_xa, FALSE); + storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE); + hc08_freeReg (hc08_reg_xa); + return; + } + - //emitcode (";", "signed"); + /* case 3 */ adjustStack (-1); emitcode ("clr", "1,s"); - tlbl1 = newiTempLabel (NULL); loadRegFromAop (hc08_reg_a, AOP (left), 0); - emitcode ("tsta",""); - emitBranch ("bpl", tlbl1); - emitcode ("inc", "1,s"); - rmwWithReg ("neg", hc08_reg_a); - emitLabel (tlbl1); + if (!lUnsigned) + { + tlbl1 = newiTempLabel (NULL); + emitcode ("tsta",""); + emitBranch ("bpl", tlbl1); + emitcode ("inc", "1,s"); + rmwWithReg ("neg", hc08_reg_a); + emitLabel (tlbl1); + } - if (AOP_TYPE(right)==AOP_LIT) + if (AOP_TYPE(right)==AOP_LIT && !rUnsigned) { - signed char val=floatFromVal (AOP (right)->aopu.aop_lit); + signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit); /* AND literal negative */ if (val < 0) { emitcode ("ldx", "#0x%02x", -val); @@ -3464,13 +3655,16 @@ genMultOneByte (operand * left, } else { - tlbl2 = newiTempLabel (NULL); loadRegFromAop (hc08_reg_x, AOP (right), 0); - emitcode ("tstx", ""); - emitBranch ("bpl", tlbl2); - emitcode ("inc", "1,s"); - rmwWithReg ("neg", hc08_reg_x); - emitLabel (tlbl2); + if (!rUnsigned) + { + tlbl2 = newiTempLabel (NULL); + emitcode ("tstx", ""); + emitBranch ("bpl", tlbl2); + emitcode ("inc", "1,s"); + rmwWithReg ("neg", hc08_reg_x); + emitLabel (tlbl2); + } } emitcode ("mul", ""); @@ -3478,20 +3672,17 @@ genMultOneByte (operand * left, tlbl3 = newiTempLabel (NULL); emitcode ("dec", "1,s"); - if (negLiteral) - emitBranch ("bne", tlbl3); - else + if (!lUnsigned && !rUnsigned && negLiteral) emitBranch ("beq", tlbl3); + else + emitBranch ("bne", tlbl3); rmwWithReg ("neg", hc08_reg_a); - if (size>1) - { - tlbl4 = newiTempLabel (NULL); - emitBranch ("bcc", tlbl4); - rmwWithReg ("inc", hc08_reg_x); - emitLabel (tlbl4); - rmwWithReg ("neg", hc08_reg_x); - } + tlbl4 = newiTempLabel (NULL); + emitBranch ("bcc", tlbl4); + rmwWithReg ("inc", hc08_reg_x); + emitLabel (tlbl4); + rmwWithReg ("neg", hc08_reg_x); emitLabel (tlbl3); adjustStack (1); @@ -3519,9 +3710,9 @@ genMult (iCode * ic) /* special cases first */ /* if both are of size == 1 */ -// if (getSize(operandType(left)) == 1 && +// if (getSize(operandType(left)) == 1 && // getSize(operandType(right)) == 1) - if (AOP_SIZE (left) == 1 && + if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) { genMultOneByte (left, right, result); @@ -3530,9 +3721,9 @@ genMult (iCode * ic) /* should have been converted to function call */ fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type), - getSize(OP_SYMBOL(right)->type)); + getSize(OP_SYMBOL(right)->type)); fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left), - AOP_SIZE (right)); + AOP_SIZE (right)); assert (0); release: @@ -3546,25 +3737,28 @@ release: /*-----------------------------------------------------------------*/ static void genDivOneByte (operand * left, - operand * right, - operand * result) + operand * right, + operand * result) { - sym_link *opetype = operandType (result); -// char *l; - symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4; + symbol *tlbl1, *tlbl2, *tlbl3; int size; - bool negLiteral = FALSE; + int offset = 0; + bool lUnsigned, rUnsigned; + bool runtimeSign, compiletimeSign; + + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); D(emitcode ("; genDivOneByte","")); size = AOP_SIZE (result); /* signed or unsigned */ - if (SPEC_USIGN (opetype)) + if (lUnsigned && rUnsigned) { /* unsigned is easy */ loadRegFromAop (hc08_reg_h, AOP (left), 1); - loadRegFromAop (hc08_reg_a, AOP (left), 0); loadRegFromAop (hc08_reg_x, AOP (right), 0); + loadRegFromAop (hc08_reg_a, AOP (left), 0); emitcode ("div", ""); hc08_dirtyReg (hc08_reg_a, FALSE); hc08_dirtyReg (hc08_reg_h, FALSE); @@ -3577,66 +3771,146 @@ genDivOneByte (operand * left, /* signed is a little bit more difficult */ - adjustStack (-1); - emitcode ("clr", "1,s"); + /* now sign adjust for both left & right */ - tlbl1 = newiTempLabel (NULL); - tlbl2 = newiTempLabel (NULL); - loadRegFromAop (hc08_reg_a, AOP (left), 0); - loadRegFromAop (hc08_reg_x, AOP (left), 1); - emitBranch ("bpl", tlbl1); - emitcode ("inc", "1,s"); - rmwWithReg ("neg", hc08_reg_a); - emitBranch ("bcc", tlbl2); - rmwWithReg ("inc", hc08_reg_x); - emitLabel (tlbl2); - rmwWithReg ("neg", hc08_reg_x); - transferRegReg (hc08_reg_x, hc08_reg_h, TRUE); - emitLabel (tlbl1); + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; - if (AOP_TYPE(right)==AOP_LIT) + if (!lUnsigned) { - signed char val=floatFromVal (AOP (right)->aopu.aop_lit); - /* AND literal negative */ - if (val < 0) { + if (AOP_TYPE(left) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit); + if (val < 0) + compiletimeSign = TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + if (!rUnsigned) + { + if (AOP_TYPE(right) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit); + if (val < 0) + compiletimeSign ^= TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + /* initialize the runtime sign */ + if (runtimeSign) + { + if (compiletimeSign) + loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */ + else + loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */ + pushReg (hc08_reg_x, TRUE); + } + + /* save the signs of the operands */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit); + + if (!rUnsigned && val < 0) emitcode ("ldx", "#0x%02x", -val); - negLiteral = TRUE; - } else { - emitcode ("ldx", "#0x%02x", val); - } - hc08_useReg (hc08_reg_x); + else + emitcode ("ldx", "#0x%02x", (unsigned char) val); } - else + else /* ! literal */ { - tlbl3 = newiTempLabel (NULL); loadRegFromAop (hc08_reg_x, AOP (right), 0); - emitBranch ("bpl", tlbl3); - emitcode ("inc", "1,s"); - rmwWithReg ("neg", hc08_reg_x); - emitLabel (tlbl3); + if (!rUnsigned) + { + tlbl1 = newiTempLabel (NULL); + emitcode ("tstx", ""); + emitBranch ("bpl", tlbl1); + emitcode ("inc", "1,s"); + rmwWithReg ("neg", hc08_reg_x); + emitLabel (tlbl1); + } + } + + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit); + + if (!lUnsigned && val < 0) + emitcode ("lda", "#0x%02x", -val); + else + emitcode ("lda", "#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + loadRegFromAop (hc08_reg_a, AOP (left), 0); + if (!lUnsigned) + { + tlbl2 = newiTempLabel (NULL); + emitcode ("tsta", ""); + emitBranch ("bpl", tlbl2); + emitcode ("inc", "1,s"); + rmwWithReg ("neg", hc08_reg_a); + emitLabel (tlbl2); + } } + loadRegFromConst (hc08_reg_h, zero); emitcode ("div", ""); hc08_dirtyReg (hc08_reg_x, FALSE); hc08_dirtyReg (hc08_reg_a, FALSE); hc08_dirtyReg (hc08_reg_h, FALSE); - tlbl4 = newiTempLabel (NULL); - emitcode ("dec", "1,s"); - if (negLiteral) - emitBranch ("bne", tlbl4); + if (runtimeSign || compiletimeSign) + { + tlbl3 = newiTempLabel (NULL); + if (runtimeSign) + { + pullReg (hc08_reg_x); + rmwWithReg ("lsr", hc08_reg_x); + rmwWithReg ("ror", hc08_reg_x); + emitBranch ("bpl", tlbl3); + } + + rmwWithReg ("neg", hc08_reg_a); + if (runtimeSign) + emitLabel (tlbl3); + + storeRegToAop (hc08_reg_a, AOP (result), 0); + + if (size > 1) + { + /* msb is 0x00 or 0xff depending on the sign */ + if (runtimeSign) + { + rmwWithReg ("lsl", hc08_reg_x); + emitcode ("clra", ""); + emitcode ("sbc", "#0"); + while (--size) + storeRegToAop (hc08_reg_a, AOP (result), ++offset); + } + else /* compiletimeSign */ + while (--size) + storeConstToAop ("#0xff", AOP (result), ++offset); + } + } else - emitBranch ("beq", tlbl4); - rmwWithReg ("neg", hc08_reg_a); + { + storeRegToFullAop (hc08_reg_a, AOP (result), FALSE); + } - emitLabel (tlbl4); - adjustStack (1); - storeRegToFullAop (hc08_reg_a, AOP (result), TRUE); hc08_freeReg (hc08_reg_a); hc08_freeReg (hc08_reg_x); hc08_freeReg (hc08_reg_h); - - } /*-----------------------------------------------------------------*/ @@ -3678,98 +3952,149 @@ release: /*-----------------------------------------------------------------*/ static void genModOneByte (operand * left, - operand * right, - operand * result) + operand * right, + operand * result) { - sym_link *opetype = operandType (result); -// symbol *lbl; - symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4; + symbol *tlbl1, *tlbl2, *tlbl3; int size; - bool negLiteral = FALSE; + int offset = 0; + bool lUnsigned, rUnsigned; + bool runtimeSign, compiletimeSign; + + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); D(emitcode ("; genModOneByte","")); size = AOP_SIZE (result); - /* signed or unsigned */ - if (SPEC_USIGN (opetype)) + + if (lUnsigned && rUnsigned) { /* unsigned is easy */ + loadRegFromAop (hc08_reg_x, AOP (right), 0); loadRegFromAop (hc08_reg_h, AOP (left), 1); loadRegFromAop (hc08_reg_a, AOP (left), 0); - loadRegFromAop (hc08_reg_x, AOP (right), 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; } /* signed is a little bit more difficult */ - adjustStack (-1); - emitcode ("clr", "1,s"); - - tlbl1 = newiTempLabel (NULL); - tlbl2 = newiTempLabel (NULL); - loadRegFromAop (hc08_reg_a, AOP (left), 0); - loadRegFromAop (hc08_reg_x, AOP (left), 1); - emitBranch ("bpl", tlbl1); - emitcode ("inc", "1,s"); - rmwWithReg ("neg", hc08_reg_a); - emitBranch ("bcc", tlbl2); - rmwWithReg ("inc", hc08_reg_x); - emitLabel (tlbl2); - rmwWithReg ("neg", hc08_reg_x); - transferRegReg (hc08_reg_x, hc08_reg_h, TRUE); - emitLabel (tlbl1); - - if (AOP_TYPE(right)==AOP_LIT) + if (AOP_TYPE(right) == AOP_LIT) { - signed char val=floatFromVal (AOP (right)->aopu.aop_lit); - /* AND literal negative */ - if (val < 0) { + signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit); + + if (!rUnsigned && val < 0) emitcode ("ldx", "#0x%02x", -val); - negLiteral = TRUE; - } else { - emitcode ("ldx", "#0x%02x", val); - } - hc08_useReg (hc08_reg_x); + else + emitcode ("ldx", "#0x%02x", (unsigned char) val); } - else + else /* ! literal */ { - tlbl3 = newiTempLabel (NULL); loadRegFromAop (hc08_reg_x, AOP (right), 0); - emitBranch ("bpl", tlbl3); - emitcode ("inc", "1,s"); - rmwWithReg ("neg", hc08_reg_x); - emitLabel (tlbl3); + if (!rUnsigned) + { + tlbl1 = newiTempLabel (NULL); + emitcode ("tstx", ""); + emitBranch ("bpl", tlbl1); + rmwWithReg ("neg", hc08_reg_x); + emitLabel (tlbl1); + } } - emitcode ("div", ""); - hc08_dirtyReg (hc08_reg_x, FALSE); - hc08_dirtyReg (hc08_reg_a, FALSE); - hc08_dirtyReg (hc08_reg_h, FALSE); + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; - tlbl4 = newiTempLabel (NULL); - transferRegReg (hc08_reg_h, hc08_reg_a, TRUE); - emitcode ("dec", "1,s"); - if (negLiteral) - emitBranch ("bne", tlbl4); - else - emitBranch ("beq", tlbl4); - rmwWithReg ("neg", hc08_reg_a); + /* sign adjust left side */ + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit); - emitLabel (tlbl4); - adjustStack (1); - storeRegToFullAop (hc08_reg_a, AOP (result), TRUE); + if (!lUnsigned && val < 0) + { + compiletimeSign = TRUE; /* set sign flag */ + emitcode ("lda", "#0x%02x", -val); + } + else + emitcode ("lda", "#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + if (lUnsigned) + loadRegFromAop (hc08_reg_a, AOP (left), 0); + else + { + runtimeSign = TRUE; + adjustStack (-1); + emitcode ("clr", "1,s"); + + loadRegFromAop (hc08_reg_a, AOP (left), 0); + tlbl2 = newiTempLabel (NULL); + emitcode ("tsta", ""); + emitBranch ("bpl", tlbl2); + emitcode ("inc", "1,s"); + rmwWithReg ("neg", hc08_reg_a); + emitLabel (tlbl2); + } + } + + loadRegFromConst (hc08_reg_h, zero); + emitcode ("div", ""); hc08_freeReg (hc08_reg_a); hc08_freeReg (hc08_reg_x); - hc08_freeReg (hc08_reg_h); + hc08_dirtyReg (hc08_reg_h, FALSE); -} + if (runtimeSign || compiletimeSign) + { + transferRegReg (hc08_reg_h, hc08_reg_a, TRUE); + tlbl3 = newiTempLabel (NULL); + if (runtimeSign) + { + pullReg (hc08_reg_x); + rmwWithReg ("lsr", hc08_reg_x); + rmwWithReg ("ror", hc08_reg_x); + emitBranch ("bpl", tlbl3); + } + + rmwWithReg ("neg", hc08_reg_a); + if (runtimeSign) + emitLabel (tlbl3); + + storeRegToAop (hc08_reg_a, AOP (result), 0); + + if (size > 1) + { + /* msb is 0x00 or 0xff depending on the sign */ + if (runtimeSign) + { + rmwWithReg ("lsl", hc08_reg_x); + emitcode ("clra", ""); + emitcode ("sbc", "#0"); + while (--size) + storeRegToAop (hc08_reg_a, AOP (result), ++offset); + } + else /* compiletimeSign */ + while (--size) + storeConstToAop ("#0xff", AOP (result), ++offset); + } + } + else + { + storeRegToFullAop (hc08_reg_h, AOP (result), FALSE); + } + + hc08_freeReg (hc08_reg_a); + hc08_freeReg (hc08_reg_x); + hc08_freeReg (hc08_reg_h); +} /*-----------------------------------------------------------------*/ /* genMod - generates code for division */ @@ -3849,109 +4174,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 - { - needpula = pushRegIfUsed (hc08_reg_a); - 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"; +/*------------------------------------------------------------------*/ +/* nameCmp : helper function for human readable debug output */ +/*------------------------------------------------------------------*/ +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"; } +} -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 + return "bhi"; + case LE_OP: + if (sign) + return "ble"; + else + return "bls"; + case GE_OP: + if (sign) + return "bge"; else - if (!sign) - outBitC (result); - else - outBitNV (result); - pullOrFreeReg(hc08_reg_a,needpula); + 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); @@ -3965,22 +4327,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); + } + + 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 = ulFromVal (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); + } - 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; - D(emitcode ("; genCmpLt","")); + opcode = ic->op; + + D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode))); result = IC_RESULT (ic); left = IC_LEFT (ic); @@ -3989,141 +4465,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); + size = max (AOP_SIZE (left), AOP_SIZE (right)); - /* 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) + 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 */ /*-----------------------------------------------------------------*/ @@ -4151,71 +4614,93 @@ 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 */ - emitcode("","; checking lic"); + DD(emitcode("","; checking lic")); if (!lic) return FALSE; /* Make sure the result of the addition is an iCode */ - 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); - emitcode("","; pset=%d, pget=%d",pset,pget); + DD(emitcode("","; pset=%d, pget=%d",pset,pget)); if (!pset && !pget) return FALSE; - emitcode("", "; checking pset operandsEqu"); + /* Make sure this is the only use of the pointer */ + if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1) + return FALSE; + + DD(emitcode("", "; checking pset operandsEqu")); if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic))) return FALSE; - emitcode("", "; checking pget operandsEqu"); + DD(emitcode("", "; checking pget operandsEqu")); if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic))) return FALSE; - emitcode("", "; checking IS_SYMOP"); + DD(emitcode("", "; checking IS_SYMOP")); if (!IS_SYMOP (IC_LEFT (ic))) return FALSE; - 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)); - - emitcode("", "; checking remat"); + + DD(emitcode("", "; checking remat")); if (!sym->remat) return FALSE; - + + if (pget) { D(emitcode ("; genPointerGetOfs","")); aopOp (IC_LEFT(ic), ic, FALSE); derefaop = aopDerefAop (AOP (IC_LEFT (ic))); freeAsmop (IC_LEFT(ic), NULL, ic, TRUE); - + aopOp (IC_RIGHT(ic), ic, FALSE); aopOp (IC_RESULT(lic), lic, FALSE); - - loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0); + if (AOP_SIZE (IC_RIGHT (ic)) == 1) + { + if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic))))) + { + loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0); + loadRegFromConst (hc08_reg_h, zero); + } + else + { + loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0); + transferRegReg (hc08_reg_a, hc08_reg_x, FALSE); + emitcode ("rola",""); + emitcode ("clra",""); + emitcode ("sbc", "#0"); + hc08_useReg (hc08_reg_a); + transferRegReg (hc08_reg_a, hc08_reg_h, FALSE); + } + } + else + 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); } @@ -4225,7 +4710,7 @@ genPointerGetSetOfs (iCode *ic) freeAsmop (NULL, derefaop, ic, TRUE); freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE); freeAsmop (IC_RESULT(lic), NULL, lic, TRUE); - + return TRUE; } @@ -4238,20 +4723,36 @@ genPointerGetSetOfs (iCode *ic) aopOp (IC_RIGHT(ic), ic, FALSE); aopOp (IC_RIGHT(lic), lic, FALSE); - - loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0); + if (AOP_SIZE (IC_RIGHT (ic)) == 1) + { + if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic))))) + { + loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0); + loadRegFromConst (hc08_reg_h, zero); + } + else + { + loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0); + transferRegReg (hc08_reg_a, hc08_reg_x, FALSE); + emitcode ("rola",""); + emitcode ("clra",""); + emitcode ("sbc", "#0"); + hc08_useReg (hc08_reg_a); + transferRegReg (hc08_reg_a, hc08_reg_h, FALSE); + } + } + else + 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; @@ -4260,10 +4761,10 @@ genPointerGetSetOfs (iCode *ic) freeAsmop (NULL, derefaop, ic, TRUE); freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE); freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE); - + return TRUE; } - + return FALSE; } @@ -4278,7 +4779,7 @@ hasInc (operand *op, iCode *ic,int osize) sym_link *retype = getSpec (type); iCode *lic = ic->next; int isize ; - + /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */ if (!IS_SYMOP(op)) return NULL; @@ -4289,13 +4790,13 @@ 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) { + isOperandEqual(IC_RESULT(lic),op) && + isOperandLiteral(IC_RIGHT(lic)) && + operandLitValue(IC_RIGHT(lic)) == isize) { 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 */ @@ -4325,7 +4826,7 @@ genAndOp (iCode * ic) tlbl = newiTempLabel (NULL); tlbl0 = newiTempLabel (NULL); - + asmopToBool (AOP (left), FALSE); emitBranch ("beq", tlbl0); asmopToBool (AOP (right), FALSE); @@ -4338,7 +4839,7 @@ genAndOp (iCode * ic) hc08_useReg (hc08_reg_a); hc08_freeReg (hc08_reg_a); - + storeRegToFullAop (hc08_reg_a, AOP (result), FALSE); freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); @@ -4367,7 +4868,7 @@ genOrOp (iCode * ic) tlbl = newiTempLabel (NULL); tlbl0 = newiTempLabel (NULL); - + asmopToBool (AOP (left), FALSE); emitBranch ("bne", tlbl0); asmopToBool (AOP (right), FALSE); @@ -4380,7 +4881,7 @@ genOrOp (iCode * ic) hc08_useReg (hc08_reg_a); hc08_freeReg (hc08_reg_a); - + storeRegToFullAop (hc08_reg_a, AOP (result), FALSE); @@ -4468,8 +4969,9 @@ genAnd (iCode * ic, iCode * ifx) int size, offset = 0; unsigned long lit = 0L; unsigned long litinv; + unsigned char bytemask; + - // int bytelit = 0; // char buffer[10]; @@ -4480,12 +4982,12 @@ genAnd (iCode * ic, iCode * ifx) aopOp ((result = IC_RESULT (ic)), ic, TRUE); #ifdef DEBUG_TYPE - emitcode ("", "; Type res[%d] = l[%d]&r[%d]", - AOP_TYPE (result), - AOP_TYPE (left), AOP_TYPE (right)); - emitcode ("", "; Size res[%d] = l[%d]&r[%d]", - AOP_SIZE (result), - AOP_SIZE (left), AOP_SIZE (right)); + DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", + AOP_TYPE (result), + AOP_TYPE (left), AOP_TYPE (right))); + DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", + AOP_SIZE (result), + AOP_SIZE (left), AOP_SIZE (right))); #endif /* if left is a literal & right is not then exchange them */ @@ -4496,7 +4998,7 @@ genAnd (iCode * ic, iCode * ifx) left = tmp; } - /* if left is accumulator & right is not then exchange them */ + /* if right is accumulator & left is not then exchange them */ if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG) { operand *tmp = right; @@ -4504,13 +5006,84 @@ genAnd (iCode * ic, iCode * ifx) left = tmp; } + if (AOP_TYPE (right) == AOP_LIT) + lit = ulFromVal (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"); + + offset = 0; + while (size--) + { + bytemask = (lit >> (offset*8)) & 0xff; + + if (AOP_TYPE (right) == AOP_LIT && bytemask == 0) + { + /* do nothing */ + } + else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff) + { + rmwWithAop ("tst", AOP (left), offset); + if (size) + { + if (!tlbl) + tlbl = newiTempLabel (NULL); + emitBranch ("bne", tlbl); + } + } + else + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop ("and", AOP (right), offset); + hc08_freeReg( hc08_reg_a); + if (size) + { + if (!tlbl) + tlbl = newiTempLabel (NULL); + emitBranch ("bne", tlbl); + } + } + offset++; + } + if (tlbl) + emitLabel (tlbl); + genIfxJump (ifx, "a"); + goto release; + } + size = AOP_SIZE (result); if (AOP_TYPE (right) == AOP_LIT) { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ; - if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv)) { @@ -4524,12 +5097,29 @@ genAnd (iCode * ic, iCode * ifx) offset = 0; while (size--) { - loadRegFromAop (hc08_reg_a, AOP (left), offset); - if ((AOP_TYPE (right) != AOP_LIT) - || (((lit >> (offset*8)) & 0xff) != 0xff)) - accopWithAop ("and", AOP (right), offset); - storeRegToAop (hc08_reg_a, AOP (result), offset++); - hc08_freeReg( hc08_reg_a); + bytemask = (lit >> (offset*8)) & 0xff; + + if (AOP_TYPE (right) == AOP_LIT && bytemask == 0) + { + if (isOperandVolatile (left, FALSE)) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + hc08_freeReg( hc08_reg_a); + } + storeConstToAop (zero, AOP (result), offset); + } + else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff) + { + transferAopAop (AOP (left), offset, AOP (result), offset); + } + else + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop ("and", AOP (right), offset); + storeRegToAop (hc08_reg_a, AOP (result), offset); + hc08_freeReg (hc08_reg_a); + } + offset++; } release: @@ -4547,6 +5137,7 @@ genOr (iCode * ic, iCode * ifx) operand *left, *right, *result; int size, offset = 0; unsigned long lit = 0L; + unsigned char bytemask; D(emitcode ("; genOr","")); @@ -4555,12 +5146,12 @@ genOr (iCode * ic, iCode * ifx) aopOp ((result = IC_RESULT (ic)), ic, TRUE); #ifdef DEBUG_TYPE - emitcode ("", "; Type res[%d] = l[%d]&r[%d]", - AOP_TYPE (result), - AOP_TYPE (left), AOP_TYPE (right)); - emitcode ("", "; Size res[%d] = l[%d]&r[%d]", - AOP_SIZE (result), - AOP_SIZE (left), AOP_SIZE (right)); + DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", + AOP_TYPE (result), + AOP_TYPE (left), AOP_TYPE (right))); + DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", + AOP_SIZE (result), + AOP_SIZE (left), AOP_SIZE (right))); #endif /* if left is a literal & right is not then exchange them */ @@ -4579,16 +5170,76 @@ genOr (iCode * ic, iCode * ifx) left = tmp; } - /* if right is bit then exchange them */ - if (AOP_TYPE (right) == AOP_CRY && - AOP_TYPE (left) != AOP_CRY) + if (AOP_TYPE (right) == AOP_LIT) + lit = ulFromVal (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))) { - operand *tmp = right; - right = left; - left = tmp; + /* 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"); + + offset = 0; + while (size--) + { + bytemask = (lit >> (offset*8)) & 0xff; + + if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00) + { + rmwWithAop ("tst", AOP (left), offset); + if (size) + { + if (!tlbl) + tlbl = newiTempLabel (NULL); + emitBranch ("bne", tlbl); + } + } + else + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop ("ora", AOP (right), offset); + hc08_freeReg( hc08_reg_a); + if (size) + { + if (!tlbl) + tlbl = newiTempLabel (NULL); + emitBranch ("bne", tlbl); + } + } + offset++; + } + if (tlbl) + emitLabel (tlbl); + genIfxJump (ifx, "a"); + } + if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); size = AOP_SIZE (result); @@ -4601,16 +5252,33 @@ genOr (iCode * ic, iCode * ifx) aopAdrStr (AOP (left), bitpos >> 3, FALSE)); goto release; } - - offset = 0; while (size--) { - loadRegFromAop (hc08_reg_a, AOP (left), offset); - accopWithAop ("ora", AOP (right), offset); - storeRegToAop (hc08_reg_a, AOP (result), offset++); - hc08_freeReg( hc08_reg_a); + bytemask = (lit >> (offset*8)) & 0xff; + + if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff) + { + if (isOperandVolatile (left, FALSE)) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + hc08_freeReg( hc08_reg_a); + } + transferAopAop (AOP (right), offset, AOP (result), offset); + } + else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0) + { + transferAopAop (AOP (left), offset, AOP (result), offset); + } + else + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + accopWithAop ("ora", AOP (right), offset); + storeRegToAop (hc08_reg_a, AOP (result), offset); + hc08_freeReg (hc08_reg_a); + } + offset++; } @@ -4637,12 +5305,12 @@ genXor (iCode * ic, iCode * ifx) aopOp ((result = IC_RESULT (ic)), ic, TRUE); #ifdef DEBUG_TYPE - emitcode ("", "; Type res[%d] = l[%d]&r[%d]", - AOP_TYPE (result), - AOP_TYPE (left), AOP_TYPE (right)); - emitcode ("", "; Size res[%d] = l[%d]&r[%d]", - AOP_SIZE (result), - AOP_SIZE (left), AOP_SIZE (right)); + DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]", + AOP_TYPE (result), + AOP_TYPE (left), AOP_TYPE (right))); + DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]", + AOP_SIZE (result), + AOP_SIZE (left), AOP_SIZE (right))); #endif /* if left is a literal & right is not || @@ -4662,16 +5330,36 @@ genXor (iCode * ic, iCode * ifx) left = tmp; } - /* if right is bit then exchange them */ - if (AOP_TYPE (right) == AOP_CRY && - AOP_TYPE (left) != AOP_CRY) + if (AOP_TYPE (result) == AOP_CRY) { - operand *tmp = right; - right = left; - left = tmp; + symbol *tlbl; + wassertl (ifx, "AOP_CPY result without ifx"); + + tlbl = newiTempLabel (NULL); + size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right); + offset = 0; + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (left), offset); + if ((AOP_TYPE (right) == AOP_LIT) + && (((lit >> (offset*8)) & 0xff) == 0)) + emitcode ("tsta",""); + else + accopWithAop ("eor", AOP (right), offset); + hc08_freeReg( hc08_reg_a); + if (size) + emitBranch ("bne", tlbl); + else + { + emitLabel (tlbl); + genIfxJump (ifx, "a"); + } + offset++; + } } + if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); + lit = ulFromVal (AOP (right)->aopu.aop_lit); size = AOP_SIZE (result); offset = 0; @@ -4680,10 +5368,9 @@ genXor (iCode * ic, iCode * ifx) loadRegFromAop (hc08_reg_a, AOP (left), offset); accopWithAop ("eor", AOP (right), offset); storeRegToAop (hc08_reg_a, AOP (result), offset++); - hc08_freeReg( hc08_reg_a); + hc08_freeReg( hc08_reg_a); } - //release: freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); @@ -4700,13 +5387,13 @@ emitinline (iCode * ic, char *inlin) symbol *sym, *tempsym; asmop *aop; char *l; - + while (*inlin) { if (*inlin == '_') { symname = ++inlin; - while (isalnum(*inlin) || (*inlin == '_')) + while (isalnum((unsigned char)*inlin) || (*inlin == '_')) inlin++; c = *inlin; *inlin = '\0'; @@ -4727,7 +5414,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, @@ -4756,7 +5443,7 @@ endofline: if ((2+bp-buffer)>sizeof(buffer)) fprintf(stderr, "Inline assembly buffer overflow\n"); - + //printf("%s\n",buffer); emitcode (buffer,""); } @@ -4769,44 +5456,51 @@ static void genInline (iCode * ic) { char *buffer, *bp, *bp1; + bool inComment = FALSE; D(emitcode ("; genInline","")); _G.inLine += (!options.asmpeep); - buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1); - strcpy (buffer, IC_INLINE (ic)); + buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic)); /* emit each line as a code */ while (*bp) { - if (*bp == '\n') - { - *bp++ = '\0'; - /* emitcode (bp1, ""); */ - emitinline (ic, bp1); - bp1 = bp; - } - else - { - if (*bp == ':') - { - bp++; - *bp = '\0'; - bp++; - emitcode (bp1, ""); - bp1 = bp; - } - else - bp++; - } + switch (*bp) + { + case ';': + inComment = TRUE; + ++bp; + break; + + case '\n': + inComment = FALSE; + *bp++ = '\0'; + emitinline (ic, bp1); + bp1 = bp; + break; + + default: + /* Add \n for labels, not dirs such as c:\mydir */ + if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1]))) + { + ++bp; + *bp = '\0'; + ++bp; + emitcode (bp1, ""); + bp1 = bp; + } + else + ++bp; + break; + } } if (bp1 != bp) - { - /* emitcode (bp1, ""); */ - emitinline (ic, bp1); - } - /* emitcode("",buffer); */ + emitinline (ic, bp1); + + Safe_free (buffer); + _G.inLine -= (!options.asmpeep); } @@ -4987,7 +5681,7 @@ genGetHbit (iCode * ic) hc08_dirtyReg (hc08_reg_a, FALSE); storeRegToFullAop (hc08_reg_a, AOP (result), FALSE); hc08_freeReg (hc08_reg_a); - + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } @@ -5006,7 +5700,7 @@ genSwap (iCode * ic) result = IC_RESULT (ic); aopOp (left, ic, FALSE); aopOp (result, ic, FALSE); - + switch (AOP_SIZE (left)) { case 1: /* swap nibbles in byte */ @@ -5017,7 +5711,7 @@ genSwap (iCode * ic) hc08_freeReg (hc08_reg_a); break; case 2: /* swap bytes in a word */ - if (operandsEqu (left, result)) + if (operandsEqu (left, result) || sameRegs (AOP (left), AOP (result))) { loadRegFromAop (hc08_reg_a, AOP (left), 0); hc08_useReg (hc08_reg_a); @@ -5034,7 +5728,7 @@ genSwap (iCode * ic) default: wassertl(FALSE, "unsupported SWAP operand size"); } - + freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); } @@ -5046,40 +5740,40 @@ genSwap (iCode * ic) static void AccRol (int shCount) { - shCount &= 0x0007; // shCount : 0..7 + shCount &= 0x0007; // shCount : 0..7 switch (shCount) { case 0: break; case 1: - emitcode ("rola", ""); /* 1 cycle */ + emitcode ("rola", ""); /* 1 cycle */ break; case 2: - emitcode ("rola", ""); /* 1 cycle */ - emitcode ("rola", ""); /* 1 cycle */ + emitcode ("rola", ""); /* 1 cycle */ + emitcode ("rola", ""); /* 1 cycle */ break; case 3: emitcode ("nsa", ""); emitcode ("rora", ""); break; case 4: - emitcode ("nsa", ""); /* 3 cycles */ + emitcode ("nsa", ""); /* 3 cycles */ break; case 5: - emitcode ("nsa", ""); /* 3 cycles */ - emitcode ("rola", ""); /* 1 cycle */ + emitcode ("nsa", ""); /* 3 cycles */ + emitcode ("rola", ""); /* 1 cycle */ break; case 6: - emitcode ("nsa", ""); /* 3 cycles */ - emitcode ("rola", ""); /* 1 cycle */ - emitcode ("rola", ""); /* 1 cycle */ + emitcode ("nsa", ""); /* 3 cycles */ + emitcode ("rola", ""); /* 1 cycle */ + emitcode ("rola", ""); /* 1 cycle */ break; case 7: - emitcode ("nsa", ""); /* 3 cycles */ - emitcode ("rola", ""); /* 1 cycle */ - emitcode ("rola", ""); /* 1 cycle */ - emitcode ("rola", ""); /* 1 cycle */ + emitcode ("nsa", ""); /* 3 cycles */ + emitcode ("rola", ""); /* 1 cycle */ + emitcode ("rola", ""); /* 1 cycle */ + emitcode ("rola", ""); /* 1 cycle */ break; } } @@ -5093,8 +5787,8 @@ static void AccLsh (int shCount) { int i; - - shCount &= 0x0007; // shCount : 0..7 + + shCount &= 0x0007; // shCount : 0..7 /* Shift counts of 4 and 5 are currently optimized for code size. */ /* Falling through to the unrolled loop would be optimal for code speed. */ @@ -5102,11 +5796,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", ""); @@ -5141,8 +5839,8 @@ static void AccSRsh (int shCount) { int i; - - shCount &= 0x0007; // shCount : 0..7 + + shCount &= 0x0007; // shCount : 0..7 if (shCount == 7) { @@ -5164,14 +5862,14 @@ static void AccRsh (int shCount, bool sign) { int i; - + if (sign) { AccSRsh (shCount); return; } - - shCount &= 0x0007; // shCount : 0..7 + + shCount &= 0x0007; // shCount : 0..7 /* Shift counts of 4 and 5 are currently optimized for code size. */ /* Falling through to the unrolled loop would be optimal for code speed. */ @@ -5179,11 +5877,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", ""); @@ -5218,8 +5920,8 @@ static void XAccLsh (int shCount) { int i; - - shCount &= 0x000f; // shCount : 0..15 + + shCount &= 0x000f; // shCount : 0..15 if (shCount>=8) { @@ -5269,8 +5971,8 @@ static void XAccSRsh (int shCount) { int i; - - shCount &= 0x000f; // shCount : 0..7 + + shCount &= 0x000f; // shCount : 0..7 /* if we can beat 2n cycles or bytes for some special case, do it here */ switch (shCount) @@ -5323,7 +6025,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;i= 8 */ @@ -5622,11 +6330,11 @@ genlshTwo (operand * result, operand * left, int shCount) shCount -= 8; if (size > 1) - { + { loadRegFromAop (hc08_reg_a, AOP (left), 0); AccLsh (shCount); - storeRegToAop (hc08_reg_a, AOP (result), 1); - } + storeRegToAop (hc08_reg_a, AOP (result), 1); + } storeConstToAop(zero, AOP (result), LSB); } @@ -5641,7 +6349,7 @@ genlshTwo (operand * result, operand * left, int shCount) /*-----------------------------------------------------------------*/ /* shiftLLong - shift left one long from left to result */ -/* offl = LSB or MSB16 */ +/* offr = LSB or MSB16 */ /*-----------------------------------------------------------------*/ static void shiftLLong (operand * left, operand * result, int offr) @@ -5658,10 +6366,10 @@ shiftLLong (operand * left, operand * result, int offr) loadRegFromAop (hc08_reg_xa, AOP (left), LSB); rmwWithReg ("lsl", hc08_reg_a); rmwWithReg ("rol", hc08_reg_x); - storeRegToAop (hc08_reg_xa, AOP (result), offr); if (offr==LSB) { + storeRegToAop (hc08_reg_xa, AOP (result), offr); loadRegFromAop (hc08_reg_xa, AOP (left), MSB24); rmwWithReg ("rol", hc08_reg_a); rmwWithReg ("rol", hc08_reg_x); @@ -5669,9 +6377,12 @@ shiftLLong (operand * left, operand * result, int offr) } else if (offr==MSB16) { + storeRegToAop (hc08_reg_a, AOP (result), offr); loadRegFromAop (hc08_reg_a, AOP (left), MSB24); + storeRegToAop (hc08_reg_x, AOP (result), offr+1); rmwWithReg ("rol", hc08_reg_a); storeRegToAop (hc08_reg_a, AOP (result), offr+2); + storeConstToAop (zero, AOP (result), 0); } pullOrFreeReg (hc08_reg_x, needpulx); @@ -5697,11 +6408,11 @@ genlshFour (operand * result, operand * left, int shCount) { shCount -= 24; if (shCount) - /* lowest order of left goes to the highest - order of the destination */ - shiftL1Left2Result (left, LSB, result, MSB32, shCount); + /* lowest order of left goes to the highest + order of the destination */ + shiftL1Left2Result (left, LSB, result, MSB32, shCount); else - movLeft2Result (left, LSB, result, MSB32, 0); + movLeft2Result (left, LSB, result, MSB32, 0); storeConstToAop (zero, AOP (result), LSB); storeConstToAop (zero, AOP (result), MSB16); storeConstToAop (zero, AOP (result), MSB24); @@ -5715,12 +6426,12 @@ genlshFour (operand * result, operand * left, int shCount) shCount -= 16; /* if some more remaining */ if (shCount) - shiftL2Left2Result (left, LSB, result, MSB24, shCount); + shiftL2Left2Result (left, LSB, result, MSB24, shCount); else - { - movLeft2Result (left, MSB16, result, MSB32, 0); - movLeft2Result (left, LSB, result, MSB24, 0); - } + { + movLeft2Result (left, MSB16, result, MSB32, 0); + movLeft2Result (left, LSB, result, MSB24, 0); + } storeConstToAop (zero, AOP (result), LSB); storeConstToAop (zero, AOP (result), MSB16); return; @@ -5732,31 +6443,31 @@ genlshFour (operand * result, operand * left, int shCount) /* lower order three bytes goes to higher order three bytes */ shCount -= 8; if (size == 2) - { - if (shCount) - shiftL1Left2Result (left, LSB, result, MSB16, shCount); - else - movLeft2Result (left, LSB, result, MSB16, 0); - } + { + if (shCount) + shiftL1Left2Result (left, LSB, result, MSB16, shCount); + else + movLeft2Result (left, LSB, result, MSB16, 0); + } else - { /* size = 4 */ - if (shCount == 0) - { - movLeft2Result (left, MSB24, result, MSB32, 0); - movLeft2Result (left, MSB16, result, MSB24, 0); - movLeft2Result (left, LSB, result, MSB16, 0); + { /* size = 4 */ + if (shCount == 0) + { + movLeft2Result (left, MSB24, result, MSB32, 0); + movLeft2Result (left, MSB16, result, MSB24, 0); + movLeft2Result (left, LSB, result, MSB16, 0); storeConstToAop (zero, AOP (result), LSB); - } - else if (shCount == 1) - shiftLLong (left, result, MSB16); - else - { - shiftL2Left2Result (left, MSB16, result, MSB24, shCount); - shiftL1Left2Result (left, LSB, result, MSB16, shCount); - shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount); + } + else if (shCount == 1) + shiftLLong (left, result, MSB16); + else + { + shiftL2Left2Result (left, MSB16, result, MSB24, shCount); + shiftL1Left2Result (left, LSB, result, MSB16, shCount); + shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount); storeConstToAop (zero, AOP (result), LSB); - } - } + } + } } /* 1 <= shCount <= 7 */ @@ -5764,7 +6475,7 @@ genlshFour (operand * result, operand * left, int shCount) { shiftLLong (left, result, LSB); if (shCount == 2) - shiftLLong (result, result, LSB); + shiftLLong (result, result, LSB); } /* 3 <= shCount <= 7, optimize */ else @@ -5780,11 +6491,11 @@ genlshFour (operand * result, operand * left, int shCount) /*-----------------------------------------------------------------*/ static void genLeftShiftLiteral (operand * left, - operand * right, - operand * result, - iCode * ic) + operand * right, + operand * result, + iCode * ic) { - int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); + int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit); int size; D(emitcode ("; genLeftShiftLiteral","")); @@ -5798,8 +6509,8 @@ genLeftShiftLiteral (operand * left, size = AOP_SIZE (result); #if VIEW_SIZE - emitcode ("; shift left ", "result %d, left %d", size, - AOP_SIZE (left)); + DD(emitcode ("; shift left ", "result %d, left %d", size, + AOP_SIZE (left))); #endif if (shCount == 0) @@ -5815,23 +6526,23 @@ genLeftShiftLiteral (operand * left, else { switch (size) - { - case 1: - genlshOne (result, left, shCount); - break; - - case 2: - genlshTwo (result, left, shCount); - break; - - case 4: - genlshFour (result, left, shCount); - break; - default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "*** ack! mystery literal shift!\n"); - break; - } + { + case 1: + genlshOne (result, left, shCount); + break; + + case 2: + genlshTwo (result, left, shCount); + break; + + case 4: + genlshFour (result, left, shCount); + break; + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "*** ack! mystery literal shift!\n"); + break; + } } freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); @@ -5846,9 +6557,8 @@ genLeftShift (iCode * ic) operand *left, *right, *result; int size, offset; symbol *tlbl, *tlbl1; -// int i; char *shift; - regs *reg; + asmop *aopResult; D(emitcode ("; genLeftShift","")); @@ -5867,53 +6577,57 @@ genLeftShift (iCode * ic) } /* shift count is unknown then we have to form - a loop get the loop count in A : Note: we take + a loop get the loop count in X : Note: we take only the lower order byte since shifting more that 32 bits make no sense anyway, ( the largest size of an object can be only 32 bits ) */ - aopOp (left, ic, FALSE); aopOp (result, ic, FALSE); + aopOp (left, ic, FALSE); + aopResult = AOP (result); + + if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)) + || isOperandVolatile (result, FALSE)) + aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result))); /* now move the left to the result if they are not the same */ - if (!sameRegs (AOP (left), AOP (result))) + if (!sameRegs (AOP (left), aopResult)) { - size = AOP_SIZE (result); offset = 0; while (size--) - { - transferAopAop (AOP (left), offset, AOP (result), offset); - offset++; - } + { + transferAopAop (AOP (left), offset, aopResult, offset); + offset++; + } } freeAsmop (left, NULL, ic, TRUE); - + AOP (result) = aopResult; + tlbl = newiTempLabel (NULL); size = AOP_SIZE (result); offset = 0; tlbl1 = newiTempLabel (NULL); - reg = hc08_reg_a; - - loadRegFromAop (reg, AOP (right), 0); - freeAsmop (right, NULL, ic, TRUE); + loadRegFromAop (hc08_reg_x, AOP (right), 0); + emitcode ("tstx", ""); emitBranch ("beq", tlbl1); emitLabel (tlbl); - + shift="lsl"; for (offset=0;offset= 8) { if (shCount == 1) - shiftRLong (left, MSB16, result, sign); + shiftRLong (left, MSB16, result, sign); else if (shCount == 8) - { - transferAopAop (AOP (left), 1, AOP (result), 0); - transferAopAop (AOP (left), 2, AOP (result), 1); - loadRegFromAop (hc08_reg_a, AOP (left), 3); + { + transferAopAop (AOP (left), 1, AOP (result), 0); + transferAopAop (AOP (left), 2, AOP (result), 1); + loadRegFromAop (hc08_reg_a, AOP (left), 3); storeRegToAop (hc08_reg_a, AOP (result), 2); storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign); - } + } else if (shCount == 9) { - shiftRLong (left, MSB16, result, sign); + shiftRLong (left, MSB16, result, sign); } else - { - loadRegFromAop (hc08_reg_xa, AOP (left), 1); - XAccRsh (shCount-8, FALSE); - storeRegToAop (hc08_reg_xa, AOP (result), 0); - loadRegFromAop (hc08_reg_x, AOP (left), 3); - loadRegFromConst (hc08_reg_a, zero); - XAccRsh (shCount-8, sign); - accopWithAop ("ora", AOP (result), 1); - storeRegToFullAop (hc08_reg_xa, AOP (result), 1); - } + { + loadRegFromAop (hc08_reg_xa, AOP (left), 1); + XAccRsh (shCount-8, FALSE); + storeRegToAop (hc08_reg_xa, AOP (result), 0); + loadRegFromAop (hc08_reg_x, AOP (left), 3); + loadRegFromConst (hc08_reg_a, zero); + XAccRsh (shCount-8, sign); + accopWithAop ("ora", AOP (result), 1); + storeRegToAop (hc08_reg_xa, AOP (result), 1); + storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign); + } } else - { /* 1 <= shCount <= 7 */ + { /* 1 <= shCount <= 7 */ if (shCount == 1) - { - shiftRLong (left, LSB, result, sign); - } + { + shiftRLong (left, LSB, result, sign); + } else - { - loadRegFromAop (hc08_reg_xa, AOP (left), 0); - XAccRsh (shCount, FALSE); - storeRegToAop (hc08_reg_xa, AOP (result), 0); - loadRegFromAop (hc08_reg_a, AOP (left), 2); - AccLsh (8-shCount); - accopWithAop ("ora", AOP (result), 1); - storeRegToFullAop (hc08_reg_xa, AOP (result), 1); - loadRegFromAop (hc08_reg_xa, AOP (left), 2); - XAccRsh (shCount, sign); - storeRegToAop (hc08_reg_xa, AOP (result), 2); - } + { + loadRegFromAop (hc08_reg_xa, AOP (left), 0); + XAccRsh (shCount, FALSE); + storeRegToAop (hc08_reg_xa, AOP (result), 0); + loadRegFromAop (hc08_reg_a, AOP (left), 2); + AccLsh (8-shCount); + accopWithAop ("ora", AOP (result), 1); + storeRegToAop (hc08_reg_a, AOP (result), 1); + loadRegFromAop (hc08_reg_xa, AOP (left), 2); + XAccRsh (shCount, sign); + storeRegToAop (hc08_reg_xa, AOP (result), 2); + } } } @@ -6092,12 +6821,12 @@ genrshFour (operand * result, operand * left, /*-----------------------------------------------------------------*/ static void genRightShiftLiteral (operand * left, - operand * right, - operand * result, - iCode * ic, - int sign) + operand * right, + operand * result, + iCode * ic, + int sign) { - int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); + int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit); int size; D(emitcode ("; genRightShiftLiteral","")); @@ -6108,8 +6837,8 @@ genRightShiftLiteral (operand * left, aopOp (result, ic, FALSE); #if VIEW_SIZE - emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result), - AOP_SIZE (left)); + DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result), + AOP_SIZE (left))); #endif size = getDataSize (left); @@ -6120,34 +6849,34 @@ genRightShiftLiteral (operand * left, { size = getDataSize (result); while (size--) - transferAopAop (AOP (left), size, AOP(result), size); + transferAopAop (AOP (left), size, AOP(result), size); } else if (shCount >= (size * 8)) { if (sign) { - /* get sign in acc.7 */ - loadRegFromAop (hc08_reg_a, AOP (left), size -1); + /* get sign in acc.7 */ + loadRegFromAop (hc08_reg_a, AOP (left), size -1); } addSign (result, LSB, sign); } else { switch (size) - { - case 1: - genrshOne (result, left, shCount, sign); - break; - - case 2: - genrshTwo (result, left, shCount, sign); - break; - - case 4: - genrshFour (result, left, shCount, sign); - break; - default: - break; - } + { + case 1: + genrshOne (result, left, shCount, sign); + break; + + case 2: + genrshTwo (result, left, shCount, sign); + break; + + case 4: + genrshFour (result, left, shCount, sign); + break; + default: + break; + } } freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); @@ -6163,11 +6892,11 @@ genRightShift (iCode * ic) operand *right, *left, *result; sym_link *retype; int size, offset; -// char *l; symbol *tlbl, *tlbl1; char *shift; bool sign; - + asmop *aopResult; + D(emitcode ("; genRightShift","")); /* if signed then we do it the hard way preserve the @@ -6202,20 +6931,29 @@ genRightShift (iCode * ic) more that 32 bits make no sense anyway, ( the largest size of an object can be only 32 bits ) */ - aopOp (left, ic, FALSE); aopOp (result, ic, FALSE); + aopOp (left, ic, FALSE); + aopResult = AOP (result); - if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))) - AOP (result) = forceStackedAop (AOP (result)); - - size = AOP_SIZE (result); - offset = size-1; - while (size--) + if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)) + || isOperandVolatile (result, FALSE)) + aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result))); + + /* now move the left to the result if they are not the + same */ + if (!sameRegs (AOP (left), aopResult)) { - transferAopAop (AOP (left), offset, AOP (result), offset); - offset--; + size = AOP_SIZE (result); + offset = 0; + while (size--) + { + transferAopAop (AOP (left), offset, aopResult, offset); + offset++; + } } - + freeAsmop (left, NULL, ic, TRUE); + AOP (result) = aopResult; + tlbl = newiTempLabel (NULL); size = AOP_SIZE (result); offset = 0; @@ -6223,8 +6961,9 @@ genRightShift (iCode * ic) loadRegFromAop (hc08_reg_x, AOP (right), 0); emitcode ("tstx", ""); - emitcode ("beq", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); + emitBranch ("beq", tlbl1); + emitLabel (tlbl); + shift= sign ? "asr" : "lsr"; for (offset=size-1;offset>=0;offset--) { @@ -6232,26 +6971,27 @@ 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); } + /*-----------------------------------------------------------------*/ /* genUnpackBits - generates code for unpacking bits */ /*-----------------------------------------------------------------*/ static void -genUnpackBits (operand * result) +genUnpackBits (operand * result, iCode *ifx) { - int offset = 0; /* result byte offset */ - int rsize; /* result size */ - int rlen = 0; /* remaining bitfield length */ - sym_link *etype; /* bitfield type information */ - int blen; /* bitfield length */ - int bstr; /* bitfield starting bit within byte */ + int offset = 0; /* result byte offset */ + int rsize; /* result size */ + int rlen = 0; /* remaining bitfield length */ + sym_link *etype; /* bitfield type information */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ D(emitcode ("; genUnpackBits","")); @@ -6260,6 +7000,20 @@ genUnpackBits (operand * result) blen = SPEC_BLEN (etype); bstr = SPEC_BSTR (etype); + if (ifx && blen <= 8) + { + emitcode ("lda", ",x"); + hc08_dirtyReg (hc08_reg_a, FALSE); + 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) { @@ -6267,6 +7021,16 @@ genUnpackBits (operand * result) 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; } @@ -6277,7 +7041,8 @@ genUnpackBits (operand * result) { emitcode ("lda", ",x"); hc08_dirtyReg (hc08_reg_a, FALSE); - storeRegToAop (hc08_reg_a, AOP (result), offset++); + storeRegToAop (hc08_reg_a, AOP (result), offset); + offset++; if (rlen>8) emitcode ("aix", "#1"); } @@ -6287,6 +7052,16 @@ genUnpackBits (operand * result) { 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++); } @@ -6294,24 +7069,44 @@ 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++); + } } } /*-----------------------------------------------------------------*/ -/* genDataPointerGet - generates code when ptr offset is known */ +/* genUnpackBitsImmed - generates code for unpacking bits */ /*-----------------------------------------------------------------*/ static void -genDataPointerGet (operand * left, - operand * result, - iCode * ic) +genUnpackBitsImmed (operand * left, + operand * result, + iCode *ic, + iCode *ifx) { - int size, offset = 0; + int size; + int offset = 0; /* result byte offset */ + int rsize; /* result size */ + int rlen = 0; /* remaining bitfield length */ + sym_link *etype; /* bitfield type information */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ asmop *derefaop; - - D(emitcode ("; genDataPointerGet","")); + + D(emitcode ("; genUnpackBitsImmed","")); aopOp (result, ic, TRUE); size = AOP_SIZE (result); @@ -6319,117 +7114,223 @@ genDataPointerGet (operand * left, derefaop = aopDerefAop (AOP (left)); freeAsmop (left, NULL, ic, TRUE); derefaop->size = size; - - while (size--) + + etype = getSpec (operandType (result)); + rsize = getSize (operandType (result)); + blen = SPEC_BLEN (etype); + bstr = SPEC_BSTR (etype); + + /* if the bitfield is a single bit in the direct page */ + if (blen == 1 && derefaop->type == AOP_DIR) + { + if (!ifx && bstr) + { + symbol *tlbl = newiTempLabel (NULL); + + loadRegFromConst (hc08_reg_a, zero); + emitcode ("brclr", "#%d,%s,%05d$", + bstr, aopAdrStr (derefaop, 0, FALSE), + (tlbl->key + 100)); + 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); + offset++; + goto finish; + } + else if (ifx) + { + symbol *tlbl = newiTempLabel (NULL); + symbol *jlbl; + char * inst; + + if (IC_TRUE (ifx)) + { + jlbl = IC_TRUE (ifx); + inst = "brclr"; + } + else + { + jlbl = IC_FALSE (ifx); + inst = "brset"; + } + emitcode (inst, "#%d,%s,%05d$", + bstr, aopAdrStr (derefaop, 0, FALSE), + (tlbl->key + 100)); + emitBranch ("jmp", jlbl); + emitLabel (tlbl); + ifx->generated = 1; + offset++; + goto finish; + } + } + + /* If the bitfield length is less than a byte */ + if (blen < 8) + { + loadRegFromAop (hc08_reg_a, derefaop, 0); + if (!ifx) + { + 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 + { + emitcode ("and", "#0x%02x", + (((unsigned char) -1) >> (8 - blen)) << bstr); + hc08_dirtyReg (hc08_reg_a, FALSE); + } + offset++; + goto finish; + } + + /* Bit field did not fit in a byte. Copy all + but the partial byte at the end. */ + for (rlen=blen;rlen>=8;rlen-=8) { - transferAopAop(derefaop, offset, AOP (result), offset); + loadRegFromAop (hc08_reg_a, derefaop, size-offset-1); + if (!ifx) + storeRegToAop (hc08_reg_a, AOP (result), offset); + else + emitcode ("tsta", ""); offset++; } + /* Handle the partial byte at the end */ + if (rlen) + { + 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++); + } + +finish: + if (offset < rsize) + { + rsize -= 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); freeAsmop (result, NULL, ic, TRUE); + + if (ifx && !ifx->generated) + { + genIfxJump (ifx, "a"); + } } -#if 0 + /*-----------------------------------------------------------------*/ -/* genNearPointerGet - emitcode for near pointer fetch */ +/* genDataPointerGet - generates code when ptr offset is known */ /*-----------------------------------------------------------------*/ static void -genNearPointerGet (operand * left, - operand * result, - iCode * ic, - iCode * pi) +genDataPointerGet (operand * left, + operand * result, + iCode * ic, + iCode * ifx) { - int size, offset; - sym_link *retype = getSpec (operandType (result)); - - D(emitcode ("; genNearPointerGet","")); - - aopOp (left, ic, FALSE); + int size; + asmop *derefaop; - /* if left is rematerialisable and - result is not bit variable type and - the left is pointer to data space i.e - lower 128 bytes of space */ - if ((AOP_TYPE (left) == AOP_IMMD) - || (AOP_TYPE (left) == AOP_LIT) - /* !IS_BITVAR (retype) */ - /* && DCL_TYPE (ltype) == POINTER */ ) - { - genDataPointerGet (left, result, ic); - return; - } + D(emitcode ("; genDataPointerGet","")); - /* if the operand is already in hx - then we do nothing else we move the value to hx */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - loadRegFromAop (hc08_reg_x, AOP (left), 0); - loadRegFromConst (hc08_reg_h, zero); - } + aopOp (result, ic, TRUE); + size = AOP_SIZE (result); - /* so hx now contains the address */ - aopOp (result, ic, FALSE); + derefaop = aopDerefAop (AOP (left)); + freeAsmop (left, NULL, ic, TRUE); + derefaop->size = size; - /* if bit then unpack */ - if (IS_BITVAR (retype)) - genUnpackBits (result); - else + while (size--) { - size = AOP_SIZE (result); - offset = size-1; - - while (size--) - { - accopWithMisc ("lda", ",x"); - if (size || pi) - { - rmwWithReg ("inc", hc08_reg_x); - } - storeRegToAop (hc08_reg_a, AOP (result), offset--); - hc08_freeReg (hc08_reg_a); - } + if (!ifx) + transferAopAop (derefaop, size, AOP (result), size); + else + loadRegFromAop (hc08_reg_a, derefaop, size); } - freeAsmop (left, NULL, ic, TRUE); + freeAsmop (NULL, derefaop, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); - - if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) { - aopOp (IC_RESULT (pi), pi, FALSE); - storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0); - freeAsmop (IC_RESULT (pi), NULL, pi, TRUE); - pi->generated = 1; - } - hc08_freeReg (hc08_reg_hx); + if (ifx && !ifx->generated) + { + genIfxJump (ifx, "a"); + } } -#endif + /*-----------------------------------------------------------------*/ -/* genFarPointerGet - get value from far space */ +/* genPointerGet - generate code for pointer get */ /*-----------------------------------------------------------------*/ static void -genFarPointerGet (operand * left, - operand * result, iCode * ic, iCode * pi) +genPointerGet (iCode * ic, iCode *pi, iCode *ifx) { + operand *left = IC_LEFT (ic); + operand *result = IC_RESULT (ic); int size, offset; sym_link *retype = getSpec (operandType (result)); - D(emitcode ("; genFarPointerGet","")); + D(emitcode ("; genPointerGet","")); + + if (getSize (operandType (result))>1) + ifx = NULL; aopOp (left, ic, FALSE); /* if left is rematerialisable and - result is not bit variable type and - the left is pointer to data space i.e - lower 128 bytes of space */ - if (AOP_TYPE (left) == AOP_IMMD && - !IS_BITVAR (retype) - /* && DCL_TYPE (ltype) == POINTER */ ) - { - genDataPointerGet (left, result, ic); - return; + result is not bit variable type */ + if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT) + { + if (!IS_BITVAR (retype)) + { + genDataPointerGet (left, result, ic, ifx); + return; + } + else + { + genUnpackBitsImmed (left, result, ic, ifx); + return; + } } /* if the operand is already in hx @@ -6445,94 +7346,43 @@ genFarPointerGet (operand * left, /* if bit then unpack */ if (IS_BITVAR (retype)) - genUnpackBits (result); + genUnpackBits (result, ifx); else { size = AOP_SIZE (result); offset = size-1; while (size--) - { - accopWithMisc ("lda", ",x"); - if (size || pi) + { + accopWithMisc ("lda", ",x"); + if (size || pi) { - emitcode ("aix", "#1"); - hc08_dirtyReg (hc08_reg_hx, FALSE); + emitcode ("aix", "#1"); + hc08_dirtyReg (hc08_reg_hx, FALSE); } - storeRegToAop (hc08_reg_a, AOP (result), offset--); + if (!ifx) + storeRegToAop (hc08_reg_a, AOP (result), offset); + offset--; hc08_freeReg (hc08_reg_a); - } + } } freeAsmop (left, NULL, ic, TRUE); freeAsmop (result, NULL, ic, TRUE); - - if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) { + + if (pi) { aopOp (IC_RESULT (pi), pi, FALSE); storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0); freeAsmop (IC_RESULT (pi), NULL, pi, TRUE); pi->generated = 1; } - hc08_freeReg (hc08_reg_hx); - -} - - - -/*-----------------------------------------------------------------*/ -/* genPointerGet - generate code for pointer get */ -/*-----------------------------------------------------------------*/ -static void -genPointerGet (iCode * ic, iCode *pi) -{ - operand *left, *result; - sym_link *type, *etype; - int p_type; - - D(emitcode ("; genPointerGet","")); - - left = IC_LEFT (ic); - result = IC_RESULT (ic); - - /* depending on the type of pointer we need to - move it to the correct pointer register */ - type = operandType (left); - etype = getSpec (type); - /* if left is of type of pointer then it is simple */ - if (IS_PTR (type) && !IS_FUNC (type->next)) - p_type = DCL_TYPE (type); - else + if (ifx && !ifx->generated) { - /* we have to go by the storage class */ - p_type = PTR_TYPE (SPEC_OCLS (etype)); + genIfxJump (ifx, "a"); } - /* special case when cast remat */ - if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat && - IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) { - left = IC_RIGHT(OP_SYMBOL(left)->rematiCode); - type = operandType (left); - p_type = DCL_TYPE (type); - } - /* now that we have the pointer type we assign - the pointer values */ - switch (p_type) - { - - case POINTER: - case IPOINTER: -#if 0 - genNearPointerGet (left, result, ic, pi); - break; -#endif - case GPOINTER: - case CPOINTER: - case FPOINTER: - genFarPointerGet (left, result, ic, pi); - break; - - } + hc08_freeReg (hc08_reg_hx); } @@ -6541,31 +7391,32 @@ genPointerGet (iCode * ic, iCode *pi) /*-----------------------------------------------------------------*/ static void genPackBits (sym_link * etype, - operand * right) + operand * right) { - int offset = 0; /* source byte offset */ - int rlen = 0; /* remaining bitfield length */ - int blen; /* bitfield length */ - int bstr; /* bitfield starting bit within byte */ - int litval; /* source literal value (if AOP_LIT) */ - unsigned char mask; /* bitmask within current byte */ + int offset = 0; /* source byte offset */ + int rlen = 0; /* remaining bitfield length */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ + int litval; /* source literal value (if AOP_LIT) */ + unsigned char mask; /* bitmask within current byte */ + int xoffset = 0; D(emitcode ("; genPackBits","")); blen = SPEC_BLEN (etype); bstr = SPEC_BSTR (etype); - + /* If the bitfield length is less than a byte */ if (blen < 8) { mask = ((unsigned char) (0xFF << (blen + bstr)) | - (unsigned char) (0xFF >> (8 - bstr))); + (unsigned char) (0xFF >> (8 - bstr))); if (AOP_TYPE (right) == AOP_LIT) { /* Case with a bitfield length <8 and literal source */ - litval = (int) floatFromVal (AOP (right)->aopu.aop_lit); + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); litval <<= bstr; litval &= (~mask) & 0xff; @@ -6576,11 +7427,11 @@ genPackBits (sym_link * etype, emitcode ("ora","#0x%02x", litval); hc08_dirtyReg (hc08_reg_a, FALSE); emitcode ("sta", ",x"); - + hc08_freeReg (hc08_reg_a); return; } - + /* Case with a bitfield length < 8 and arbitrary source */ loadRegFromAop (hc08_reg_a, AOP (right), 0); @@ -6595,7 +7446,7 @@ genPackBits (sym_link * etype, emitcode ("ora", "1,s"); emitcode ("sta", ",x"); pullReg (hc08_reg_a); - + hc08_freeReg (hc08_reg_a); return; } @@ -6607,6 +7458,7 @@ genPackBits (sym_link * etype, if (AOP (right)->type == AOP_DIR) { emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE)); + xoffset++; } else { @@ -6620,37 +7472,37 @@ genPackBits (sym_link * etype, if (rlen) { mask = (((unsigned char) -1 << rlen) & 0xff); - + if (AOP_TYPE (right) == AOP_LIT) { /* Case with partial byte and literal source */ - litval = (int) floatFromVal (AOP (right)->aopu.aop_lit); + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); litval >>= (blen-rlen); litval &= (~mask) & 0xff; - emitcode ("lda", "%d,x", offset); + emitcode ("lda", "%d,x", offset - xoffset); hc08_dirtyReg (hc08_reg_a, FALSE); if ((mask|litval)!=0xff) emitcode ("and","#0x%02x", mask); if (litval) emitcode ("ora","#0x%02x", litval); - emitcode ("sta", "%d,x", offset); + emitcode ("sta", "%d,x", offset - xoffset); hc08_dirtyReg (hc08_reg_a, FALSE); hc08_freeReg (hc08_reg_a); return; } - + /* Case with partial byte and arbitrary source */ - loadRegFromAop (hc08_reg_a, AOP (right), offset++); + loadRegFromAop (hc08_reg_a, AOP (right), offset); emitcode ("and", "#0x%02x", (~mask) & 0xff); hc08_dirtyReg (hc08_reg_a, FALSE); pushReg (hc08_reg_a, TRUE); - emitcode ("lda", ",x"); + emitcode ("lda", "%d,x", offset - xoffset); emitcode ("and", "#0x%02x", mask); emitcode ("ora", "1,s"); - emitcode ("sta", ",x"); + emitcode ("sta", "%d,x", offset - xoffset); pullReg (hc08_reg_a); } @@ -6658,17 +7510,24 @@ genPackBits (sym_link * etype, } /*-----------------------------------------------------------------*/ -/* genDataPointerSet - remat pointer to data space */ +/* genPackBitsImmed - generates code for packed bit storage */ /*-----------------------------------------------------------------*/ static void -genDataPointerSet (operand * right, - operand * result, - iCode * ic) +genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic) { - int size, offset = 0; asmop *derefaop; + int size; + int offset = 0; /* source byte offset */ + int rlen = 0; /* remaining bitfield length */ + int blen; /* bitfield length */ + int bstr; /* bitfield starting bit within byte */ + int litval; /* source literal value (if AOP_LIT) */ + unsigned char mask; /* bitmask within current byte */ - D(emitcode ("; genDataPointerSet","")); + D(emitcode ("; genPackBitsImmed","")); + + blen = SPEC_BLEN (etype); + bstr = SPEC_BSTR (etype); aopOp (right, ic, FALSE); size = AOP_SIZE (right); @@ -6676,115 +7535,196 @@ genDataPointerSet (operand * right, derefaop = aopDerefAop (AOP (result)); freeAsmop (result, NULL, ic, TRUE); derefaop->size = size; - - while (size--) + + /* if the bitfield is a single bit in the direct page */ + if (blen == 1 && derefaop->type == AOP_DIR) { - transferAopAop (AOP (right), offset, derefaop, offset); - offset++; + if (AOP_TYPE (right) == AOP_LIT) + { + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); + + emitcode ((litval & 1) ? "bset" : "bclr", + "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE)); + } + else + { + symbol *tlbl1 = newiTempLabel (NULL); + symbol *tlbl2 = newiTempLabel (NULL); + + loadRegFromAop (hc08_reg_a, AOP (right), 0); + emitcode ("bit", "#1"); + emitBranch ("bne", tlbl1); + emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE)); + emitBranch ("bra", tlbl2); + emitLabel (tlbl1); + emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE)); + emitLabel (tlbl2); + hc08_freeReg (hc08_reg_a); + } + goto release; } - freeAsmop (right, NULL, ic, TRUE); - freeAsmop (NULL, derefaop, ic, TRUE); -} + /* If the bitfield length is less than a byte */ + if (blen < 8) + { + mask = ((unsigned char) (0xFF << (blen + bstr)) | + (unsigned char) (0xFF >> (8 - bstr))); -#if 0 -/*-----------------------------------------------------------------*/ -/* genNearPointerSet - emitcode for near pointer put */ -/*-----------------------------------------------------------------*/ -static void -genNearPointerSet (operand * right, - operand * result, - iCode * ic, - iCode * pi) -{ - int size, offset; - sym_link *retype = getSpec (operandType (right)); - sym_link *letype = getSpec (operandType (result)); + if (AOP_TYPE (right) == AOP_LIT) + { + /* Case with a bitfield length <8 and literal source + */ + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); + litval <<= bstr; + litval &= (~mask) & 0xff; - D(emitcode ("; genNearPointerSet","")); + loadRegFromAop (hc08_reg_a, derefaop, 0); + if ((mask|litval)!=0xff) + emitcode ("and","#0x%02x", mask); + if (litval) + emitcode ("ora","#0x%02x", litval); + hc08_dirtyReg (hc08_reg_a, FALSE); + storeRegToAop (hc08_reg_a, derefaop, 0); - aopOp (result, ic, FALSE); + hc08_freeReg (hc08_reg_a); + goto release; + } - /* if the result is rematerializable & - in data space & not a bit variable */ - if (AOP_TYPE (result) == AOP_IMMD && - /* DCL_TYPE (ptype) == POINTER && */ - !IS_BITVAR (retype) && - !IS_BITVAR (letype)) - { - genDataPointerSet (right, result, ic); - return; + /* Case with a bitfield length < 8 and arbitrary source + */ + loadRegFromAop (hc08_reg_a, AOP (right), 0); + /* shift and mask source value */ + AccLsh (bstr); + emitcode ("and", "#0x%02x", (~mask) & 0xff); + hc08_dirtyReg (hc08_reg_a, FALSE); + pushReg (hc08_reg_a, TRUE); + + loadRegFromAop (hc08_reg_a, derefaop, 0); + emitcode ("and", "#0x%02x", mask); + emitcode ("ora", "1,s"); + storeRegToAop (hc08_reg_a, derefaop, 0); + pullReg (hc08_reg_a); + + hc08_freeReg (hc08_reg_a); + goto release; } - /* if the operand is already in hx - then we do nothing else we move the value to hx */ - if (AOP_TYPE (result) != AOP_STR) + /* Bit length is greater than 7 bits. In this case, copy */ + /* all except the partial byte at the end */ + for (rlen=blen;rlen>=8;rlen-=8) { - loadRegFromAop (hc08_reg_x, AOP (result), 0); - loadRegFromConst (hc08_reg_h, zero); + transferAopAop (AOP (right), offset, derefaop, size-offset-1); + offset++; } - /* so hx now contains the address */ - aopOp (right, ic, FALSE); - /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right); - else + /* If there was a partial byte at the end */ + if (rlen) { - size = AOP_SIZE (right); - offset = size-1; + mask = (((unsigned char) -1 << rlen) & 0xff); - while (size--) - { - loadRegFromAop (hc08_reg_a, AOP (right), offset--); - accopWithMisc ("sta", ",x"); - if (size || pi) - { - rmwWithReg ("inc", hc08_reg_x); - } + if (AOP_TYPE (right) == AOP_LIT) + { + /* Case with partial byte and literal source + */ + litval = (int) ulFromVal (AOP (right)->aopu.aop_lit); + litval >>= (blen-rlen); + litval &= (~mask) & 0xff; + loadRegFromAop (hc08_reg_a, derefaop, size-offset-1); + if ((mask|litval)!=0xff) + emitcode ("and","#0x%02x", mask); + if (litval) + emitcode ("ora","#0x%02x", litval); + hc08_dirtyReg (hc08_reg_a, FALSE); + storeRegToAop (hc08_reg_a, derefaop, size-offset-1); + hc08_dirtyReg (hc08_reg_a, FALSE); hc08_freeReg (hc08_reg_a); - } + goto release; + } + + /* Case with partial byte and arbitrary source + */ + loadRegFromAop (hc08_reg_a, AOP (right), offset); + emitcode ("and", "#0x%02x", (~mask) & 0xff); + hc08_dirtyReg (hc08_reg_a, FALSE); + pushReg (hc08_reg_a, TRUE); + + loadRegFromAop (hc08_reg_a, derefaop, size-offset-1); + emitcode ("and", "#0x%02x", mask); + emitcode ("ora", "1,s"); + storeRegToAop (hc08_reg_a, derefaop, size-offset-1); + pullReg (hc08_reg_a); } - freeAsmop (result, NULL, ic, TRUE); + hc08_freeReg (hc08_reg_a); + +release: freeAsmop (right, NULL, ic, TRUE); + freeAsmop (NULL, derefaop, ic, TRUE); +} - if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) { - aopOp (IC_RESULT (pi), pi, FALSE); - storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0); - freeAsmop (IC_RESULT (pi), NULL, pi, TRUE); - pi->generated=1; - } +/*-----------------------------------------------------------------*/ +/* genDataPointerSet - remat pointer to data space */ +/*-----------------------------------------------------------------*/ +static void +genDataPointerSet (operand * right, + operand * result, + iCode * ic) +{ + int size; + asmop *derefaop; - hc08_freeReg (hc08_reg_hx); - + D(emitcode ("; genDataPointerSet","")); + + aopOp (right, ic, FALSE); + size = AOP_SIZE (right); + + derefaop = aopDerefAop (AOP (result)); + freeAsmop (result, NULL, ic, TRUE); + derefaop->size = size; + + while (size--) + { + transferAopAop (AOP (right), size, derefaop, size); + } + + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (NULL, derefaop, ic, TRUE); } -#endif + /*-----------------------------------------------------------------*/ -/* genFarPointerSet - set value from far space */ +/* genPointerSet - stores the value into a pointer location */ /*-----------------------------------------------------------------*/ static void -genFarPointerSet (operand * right, - operand * result, iCode * ic, iCode * pi) +genPointerSet (iCode * ic, iCode *pi) { + operand *right = IC_RIGHT (ic); + operand *result = IC_RESULT (ic); + sym_link *type, *etype; int size, offset; sym_link *retype = getSpec (operandType (right)); sym_link *letype = getSpec (operandType (result)); - D(emitcode ("; genFarPointerSet","")); + D(emitcode ("; genPointerSet","")); + + type = operandType (result); + etype = getSpec (type); aopOp (result, ic, FALSE); - /* if the result is rematerializable & - in data space & not a bit variable */ - if (AOP_TYPE (result) == AOP_IMMD && - /* DCL_TYPE (ptype) == POINTER && */ - !IS_BITVAR (retype) && - !IS_BITVAR (letype)) + /* if the result is rematerializable */ + if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT) { - genDataPointerSet (right, result, ic); - return; + if (!IS_BITVAR (retype) && !IS_BITVAR (letype)) + { + genDataPointerSet (right, result, ic); + return; + } + else + { + genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic); + return; + } } /* if the operand is already in hx @@ -6805,21 +7745,21 @@ genFarPointerSet (operand * right, offset = size-1; while (size--) - { + { loadRegFromAop (hc08_reg_a, AOP (right), offset--); - accopWithMisc ("sta", ",x"); - if (size || pi) - { - emitcode ("aix", "#1"); - } + accopWithMisc ("sta", ",x"); + if (size || pi) + { + emitcode ("aix", "#1"); + } hc08_freeReg (hc08_reg_a); - } + } } freeAsmop (result, NULL, ic, TRUE); freeAsmop (right, NULL, ic, TRUE); - if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) { + if (pi) { aopOp (IC_RESULT (pi), pi, FALSE); storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0); freeAsmop (IC_RESULT (pi), NULL, pi, TRUE); @@ -6827,69 +7767,6 @@ genFarPointerSet (operand * right, } hc08_freeReg (hc08_reg_hx); - - -} - - -/*-----------------------------------------------------------------*/ -/* genPointerSet - stores the value into a pointer location */ -/*-----------------------------------------------------------------*/ -static void -genPointerSet (iCode * ic, iCode *pi) -{ - operand *right, *result; - sym_link *type, *etype; - int p_type; - - D(emitcode ("; genPointerSet","")); - - right = IC_RIGHT (ic); - result = IC_RESULT (ic); - - /* depending on the type of pointer we need to - move it to the correct pointer register */ - type = operandType (result); - etype = getSpec (type); - /* if left is of type of pointer then it is simple */ - if (IS_PTR (type) && !IS_FUNC (type->next)) - { - p_type = DCL_TYPE (type); - } - else - { - /* we have to go by the storage class */ - p_type = PTR_TYPE (SPEC_OCLS (etype)); - } - - /* special case when cast remat */ - if (p_type == GPOINTER && OP_SYMBOL(result)->remat && - IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) { - result = IC_RIGHT(OP_SYMBOL(result)->rematiCode); - type = operandType (result); - p_type = DCL_TYPE (type); - } - /* now that we have the pointer type we assign - the pointer values */ - switch (p_type) - { - - case POINTER: - case IPOINTER: -#if 0 - genNearPointerSet (right, result, ic, pi); - break; -#endif - - case GPOINTER: - case FPOINTER: - genFarPointerSet (right, result, ic, pi); - break; - - default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "genPointerSet: illegal pointer type"); - } } @@ -6906,6 +7783,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 = ulFromVal (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); @@ -6948,11 +7849,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); @@ -6968,15 +7879,15 @@ genAddrOf (iCode * ic) char s[SDCC_NAME_MAX+10]; switch (offset) { case 0: - sprintf (s, "#%s", sym->rname); - break; + sprintf (s, "#%s", sym->rname); + break; case 1: - sprintf (s, "#>%s", sym->rname); - break; + sprintf (s, "#>%s", sym->rname); + break; default: - sprintf (s, "#(%s >> %d)", - sym->rname, - offset * 8); + sprintf (s, "#(%s >> %d)", + sym->rname, + offset * 8); } storeConstToAop(s, AOP (IC_RESULT (ic)), offset++); } @@ -6993,7 +7904,7 @@ static void genAssign (iCode * ic) { operand *result, *right; - int size, offset; + int size; // unsigned long lit = 0L; D(emitcode("; genAssign","")); @@ -7019,15 +7930,12 @@ genAssign (iCode * ic) loadRegFromAop(hc08_reg_hx, AOP (right), 0); goto release; } - + /* 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: @@ -7036,37 +7944,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); - jtab = newiTempLabel (NULL); - emitcode ("jmp", "%05d$,x", jtab->key + 100); - emitcode ("", "%05d$:", jtab->key + 100); + 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(); + } + /* now generate the jump labels */ + emitLabel (jtablo); for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; jtab = setNextItem (IC_JTLABELS (ic))) - emitcode ("jmp", "%05d$", jtab->key + 100); + emitcode (".db", "%05d$", jtab->key + 100); + emitLabel (jtabhi); + for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; + jtab = setNextItem (IC_JTLABELS (ic))) + emitcode (".db", ">%05d$", jtab->key + 100); - hc08_dirtyReg (hc08_reg_a, TRUE); - hc08_dirtyReg (hc08_reg_hx, TRUE); } /*-----------------------------------------------------------------*/ @@ -7098,17 +8034,17 @@ genCast (iCode * ic) /* if they are in the same place */ #if 0 if (sameRegs (AOP (right), AOP (result))) - goto release; + goto release; #endif /* if they in different places then copy */ size = AOP_SIZE (result); offset = 0; while (size--) - { - transferAopAop(AOP (right), offset, AOP (result), offset); - offset++; - } + { + transferAopAop(AOP (right), offset, AOP (result), offset); + offset++; + } goto release; } @@ -7123,55 +8059,55 @@ genCast (iCode * ic) /* pointer to generic pointer */ if (IS_GENPTR (ctype)) - { - if (IS_PTR (type)) - p_type = DCL_TYPE (type); - else - { - if (SPEC_SCLS(etype)==S_REGISTER) { - // let's assume it is a generic pointer - p_type=GPOINTER; - } else { - /* we have to go by the storage class */ - p_type = PTR_TYPE (SPEC_OCLS (etype)); - } - } - - /* the first two bytes are known */ - size = GPTRSIZE - 1; - offset = 0; - while (size--) - { + { + if (IS_PTR (type)) + p_type = DCL_TYPE (type); + else + { + if (SPEC_SCLS(etype)==S_REGISTER) { + // let's assume it is a generic pointer + p_type=GPOINTER; + } else { + /* we have to go by the storage class */ + p_type = PTR_TYPE (SPEC_OCLS (etype)); + } + } + + /* the first two bytes are known */ + size = GPTRSIZE - 1; + offset = 0; + while (size--) + { transferAopAop(AOP (right), offset, AOP (result), offset); - offset++; - } - /* the last byte depending on type */ + offset++; + } + /* the last byte depending on type */ #if 0 - { - int gpVal = pointerTypeToGPByte(p_type, NULL, NULL); - char gpValStr[10]; - - if (gpVal == -1) - { - // pointerTypeToGPByte will have bitched. - exit(1); - } - - sprintf(gpValStr, "#0x%d", gpVal); - aopPut (AOP (result), gpValStr, GPTRSIZE - 1); - } + { + int gpVal = pointerTypeToGPByte(p_type, NULL, NULL); + char gpValStr[10]; + + if (gpVal == -1) + { + // pointerTypeToGPByte will have bitched. + exit(1); + } + + sprintf(gpValStr, "#0x%x", gpVal); + aopPut (AOP (result), gpValStr, GPTRSIZE - 1); + } #endif - goto release; - } + goto release; + } /* just copy the pointers */ size = AOP_SIZE (result); offset = 0; while (size--) - { + { transferAopAop(AOP (right), offset, AOP (result), offset); - offset++; - } + offset++; + } goto release; } @@ -7192,7 +8128,7 @@ genCast (iCode * ic) if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY) { while (size--) - storeConstToAop (zero, AOP (result), offset++); + storeConstToAop (zero, AOP (result), offset++); } else { @@ -7202,7 +8138,7 @@ genCast (iCode * ic) accopWithMisc ("clra", ""); accopWithMisc ("sbc", zero); while (size--) - storeRegToAop (hc08_reg_a, AOP (result), offset++); + storeRegToAop (hc08_reg_a, AOP (result), offset++); } /* we are done hurray !!!! */ @@ -7260,8 +8196,8 @@ genDjnz (iCode * ic, iCode * ifx) emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE), - lbl->key + 100); - + lbl->key + 100); + emitBranch ("bra", lbl1); emitLabel (lbl); emitBranch ("jmp", IC_TRUE (ifx)); @@ -7285,16 +8221,16 @@ genReceive (iCode * ic) aopOp (IC_RESULT (ic), ic, FALSE); size = AOP_SIZE (IC_RESULT (ic)); offset = 0; - + if (ic->argreg) { while (size--) { - transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0, - AOP (IC_RESULT (ic)), offset); - if (hc08_aop_pass[offset]->type == AOP_REG) - hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]); - offset++; + transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0, + AOP (IC_RESULT (ic)), offset); + if (hc08_aop_pass[offset]->type == AOP_REG) + hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]); + offset++; } - } + } freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } @@ -7305,28 +8241,47 @@ genReceive (iCode * ic) static void genDummyRead (iCode * ic) { - operand *right; + operand *op; int size, offset; D(emitcode("; genDummyRead","")); - right = IC_RIGHT (ic); + op = IC_RIGHT (ic); + if (op && IS_SYMOP (op)) + { - aopOp (right, ic, FALSE); + aopOp (op, ic, FALSE); - /* bit variables done */ - /* general case */ - size = AOP_SIZE (right); - offset = 0; + size = AOP_SIZE (op); + offset = 0; - while (size--) + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (op), offset); + hc08_freeReg (hc08_reg_a); + offset++; + } + + freeAsmop (op, NULL, ic, TRUE); + } + op = IC_LEFT (ic); + if (op && IS_SYMOP (op)) { - loadRegFromAop (hc08_reg_a, AOP (right), offset); - hc08_freeReg (hc08_reg_a); - offset++; - } - freeAsmop (right, NULL, ic, TRUE); + aopOp (op, ic, FALSE); + + size = AOP_SIZE (op); + offset = 0; + + while (size--) + { + loadRegFromAop (hc08_reg_a, AOP (op), offset); + hc08_freeReg (hc08_reg_a); + offset++; + } + + freeAsmop (op, NULL, ic, TRUE); + } } /*-----------------------------------------------------------------*/ @@ -7336,7 +8291,7 @@ static void genCritical (iCode *ic) { D(emitcode("; genCritical","")); - + if (IC_RESULT (ic)) aopOp (IC_RESULT (ic), ic, TRUE); @@ -7361,7 +8316,7 @@ static void genEndCritical (iCode *ic) { D(emitcode("; genEndCritical","")); - + if (IC_RIGHT (ic)) { aopOp (IC_RIGHT (ic), ic, FALSE); @@ -7378,6 +8333,7 @@ genEndCritical (iCode *ic) } + /*-----------------------------------------------------------------*/ /* genhc08Code - generate code for HC08 based controllers */ /*-----------------------------------------------------------------*/ @@ -7386,22 +8342,26 @@ genhc08Code (iCode * lic) { iCode *ic; int cln = 0; + int clevel = 0; + int cblock = 0; lineHead = lineCurr = NULL; /* print the allocation information */ if (allocInfo && currFunc) - printAllocInfo (currFunc, codeOutFile); + printAllocInfo (currFunc, codeOutBuf); /* if debug information required */ if (options.debug && currFunc) { - debugFile->writeFunction(currFunc); + debugFile->writeFunction (currFunc, lic); + #if 0 _G.debugLine = 1; if (IS_STATIC (currFunc->etype)) - emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name); + emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name); else - emitcode ("", "G$%s$0$0 ==.", currFunc->name); + emitcode ("", "G$%s$0$0 ==.", currFunc->name); _G.debugLine = 0; + #endif } /* stack pointer name */ if (options.useXstack) @@ -7409,6 +8369,8 @@ genhc08Code (iCode * lic) else spname = "sp"; + debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */ + hc08_aop_pass[0] = newAsmop (AOP_REG); hc08_aop_pass[0]->size=1; hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a; @@ -7425,45 +8387,63 @@ genhc08Code (iCode * lic) for (ic = lic; ic; ic = ic->next) { + _G.current_iCode = ic; + + if (ic->level != clevel || ic->block != cblock) + { + if (options.debug) + { + debugFile->writeScope(ic); + } + clevel = ic->level; + cblock = ic->block; + } + if (ic->lineno && cln != ic->lineno) - { - if (options.debug) - { - _G.debugLine = 1; - emitcode ("", "C$%s$%d$%d$%d ==.", - FileBaseName (ic->filename), ic->lineno, - ic->level, ic->block); - _G.debugLine = 0; - } - if (!options.noCcodeInAsm) { - emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, - printCLine(ic->filename, ic->lineno)); - } - cln = ic->lineno; - } + { + if (options.debug) + { + debugFile->writeCLine(ic); + #if 0 + _G.debugLine = 1; + emitcode ("", "C$%s$%d$%d$%d ==.", + FileBaseName (ic->filename), ic->lineno, + ic->level, ic->block); + _G.debugLine = 0; + #endif + } + if (!options.noCcodeInAsm) { + emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, + printCLine(ic->filename, ic->lineno)); + } + cln = ic->lineno; + } if (options.iCodeInAsm) { - char regsInUse[80]; - int i; - - for (i=0; i<6; i++) { - sprintf (®sInUse[i], - "%c", ic->riu & (1<seq, printILine(ic)); + char regsInUse[80]; + int i; + const 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 this has already been generated then do nothing */ if (resultRemat (ic) || ic->generated) - continue; + continue; { int i; regs *reg; symbol *sym; - + for (i=A_IDX;i<=XA_IDX;i++) { reg = hc08_regWithIdx(i); @@ -7503,224 +8483,219 @@ genhc08Code (iCode * lic) } } } - + /* depending on the operation */ switch (ic->op) - { - case '!': - genNot (ic); - break; - - case '~': - genCpl (ic); - break; - - case UNARYMINUS: - genUminus (ic); - break; - - case IPUSH: - genIpush (ic); - break; - - case IPOP: - /* IPOP happens only when trying to restore a - spilt live range, if there is an ifx statement - following this pop then the if statement might - be using some of the registers being popped which - would destory the contents of the register so - we need to check for this condition and handle it */ - if (ic->next && - ic->next->op == IFX && - regsInCommon (IC_LEFT (ic), IC_COND (ic->next))) - genIfx (ic->next, ic); - else - genIpop (ic); - break; - - case CALL: - genCall (ic); - break; - - case PCALL: - genPcall (ic); - break; - - case FUNCTION: - genFunction (ic); - break; - - case ENDFUNCTION: - genEndFunction (ic); - break; - - case RETURN: - genRet (ic); - break; - - case LABEL: - genLabel (ic); - break; - - case GOTO: - genGoto (ic); - break; - - case '+': + { + case '!': + genNot (ic); + break; + + case '~': + genCpl (ic); + break; + + case UNARYMINUS: + genUminus (ic); + break; + + case IPUSH: + genIpush (ic); + break; + + case IPOP: + /* IPOP happens only when trying to restore a + spilt live range, if there is an ifx statement + following this pop then the if statement might + be using some of the registers being popped which + would destory the contents of the register so + we need to check for this condition and handle it */ + if (ic->next && + ic->next->op == IFX && + regsInCommon (IC_LEFT (ic), IC_COND (ic->next))) + genIfx (ic->next, ic); + else + genIpop (ic); + break; + + case CALL: + genCall (ic); + break; + + case PCALL: + genPcall (ic); + break; + + case FUNCTION: + genFunction (ic); + break; + + case ENDFUNCTION: + genEndFunction (ic); + break; + + case RETURN: + genRet (ic); + break; + + case LABEL: + genLabel (ic); + break; + + case GOTO: + genGoto (ic); + break; + + case '+': if (!genPointerGetSetOfs (ic)) - genPlus (ic); - break; - - case '-': - if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic))) - genMinus (ic); - break; - - case '*': - genMult (ic); - break; - - case '/': - genDiv (ic); - break; - - case '%': - genMod (ic); - 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; - - case EQ_OP: - genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case AND_OP: - genAndOp (ic); - break; - - case OR_OP: - genOrOp (ic); - break; - - case '^': - genXor (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case '|': - genOr (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case BITWISEAND: - genAnd (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case INLINEASM: - genInline (ic); - break; - - case RRC: - genRRC (ic); - break; - - case RLC: - genRLC (ic); - break; - - case GETHBIT: - genGetHbit (ic); - break; - - case LEFT_OP: - genLeftShift (ic); - break; - - case RIGHT_OP: - genRightShift (ic); - break; - - case GET_VALUE_AT_ADDRESS: - genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic))))); - break; - - case '=': - if (POINTER_SET (ic)) - genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic))))); - else - genAssign (ic); - break; - - case IFX: - genIfx (ic, NULL); - break; - - case ADDRESS_OF: - genAddrOf (ic); - break; - - case JUMPTABLE: - genJumpTab (ic); - break; - - case CAST: - genCast (ic); - break; - - case RECEIVE: - genReceive (ic); - break; - - case SEND: - addSet (&_G.sendSet, ic); - break; - - case DUMMY_READ_VOLATILE: - genDummyRead (ic); - break; - - case CRITICAL: - genCritical (ic); - break; - - case ENDCRITICAL: - genEndCritical (ic); - break; - + genPlus (ic); + break; + + case '-': + if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic))) + genMinus (ic); + break; + + case '*': + genMult (ic); + break; + + case '/': + genDiv (ic); + break; + + case '%': + genMod (ic); + break; + + case '>': + case '<': + case LE_OP: + case GE_OP: + genCmp (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case NE_OP: + case EQ_OP: + genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case AND_OP: + genAndOp (ic); + break; + + case OR_OP: + genOrOp (ic); + break; + + case '^': + genXor (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case '|': + genOr (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case BITWISEAND: + genAnd (ic, ifxForOp (IC_RESULT (ic), ic)); + break; + + case INLINEASM: + genInline (ic); + break; + + case RRC: + genRRC (ic); + break; + + case RLC: + genRLC (ic); + break; + + case GETHBIT: + genGetHbit (ic); + break; + + case LEFT_OP: + genLeftShift (ic); + break; + + case RIGHT_OP: + genRightShift (ic); + break; + + case GET_VALUE_AT_ADDRESS: + genPointerGet (ic, + hasInc (IC_LEFT (ic), ic, + getSize (operandType (IC_RESULT (ic)))), + ifxForOp (IC_RESULT (ic), ic) ); + break; + + case '=': + if (POINTER_SET (ic)) + genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic))))); + else + genAssign (ic); + break; + + case IFX: + genIfx (ic, NULL); + break; + + case ADDRESS_OF: + genAddrOf (ic); + break; + + case JUMPTABLE: + genJumpTab (ic); + break; + + case CAST: + genCast (ic); + break; + + case RECEIVE: + genReceive (ic); + break; + + case SEND: + addSet (&_G.sendSet, ic); + break; + + case DUMMY_READ_VOLATILE: + genDummyRead (ic); + break; + + case CRITICAL: + genCritical (ic); + break; + + case ENDCRITICAL: + genEndCritical (ic); + break; + case SWAP: - genSwap (ic); + genSwap (ic); break; - default: - ic = ic; - } + default: + ic = ic; + } if (!hc08_reg_a->isFree) - emitcode("","; forgot to free a"); + DD(emitcode("","; forgot to free a")); if (!hc08_reg_x->isFree) - emitcode("","; forgot to free x"); + DD(emitcode("","; forgot to free x")); if (!hc08_reg_h->isFree) - emitcode("","; forgot to free h"); + DD(emitcode("","; forgot to free h")); if (!hc08_reg_hx->isFree) - emitcode("","; forgot to free hx"); + DD(emitcode("","; forgot to free hx")); if (!hc08_reg_xa->isFree) - emitcode("","; forgot to free xa"); + DD(emitcode("","; forgot to free xa")); } + debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */ + /* now we are ready to call the peep hole optimizer */ @@ -7728,6 +8703,6 @@ genhc08Code (iCode * lic) peepHole (&lineHead); /* now do the actual printing */ - printLine (lineHead, codeOutFile); + printLine (lineHead, codeOutBuf); return; }