X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=c03145c48b829e10b2cd956c8bf09602c261e20b;hb=3062f96ccb55d1d05caf9c8782f4961f87b341ce;hp=d2c7f0363d811bc6bd04037e712be068cd1db0eb;hpb=670bb6fb5c7996b6eb0e3412f12ada73f2c2635b;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index d2c7f036..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); @@ -949,7 +955,9 @@ static asmop *aopForRemat (operand *op, bool result) // x symbol *sym) 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)); @@ -1287,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; } @@ -1411,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; } @@ -1822,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); @@ -1869,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 */ /*-----------------------------------------------------------------*/ @@ -1938,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; @@ -1973,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); } @@ -1995,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); } @@ -2035,9 +2049,9 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) // char *rs; pCodeOp *pcop; - FENTRY2; - /* offset is greater than - * size then zero */ + FENTRY2; + + /* offset is greater than size then zero */ // if (offset > (aop->size - 1) && // aop->type != AOP_LIT) @@ -2115,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__); @@ -2490,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(); @@ -2981,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; @@ -3000,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. @@ -3384,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)))); @@ -3531,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)))); @@ -3569,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 */ @@ -3681,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)); @@ -3731,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); } @@ -3751,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)); } } @@ -3906,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 )); @@ -3971,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) @@ -3990,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)); - } } /*-----------------------------------------------------------------*/ @@ -4194,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 */ /*-----------------------------------------------------------------*/ @@ -4233,7 +4277,9 @@ static void genMultOneWord (operand *left, pic16_genMult16X16_16(left, right,result); } +#endif +#if 0 /*-----------------------------------------------------------------*/ /* genMultOneLong : 32 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -4270,6 +4316,7 @@ static void genMultOneLong (operand *left, pic16_genMult32X32_32(left, right,result); } +#endif @@ -4305,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) { @@ -4318,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."); @@ -4332,6 +4384,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genDivbits :- division of bits */ /*-----------------------------------------------------------------*/ @@ -4501,6 +4554,7 @@ static void genDivOneByte (operand *left, pic16_aopPut(AOP(result),"a",offset++); } +#endif /*-----------------------------------------------------------------*/ /* genDiv - generates code for division */ @@ -4510,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 @@ -4524,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 && @@ -4538,6 +4797,7 @@ static void genDiv (iCode *ic) genDivOneByte(left,right,result); goto release ; } +#endif /* should have been converted to function call */ assert(0); @@ -4547,6 +4807,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genModbits :- modulus of bits */ /*-----------------------------------------------------------------*/ @@ -4646,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); @@ -4685,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 } /*-----------------------------------------------------------------*/ @@ -6025,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 */ @@ -7671,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); @@ -7976,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); @@ -9065,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; @@ -9082,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)); } @@ -9409,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; @@ -10014,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); @@ -10512,7 +10782,18 @@ static void genRightShift (iCode *ic) { void pic16_loadFSR0(operand *op, int lit) { if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) { - pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + 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 (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat); // set up FSR0 with address of result @@ -10684,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 ; } @@ -11183,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; } @@ -11440,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) { @@ -11475,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))) @@ -11493,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 @@ -11620,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); } @@ -12501,47 +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 */ + 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)); + } + } } - } - + offset++; } + pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right))); release: pic16_freeAsmop (right,NULL,ic,FALSE); @@ -12987,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); @@ -13272,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); @@ -13354,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 @@ -13566,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"));