X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=c03145c48b829e10b2cd956c8bf09602c261e20b;hb=3062f96ccb55d1d05caf9c8782f4961f87b341ce;hp=6a0d0683019811532b83bb9273cd0e622edfd983;hpb=79d9f687503784b973f9174d7834ab6e7ad75801;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index 6a0d0683..c03145c4 100644 --- a/src/pic16/gen.c +++ b/src/pic16/gen.c @@ -6,8 +6,8 @@ Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a) PIC port - Scott Dattalo scott@dattalo.com (2000) PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002) - - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005) - Bug Fixes - Raphael Neider rneider@web.de (2004,2005) + - Vangelis Rokas (2003-2006) + Bug Fixes - Raphael Neider (2004,2005) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -47,6 +47,7 @@ #include "genutils.h" #include "device.h" #include "main.h" +#include "glue.h" /* Set the following to 1 to enable the slower/bigger * but more robust generic shifting routine (which also @@ -74,11 +75,13 @@ /* Wrapper to execute `code' at most once. */ #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0) +void pic16_genMult8X8_n (operand *, operand *,operand *); +#if 0 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *); extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *); -void pic16_genMult8X8_8 (operand *, operand *,operand *); void pic16_genMult16X16_16(operand *, operand *, operand *); void pic16_genMult32X32_32(operand *, operand *, operand *); +#endif pCode *pic16_AssembleLine(char *line, int peeps); extern void pic16_printpBlock(FILE *of, pBlock *pb); static asmop *newAsmop (short type); @@ -110,7 +113,6 @@ static int GpsuedoStkPtr=0; pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index); -unsigned int pic16aopLiteral (value *val, int offset); const char *pic16_AopType(short type); static iCode *ifxForOp ( operand *op, iCode *ic ); @@ -180,7 +182,7 @@ static struct { extern int pic16_ptrRegReq ; extern int pic16_nRegs; -extern FILE *codeOutFile; +extern struct dbuf_s *codeOutBuf; //static void saverbank (int, iCode *,bool); static lineNode *lineHead = NULL; @@ -249,7 +251,7 @@ void pic16_emitpcomment (char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - unsigned char *lbp = lb; + unsigned char *lbp = (unsigned char *)lb; va_start(ap,fmt); @@ -264,6 +266,7 @@ void pic16_emitpcomment (char *fmt, ...) (lineHead = newLineNode(lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->isComment = 1; pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb)); va_end(ap); @@ -275,7 +278,7 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - unsigned char *lbp = lb; + unsigned char *lbp = (unsigned char *)lb; if(!pic16_debug_verbose) return; @@ -376,6 +379,8 @@ void pic16_emitcode (char *inst,char *fmt, ...) (lineHead = newLineNode(lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':'); + lineCurr->isComment = (*lbp == ';'); // VR fprintf(stderr, "lb = <%s>\n", lbp); @@ -410,7 +415,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) bool fsr0iu = FALSE, fsr0ou; bool fsr2iu = FALSE, fsr2ou; - fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result); + //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result); fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2); @@ -428,7 +433,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0); (*aopp)->type = AOP_FSR0; - fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__); + //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__); return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0)); } @@ -707,6 +712,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) /* if SEND do the send here */ _G.resDirect = 1; } else { +// debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq); for(i=0;isize;i++) { aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 ); _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx); @@ -851,14 +857,21 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } /* if it is in direct space */ if (IN_DIRSPACE(space)) { - sym->aop = aop = newAsmop (AOP_DIR); - aop->aopu.aop_dir = sym->rname ; - aop->size = getSize(sym->type); - DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size); - pic16_allocDirReg( IC_LEFT(ic) ); - return aop; - } - + if(!strcmp(sym->rname, "_WREG")) { + sym->aop = aop = newAsmop (AOP_ACC); + aop->size = getSize(sym->type); /* should always be 1 */ + assert(aop->size == 1); + DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size); + return (aop); + } else { + sym->aop = aop = newAsmop (AOP_DIR); + aop->aopu.aop_dir = sym->rname ; + aop->size = getSize(sym->type); + DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size); + pic16_allocDirReg( IC_LEFT(ic) ); + return (aop); + } + } if (IN_FARSPACE(space) && !IN_CODESPACE(space)) { sym->aop = aop = newAsmop (AOP_DIR); @@ -920,7 +933,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) /*-----------------------------------------------------------------*/ /* aopForRemat - rematerialzes an object */ /*-----------------------------------------------------------------*/ -static asmop *aopForRemat (operand *op) // x symbol *sym) +static asmop *aopForRemat (operand *op, bool result) // x symbol *sym) { symbol *sym = OP_SYMBOL(op); operand *refop; @@ -938,10 +951,13 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__); } +// if(!result) /* fixme-vr */ for (;;) { oldic = ic; -// pic16_emitpcomment("ic: %s\n", printILine(ic)); +// chat *iLine = printILine(ic); +// pic16_emitpcomment("ic: %s\n", iLine); +// dbuf_free(iLine); if (ic->op == '+') { val += (int) operandLitValue(IC_RIGHT(ic)); @@ -1225,7 +1241,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) /* rematerialize it NOW */ if (sym->remat) { - sym->aop = op->aop = aop = aopForRemat (op); + sym->aop = op->aop = aop = aopForRemat (op, result); // aop->size = getSize(sym->type); // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd); return; @@ -1279,19 +1295,30 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) sym->rname, sym->usl.spillLoc->offset); #endif - sym->aop = op->aop = aop = newAsmop(AOP_PCODE); //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); if (sym->usl.spillLoc && sym->usl.spillLoc->rname) { + sym->aop = op->aop = aop = newAsmop(AOP_PCODE); aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, getSize(sym->type), sym->usl.spillLoc->offset, op); - } else { - fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__); + } else if (getSize(sym->type) <= 1) { + //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type)); pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__); assert (getSize(sym->type) <= 1); + sym->aop = op->aop = aop = newAsmop(AOP_PCODE); aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg); + } else { + /* We need some kind of dummy area for getSize(sym->type) byte, + * use WREG for all storage locations. + * XXX: This only works if we are implementing a `dummy read', + * the stored value will not be retrievable... + * See #1503234 for a case requiring this. */ + sym->aop = op->aop = aop = newAsmop(AOP_REG); + aop->size = getSize(sym->type); + for ( i = 0 ; i < aop->size ;i++) + aop->aopu.aop_reg[i] = pic16_pc_wreg.r; } - aop->size = getSize(sym->type); + aop->size = getSize(sym->type); return; } @@ -1403,10 +1430,21 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) for(i=0;isize;i++) { PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1; - if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) + if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) { bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx); +// pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0); + } } + + { + regs *sr; + _G.sregsAllocSet = reverseSet( _G.sregsAllocSet ); + for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) { + pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) ); + deleteSetItem( &_G.sregsAllocSet, sr ); + } + } } _G.resDirect = 0; } @@ -1581,7 +1619,7 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) // return "acc"; if(!strcmp(aop->aopu.aop_str[offset], "WREG")) { aop->type = AOP_ACC; - return Safe_strdup("WREG"); + return Safe_strdup("_WREG"); } DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]); @@ -1658,7 +1696,7 @@ int _TempReg_lock = 0; /*-----------------------------------------------------------------*/ pCodeOp *pic16_popGetTempReg(int lock) { - pCodeOp *pcop; + pCodeOp *pcop=NULL; symbol *cfunc; // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -1671,6 +1709,34 @@ pCodeOp *pic16_popGetTempReg(int lock) cfunc = currFunc; currFunc = NULL; +#if 0 + { + regs *rr; + int i; + + /* this code might seem better but it does the *same* job with + * the old code, it all depends on ralloc.c to get a free/unused + * register */ + + i=0; + while(i < pic16_nRegs) { + rr = pic16_typeRegWithIdx(i, REG_GPR, 0); + fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr); + if((!rr || (rr && rr->isFree)) + && !bitVectBitValue(cfunc->regsUsed, i)) { + pcop = pic16_newpCodeOpReg( i ); + PCOR(pcop)->r->wasUsed = 1; + PCOR(pcop)->r->isFree = 0; + break; + } + i++; + } + + if(pcop) { + pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + } + } +#else pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP); if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { PCOR(pcop)->r->wasUsed=1; @@ -1679,6 +1745,7 @@ pCodeOp *pic16_popGetTempReg(int lock) /* push value on stack */ pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); } +#endif currFunc = cfunc; @@ -1785,7 +1852,7 @@ void pic16_popReleaseTempReg(pCodeOp *pcop, int lock) /*-----------------------------------------------------------------*/ /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetLabel(unsigned int key) +pCodeOp *pic16_popGetLabel(int key) { DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset); @@ -1832,6 +1899,12 @@ pCodeOp *pic16_popGetLit(int lit) return pic16_newpCodeOpLit(lit); } +/* Allow for 12 bit literals (LFSR x, ). */ +pCodeOp *pic16_popGetLit12(int lit) +{ + return pic16_newpCodeOpLit12(lit); +} + /*-----------------------------------------------------------------*/ /* pic16_popGetLit2 - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ @@ -1889,6 +1962,7 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING")); PCOR(pcop)->r = pic16_dirregWithName(pcop->name); +// PCOR(pcop)->r->wasUsed = 1; /* make sure that register doesn't exist, * and operand isn't NULL @@ -1900,7 +1974,7 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand // __FUNCTION__, __LINE__, str, size, offset); PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op); - fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str); + //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str); } PCOR(pcop)->instance = offset; @@ -1913,11 +1987,14 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx) pCodeOp *pcop; // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx); - +// fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx); + pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); PCOR(pcop)->rIdx = rIdx; PCOR(pcop)->r = pic16_regWithIdx(rIdx); - + if(!PCOR(pcop)->r) + PCOR(pcop)->r = pic16_allocWithIdx(rIdx); + PCOR(pcop)->r->isFree = 0; PCOR(pcop)->r->wasUsed = 1; @@ -1932,17 +2009,8 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx) /*---------------------------------------------------------------------------------*/ pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset) { - pCodeOpReg2 *pcop2; - pCodeOp *temp; - - pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset); - - /* comment the following check, so errors to throw up */ -// if(!pcop2)return NULL; - - temp = pic16_popGet(aop_dst, offset); - pcop2->pcop2 = temp; - + pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2( + pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset)); return PCOP(pcop2); } @@ -1954,32 +2022,19 @@ pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset) /*--------------------------------------------------------------------------------.-*/ pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst) { - pCodeOpReg2 *pcop2; - - pcop2 = (pCodeOpReg2 *)src; - pcop2->pcop2 = dst; - - return PCOP(pcop2); + pCodeOp2 *pcop2; + pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst); + return PCOP(pcop2); } - - /*---------------------------------------------------------------------------------*/ /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */ /* movff instruction */ /*---------------------------------------------------------------------------------*/ pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc) { - pCodeOpReg2 *pcop2; - - if(!noalloc) { - pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src); - pcop2->pcop2 = pic16_popCopyReg(dst); - } else { - /* the pCodeOp may be already allocated */ - pcop2 = (pCodeOpReg2 *)(src); - pcop2->pcop2 = (pCodeOp *)(dst); - } + pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2( + pic16_popCopyReg(src), pic16_popCopyReg(dst) ); return PCOP(pcop2); } @@ -1990,13 +2045,13 @@ pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc) /*-----------------------------------------------------------------*/ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) { - //char *s = buffer ; - char *rs; +// char *s = buffer ; +// char *rs; pCodeOp *pcop; FENTRY2; - /* offset is greater than - size then zero */ + + /* offset is greater than size then zero */ // if (offset > (aop->size - 1) && // aop->type != AOP_LIT) @@ -2004,69 +2059,65 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) /* depending on type */ switch (aop->type) { - - case AOP_R0: - case AOP_R1: - case AOP_DPTR: - case AOP_DPTR2: - DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type)); - fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type)); - assert( 0 ); - return NULL; - - - case AOP_FSR0: - case AOP_FSR2: - pcop = Safe_calloc(1, sizeof(pCodeOpReg)); - PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */ - PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx ); - PCOR(pcop)->r->wasUsed = 1; - PCOR(pcop)->r->isFree = 0; + case AOP_R0: + case AOP_R1: + case AOP_DPTR: + case AOP_DPTR2: + DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type)); + fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type)); + assert( 0 ); + return NULL; + + case AOP_FSR0: + case AOP_FSR2: + pcop = Safe_calloc(1, sizeof(pCodeOpReg)); + PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */ + PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx ); + PCOR(pcop)->r->wasUsed = 1; + PCOR(pcop)->r->isFree = 0; - PCOR(pcop)->instance = offset; - pcop->type = PCOR(pcop)->r->pc_type; - return (pcop); - - case AOP_IMMD: - DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__); - return pic16_popGetImmd(aop->aopu.aop_immd,offset,0); - - case AOP_STA: - /* pCodeOp is already allocated from aopForSym */ - DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset); - pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]); - - return (pcop); + PCOR(pcop)->instance = offset; + pcop->type = PCOR(pcop)->r->pc_type; + return (pcop); + + case AOP_IMMD: + DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__); + return pic16_popGetImmd(aop->aopu.aop_immd,offset,0); + + case AOP_STA: + /* pCodeOp is already allocated from aopForSym */ + DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset); + pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]); + return (pcop); - case AOP_ACC: - { - int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx; + case AOP_ACC: + { + int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx; - fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]); + fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]); - DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__); + DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__); - pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); - PCOR(pcop)->rIdx = rIdx; - PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx); - PCOR(pcop)->r->wasUsed=1; - PCOR(pcop)->r->isFree=0; + pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); + PCOR(pcop)->rIdx = rIdx; + PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx); + PCOR(pcop)->r->wasUsed=1; + PCOR(pcop)->r->isFree=0; - PCOR(pcop)->instance = offset; - pcop->type = PCOR(pcop)->r->pc_type; -// rs = aop->aopu.aop_reg[offset]->name; -// DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs); - return pcop; + PCOR(pcop)->instance = offset; + pcop->type = PCOR(pcop)->r->pc_type; +// DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs); + return pcop; // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset); // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]); // assert( 0 ); - } + } case AOP_DIR: - DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__); + DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir); return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL); #if 0 @@ -2078,7 +2129,9 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) case AOP_REG: { int rIdx; - assert (aop && aop->aopu.aop_reg[offset] != NULL); + +// debugf2("aop = %p\toffset = %d\n", aop, offset); +// assert (aop && aop->aopu.aop_reg[offset] != NULL); rIdx = aop->aopu.aop_reg[offset]->rIdx; DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__); @@ -2086,7 +2139,7 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); // pcop->type = PO_GPR_REGISTER; PCOR(pcop)->rIdx = rIdx; - PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx); + PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx); PCOR(pcop)->r->wasUsed=1; PCOR(pcop)->r->isFree=0; @@ -2094,8 +2147,8 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) pcop->type = PCOR(pcop)->r->pc_type; DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type)); - rs = aop->aopu.aop_reg[offset]->name; - DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs); +// rs = aop->aopu.aop_reg[offset]->name; +// DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs); return pcop; } @@ -2453,7 +2506,12 @@ void pic16_testStackOverflow(void) void pic16_pushpCodeOp(pCodeOp *pcop) { // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); + if (pcop->type == PO_LITERAL) { + pic16_emitpcode(POC_MOVLW, pcop); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); + } if(pic16_options.gstack) pic16_testStackOverflow(); @@ -2487,6 +2545,8 @@ void pushaop(asmop *aop, int offset) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if(_G.resDirect)return; + if(is_LitAOp(aop)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset)); pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); @@ -2942,7 +3002,7 @@ void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) /* assignResultValue - assign results to oper, rescall==1 is */ /* called from genCall() or genPcall() */ /*-----------------------------------------------------------------*/ -static void assignResultValue(operand * oper, int rescall) +static void assignResultValue(operand * oper, int res_size, int rescall) { int size = AOP_SIZE(oper); int offset=0; @@ -2961,20 +3021,22 @@ static void assignResultValue(operand * oper, int rescall) /* 8-bits, result in WREG */ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0)); - if(size>1) { + if(size > 1 && res_size > 1) { /* 16-bits, result in PRODL:WREG */ pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl)); } - if(size>2) { + if(size > 2 && res_size > 2) { /* 24-bits, result in PRODH:PRODL:WREG */ pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14 } - if(size>3) { + if(size > 3 && res_size > 3) { /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */ pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14 } + + pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper))); } else { /* >32-bits, result on stack, and FSR0 points to beginning. @@ -3308,8 +3370,8 @@ static void genCall (iCode *ic) DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); // pushaop(AOP(IC_LEFT(sic)), size); - pic16_mov2w (AOP(IC_LEFT(sic)), size); - + pic16_mov2w( AOP(IC_LEFT(sic)), size ); + if(!_G.resDirect) pushw(); } @@ -3345,7 +3407,11 @@ static void genCall (iCode *ic) pic16_aopOp(IC_RESULT(ic),ic,FALSE); _G.accInUse--; - assignResultValue(IC_RESULT(ic), 1); + /* Must not assign an 8-bit result to a 16-bit variable; + * this would use (used...) the uninitialized PRODL! */ + /* FIXME: Need a proper way to obtain size of function result type, + * OP_SYM_ETYPE does not work: it dereferences pointer types! */ + assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1); DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); @@ -3492,7 +3558,9 @@ static void genPcall (iCode *ic) pic16_aopOp(IC_RESULT(ic),ic,FALSE); _G.accInUse--; - assignResultValue(IC_RESULT(ic), 1); + /* FIXME: Need proper way to obtain the function result's type. + * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */ + assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1); DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); @@ -3530,12 +3598,6 @@ static int resultRemat (iCode *ic) return 0; } -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define STRCASECMP stricmp -#else -#define STRCASECMP strcasecmp -#endif - #if 0 /*-----------------------------------------------------------------*/ /* inExcludeList - return 1 if the string is in exclude Reg list */ @@ -3642,6 +3704,9 @@ static void genFunction (iCode *ic) pic16_emitcode(";"," function %s",sym->name); pic16_emitcode(";","-----------------------------------------"); + /* prevent this symbol from being emitted as 'extern' */ + pic16_stringInSet(sym->rname, &pic16_localFunctions, 1); + pic16_emitcode("","%s:",sym->rname); pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname)); @@ -3692,6 +3757,8 @@ static void genFunction (iCode *ic) pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l )); pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu )); // pic16_pBlockConvert2ISR(pb); } @@ -3712,9 +3779,9 @@ static void genFunction (iCode *ic) pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi)); pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo)); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0)); if(STACK_MODEL_LARGE) pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0)); } } @@ -3745,22 +3812,41 @@ static void genFunction (iCode *ic) /* if any registers used */ if (sym->regsUsed) { - /* save the registers used */ - DEBUGpic16_emitcode("; **", "Saving used registers in stack"); - pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); - for ( i = 0 ; i < sym->regsUsed->size ; i++) { - if (bitVectBitValue(sym->regsUsed,i)) { - pic16_pushpCodeOp( pic16_popRegFromIdx(i) ); - _G.nRegsSaved++; - - if(!pic16_regWithIdx(i)->wasUsed) { - fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n", - __FILE__, __LINE__, pic16_regWithIdx(i)->name); - pic16_regWithIdx(i)->wasUsed = 1; + pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); + + if(!xinst) { + /* save the registers used */ + DEBUGpic16_emitcode("; **", "Saving used registers in stack"); + for ( i = 0 ; i < sym->regsUsed->size ; i++) { + if (bitVectBitValue(sym->regsUsed,i)) { +#if 0 + fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i); +#endif + pic16_pushpCodeOp( pic16_popRegFromIdx(i) ); + _G.nRegsSaved++; + + if(!pic16_regWithIdx(i)->wasUsed) { + fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n", + __FILE__, __LINE__, pic16_regWithIdx(i)->name); + pic16_regWithIdx(i)->wasUsed = 1; + } } } + } else { + + /* xinst */ + DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers"); + for(i=0;iregsUsed->size;i++) { + if(bitVectBitValue(sym->regsUsed, i)) { + _G.nRegsSaved++; + } + } + +// pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved))); } + pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END)); + } } @@ -3848,15 +3934,17 @@ static void genEndFunction (iCode *ic) || FUNC_HASSTACKPARM(sym->etype) ) { /* restore stack frame */ + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); if(STACK_MODEL_LARGE) pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi )); - pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); } } _G.useWreg = 0; if (IFFUNC_ISISR(sym->type)) { + pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu )); + pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l)); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); @@ -3913,7 +4001,7 @@ void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest) { unsigned long lit=1; operand *op; - + op = IC_LEFT(ic); // this fails for is_LitOp(op) (if op is an AOP_PCODE) @@ -3932,15 +4020,28 @@ void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest) } } - if(is_LitOp(op)) { - pic16_movLit2f(dest, lit); + if (AOP_TYPE(op) == AOP_LIT) { + /* FIXME: broken for + * char __at(0x456) foo; + * return &foo; + * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */ + pic16_movLit2f(dest, (lit >> (8ul*offset))); + } else if (AOP_TYPE(op) == AOP_PCODE + && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) { + /* char *s= "aaa"; return s; */ + /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so + * that the generic pointer is interpreted correctly + * as referring to __code space, but this is fragile! */ + pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset )); + /* XXX: should check that dest != WREG */ + pic16_emitpcode(POC_MOVWF, dest); } else { if(dest->type == PO_WREG && (offset == 0)) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset)); - return; + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset)); + return; + } + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest)); } - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest)); - } } /*-----------------------------------------------------------------*/ @@ -4136,9 +4237,10 @@ static void genMultOneByte (operand *left, pic16_aopGet(AOP(result),0,FALSE,FALSE)); } - pic16_genMult8X8_8 (left, right,result); + pic16_genMult8X8_n (left, right,result); } +#if 0 /*-----------------------------------------------------------------*/ /* genMultOneWord : 16 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -4175,7 +4277,9 @@ static void genMultOneWord (operand *left, pic16_genMult16X16_16(left, right,result); } +#endif +#if 0 /*-----------------------------------------------------------------*/ /* genMultOneLong : 32 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -4212,6 +4316,7 @@ static void genMultOneLong (operand *left, pic16_genMult32X32_32(left, right,result); } +#endif @@ -4247,6 +4352,7 @@ static void genMult (iCode *ic) goto release ; } +#if 0 /* if both are of size == 2 */ if(AOP_SIZE(left) == 2 && AOP_SIZE(right) == 2) { @@ -4260,7 +4366,11 @@ static void genMult (iCode *ic) genMultOneLong(left, right, result); goto release; } - +#endif + + fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ ); + assert( !"Multiplication should have been transformed into function call!" ); + pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor."); @@ -4274,6 +4384,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genDivbits :- division of bits */ /*-----------------------------------------------------------------*/ @@ -4443,6 +4554,7 @@ static void genDivOneByte (operand *left, pic16_aopPut(AOP(result),"a",offset++); } +#endif /*-----------------------------------------------------------------*/ /* genDiv - generates code for division */ @@ -4452,8 +4564,12 @@ static void genDiv (iCode *ic) operand *left = IC_LEFT(ic); operand *right = IC_RIGHT(ic); operand *result= IC_RESULT(ic); - - + int negated = 0; + int leftVal = 0, rightVal = 0; + int signedLits = 0; + char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } }; + int op = 0; + /* Division is a very lengthy algorithm, so it is better * to call support routines than inlining algorithm. * Division functions written here just in case someone @@ -4466,6 +4582,207 @@ static void genDiv (iCode *ic) pic16_aopOp (right,ic,FALSE); pic16_aopOp (result,ic,TRUE); + if (ic->op == '/') + op = 0; + else if (ic->op == '%') + op = 1; + else + assert( !"invalid operation requested in genDivMod" ); + + /* get literal values */ + if (IS_VALOP(left)) { + leftVal = (int)floatFromVal( OP_VALUE(left) ); + assert( leftVal >= -128 && leftVal < 256 ); + if (leftVal < 0) { signedLits++; } + } + if (IS_VALOP(right)) { + rightVal = (int)floatFromVal( OP_VALUE(right) ); + assert( rightVal >= -128 && rightVal < 256 ); + if (rightVal < 0) { signedLits++; } + } + + /* We should only come here to convert all + * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t} + * with exactly one operand being s8_t into + * u8_t x u8_t -> u8_t. All other cases should have been + * turned into calls to support routines beforehand... */ + if ((AOP_SIZE(left) == 1 || IS_VALOP(left)) + && (AOP_SIZE(right) == 1 || IS_VALOP(right))) + { + if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0) + && (!IS_UNSIGNED(operandType(left)) || leftVal < 0)) + { + /* Both operands are signed or negative, use _divschar + * instead of _divuchar */ + pushaop(AOP(right), 0); + pushaop(AOP(left), 0); + + /* call _divschar */ + pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0])); + + { + symbol *sym; + sym = newSymbol( functions[op][0], 0 ); + sym->used++; + strcpy(sym->rname, functions[op][0]); + checkAddSym(&externs, sym); + } + + /* assign result */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + if (AOP_SIZE(result) > 1) + { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), + pic16_popGet(AOP(result), 1))); + /* sign extend */ + pic16_addSign(result, 2, 1); + } + + /* clean up stack */ + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + + goto release; + } + + /* push right operand */ + if (IS_VALOP(right)) { + if (rightVal < 0) { + pic16_pushpCodeOp( pic16_popGetLit(-rightVal) ); + negated++; + } else { + pushaop(AOP(right), 0); + } + } else if (!IS_UNSIGNED(operandType(right))) { + pic16_mov2w(AOP(right), 0); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec)); + negated++; + } else { + pushaop(AOP(right), 0); + } + + /* push left operand */ + if (IS_VALOP(left)) { + if (leftVal < 0) { + pic16_pushpCodeOp(pic16_popGetLit(-leftVal)); + negated++; + } else { + pushaop(AOP(left), 0); + } + } else if (!IS_UNSIGNED(operandType(left))) { + pic16_mov2w(AOP(left),0); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec)); + negated++; + } else { + pushaop(AOP(left), 0); + } + + /* call _divuchar */ + pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1])); + + { + symbol *sym; + sym = newSymbol( functions[op][1], 0 ); + sym->used++; + strcpy(sym->rname, functions[op][1]); + checkAddSym(&externs, sym); + } + + /* Revert negation(s) from above. + * This is inefficient: if both operands are negative, this + * should not touch WREG. However, determining that exactly + * one operand was negated costs at least 3 instructions, + * so there is nothing to be gained here, is there? + * + * I negate WREG because either operand might share registers with + * result, so assigning first might destroy an operand. */ + + /* For the modulus operator, (a/b)*b == a shall hold. + * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0 + * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining) + * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining) + * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining) + * Only invert the result if the left operand is negative (sigh). + */ + if (AOP_SIZE(result) <= 1 || !negated) + { + if (ic->op == '/') + { + if (IS_VALOP(right)) { + if (rightVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + } else if (!IS_UNSIGNED(operandType(right))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + } + + if (IS_VALOP(left)) { + if (leftVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + } else if (!IS_UNSIGNED(operandType(left))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + + /* Move result to destination. */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + + /* Zero-extend: no operand was signed (or result is just a byte). */ + pic16_addSign(result, 1, 0); + } else { + assert( AOP_SIZE(result) > 1 ); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1)); + if (ic->op == '/') + { + if (IS_VALOP(right)) { + if (rightVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + } else if (!IS_UNSIGNED(operandType(right))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + } + + if (IS_VALOP(left)) { + if (leftVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + } else if (!IS_UNSIGNED(operandType(left))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + + /* Move result to destination. */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + + /* Negate result if required. */ + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7)); + pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0)); + + /* Sign-extend. */ + pic16_addSign(result, 2, 1); + } + + /* clean up stack */ + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + goto release; + } + +#if 0 /* special cases first */ /* both are bits */ if (AOP_TYPE(left) == AOP_CRY && @@ -4480,6 +4797,7 @@ static void genDiv (iCode *ic) genDivOneByte(left,right,result); goto release ; } +#endif /* should have been converted to function call */ assert(0); @@ -4489,6 +4807,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genModbits :- modulus of bits */ /*-----------------------------------------------------------------*/ @@ -4588,12 +4907,16 @@ static void genModOneByte (operand *left, pic16_aopPut(AOP(result),"b",0); } +#endif /*-----------------------------------------------------------------*/ /* genMod - generates code for division */ /*-----------------------------------------------------------------*/ static void genMod (iCode *ic) { + /* Task deferred to genDiv */ + genDiv(ic); +#if 0 operand *left = IC_LEFT(ic); operand *right = IC_RIGHT(ic); operand *result= IC_RESULT(ic); @@ -4627,6 +4950,7 @@ release : pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); pic16_freeAsmop(result,NULL,ic,TRUE); +#endif } /*-----------------------------------------------------------------*/ @@ -5967,7 +6291,7 @@ static void genCmp (operand *left, operand *right, pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); werror(W_POSSBUG2, __FILE__, __LINE__); - exit(-1); + exit(EXIT_FAILURE); } /* if literal is on the right then swap with left */ @@ -7613,6 +7937,7 @@ static void genOr (iCode *ic, iCode *ifx) unsigned long lit = 0L; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); @@ -7918,6 +8243,7 @@ static void genXor (iCode *ic, iCode *ifx) unsigned long lit = 0L; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); @@ -9007,8 +9333,9 @@ static void shiftR2Left2Result (operand *left, int offl, case 1: case 2: case 3: + /* obtain sign from left operand */ if(sign) - pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16)); else emitCLRC; @@ -9024,9 +9351,10 @@ static void shiftR2Left2Result (operand *left, int offl, while(--shCount) { if(sign) - pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); + /* now get sign from already assigned result (avoid BANKSEL) */ + pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); else - emitCLRC; + emitCLRC; pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16)); pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr)); } @@ -9351,7 +9679,7 @@ void pic16_genLeftShiftLiteral (operand *left, operand *result, iCode *ic) { - int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit)); + int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit)); int size; FENTRY; @@ -9956,7 +10284,7 @@ static void genRightShiftLiteral (operand *left, iCode *ic, int sign) { - int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit)); + int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit)); int lsize,res_size; pic16_freeAsmop(right,NULL,ic,TRUE); @@ -10453,10 +10781,21 @@ static void genRightShift (iCode *ic) { /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */ void pic16_loadFSR0(operand *op, int lit) { - if(OP_SYMBOL(op)->remat || is_LitOp( op )) { - pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) { + if (AOP_TYPE(op) == AOP_LIT) { + /* handle 12 bit integers correctly */ + unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit); + if ((val & 0x0fff) != val) { + fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n", + val, (val & 0x0fff) ); + val &= 0x0fff; + } + pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val))); + } else { + pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + } } else { - assert (!OP_SYMBOL(op)->remat); + assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat); // set up FSR0 with address of result pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l))); pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h))); @@ -10626,9 +10965,9 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp return ; } - fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); + fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n"); fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); - exit(-1); + exit(EXIT_FAILURE); return ; } @@ -11125,7 +11464,7 @@ static void genGenPointerGet (operand *left, pic16_mov2w(AOP(left), 2); pic16_callGenericPointerRW(0, size); - assignResultValue(result, 1); + assignResultValue(result, size, 1); goto release; } @@ -11382,7 +11721,7 @@ static void genPackBits (sym_link *etype , operand *result, || SPEC_BLEN(etype) <= 8 ) { int fsr0_setup = 0; - if (blen != 8 || bstr != 0) { + if (blen != 8 || (bstr % 8) != 0) { // we need to combine the value with the old value if(!shifted_and_masked) { @@ -11417,7 +11756,12 @@ static void genPackBits (sym_link *etype , operand *result, if (lit != 0) pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit)); } - } // if (blen != 8 || bstr != 0) + } else { // if (blen == 8 && (bstr % 8) == 0) + if (shifted_and_masked) { + // move right (literal) to WREG (only case where right is not yet in WREG) + pic16_mov2w(AOP(right), (bstr / 8)); + } + } /* write new value back */ if ((IS_SYMOP(result) && !IS_PTR(operandType(result))) @@ -11435,7 +11779,7 @@ static void genPackBits (sym_link *etype , operand *result, #if 0 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); - exit(-1); + exit(EXIT_FAILURE); #endif @@ -11562,29 +11906,15 @@ static void genDataPointerSet(operand *right, while (size--) { if (AOP_TYPE(right) == AOP_LIT) { - unsigned int lit; - - if(!IS_FLOAT(operandType( right ))) - lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); - else { - union { - unsigned long lit_int; - float lit_float; - } info; - - /* take care if literal is a float */ - info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); - lit = info.lit_int; - } - lit = lit >> (8*offset); - pic16_movLit2f(pic16_popGet(AOP(result),offset), lit); - } else { - pic16_mov2w(AOP(right), offset); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8 - } - offset++; - resoffset++; - } + unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset); + pic16_movLit2f(pic16_popGet(AOP(result), offset), lit); + } else { + pic16_mov2w(AOP(right), offset); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8 + } + offset++; + resoffset++; + } pic16_freeAsmop(right,NULL,ic,TRUE); } @@ -12443,39 +12773,50 @@ static void genAssign (iCode *ic) } #endif - know_W=-1; - while (size--) { - DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size); - if(AOP_TYPE(right) == AOP_LIT) { - if(lit&0xff) { - if(know_W != (lit&0xff)) - pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff)); - know_W = lit&0xff; - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - } else - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); + size = AOP_SIZE(right); + if (size > AOP_SIZE(result)) size = AOP_SIZE(result); + know_W=-1; + while (size--) { + DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size); + if(AOP_TYPE(right) == AOP_LIT) { + if(lit&0xff) { + if(know_W != (lit&0xff)) + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff)); + know_W = lit&0xff; + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + } else + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - lit >>= 8; + lit >>= 8; - } else if (AOP_TYPE(right) == AOP_CRY) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - if(offset == 0) { - //debugf("%s: BTFSS offset == 0\n", __FUNCTION__); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); - } - } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) { + } else if (AOP_TYPE(right) == AOP_CRY) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); + if(offset == 0) { + //debugf("%s: BTFSS offset == 0\n", __FUNCTION__); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); + } + } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) { pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - } else { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + } else { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + if(!_G.resDirect) { /* use this aopForSym feature */ + if(AOP_TYPE(result) == AOP_ACC) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset)); + } else + if(AOP_TYPE(right) == AOP_ACC) { + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); + } + } + } - if(!_G.resDirect) /* use this aopForSym feature */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); - } - offset++; } + pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right))); release: pic16_freeAsmop (right,NULL,ic,FALSE); @@ -12921,10 +13262,13 @@ static void genCast (iCode *ic) if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) { pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); - if(AOP_SIZE(result) <2) - fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__); + + if(AOP_SIZE(result) < 2) { + fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__); + } else { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); + } } else { /* if they in different places then copy */ size = AOP_SIZE(result); @@ -13206,7 +13550,9 @@ static void genReceive (iCode *ic) GpsuedoStkPtr = ic->parmBytes; /* setting GpsuedoStkPtr has side effects here: */ - assignResultValue(IC_RESULT(ic), 0); + /* FIXME: What's the correct size of the return(ed) value? + * For now, assuming '4' as before... */ + assignResultValue(IC_RESULT(ic), 4, 0); } pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); @@ -13288,11 +13634,12 @@ void genpic16Code (iCode *lic) } if(options.iCodeInAsm) { - char *l; + char *iLine; /* insert here code to print iCode as comment */ - l = Safe_strdup(printILine(ic)); - pic16_emitpcomment("ic:%d: %s", ic->seq, l); + iLine = printILine(ic); + pic16_emitpcomment("ic:%d: %s", ic->seq, iLine); + dbuf_free(iLine); } /* if the result is marked as @@ -13500,7 +13847,7 @@ void genpic16Code (iCode *lic) peepHole (&lineHead); /* now do the actual printing */ - printLine (lineHead, codeOutFile); + printLine (lineHead, codeOutBuf); #ifdef PCODE_DEBUG DFPRINTF((stderr,"printing pBlock\n\n"));