X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=c03145c48b829e10b2cd956c8bf09602c261e20b;hb=3062f96ccb55d1d05caf9c8782f4961f87b341ce;hp=52b13c785be8be42df0c48c269032c19ef92a45e;hpb=4e39e662bca4e52121166ee8f3b8dae33eb568d6;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index 52b13c78..c03145c4 100644 --- a/src/pic16/gen.c +++ b/src/pic16/gen.c @@ -1,4 +1,4 @@ -/*------------------------------------------------------------------------- + /*------------------------------------------------------------------------- gen.c - source file for code generation for pic16 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) @@ -6,7 +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) + - 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 @@ -46,19 +47,46 @@ #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 + * operates correctly with negative shift values). */ +#define USE_GENERIC_SIGNED_SHIFT 1 + +/* Set the following to 1 to enable the new + * stripped down genCmp version. + * This version should be easier to understand, + * more reliable and (sigh) slighly slower. */ +#define USE_SIMPLE_GENCMP 1 + +/* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */ +#define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) +#define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) +#define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x)) +#define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR)) + +/* If you change these, you also have to update the library files + * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */ +#define GPTR_TAG_DATA 0x80 +#define GPTR_TAG_EEPROM 0x40 +#define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */ + +/* 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); static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op); extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...); -static void mov2w (asmop *aop, int offset); -static void mov2f(asmop *dst, asmop *src, int offset); static void mov2fp(pCodeOp *dst, asmop *src, int offset); static pCodeOp *pic16_popRegFromIdx(int rIdx); @@ -66,7 +94,9 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx); int pic16_labelOffset=0; extern int pic16_debug_verbose; +#if !(USE_GENERIC_SIGNED_SHIFT) static int optimized_for_speed = 0; +#endif /* hack hack @@ -83,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 ); @@ -123,6 +152,7 @@ static char *one = "#0x01"; char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" }; +int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L }; unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */ static char **fReturn = fReturnpic16; @@ -141,27 +171,18 @@ static struct { short ipushRegs; set *sendSet; set *stackRegSet; - int interruptvector; int usefastretfie; - bitVect *fregsUsed; + bitVect *fregsUsed; /* registers used in function */ + bitVect *sregsAlloc; + set *sregsAllocSet; /* registers used to store stack variables */ int stack_lat; /* stack offset latency */ int resDirect; int useWreg; /* flag when WREG is used to pass function parameter */ } _G; -/* Resolved ifx structure. This structure stores information - about an iCode ifx that makes it easier to generate code. -*/ -typedef struct resolvedIfx { - symbol *lbl; /* pointer to a label */ - int condition; /* true or false ifx */ - int generated; /* set true when the code associated with the ifx - * is generated */ -} resolvedIfx; - 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; @@ -183,7 +204,7 @@ static pBlock *pb; /* return y; */ /* return -1; */ /*-----------------------------------------------------------------*/ -static int my_powof2 (unsigned long num) +int pic16_my_powof2 (unsigned long num) { if(num) { if( (num & (num-1)) == 0) { @@ -230,7 +251,7 @@ void pic16_emitpcomment (char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = (unsigned char *)lb; va_start(ap,fmt); @@ -245,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); @@ -256,7 +278,7 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = (unsigned char *)lb; if(!pic16_debug_verbose) return; @@ -287,6 +309,8 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...) // fprintf(stderr, "%s\n", lb); } + + void pic16_emitpLabel(int key) { pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset)); @@ -297,7 +321,9 @@ void pic16_emitpLabelFORCE(int key) pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset)); } -void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop) +/* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand + * NEVER call pic16_emitpcode_real directly, please... */ +void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop) { if(pcop) @@ -332,7 +358,7 @@ void pic16_emitcode (char *inst,char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = lb; va_start(ap,fmt); @@ -353,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); @@ -387,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); @@ -405,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)); } @@ -551,8 +579,9 @@ static void genSetDPTR(int n) /*-----------------------------------------------------------------*/ static void resolveIfx(resolvedIfx *resIfx, iCode *ifx) { - - DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY2; + +// DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); if(!resIfx) return; @@ -613,8 +642,8 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) asmop *aop; memmap *space= SPEC_OCLS(sym->etype); - DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); - + FENTRY2; + _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */ // sym = OP_SYMBOL(op); @@ -633,11 +662,29 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } #endif + +#if 0 + if(sym->iaccess) { + if(space->paged) { + fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name); + + sym->aop = aop = newAsmop (AOP_PAGED); + aop->aopu.aop_dir = sym->rname ; + aop->size = getSize(sym->type); + DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size); + pic16_allocDirReg( IC_LEFT(ic) ); + return aop; + } + assert( 0 ); + } +#endif + #if 1 /* assign depending on the storage class */ /* if it is on the stack or indirectly addressable */ /* space we need to assign either r0 or r1 to it */ - if (sym->onStack || sym->iaccess) { + if (sym->onStack) // || sym->iaccess) + { pCodeOp *pcop[4]; int i; @@ -651,26 +698,36 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) aop->size = getSize(sym->type); - DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__); - pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) )); - if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) ) - && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) { + DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op)); + if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) ) + && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) { +// pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) )); for(i=0;isize;i++) aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx); _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */ } else + if(1 && ic->op == SEND) { + + /* 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, 0 ); - _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx); + aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 ); + _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx); } + } // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size); #if 1 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack); - + + // we do not need to load the value if it is to be defined... + if (result) return aop; + if(_G.accInUse) { pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); } @@ -678,11 +735,28 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) for(i=0;isize;i++) { /* initialise for stack access via frame pointer */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat)); - - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_plusw2), pcop[i])); - } + // operands on stack are accessible via "{FRAME POINTER} + index" with index + // starting at 2 for arguments and growing from 0 downwards for + // local variables (index == 0 is not assigned so we add one here) + { + int soffs = sym->stack; + if (soffs <= 0) { + assert (soffs < 0); + soffs++; + } // if + + if(1 && ic->op == SEND) { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg( pic16_frame_plusw ), + pic16_popCopyReg(pic16_stack_postdec ))); + } else { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg( pic16_frame_plusw ), pcop[i])); + } + } + } if(_G.accInUse) { pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); @@ -756,7 +830,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } #endif -#if 0 +#if 1 /* special case for a function */ if (IS_FUNC(sym->type)) { sym->aop = aop = newAsmop(AOP_PCODE); @@ -783,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 = %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); @@ -828,11 +909,15 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) aop->size = PTRSIZE; else if(IN_CODESPACE( space ) || IN_FARSPACE( space )) aop->size = FPTRSIZE; - else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) ); - else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) ); + else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) ); + else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) ); else if(sym->onStack) { aop->size = PTRSIZE; } else { + if(SPEC_SCLS(sym->etype) == S_PDATA) { + fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__); + aop->size = FPTRSIZE; + } else assert( 0 ); } @@ -848,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; @@ -858,19 +943,21 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) int offset = 0; int viaimmd=0; - + FENTRY2; + ic = sym->rematiCode; - DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__); - if(IS_OP_POINTER(op)) { 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)); @@ -1046,10 +1133,12 @@ bool pic16_sameRegs (asmop *aop1, asmop *aop2 ) aop2->type != AOP_REG ) return FALSE ; + /* This is a bit too restrictive if one is a subset of the other... if (aop1->size != aop2->size ) return FALSE ; + */ - for (i = 0 ; i < aop1->size ; i++ ) { + for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) { // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE; // if(aop1->aopu.aop_reg[i]->type == AOP_REG) @@ -1147,11 +1236,12 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) b) has a spill location */ if (sym->isspilt || sym->nRegs == 0) { +// debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs); DEBUGpic16_emitcode(";","%d",__LINE__); /* 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; @@ -1173,7 +1263,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) #endif #if 1 - if (sym->ruonly ) { + if (sym->ruonly) { /* sym->aop = op->aop = aop = newAsmop(AOP_PCODE); aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); @@ -1183,10 +1273,10 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) unsigned i; - aop = op->aop = sym->aop = newAsmop(AOP_STR); + aop = op->aop = sym->aop = newAsmop(AOP_REG); aop->size = getSize(sym->type); for ( i = 0 ; i < pic16_fReturnSizePic ; i++ ) - aop->aopu.aop_str[i] = fReturn[i]; + aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r; DEBUGpic16_emitcode(";","%d",__LINE__); return; @@ -1205,12 +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); - aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, - getSize(sym->type), - sym->usl.spillLoc->offset, op); - aop->size = getSize(sym->type); + 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 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); return; } @@ -1299,21 +1407,44 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) /* we must store the result on stack */ if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) { + // operands on stack are accessible via "FSR2 + index" with index + // starting at 2 for arguments and growing from 0 downwards for + // local variables (index == 0 is not assigned so we add one here) + int soffs = OP_SYMBOL(IC_RESULT(ic))->stack; + if (soffs <= 0) { + assert (soffs < 0); + soffs++; + } // if if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); for(i=0;isize;i++) { - /* initialise for stack access via frame pointer */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat)); - - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2))); - } + /* initialise for stack access via frame pointer */ + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw))); + } if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); } if(!_G.resDirect) { - for(i=0;isize;i++) + 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)) { + 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; } @@ -1461,13 +1592,9 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) return rs; case AOP_REG: - //if (dname) - // return aop->aopu.aop_reg[offset]->dname; - //else - return aop->aopu.aop_reg[offset]->name; + return aop->aopu.aop_reg[offset]->name; case AOP_CRY: - //pic16_emitcode(";","%d",__LINE__); return aop->aopu.aop_dir; case AOP_ACC: @@ -1486,9 +1613,14 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) case AOP_STR: aop->coff = offset ; - if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && - dname) - return "acc"; + +// if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && +// dname) +// return "acc"; + if(!strcmp(aop->aopu.aop_str[offset], "WREG")) { + aop->type = AOP_ACC; + return Safe_strdup("_WREG"); + } DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]); return aop->aopu.aop_str[offset]; @@ -1500,7 +1632,11 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) if(pcop->name) { DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset); //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset); - sprintf(s,"%s", pcop->name); + if (offset) { + sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset); + } else { + sprintf(s,"%s", pic16_get_op (pcop, NULL, 0)); + } } else sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset); @@ -1509,6 +1645,21 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) strcpy(rs,s); return rs; +#if 0 + case AOP_PAGED: + DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s); + if (offset) { + sprintf(s,"(%s + %d)", + aop->aopu.aop_dir, + offset); + } else + sprintf(s,"%s",aop->aopu.aop_dir); + DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s); + rs = Safe_calloc(1,strlen(s)+1); + strcpy(rs,s); + return rs; +#endif + case AOP_STA: rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name); return (rs); @@ -1545,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__); @@ -1558,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; @@ -1566,6 +1745,7 @@ pCodeOp *pic16_popGetTempReg(int lock) /* push value on stack */ pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); } +#endif currFunc = cfunc; @@ -1573,13 +1753,15 @@ pCodeOp *pic16_popGetTempReg(int lock) } /*-----------------------------------------------------------------*/ -/* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */ -/* don't save if inside v */ +/* pic16_popGetTempRegCond - create a new temporary pCodeOp which */ +/* is not part of f, but don't save if */ +/* inside v */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock) +pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock) { - pCodeOp *pcop; + pCodeOp *pcop=NULL; symbol *cfunc; + int i; // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -1592,15 +1774,58 @@ pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock) cfunc = currFunc; currFunc = NULL; - pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP); - if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { - PCOR(pcop)->r->wasUsed=1; - PCOR(pcop)->r->isFree=0; + i = bitVectFirstBit(f); + while(i < 128) { - if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) { - /* push value on stack */ - pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + /* bypass registers that are used by function */ + if(!bitVectBitValue(f, i)) { + + /* bypass registers that are already allocated for stack access */ + if(!bitVectBitValue(v, i)) { + +// debugf("getting register rIdx = %d\n", i); + /* ok, get the operand */ + pcop = pic16_newpCodeOpReg( i ); + + /* should never by NULL */ + assert( pcop != NULL ); + + + /* sanity check */ + if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { + int found=0; + + PCOR(pcop)->r->wasUsed=1; + PCOR(pcop)->r->isFree=0; + + + { + regs *sr; + + for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) { + + if(sr->rIdx == PCOR(pcop)->r->rIdx) { + /* already used in previous steps, break */ + found=1; + break; + } + } + } + + /* caller takes care of the following */ +// bitVectSetBit(v, i); + + if(!found) { + /* push value on stack */ + pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + addSet(&_G.sregsAllocSet, PCOR(pcop)->r); + } + + break; + } + } } + i++; } currFunc = cfunc; @@ -1620,13 +1845,14 @@ void pic16_popReleaseTempReg(pCodeOp *pcop, int lock) if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { PCOR(pcop)->r->isFree = 1; + pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) ); } } /*-----------------------------------------------------------------*/ /* 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); @@ -1645,16 +1871,20 @@ pCodeOp *pic16_popCopyReg(pCodeOpReg *pc) pCodeOpReg *pcor; pcor = Safe_calloc(1,sizeof(pCodeOpReg) ); - pcor->pcop.type = pc->pcop.type; + memcpy (pcor, pc, sizeof (pCodeOpReg)); + pcor->r->wasUsed = 1; + + //pcor->pcop.type = pc->pcop.type; if(pc->pcop.name) { if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name))) fprintf(stderr,"oops %s %d",__FILE__,__LINE__); } else pcor->pcop.name = NULL; - pcor->r = pc->r; - pcor->rIdx = pc->rIdx; - pcor->r->wasUsed=1; + //pcor->r = pc->r; + //pcor->rIdx = pc->rIdx; + //pcor->r->wasUsed=1; + //pcor->instance = pc->instance; // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx); @@ -1669,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 */ /*-----------------------------------------------------------------*/ @@ -1726,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 @@ -1737,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; @@ -1750,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; @@ -1769,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); } @@ -1791,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); } @@ -1827,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; - //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* offset is greater than - size then zero */ + FENTRY2; + + /* offset is greater than size then zero */ // if (offset > (aop->size - 1) && // aop->type != AOP_LIT) @@ -1841,90 +2059,96 @@ 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 + case AOP_PAGED: + DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__); + return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL); +#endif + case AOP_REG: { - int rIdx = aop->aopu.aop_reg[offset]->rIdx; + int rIdx; + +// 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__); 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; PCOR(pcop)->instance = offset; pcop->type = PCOR(pcop)->r->pc_type; - DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type)); - rs = aop->aopu.aop_reg[offset]->name; - DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs); + 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); return pcop; } @@ -1961,16 +2185,16 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) __LINE__, ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset); pcop = pic16_pCodeOpCopy(aop->aopu.pcop); -#if 1 - switch( aop->aopu.pcop->type ) { - case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8 - case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break; - default: - assert( 0 ); /* should never reach here */; - } -#else - PCOI(pcop)->offset = offset; -#endif + switch( aop->aopu.pcop->type ) { + case PO_DIR: PCOR(pcop)->instance += offset; break; + case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break; + case PO_WREG: + assert (offset==0); + break; + default: + fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type); + assert( 0 ); /* should never reach here */; + } return pcop; } @@ -2213,9 +2437,9 @@ void pic16_aopPut (asmop *aop, char *s, int offset) } /*-----------------------------------------------------------------*/ -/* mov2w - generate either a MOVLW or MOVFW based operand type */ +/* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */ /*-----------------------------------------------------------------*/ -static void mov2w (asmop *aop, int offset) +void pic16_mov2w (asmop *aop, int offset) { DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset); @@ -2225,7 +2449,7 @@ static void mov2w (asmop *aop, int offset) pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset)); } -static void mov2f(asmop *dst, asmop *src, int offset) +void pic16_mov2f(asmop *dst, asmop *src, int offset) { if(is_LitAOp(src)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset)); @@ -2237,6 +2461,20 @@ static void mov2f(asmop *dst, asmop *src, int offset) } } +static void pic16_movLit2f(pCodeOp *pc, int lit) +{ + if (0 == (lit & 0x00ff)) + { + pic16_emitpcode (POC_CLRF, pc); + } else if (0xff == (lit & 0x00ff)) + { + pic16_emitpcode (POC_SETF, pc); + } else { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff)); + if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc); + } +} + static void mov2fp(pCodeOp *dst, asmop *src, int offset) { if(is_LitAOp(src)) { @@ -2249,7 +2487,7 @@ static void mov2fp(pCodeOp *dst, asmop *src, int offset) void pic16_testStackOverflow(void) { -#define GSTACK_TEST_NAME "__gstack_test" +#define GSTACK_TEST_NAME "_gstack_test" pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME )); @@ -2257,7 +2495,8 @@ void pic16_testStackOverflow(void) symbol *sym; sym = newSymbol( GSTACK_TEST_NAME , 0 ); - strcpy(sym->rname, GSTACK_TEST_NAME); + sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME); +// strcpy(sym->rname, GSTACK_TEST_NAME); checkAddSym(&externs, sym); } @@ -2267,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_pc_postdec1))); + 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(); @@ -2276,7 +2520,7 @@ void pic16_pushpCodeOp(pCodeOp *pcop) /* pop pcop from stack */ void pic16_poppCodeOp(pCodeOp *pcop) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop)); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2288,7 +2532,7 @@ void pic16_poppCodeOp(pCodeOp *pcop) void pushw(void) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2301,15 +2545,16 @@ 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_pc_postdec1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); } else { pic16_emitpcode(POC_MOVFF, - pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1))); + pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); } -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0)); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2320,7 +2565,7 @@ void pushaop(asmop *aop, int offset) void popaop(asmop *aop, int offset) { DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0)); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2334,11 +2579,12 @@ void popaopidx(asmop *aop, int offset, int index) if(STACK_MODEL_LARGE)ofs++; pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs)); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0)); if(pic16_options.gstack) pic16_testStackOverflow(); } +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* reAdjustPreg - points a register back to where it should */ /*-----------------------------------------------------------------*/ @@ -2377,7 +2623,7 @@ static void reAdjustPreg (asmop *aop) } } - +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -2517,186 +2763,102 @@ void pic16_toBoolean(operand *oper) } } - -#if !defined(GEN_Not) /*-----------------------------------------------------------------*/ -/* genNot - generate code for ! operation */ +/* genUminusFloat - unary minus for floating points */ /*-----------------------------------------------------------------*/ -static void pic16_genNot (iCode *ic) +static void genUminusFloat(operand *op,operand *result) { - symbol *tlbl; - int size; + int size ,offset =0 ; + + FENTRY; + /* for this we just need to flip the + first it then copy the rest in place */ + size = AOP_SIZE(op); + assert( size == AOP_SIZE(result) ); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* assign asmOps to operand & result */ - pic16_aopOp (IC_LEFT(ic),ic,FALSE); - pic16_aopOp (IC_RESULT(ic),ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic)); - /* if in bit space then a special case */ - if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) { - if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) { - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - } else { - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0)); + while(size--) { + pic16_mov2f(AOP(result), AOP(op), offset); + offset++; } - goto release; - } - - size = AOP_SIZE(IC_LEFT(ic)); - if(size == 1) { - pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - goto release; - } - pic16_toBoolean(IC_LEFT(ic)); - - tlbl = newiTempLabel(NULL); - pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_outBitC(IC_RESULT(ic)); - - release: - /* release the aops */ - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + + /* toggle the MSB's highest bit */ + pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7)); } -#endif - -#if !defined(GEN_Cpl) /*-----------------------------------------------------------------*/ -/* genCpl - generate code for complement */ +/* genUminus - unary minus code generation */ /*-----------------------------------------------------------------*/ -static void pic16_genCpl (iCode *ic) +static void genUminus (iCode *ic) { - int offset = 0; - int size ; + int size, i; + sym_link *optype, *rtype; + symbol *label; + int needLabel=0; + FENTRY; + + /* assign asmops */ + pic16_aopOp(IC_LEFT(ic),ic,FALSE); + pic16_aopOp(IC_RESULT(ic),ic,TRUE); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* assign asmOps to operand & result */ - pic16_aopOp (IC_LEFT(ic),ic,FALSE); - pic16_aopOp (IC_RESULT(ic),ic,TRUE); - - /* if both are in bit space then - a special case */ - if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && - AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { - - pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); - pic16_emitcode("cpl","c"); - pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); + /* if both in bit space then special case */ + if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY + && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { + + pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0)); + pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0)); + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0)); goto release; } - size = AOP_SIZE(IC_RESULT(ic)); - while (size--) { -/* - char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE); - MOVA(l); - pic16_emitcode("cpl","a"); - pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++); -*/ - if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset)); - } else { - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } - offset++; + optype = operandType(IC_LEFT(ic)); + rtype = operandType(IC_RESULT(ic)); - } + /* if float then do float stuff */ + if (IS_FLOAT(optype) || IS_FIXED(optype)) { + if(IS_FIXED(optype)) + debugf("implement fixed16x16 type\n", 0); + + genUminusFloat(IC_LEFT(ic),IC_RESULT(ic)); + goto release; + } -release: - /* release the aops */ - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); -} -#endif - -/*-----------------------------------------------------------------*/ -/* genUminusFloat - unary minus for floating points */ -/*-----------------------------------------------------------------*/ -static void genUminusFloat(operand *op,operand *result) -{ - int size ,offset =0 ; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* for this we just need to flip the - first it then copy the rest in place */ - size = AOP_SIZE(op); - - while(size--) { - mov2f(AOP(result), AOP(op), offset); - offset++; - } + /* otherwise subtract from zero by taking the 2's complement */ + size = AOP_SIZE(IC_LEFT(ic)); + assert( size == AOP_SIZE(IC_RESULT(ic)) ); + label = newiTempLabel ( NULL ); - /* toggle the MSB's highest bit */ - pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7)); -} - -/*-----------------------------------------------------------------*/ -/* genUminus - unary minus code generation */ -/*-----------------------------------------------------------------*/ -static void genUminus (iCode *ic) -{ - int size, i; - sym_link *optype, *rtype; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - /* assign asmops */ - pic16_aopOp(IC_LEFT(ic),ic,FALSE); - pic16_aopOp(IC_RESULT(ic),ic,TRUE); - - /* if both in bit space then special case */ - if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY - && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { - - pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0)); - pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0)); - - goto release; - } - - optype = operandType(IC_LEFT(ic)); - rtype = operandType(IC_RESULT(ic)); - - /* if float then do float stuff */ - if (IS_FLOAT(optype)) { - genUminusFloat(IC_LEFT(ic),IC_RESULT(ic)); - goto release; - } - - /* otherwise subtract from zero by taking the 2's complement */ - size = AOP_SIZE(IC_LEFT(ic)); - - for(i=0; i 0; i--) { + pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i)); + } // for + pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0)); + for (i=1; i < size; i++) { + if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; } + pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i)); + } // for + } else { + for (i=size-1; i >= 0; i--) { + pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i)); + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i)); + } // for + if (size > 1) { + for (i=0; i < size-2; i++) { + pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i)); + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; + } // for + pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2)); + } // if + pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1)); + } + if (needLabel) + pic16_emitpLabel (label->key); release: - /* release the aops */ - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + /* release the aops */ + pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); + pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); } #if 0 @@ -2826,7 +2988,7 @@ static void pushSide(operand * oper, int size) void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) { - if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) { + if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) { pic16_emitpcode(POC_MOVFW, src); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset)); } else { @@ -2840,12 +3002,13 @@ 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; - DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14 + FENTRY2; +// DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL); if(rescall) { @@ -2858,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. @@ -2888,10 +3053,10 @@ static void assignResultValue(operand * oper, int rescall) /* fix stack */ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) )); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l )); if(STACK_MODEL_LARGE) { emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h )); } } } else { @@ -2902,6 +3067,9 @@ static void assignResultValue(operand * oper, int rescall) /* its called from genReceive (probably) -- VR */ + /* I hope this code will not be called from somewhere else in the future! + * We manually set the pseudo stack pointer in genReceive. - dw + */ if(!GpsuedoStkPtr && _G.useWreg) { // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr); @@ -2912,6 +3080,7 @@ static void assignResultValue(operand * oper, int rescall) offset++; // debugf("receive from WREG\n", 0); } + GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */ } // GpsuedoStkPtr++; _G.stack_lat = AOP_SIZE(oper)-1; @@ -2919,7 +3088,7 @@ static void assignResultValue(operand * oper, int rescall) while (size) { size--; GpsuedoStkPtr++; - popaopidx(AOP(oper), offset, GpsuedoStkPtr); + popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg); // debugf("receive from STACK\n", 0); offset++; } @@ -2934,6 +3103,7 @@ static void genIpush (iCode *ic) { // int size, offset=0; + FENTRY; DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__); if(ic->parmPush) { @@ -2982,6 +3152,7 @@ static void genIpush (iCode *ic) /*-----------------------------------------------------------------*/ static void genIpop (iCode *ic) { + FENTRY; DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__); #if 0 int size,offset ; @@ -3123,7 +3294,7 @@ static void genCall (iCode *ic) int inwparam=0; char *fname; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; ftype = OP_SYM_TYPE(IC_LEFT(ic)); /* if caller saves & we have not saved then */ @@ -3134,7 +3305,7 @@ static void genCall (iCode *ic) // stackParms = psuedoStkPtr; // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes); fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name; - inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name); + inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic)))); #if 0 gpsimDebug_StackDump(__FILE__, __LINE__, fname ); @@ -3185,7 +3356,7 @@ static void genCall (iCode *ic) firstTimeThruLoop=0; - mov2w (AOP(IC_LEFT(sic)), size); + pic16_mov2w (AOP(IC_LEFT(sic)), size); // offset++; } @@ -3199,8 +3370,10 @@ static void genCall (iCode *ic) DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); // pushaop(AOP(IC_LEFT(sic)), size); - mov2w (AOP(IC_LEFT(sic)), size); - pushw(); + pic16_mov2w( AOP(IC_LEFT(sic)), size ); + + if(!_G.resDirect) + pushw(); } } @@ -3234,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)))); @@ -3250,14 +3427,14 @@ static void genCall (iCode *ic) if(stackParms>0) { if(stackParms == 1) { - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l)); + pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l)); } else { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l )); } if(STACK_MODEL_LARGE) { emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h )); } } @@ -3287,14 +3464,13 @@ static void genCall (iCode *ic) /*-----------------------------------------------------------------*/ static void genPcall (iCode *ic) { - sym_link *ftype, *fntype; + sym_link *fntype; int stackParms=0; symbol *retlbl = newiTempLabel(NULL); pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; - ftype = OP_SYM_TYPE(IC_LEFT(ic)); fntype = operandType( IC_LEFT(ic) )->next; /* if send set is not empty the assign */ @@ -3322,7 +3498,7 @@ static void genPcall (iCode *ic) pic16_AopType(AOP_TYPE(IC_LEFT(sic)))); DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); - mov2w (AOP(IC_LEFT(sic)), size); + pic16_mov2w (AOP(IC_LEFT(sic)), size); pushw(); } @@ -3338,6 +3514,11 @@ static void genPcall (iCode *ic) // push return address // push $ on return stack, then replace with retlbl + /* Thanks to Thorsten Klose for pointing out that the following + * snippet should be interrupt safe */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1))); + pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7)); + pic16_emitpcodeNULLop(POC_PUSH); pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0)); @@ -3347,12 +3528,17 @@ static void genPcall (iCode *ic) pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0)); pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu)); + + /* restore interrupt control register */ + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon)); + /* make the call by writing the pointer into pc */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath))); + mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2); + mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1); // note: MOVFF to PCL not allowed - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); + pic16_mov2w(AOP(IC_LEFT(ic)), 0); pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl)); @@ -3372,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)))); @@ -3384,11 +3572,10 @@ static void genPcall (iCode *ic) if(stackParms>0) { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); if(STACK_MODEL_LARGE) { - /* this implies that stackParms < 256 !!! -- VR */ emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); } } } @@ -3411,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 */ @@ -3448,6 +3629,7 @@ static void genFunction (iCode *ic) symbol *sym; sym_link *ftype; + FENTRY; DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key); pic16_labelOffset += (max_key+4); @@ -3465,38 +3647,33 @@ static void genFunction (iCode *ic) char asymname[128]; pBlock *apb; - { - int i, found=-1; - - sym = OP_SYMBOL( IC_LEFT(ic)); - for(i=0;i<=2;i++) { - if(interrupts[i]->name - && !STRCASECMP(interrupts[i]->name, sym->name)) { - found = i; - break; - } - } - - if(found == -1) { - fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n", - __FILE__, __LINE__, sym->name); - assert( 0 ); - } - _G.interruptvector = found; - } - - sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name); - asym = newSymbol(asymname, 0); +// debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type)); - apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section")); - pic16_addpBlock( apb ); - - pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------")); - pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name)); - pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname ))); + if(FUNC_INTNO(sym->type) == INTNO_UNSPEC) + sprintf(asymname, "ivec_%s", sym->name); + else + sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name); + + /* when an interrupt is declared as naked, do not emit the special + * wrapper segment at vector address. The user should take care for + * this instead. -- VR */ + + if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) { + asym = newSymbol(asymname, 0); + apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section")); + pic16_addpBlock( apb ); + + pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------")); + pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name)); + //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname ))); + //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0))); + pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */ - /* mark the end of this tiny function */ - pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL)); + /* mark the end of this tiny function */ + pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL)); + } else { + sprintf(asymname, "%s", sym->rname); + } { absSym *abSym; @@ -3504,14 +3681,19 @@ static void genFunction (iCode *ic) abSym = Safe_calloc(1, sizeof(absSym)); strcpy(abSym->name, asymname); - switch( _G.interruptvector ) { + switch( FUNC_INTNO(sym->type) ) { case 0: abSym->address = 0x000000; break; case 1: abSym->address = 0x000008; break; case 2: abSym->address = 0x000018; break; + + default: +// fprintf(stderr, "no interrupt number is given\n"); + abSym->address = -1; break; } /* relocate interrupt vectors if needed */ - abSym->address += pic16_options.ivt_loc; + if(abSym->address != -1) + abSym->address += pic16_options.ivt_loc; addSet(&absSymSet, abSym); } @@ -3522,10 +3704,12 @@ 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)); - { absSym *ab; @@ -3537,7 +3721,6 @@ static void genFunction (iCode *ic) } } - if(IFFUNC_ISNAKED(ftype)) { DEBUGpic16_emitcode("; ***", "_naked function, no prologue"); return; @@ -3548,7 +3731,10 @@ static void genFunction (iCode *ic) //pic16_emitcode("clr","ea"); } + currFunc = sym; /* update the currFunc symbol */ _G.fregsUsed = sym->regsUsed; + _G.sregsAlloc = newBitVect(128); + /* if this is an interrupt service routine then * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */ @@ -3556,7 +3742,7 @@ static void genFunction (iCode *ic) _G.usefastretfie = 1; /* use shadow registers by default */ /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */ - if(!(_G.interruptvector == 1)) { + if(!FUNC_ISSHADOWREGS(sym->type)) { /* do not save WREG,STATUS,BSR for high priority interrupts * because they are stored in the hardware shadow registers already */ _G.usefastretfie = 0; @@ -3571,25 +3757,31 @@ 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); - } /* emit code to setup stack frame if user enabled, * and function is not main() */ - - //fprintf(stderr, "function name: %s\n", sym->name); + +// debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type)); if(strcmp(sym->name, "main")) { - if(1 /*!options.ommitFramePtr || sym->regsUsed*/) { + if(0 + || !options.ommitFramePtr +// || sym->regsUsed + || IFFUNC_ARGS(sym->type) + || FUNC_HASSTACKPARM(sym->etype) + ) { /* setup the stack frame */ if(STACK_MODEL_LARGE) - pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h)); - pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l)); -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0)); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0)); + pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi)); + pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo)); + if(STACK_MODEL_LARGE) - pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0)); + 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)); } } @@ -3599,12 +3791,12 @@ static void genFunction (iCode *ic) if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack)); - pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l)); - emitSKPNC; - pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h)); + pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l)); + emitSKPC; + pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h)); } - if(inWparamList(sym->name)) { + if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) { if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type)) _G.useWreg = 0; else @@ -3615,27 +3807,46 @@ static void genFunction (iCode *ic) /* if callee-save to be used for this function * then save the registers being used in this function */ // if (IFFUNC_CALLEESAVES(sym->type)) - { + if(strcmp(sym->name, "main")) { int i; /* 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)); + } } @@ -3650,7 +3861,7 @@ static void genEndFunction (iCode *ic) { symbol *sym = OP_SYMBOL(IC_LEFT(ic)); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; if(IFFUNC_ISNAKED(sym->type)) { DEBUGpic16_emitcode("; ***", "_naked function, no epilogue"); @@ -3666,19 +3877,22 @@ static void genEndFunction (iCode *ic) /* TODO: add code here -- VR */ } - if ((IFFUNC_ISREENT(sym->type) || options.stackAuto) - && sym->stack) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l)); - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h)); - } - // sym->regsUsed = _G.fregsUsed; /* now we need to restore the registers */ /* if any registers used */ - if (sym->regsUsed) { + + /* first restore registers that might be used for stack access */ + if(_G.sregsAllocSet) { + regs *sr; + + _G.sregsAllocSet = reverseSet( _G.sregsAllocSet ); + for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) { + pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) ); + } + } + + if (strcmp(sym->name, "main") && sym->regsUsed) { int i; pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN)); @@ -3691,36 +3905,59 @@ static void genEndFunction (iCode *ic) } } pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END)); + } + + + if ((IFFUNC_ISREENT(sym->type) || options.stackAuto) + && sym->stack) { + if (sym->stack == 1) { + pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); + } else { + // we have to add more than one... + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value! + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1)); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); + pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)! + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value! + } } if(strcmp(sym->name, "main")) { - if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) { + if(0 + || !options.ommitFramePtr +// || sym->regsUsed + || IFFUNC_ARGS(sym->type) + || FUNC_HASSTACKPARM(sym->etype) + ) { /* restore stack frame */ + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); if(STACK_MODEL_LARGE) - pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h )); -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0)); - pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l )); -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0)); + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi )); } } _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 )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl )); - if(!(_G.interruptvector == 1)) { + if(!FUNC_ISSHADOWREGS(sym->type)) { /* do not restore interrupt vector for WREG,STATUS,BSR * for high priority interrupt, see genFunction */ pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg )); } - _G.interruptvector = 0; /* sanity check */ +// _G.interruptvector = 0; /* sanity check */ /* if debug then send end of function */ @@ -3760,23 +3997,51 @@ static void genEndFunction (iCode *ic) } -void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest) +void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest) { - if(is_LitOp(op)) { - unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit); - if(lit == 0) { - pic16_emitpcode(POC_CLRF, dest); + unsigned long lit=1; + operand *op; + + op = IC_LEFT(ic); + + // this fails for is_LitOp(op) (if op is an AOP_PCODE) + if(AOP_TYPE(op) == AOP_LIT) { + if(!IS_FLOAT(operandType( op ))) { + lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit); } else { - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); - if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest); + union { + unsigned long lit_int; + float lit_float; + } info; + + /* take care if literal is a float */ + info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit); + lit = info.lit_int; } - } else { - if(dest->type == PO_WREG && (offset == 0)) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset)); - return; } - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest)); - } + + 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_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest)); + } } /*-----------------------------------------------------------------*/ @@ -3787,7 +4052,7 @@ static void genRet (iCode *ic) int size; operand *left; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* if we have no return value then * just generate the "ret" */ @@ -3800,27 +4065,16 @@ static void genRet (iCode *ic) size = AOP_SIZE(IC_LEFT(ic)); if(size <= 4) { - if(size>3) { - pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l)); -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l))); - } - if(size>2) { - pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh)); -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh))); - } - if(size>1) { - pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl)); -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl))); - } - -// pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12 + if(size>3) + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l)); + + if(size>2) + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh)); - pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12 -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg))); + if(size>1) + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl)); + + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg)); } else { /* >32-bits, setup stack and FSR0 */ @@ -3836,13 +4090,13 @@ static void genRet (iCode *ic) /* setup FSR0 */ pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l))); if(STACK_MODEL_LARGE) { pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h))); + pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h))); } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) ); + pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi )); } } @@ -3907,15 +4161,14 @@ jumpret: /*-----------------------------------------------------------------*/ static void genLabel (iCode *ic) { + FENTRY; + /* special case never generate */ + if (IC_LABEL(ic) == entryLabel) + return ; - /* special case never generate */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (IC_LABEL(ic) == entryLabel) - return ; - - pic16_emitpLabel(IC_LABEL(ic)->key); - pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset)); + pic16_emitpLabel(IC_LABEL(ic)->key); +// pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset)); } /*-----------------------------------------------------------------*/ @@ -3924,8 +4177,9 @@ static void genLabel (iCode *ic) //tsd static void genGoto (iCode *ic) { + FENTRY; pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key)); - pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset); +// pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset); } @@ -3936,7 +4190,7 @@ static void genMultbits (operand *left, operand *right, operand *result) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; if(!pic16_sameRegs(AOP(result),AOP(right))) pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); @@ -3956,7 +4210,7 @@ static void genMultOneByte (operand *left, operand *result) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; DEBUGpic16_pic16_AopType(__LINE__,left,right,result); DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result); @@ -3983,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 */ /*-----------------------------------------------------------------*/ @@ -3993,37 +4248,38 @@ static void genMultOneWord (operand *left, operand *right, operand *result) { + FENTRY; + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result); - - /* (if two literals, the value is computed before) - * if one literal, literal on the right */ - if (AOP_TYPE(left) == AOP_LIT){ - operand *t = right; - right = left; - left = t; - } + /* (if two literals, the value is computed before) + * if one literal, literal on the right */ + if (AOP_TYPE(left) == AOP_LIT){ + operand *t = right; + right = left; + left = t; + } - /* size is checked already == 2 */ -// size = AOP_SIZE(result); + /* size is checked already == 2 */ +// size = AOP_SIZE(result); - if (AOP_TYPE(right) == AOP_LIT) { - pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", - pic16_aopGet(AOP(right),0,FALSE,FALSE), - pic16_aopGet(AOP(left),0,FALSE,FALSE), - pic16_aopGet(AOP(result),0,FALSE,FALSE)); - } else { - pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", - pic16_aopGet(AOP(right),0,FALSE,FALSE), - pic16_aopGet(AOP(left),0,FALSE,FALSE), - pic16_aopGet(AOP(result),0,FALSE,FALSE)); - } + if (AOP_TYPE(right) == AOP_LIT) { + pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", + pic16_aopGet(AOP(right),0,FALSE,FALSE), + pic16_aopGet(AOP(left),0,FALSE,FALSE), + pic16_aopGet(AOP(result),0,FALSE,FALSE)); + } else { + pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", + pic16_aopGet(AOP(right),0,FALSE,FALSE), + pic16_aopGet(AOP(left),0,FALSE,FALSE), + pic16_aopGet(AOP(result),0,FALSE,FALSE)); + } - pic16_genMult16X16_16(left, right,result); + pic16_genMult16X16_16(left, right,result); } +#endif +#if 0 /*-----------------------------------------------------------------*/ /* genMultOneLong : 32 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -4031,36 +4287,36 @@ static void genMultOneLong (operand *left, operand *right, operand *result) { + FENTRY; + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result); - - /* (if two literals, the value is computed before) - * if one literal, literal on the right */ - if (AOP_TYPE(left) == AOP_LIT){ - operand *t = right; - right = left; - left = t; - } + /* (if two literals, the value is computed before) + * if one literal, literal on the right */ + if (AOP_TYPE(left) == AOP_LIT){ + operand *t = right; + right = left; + left = t; + } - /* size is checked already == 4 */ -// size = AOP_SIZE(result); + /* size is checked already == 4 */ +// size = AOP_SIZE(result); - if (AOP_TYPE(right) == AOP_LIT) { - pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", - pic16_aopGet(AOP(right),0,FALSE,FALSE), - pic16_aopGet(AOP(left),0,FALSE,FALSE), - pic16_aopGet(AOP(result),0,FALSE,FALSE)); - } else { - pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", - pic16_aopGet(AOP(right),0,FALSE,FALSE), - pic16_aopGet(AOP(left),0,FALSE,FALSE), - pic16_aopGet(AOP(result),0,FALSE,FALSE)); - } + if (AOP_TYPE(right) == AOP_LIT) { + pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", + pic16_aopGet(AOP(right),0,FALSE,FALSE), + pic16_aopGet(AOP(left),0,FALSE,FALSE), + pic16_aopGet(AOP(result),0,FALSE,FALSE)); + } else { + pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", + pic16_aopGet(AOP(right),0,FALSE,FALSE), + pic16_aopGet(AOP(left),0,FALSE,FALSE), + pic16_aopGet(AOP(result),0,FALSE,FALSE)); + } - pic16_genMult32X32_32(left, right,result); + pic16_genMult32X32_32(left, right,result); } +#endif @@ -4073,7 +4329,7 @@ static void genMult (iCode *ic) operand *right = IC_RIGHT(ic); operand *result= IC_RESULT(ic); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* assign the amsops */ pic16_aopOp (left,ic,FALSE); pic16_aopOp (right,ic,FALSE); @@ -4096,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) { @@ -4109,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."); @@ -4123,6 +4384,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genDivbits :- division of bits */ /*-----------------------------------------------------------------*/ @@ -4130,10 +4392,9 @@ static void genDivbits (operand *left, operand *right, operand *result) { + char *l; - char *l; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* the result must be bit */ pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE)); l = pic16_aopGet(AOP(left),0,FALSE,FALSE); @@ -4152,10 +4413,10 @@ static void genDivOneByte (operand *left, operand *right, operand *result) { - sym_link *opetype = operandType(result); - char *l ; - symbol *lbl ; - int size,offset; + sym_link *opetype = operandType(result); + char *l ; + symbol *lbl ; + int size,offset; /* result = divident / divisor * - divident may be a register or a literal, @@ -4165,7 +4426,8 @@ static void genDivOneByte (operand *left, * In addition we must handle signed and unsigned, which * result in 6 final different cases -- VR */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + size = AOP_SIZE(result) - 1; offset = 1; /* signed or unsigned */ @@ -4292,6 +4554,7 @@ static void genDivOneByte (operand *left, pic16_aopPut(AOP(result),"a",offset++); } +#endif /*-----------------------------------------------------------------*/ /* genDiv - generates code for division */ @@ -4301,52 +4564,262 @@ 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 * wants to inline and not use the support libraries -- VR */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + /* assign the amsops */ pic16_aopOp (left,ic,FALSE); pic16_aopOp (right,ic,FALSE); pic16_aopOp (result,ic,TRUE); - /* special cases first */ - /* both are bits */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right)== AOP_CRY) { - genDivbits(left,right,result); - goto release ; - } - - /* if both are of size == 1 */ - if (AOP_SIZE(left) == 1 && - AOP_SIZE(right) == 1 ) { - genDivOneByte(left,right,result); - goto release ; - } + 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); - /* should have been converted to function call */ - assert(0); -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); -} + /* call _divschar */ + pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0])); -/*-----------------------------------------------------------------*/ -/* genModbits :- modulus of bits */ -/*-----------------------------------------------------------------*/ -static void genModbits (operand *left, - operand *right, - operand *result) -{ + { + symbol *sym; + sym = newSymbol( functions[op][0], 0 ); + sym->used++; + strcpy(sym->rname, functions[op][0]); + checkAddSym(&externs, sym); + } - char *l; + /* 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 && + AOP_TYPE(right)== AOP_CRY) { + genDivbits(left,right,result); + goto release ; + } + + /* if both are of size == 1 */ + if (AOP_SIZE(left) == 1 && + AOP_SIZE(right) == 1 ) { + genDivOneByte(left,right,result); + goto release ; + } +#endif + + /* should have been converted to function call */ + assert(0); +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); +} + +#if 0 +/*-----------------------------------------------------------------*/ +/* genModbits :- modulus of bits */ +/*-----------------------------------------------------------------*/ +static void genModbits (operand *left, + operand *right, + operand *result) +{ + char *l; + FENTRY; + + werror(W_POSSBUG2, __FILE__, __LINE__); /* the result must be bit */ pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE)); l = pic16_aopGet(AOP(left),0,FALSE,FALSE); @@ -4366,11 +4839,13 @@ static void genModOneByte (operand *left, operand *right, operand *result) { - sym_link *opetype = operandType(result); - char *l ; - symbol *lbl ; + sym_link *opetype = operandType(result); + char *l ; + symbol *lbl ; + + FENTRY; + werror(W_POSSBUG2, __FILE__, __LINE__); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); /* signed or unsigned */ if (SPEC_USIGN(opetype)) { /* unsigned is easy */ @@ -4432,17 +4907,22 @@ static void genModOneByte (operand *left, pic16_aopPut(AOP(result),"b",0); } +#endif /*-----------------------------------------------------------------*/ /* genMod - generates code for division */ /*-----------------------------------------------------------------*/ static void genMod (iCode *ic) { - operand *left = IC_LEFT(ic); - operand *right = IC_RIGHT(ic); - operand *result= IC_RESULT(ic); + /* Task deferred to genDiv */ + genDiv(ic); +#if 0 + operand *left = IC_LEFT(ic); + operand *right = IC_RIGHT(ic); + operand *result= IC_RESULT(ic); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + /* assign the amsops */ pic16_aopOp (left,ic,FALSE); pic16_aopOp (right,ic,FALSE); @@ -4470,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 } /*-----------------------------------------------------------------*/ @@ -4480,8 +4961,8 @@ release : */ static void genIfxJump (iCode *ic, char *jval) { - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + /* if true label then we jump if condition supplied is true */ if ( IC_TRUE(ic) ) { @@ -4489,7 +4970,7 @@ static void genIfxJump (iCode *ic, char *jval) if(strcmp(jval,"a") == 0) emitSKPZ; else if (strcmp(jval,"c") == 0) - emitSKPC; + emitSKPNC; else { DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER)); @@ -4504,7 +4985,7 @@ static void genIfxJump (iCode *ic, char *jval) if(strcmp(jval,"a") == 0) emitSKPNZ; else if (strcmp(jval,"c") == 0) - emitSKPNC; + emitSKPC; else { DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER)); @@ -4520,6 +5001,33 @@ static void genIfxJump (iCode *ic, char *jval) ic->generated = 1; } +static void genIfxpCOpJump (iCode *ic, pCodeOp *jop) +{ + FENTRY; + + /* if true label then we jump if condition + supplied is true */ + if ( IC_TRUE(ic) ) { + DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__); + pic16_emitpcode(POC_BTFSC, jop); + + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key)); + pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset); + + } else { + /* false label is present */ + DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__); + pic16_emitpcode(POC_BTFSS, jop); + + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key)); + pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset); + } + + + /* mark the icode as generated */ + ic->generated = 1; +} + #if 0 // not needed ATM @@ -4586,14 +5094,15 @@ static void genSkipc(resolvedIfx *rifx) return; if(rifx->condition) - emitSKPC; - else emitSKPNC; + else + emitSKPC; pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#if !(USE_SIMPLE_GENCMP) /*-----------------------------------------------------------------*/ /* genSkipz2 */ /*-----------------------------------------------------------------*/ @@ -4612,6 +5121,7 @@ static void genSkipz2(resolvedIfx *rifx, int invert_condition) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -4640,6 +5150,7 @@ static void genSkipz(iCode *ifx, int condition) } #endif +#if !(USE_SIMPLE_GENCMP) /*-----------------------------------------------------------------*/ /* genSkipCond */ /*-----------------------------------------------------------------*/ @@ -4657,6 +5168,7 @@ static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -4687,10 +5199,243 @@ static int genChkZeroes(operand *op, int lit, int size) } #endif + +/*-----------------------------------------------------------------*/ +/* mov2w_regOrLit :- move to WREG either the offset's byte from */ +/* aop (if it's NOT a literal) or from lit (if */ +/* aop is a literal) */ +/*-----------------------------------------------------------------*/ +void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) { + if (aop->type == AOP_LIT) { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8))); + } else { + pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset)); + } +} + /*-----------------------------------------------------------------*/ /* genCmp :- greater or less than comparison */ /*-----------------------------------------------------------------*/ -#if 1 + +#if USE_SIMPLE_GENCMP /* { */ + +/* genCmp performs a left < right comparison, stores + * the outcome in result (if != NULL) and generates + * control flow code for the ifx (if != NULL). + * + * This version leaves in sequences like + * "B[CS]F STATUS,0; BTFS[CS] STATUS,0" + * which should be optmized by the peephole + * optimizer - RN 2005-01-01 */ +static void genCmp (operand *left,operand *right, + operand *result, iCode *ifx, int sign) +{ + resolvedIfx rIfx; + int size; + int offs; + symbol *templbl; + operand *dummy; + unsigned long lit; + unsigned long mask; + int performedLt; + + FENTRY; + + assert (left && right); + assert (AOP_SIZE(left) == AOP_SIZE(right)); + + size = AOP_SIZE(right) - 1; + mask = (0x100UL << (size*8)) - 1; + // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0) + performedLt = 1; + templbl = NULL; + lit = 0; + + resolveIfx (&rIfx, ifx); + + /* handle for special cases */ + if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign)) + return; + + /********************************************************************** + * handle bits - bit compares are promoted to int compares seemingly! * + **********************************************************************/ +#if 0 + // THIS IS COMPLETELY UNTESTED! + if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) { + pCodeOp *pcleft = pic16_popGet(AOP(left), 0); + pCodeOp *pcright = pic16_popGet(AOP(right), 0); + assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT); + + emitSETC; + // 1 < {0,1} is false --> clear C by skipping the next instruction + //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit); + pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0)); + // {0,1} < 0 is false --> clear C by NOT skipping the next instruction + pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit)); + emitCLRC; // only skipped for left=0 && right=1 + + goto correct_result_in_carry; + } // if +#endif + + /************************************************* + * make sure that left is register (or the like) * + *************************************************/ + if (!isAOP_REGlike(left)) { + DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right)); + assert (isAOP_LIT(left)); + assert (isAOP_REGlike(right)); + // swap left and right + // left < right <==> right > left <==> (right >= left + 1) + lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit); + + if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) { + // MAXVALUE < right? always false + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } // if + + // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed), + // that's why we handled it above. + lit++; + + dummy = left; + left = right; + right = dummy; + + performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1" + } else if (isAOP_LIT(right)) { + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + } // if + + assert (isAOP_REGlike(left)); // left must be register or the like + assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal + + /************************************************* + * special cases go here * + *************************************************/ + + if (isAOP_LIT(right)) { + if (!sign) { + // unsigned comparison to a literal + DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1); + if (lit == 0) { + // unsigned left < 0? always false + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } + } else { + // signed comparison to a literal + DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask); + if ((lit & mask) == ((0x80 << (size*8)) & mask)) { + // signed left < 0x80000000? always false + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } else if (lit == 0) { + // compare left < 0; set CARRY if SIGNBIT(left) is set + if (performedLt) emitSETC; else emitCLRC; + pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7)); + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } + } // if (!sign) + } // right is literal + + /************************************************* + * perform a general case comparison * + * make sure we get CARRY==1 <==> left >= right * + *************************************************/ + // compare most significant bytes + //DEBUGpc ("comparing bytes at offset %d", size); + if (!sign) { + // unsigned comparison + mov2w_regOrLit (AOP(right), lit, size); + pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size)); + } else { + // signed comparison + // (add 2^n to both operands then perform an unsigned comparison) + if (isAOP_LIT(right)) { + // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0) + unsigned char litbyte = (lit >> (8*size)) & 0xFF; + + if (litbyte == 0x80) { + // left >= 0x80 -- always true, but more bytes to come + pic16_mov2w (AOP(left), size); + pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag + emitSETC; + } else { + // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100 + pic16_mov2w (AOP(left), size); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80)); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF)); + } // if + } else { + /* using PRODL as a temporary register here */ + pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl); + //pCodeOp *pctemp = pic16_popGetTempReg(1); + pic16_mov2w (AOP(left), size); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80)); + pic16_emitpcode (POC_MOVWF, pctemp); + pic16_mov2w (AOP(right), size); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80)); + pic16_emitpcode (POC_SUBFW, pctemp); + //pic16_popReleaseTempReg(pctemp, 1); + } + } // if (!sign) + + // compare remaining bytes (treat as unsigned case from above) + templbl = newiTempLabel ( NULL ); + offs = size; + while (offs--) { + //DEBUGpc ("comparing bytes at offset %d", offs); + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key)); + mov2w_regOrLit (AOP(right), lit, offs); + pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs)); + } // while (offs) + pic16_emitpLabel (templbl->key); + goto result_in_carry; + +result_in_carry: + + /**************************************************** + * now CARRY contains the result of the comparison: * + * SUBWF sets CARRY iff * + * F-W >= 0 <==> F >= W <==> !(F < W) * + * (F=left, W=right) * + ****************************************************/ + + if (performedLt) { + if (result && AOP_TYPE(result) != AOP_CRY) { + // value will be stored + emitTOGC; + } else { + // value wil only be used in the following genSkipc() + rIfx.condition ^= 1; + } + } // if + +correct_result_in_carry: + + // assign result to variable (if neccessary) + if (result && AOP_TYPE(result) != AOP_CRY) { + //DEBUGpc ("assign result"); + size = AOP_SIZE(result); + while (size--) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size)); + } // while + pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0)); + } // if (result) + + // perform conditional jump + if (ifx) { + //DEBUGpc ("generate control flow"); + genSkipc (&rIfx); + ifx->generated = 1; + } // if +} + +#elif 1 /* } */ /* { */ /* original code */ static void genCmp (operand *left,operand *right, @@ -4709,6 +5454,8 @@ static void genCmp (operand *left,operand *right, } */ + FENTRY; + resolveIfx(&rFalseIfx,ifx); truelbl = newiTempLabel(NULL); size = max(AOP_SIZE(left),AOP_SIZE(right)); @@ -4739,6 +5486,7 @@ static void genCmp (operand *left,operand *right, /* if left & right are bit variables */ if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY ) { + assert (0 && "bit variables used in genCmp"); pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); } else { @@ -5149,14 +5897,16 @@ static void genCmp (operand *left,operand *right, pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80)); pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i)); - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - - - if(ifx) ifx->generated = 1; - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) { + emitTOGC; + if(ifx) ifx->generated = 1; goto check_carry; + } else { + rFalseIfx.condition ^= 1; + genSkipc(&rFalseIfx); + if(ifx) ifx->generated = 1; + } return; } @@ -5318,7 +6068,7 @@ static void genCmp (operand *left,operand *right, pctemp = pic16_popGetTempReg(1); pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr)); + pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size)); @@ -5408,7 +6158,7 @@ check_carry: } -#else /* old version of genCmp() */ /* } else { */ +#elif 0 /* VR version of genCmp() */ /* } else { */ /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */ static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx, @@ -5518,10 +6268,6 @@ static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl, } } - - - -#if 1 /* { */ static void genCmp (operand *left, operand *right, operand *result, iCode *ifx, int sign) { @@ -5530,7 +6276,8 @@ static void genCmp (operand *left, operand *right, resolvedIfx rFalseIfx; symbol *falselbl, *tlbl; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); resolveIfx(&rFalseIfx, ifx); @@ -5544,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 */ @@ -5579,6 +6326,7 @@ static void genCmp (operand *left, operand *right, /* signed compare */ DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__); + /* using PRODL:PRODH as a temporary register here */ pct = pic16_popCopyReg(&pic16_pc_prodl); pct2 = pic16_popCopyReg(&pic16_pc_prodh); tlbl = newiTempLabel( NULL ); @@ -5659,7 +6407,6 @@ static void genCmp (operand *left, operand *right, // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl); } -// } if(ifx)ifx->generated = 1; @@ -5672,7 +6419,6 @@ static void genCmp (operand *left, operand *right, } } else { - /* unsigned compare */ DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); @@ -5683,10 +6429,8 @@ static void genCmp (operand *left, operand *right, compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL); } - if(ifx)ifx->generated = 1; - if(AOP_SIZE(result)) { pic16_emitpLabel(falselbl->key); pic16_outBitC( result ); @@ -5771,509 +6515,54 @@ static void genCmp (operand *left, operand *right, } } -#else /* } else { */ - -/* new version of genCmp -- VR 20041012 */ -static void genCmp (operand *left,operand *right, - operand *result, iCode *ifx, int sign) -{ - int size; //, offset = 0 ; - unsigned long lit = 0L,i = 0; - resolvedIfx rFalseIfx; - int willCheckCarry=0; - // resolvedIfx rTrueIfx; - symbol *truelbl; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); +#endif /* } */ - /* General concept: - * subtract right from left if at the end the carry flag is set then we - * know that left is greater than right */ - - resolveIfx(&rFalseIfx,ifx); - truelbl = newiTempLabel(NULL); - size = max(AOP_SIZE(left),AOP_SIZE(right)); - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); +/*-----------------------------------------------------------------*/ +/* genCmpGt :- greater than comparison */ +/*-----------------------------------------------------------------*/ +static void genCmpGt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; - /* POC_CPFSGT compare f, wreg, skip if f greater than wreg - * POC_CPFSLT compare f, wreg, skip if f less then wreg */ - + FENTRY; + + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); - /* if literal is on the right then swap with left */ - if ((AOP_TYPE(right) == AOP_LIT)) { - operand *tmp = right ; - unsigned long mask = (0x100 << (8*(size-1))) - 1; + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); + /* assign the amsops */ + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); - lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + genCmp(right, left, result, ifx, sign); -// lit = (lit - 1) & mask; - right = left; - left = tmp; - rFalseIfx.condition ^= 1; /* reverse compare */ - } else - if ((AOP_TYPE(left) == AOP_LIT)) { - /* float compares are handled by support functions */ - lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit); - } + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} +/*-----------------------------------------------------------------*/ +/* genCmpLt - less than comparisons */ +/*-----------------------------------------------------------------*/ +static void genCmpLt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; - //if(IC_TRUE(ifx) == NULL) - /* if left & right are bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_CRY ) { + FENTRY; - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); - - } else { - symbol *lbl = newiTempLabel(NULL); - - if(AOP_TYPE(left) == AOP_LIT) { - DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign); - - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - willCheckCarry = 1; - else willCheckCarry = 0; - - /* Special cases */ - if((lit == 0) && (sign == 0)) { - /* unsigned compare to 0 */ - DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign); - - size--; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size)); - - genSkipz2(&rFalseIfx,0); - if(ifx)ifx->generated = 1; - return; - } - - if(size==1) { - /* Special cases */ - lit &= 0xff; - if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) { - /* degenerate compare can never be true */ - if(rFalseIfx.condition == 0) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key)); - - if(ifx) ifx->generated = 1; - return; - } - - if(sign) { - /* signed comparisons to a literal byte */ - DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign); - - int lp1 = (lit+1) & 0xff; - - DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1); - switch (lp1) { - case 0: - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,0,7); - break; - case 0x7f: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f)); - genSkipz2(&rFalseIfx,1); - break; - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit )); - - if(rFalseIfx.condition) - pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0)); - else - pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0)); - - if(willCheckCarry) { - if(!rFalseIfx.condition) { emitCLRC; emitSETC; } - else { emitSETC; emitCLRC; } - - } else { - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - } - -/* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80)); - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); -*/ - break; - } - } else { - /* unsigned comparisons to a literal byte */ - DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign); - - switch(lit & 0xff ) { - /* special cases */ - case 0: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - genSkipz2(&rFalseIfx,0); - break; - case 0x7f: - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,0,7); - break; - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0)); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - rFalseIfx.condition ^= 1; - if (AOP_TYPE(result) == AOP_CRY) - genSkipc(&rFalseIfx); - else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - } - break; - } - } - - if(ifx) ifx->generated = 1; - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; - return; - - } else { - - /* Size is greater than 1 */ - - if(sign) { - int lp1 = lit+1; - - size--; - - if(lp1 == 0) { - /* this means lit = 0xffffffff, or -1 */ - - - DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__); - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,size,7); - if(ifx) ifx->generated = 1; - return; - } - - if(lit == 0) { - int s = size; - - if(rFalseIfx.condition) { - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - } - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size--) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - - - emitSKPZ; - if(rFalseIfx.condition) { - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - pic16_emitpLabel(truelbl->key); - }else { - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,s,7); - } - - if(ifx) ifx->generated = 1; - return; - } - - if((size == 1) && (0 == (lp1&0xff))) { - /* lower byte of signed word is zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit); - i = ((lp1 >> 8) & 0xff) ^0x80; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i)); - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - - - if(ifx) ifx->generated = 1; - return; - } - - if(lit & (0x80 << (size*8))) { - /* Lit is less than zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit); - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,left,size,7); - //rFalseIfx.condition ^= 1; - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - - } else { - /* Lit is greater than or equal to zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit); - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,right,size,7); - //rFalseIfx.condition ^= 1; - - //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0)); - //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - - } - - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - - while(size--) { - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - } - rFalseIfx.condition ^= 1; - //rFalseIfx.condition = 1; - genSkipc(&rFalseIfx); - - pic16_emitpLabel(truelbl->key); - - if(ifx) ifx->generated = 1; - return; - // end of if (sign) - } else { - - /* compare word or long to an unsigned literal on the right.*/ - - - size--; - if(lit < 0xff) { - DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit); - switch (lit) { - case 0: - break; /* handled above */ -/* - case 0xff: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size--) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - genSkipz2(&rFalseIfx,0); - break; -*/ - default: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(--size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - - emitSKPZ; - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0)); - - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - } - - pic16_emitpLabel(truelbl->key); - - if(ifx) ifx->generated = 1; - return; - } - - - lit++; - DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit); - i = (lit >> (size*8)) & 0xff; - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - - while(size--) { - i = (lit >> (size*8)) & 0xff; - - if(i) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - } else { - /* this byte of the lit is zero, - * if it's not the last then OR in the variable */ - if(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - } - } - - - pic16_emitpLabel(lbl->key); - - rFalseIfx.condition ^= 1; - - genSkipc(&rFalseIfx); - } - - if(sign) - pic16_emitpLabel(truelbl->key); - if(ifx) ifx->generated = 1; - return; - } - } - /* Compare two variables */ - - DEBUGpic16_emitcode(";sign","%d",sign); - - size--; - if(sign) { - /* Sigh. thus sucks... */ - if(size) { - pCodeOp *pctemp; - - pctemp = pic16_popGetTempReg(1); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_popReleaseTempReg(pctemp, 1); - } else { - /* Signed char comparison */ - /* Special thanks to Nikolai Golovchenko for this snippet */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */ - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - genSkipc(&rFalseIfx); - - if(ifx) ifx->generated = 1; - return; - } - - } else { - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); - } - - - /* The rest of the bytes of a multi-byte compare */ - while (size) { - - emitSKPZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key)); - size--; - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); - - - } - - pic16_emitpLabel(lbl->key); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || - (AOP_TYPE(result) == AOP_REG)) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - } else { - genSkipc(&rFalseIfx); - } - //genSkipc(&rFalseIfx); - if(ifx) ifx->generated = 1; - - return; - - } - -check_carry: - if ((AOP_TYPE(result) != AOP_CRY) - && AOP_SIZE(result)) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key ); - - pic16_outBitC(result); - } else { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* if the result is used in the next - ifx conditional branch then generate - code a little differently */ - if (ifx ) - genIfxJump (ifx,"c"); - else - pic16_outBitC(result); - /* leave the result in acc */ - } - -} -#endif /* } */ - - -#endif /* } */ - - - -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void genCmpGt (iCode *ic, iCode *ifx) -{ - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - result = IC_RESULT(ic); - - letype = getSpec(operandType(left)); - retype =getSpec(operandType(right)); - sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); - /* assign the amsops */ - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (right,ic,FALSE); - pic16_aopOp (result,ic,TRUE); - - genCmp(right, left, result, ifx, sign); - - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genCmpLt - less than comparisons */ -/*-----------------------------------------------------------------*/ -static void genCmpLt (iCode *ic, iCode *ifx) -{ - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - result = IC_RESULT(ic); + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); letype = getSpec(operandType(left)); retype =getSpec(operandType(right)); @@ -6638,16 +6927,19 @@ static void genCmpEq (iCode *ic, iCode *ifx) int preserve_result = 0; int generate_result = 0; int i=0; + unsigned long lit = -1; + FENTRY; + pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); DEBUGpic16_pic16_AopType(__LINE__,left,right,result); if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) ) { + werror(W_POSSBUG2, __FILE__, __LINE__); DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__); fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__); goto release; @@ -6660,6 +6952,10 @@ static void genCmpEq (iCode *ic, iCode *ifx) left = tmp; } + if (AOP_TYPE(right) == AOP_LIT) { + lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit); + } + if ( regsInCommon(left, result) || regsInCommon(right, result) ) preserve_result = 1; @@ -6672,6 +6968,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); } + assert( AOP_SIZE(left) == AOP_SIZE(right) ); for(i=0; i < AOP_SIZE(left); i++) { if(AOP_TYPE(left) != AOP_ACC) @@ -6681,9 +6978,11 @@ static void genCmpEq (iCode *ic, iCode *ifx) else pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i)); } - if(is_LitOp(right)) - pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); - else + if(is_LitOp(right)) { + if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) { + pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); + } + } else pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key)); @@ -7062,8 +7361,9 @@ release: /*-----------------------------------------------------------------*/ static iCode *ifxForOp ( operand *op, iCode *ic ) { + FENTRY2; + /* if true symbol then needs to be assigned */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); if (IS_TRUE_SYMOP(op)) return NULL ; @@ -7079,12 +7379,14 @@ static iCode *ifxForOp ( operand *op, iCode *ic ) return ic->next; } + /* if (ic->next && ic->next->op == IFX && IC_COND(ic->next)->key == op->key) { DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__); return ic->next; } + */ DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__); if (ic->next && @@ -7137,16 +7439,17 @@ static iCode *ifxForOp ( operand *op, iCode *ic ) /*-----------------------------------------------------------------*/ static void genAndOp (iCode *ic) { - operand *left,*right, *result; + operand *left,*right, *result; /* symbol *tlbl; */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + /* note here that && operations that are in an if statement are taken away by backPatchLabels only those used in arthmetic operations remain */ pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,right,result); @@ -7185,16 +7488,17 @@ static void genAndOp (iCode *ic) static void genOrOp (iCode *ic) { - operand *left,*right, *result; - symbol *tlbl; + operand *left,*right, *result; + symbol *tlbl; + + FENTRY; - /* note here that || operations that are in an + /* note here that || operations that are in an if statement are taken away by backPatchLabels only those used in arthmetic operations remain */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,right,result); @@ -7252,10 +7556,10 @@ static int isLiteralBit(unsigned long lit) /*-----------------------------------------------------------------*/ static void continueIfTrue (iCode *ic) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(IC_TRUE(ic)) - pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); - ic->generated = 1; + FENTRY; + if(IC_TRUE(ic)) + pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); + ic->generated = 1; } /*-----------------------------------------------------------------*/ @@ -7263,10 +7567,10 @@ static void continueIfTrue (iCode *ic) /*-----------------------------------------------------------------*/ static void jumpIfTrue (iCode *ic) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(!IC_TRUE(ic)) - pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); - ic->generated = 1; + FENTRY; + if(!IC_TRUE(ic)) + pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); + ic->generated = 1; } /*-----------------------------------------------------------------*/ @@ -7274,20 +7578,19 @@ static void jumpIfTrue (iCode *ic) /*-----------------------------------------------------------------*/ static void jmpTrueOrFalse (iCode *ic, symbol *tlbl) { - // ugly but optimized by peephole - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(IC_TRUE(ic)){ - symbol *nlbl = newiTempLabel(NULL); - pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); - pic16_emitcode("","%05d_DS_:",nlbl->key+100); - } - else{ - pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - } - ic->generated = 1; + // ugly but optimized by peephole + FENTRY; + if(IC_TRUE(ic)){ + symbol *nlbl = newiTempLabel(NULL); + pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100); + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); + pic16_emitcode("","%05d_DS_:",nlbl->key+100); + } else { + pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + } + ic->generated = 1; } /*-----------------------------------------------------------------*/ @@ -7301,8 +7604,8 @@ static void genAnd (iCode *ic, iCode *ifx) int bytelit = 0; resolvedIfx rIfx; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); @@ -7418,7 +7721,7 @@ static void genAnd (iCode *ic, iCode *ifx) bp -= 8; ofs++; } - + pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS), pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER)); @@ -7490,9 +7793,9 @@ static void genAnd (iCode *ic, iCode *ifx) else { if(ifx) { pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key)); - pic16_emitpLabel(tlbl->key); ifx->generated = 1; } + pic16_emitpLabel(tlbl->key); goto release; } } @@ -7518,7 +7821,7 @@ static void genAnd (iCode *ic, iCode *ifx) default: { - int p = my_powof2( (~lit) & 0xff ); + int p = pic16_my_powof2( (~lit) & 0xff ); if(p>=0) { /* only one bit is set in the literal, so use a bcf instruction */ // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p); @@ -7634,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); @@ -7822,7 +8126,7 @@ static void genOr (iCode *ic, iCode *ifx) /* or'ing with 0 has no effect */ continue; else { - int p = my_powof2(lit & 0xff); + int p = pic16_my_powof2(lit & 0xff); if(p>=0) { /* only one bit is set in the literal, so use a bsf instruction */ pic16_emitpcode(POC_BSF, @@ -7838,13 +8142,13 @@ static void genOr (iCode *ic, iCode *ifx) } else { if (AOP_TYPE(left) == AOP_ACC) { pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset)); - pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); } else { pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset)); - pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE)); } } @@ -7885,21 +8189,21 @@ static void genOr (iCode *ic, iCode *ifx) pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("movf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); +// pic16_emitcode("movf","%s,w", +// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movwf","%s", +// pic16_aopGet(AOP(result),offset,FALSE,FALSE)); break; default: pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("movlw","0x%x",t); - pic16_emitcode("iorwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); +// pic16_emitcode("movlw","0x%x",t); +// pic16_emitcode("iorwf","%s,w", +// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movwf","%s", +// pic16_aopGet(AOP(result),offset,FALSE,FALSE)); } continue; @@ -7909,17 +8213,17 @@ static void genOr (iCode *ic, iCode *ifx) // and better if result is SFR if (AOP_TYPE(left) == AOP_ACC) { pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset)); - pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); } else { pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); - pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("iorwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,w", +// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); } pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); +// pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); } } @@ -7939,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); @@ -8183,8 +8488,69 @@ static void genInline (iCode *ic) buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1); strcpy(buffer,IC_INLINE(ic)); + + while((bp1=strstr(bp, "\\n"))) { + *bp1++ = '\n'; + *bp1++ = ' '; + bp = bp1; + } + bp = bp1 = buffer; -// fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer); +#if 0 + /* This is an experimental code for #pragma inline + and is temporarily disabled for 2.5.0 release */ + if(asmInlineMap) + { + symbol *sym; + char *s; + char *cbuf; + int cblen; + + cbuf = Safe_strdup(buffer); + cblen = strlen(buffer)+1; + memset(cbuf, 0, cblen); + + bp = buffer; + bp1 = cbuf; + while(*bp) { + if(*bp != '%')*bp1++ = *bp++; + else { + int i; + + bp++; + i = *bp - '0'; + if(i>elementsInSet(asmInlineMap))break; + + bp++; + s = indexSet(asmInlineMap, i); + DEBUGpc("searching symbol s = `%s'", s); + sym = findSym(SymbolTab, NULL, s); + + if(sym->reqv) { + strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name); + } else { + strcat(bp1, sym->rname); + } + + while(*bp1)bp1++; + } + + if(strlen(bp1) > cblen - 16) { + int i = strlen(cbuf); + cblen += 50; + cbuf = realloc(cbuf, cblen); + memset(cbuf+i, 0, 50); + bp1 = cbuf + i; + } + } + + free(buffer); + buffer = Safe_strdup( cbuf ); + free(cbuf); + + bp = bp1 = buffer; + } +#endif /* 0 */ /* emit each line as a code */ while (*bp) { @@ -8204,6 +8570,11 @@ static void genInline (iCode *ic) * to denote that the argument should not be indented with tab */ pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process bp1 = bp; + } if (*bp == ';') { + /* advance to end of line (prevent splitting of comments at ':' */ + while (*bp && *bp != '\n') { + bp++; + } // while } else bp++; } @@ -8232,7 +8603,7 @@ static void genRRC (iCode *ic) left = IC_LEFT(ic); result=IC_RESULT(ic); pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); @@ -8277,7 +8648,7 @@ static void genRLC (iCode *ic) left = IC_LEFT(ic); result=IC_RESULT(ic); pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); @@ -8384,7 +8755,7 @@ static void AccRol (int shCount) /*-----------------------------------------------------------------*/ /* AccLsh - left shift accumulator by known count */ /*-----------------------------------------------------------------*/ -static void AccLsh (int shCount) +static void AccLsh (int shCount, int doMask) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); switch(shCount){ @@ -8417,8 +8788,10 @@ static void AccLsh (int shCount) pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); break; } - - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount])); + if (doMask) { + /* no masking is required in genPackBits */ + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount])); + } } /*-----------------------------------------------------------------*/ @@ -8583,7 +8956,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, } else { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER)); } @@ -8598,7 +8971,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, } else { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr)); } default: @@ -8715,7 +9088,7 @@ static void shiftL1Left2Result (operand *left, int offl, // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE); // MOVA(l); /* shift left accumulator */ - //AccLsh(shCount); // don't comment out just yet... + //AccLsh(shCount, 1); // don't comment out just yet... // pic16_aopPut(AOP(result),"a",offr); switch(shCount) { @@ -8960,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; @@ -8977,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)); } @@ -9086,7 +9461,7 @@ static void shiftLLeftOrResult (operand *left, int offl, pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl)); /* shift left accumulator */ - AccLsh(shCount); + AccLsh(shCount, 1); /* or with result */ /* back to result */ pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr)); @@ -9299,19 +9674,20 @@ static void genlshFour (operand *result, operand *left, int shCount) /*-----------------------------------------------------------------*/ /* genLeftShiftLiteral - left shifting by known count */ /*-----------------------------------------------------------------*/ -static void genLeftShiftLiteral (operand *left, +void pic16_genLeftShiftLiteral (operand *left, operand *right, operand *result, iCode *ic) { - int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); + int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit)); int size; - DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount); + FENTRY; + DEBUGpic16_emitcode ("; ***","shCount:%d", shCount); pic16_freeAsmop(right,NULL,ic,TRUE); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); size = getSize(operandType(result)); @@ -9378,6 +9754,8 @@ static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian) } } + +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* genLeftShift - generates code for left shifting */ /*-----------------------------------------------------------------*/ @@ -9400,7 +9778,7 @@ static void genLeftShift (iCode *ic) /* if the shift count is known then do it as efficiently as possible */ if (AOP_TYPE(right) == AOP_LIT) { - genLeftShiftLiteral (left,right,result,ic); + pic16_genLeftShiftLiteral (left,right,result,ic); return ; } @@ -9435,7 +9813,7 @@ static void genLeftShift (iCode *ic) #endif { /* we don't know if left is a literal or a register, take care -- VR */ - mov2f(AOP(result), AOP(left), offset); + pic16_mov2f(AOP(result), AOP(left), offset); } offset++; } @@ -9467,7 +9845,7 @@ static void genLeftShift (iCode *ic) #if 1 /* this is already done, why change it? */ if (!pic16_sameRegs(AOP(left),AOP(result))) { - mov2f(AOP(result), AOP(left), 0); + pic16_mov2f(AOP(result), AOP(left), 0); } #endif @@ -9559,7 +9937,7 @@ static void genLeftShift (iCode *ic) pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } - +#endif #if 0 @@ -9586,7 +9964,7 @@ static void genLeftShift (iCode *ic) /* if the shift count is known then do it as efficiently as possible */ if (AOP_TYPE(right) == AOP_LIT) { - genLeftShiftLiteral (left,right,result,ic); + pic16_genLeftShiftLiteral (left,right,result,ic); return ; } @@ -9618,7 +9996,7 @@ static void genLeftShift (iCode *ic) } else { /* we don't know if left is a literal or a register, take care -- VR */ - mov2f(AOP(result), AOP(left), offset); + pic16_mov2f(AOP(result), AOP(left), offset); } offset++; } @@ -9647,7 +10025,7 @@ static void genLeftShift (iCode *ic) tlbl = newiTempLabel(NULL); if (!pic16_sameRegs(AOP(left),AOP(result))) { - mov2f(AOP(result), AOP(left), 0); + pic16_mov2f(AOP(result), AOP(left), 0); // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); @@ -9769,12 +10147,7 @@ static void genrshTwo (operand *result,operand *left, else movLeft2Result(left, MSB16, result, LSB); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16)); - - if(sign) { - pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16)); - } + pic16_addSign (result, 1, sign); } /* 1 <= shCount <= 7 */ @@ -9911,13 +10284,13 @@ static void genRightShiftLiteral (operand *left, iCode *ic, int sign) { - int shCount = (int) 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); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left)); @@ -9932,8 +10305,10 @@ static void genRightShiftLiteral (operand *left, /* I suppose that the left size >= result size */ if(shCount == 0){ - while(res_size--) - movLeft2Result(left, lsize, result, res_size); + assert (res_size <= lsize); + while (res_size--) { + pic16_mov2f (AOP(result), AOP(left), res_size); + } // for } else if(shCount >= (lsize * 8)){ @@ -9942,7 +10317,7 @@ static void genRightShiftLiteral (operand *left, pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB)); if(sign) { pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB)); } } else { @@ -9983,6 +10358,7 @@ static void genRightShiftLiteral (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* genSignedRightShift - right shift of signed number */ /*-----------------------------------------------------------------*/ @@ -10123,7 +10499,10 @@ static void genSignedRightShift (iCode *ic) pic16_freeAsmop(result,NULL,ic,TRUE); pic16_freeAsmop(right,NULL,ic,TRUE); } +#endif +#if !(USE_GENERIC_SIGNED_SHIFT) +#warning This implementation of genRightShift() is incomplete! /*-----------------------------------------------------------------*/ /* genRightShift - generate code for right shifting */ /*-----------------------------------------------------------------*/ @@ -10232,19 +10611,255 @@ static void genRightShift (iCode *ic) } reAdjustPreg(AOP(result)); - pic16_emitcode("","%05d_DS_:",tlbl1->key+100); - pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); + pic16_emitcode("","%05d_DS_:",tlbl1->key+100); + pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); + +release: + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop (right,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} +#endif + +#if (USE_GENERIC_SIGNED_SHIFT) +/*-----------------------------------------------------------------*/ +/* genGenericShift - generates code for left or right shifting */ +/*-----------------------------------------------------------------*/ +static void genGenericShift (iCode *ic, int isShiftLeft) { + operand *left,*right, *result; + int offset; + int sign, signedCount; + symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative; + PIC_OPCODE pos_shift, neg_shift; + + FENTRY; + + right = IC_RIGHT(ic); + left = IC_LEFT(ic); + result = IC_RESULT(ic); + + pic16_aopOp(right,ic,FALSE); + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,TRUE); + + sign = !SPEC_USIGN(operandType (left)); + signedCount = !SPEC_USIGN(operandType (right)); + + /* if the shift count is known then do it + as efficiently as possible */ + if (AOP_TYPE(right) == AOP_LIT) { + long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit); + if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; } + // we should modify right->aopu.aop_lit here! + // Instead we use abs(shCount) in genXXXShiftLiteral()... + // lit > 8*size is handled in pic16_genXXXShiftLiteral() + if (isShiftLeft) + pic16_genLeftShiftLiteral (left,right,result,ic); + else + genRightShiftLiteral (left,right,result,ic, sign); + + goto release; + } // if (right is literal) + + /* shift count is unknown then we have to form a loop. + * Note: we take only the lower order byte since shifting + * more than 32 bits make no sense anyway, ( the + * largest size of an object can be only 32 bits ) + * Note: we perform arithmetic shifts if the left operand is + * signed and we do an (effective) right shift, i. e. we + * shift in the sign bit from the left. */ + + label_complete = newiTempLabel ( NULL ); + label_loop_pos = newiTempLabel ( NULL ); + label_loop_neg = NULL; + label_negative = NULL; + pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF; + neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF; + + if (signedCount) { + // additional labels needed + label_loop_neg = newiTempLabel ( NULL ); + label_negative = newiTempLabel ( NULL ); + } // if + + // copy source to result -- this will effectively truncate the left operand to the size of result! + // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20) + // This is fine, as it only occurs for left shifting with negative count which is not standardized! + for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) { + pic16_mov2f (AOP(result),AOP(left), offset); + } // for + + // if result is longer than left, fill with zeros (or sign) + if (AOP_SIZE(left) < AOP_SIZE(result)) { + if (sign && AOP_SIZE(left) > 0) { + // shift signed operand -- fill with sign + pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg)); + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7)); + pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF)); + for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) { + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset)); + } // for + } else { + // shift unsigned operand -- fill result with zeros + for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset)); + } // for + } + } // if (size mismatch) + + pic16_mov2w (AOP(right), 0); + pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key)); + if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key)); + +#if 0 + // perform a shift by one (shift count is positive) + // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0: + // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3] ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11]) + pic16_emitpLabel (label_loop_pos->key); + emitCLRC; + if (sign && (pos_shift == POC_RRCF)) { + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7)); + emitSETC; + } // if + genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF); + pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg)); + pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key)); +#else + // perform a shift by one (shift count is positive) + // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0: + // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6] ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14]) + // This variant is slower for 0key); + if (sign && (pos_shift == POC_RRCF)) { + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7)); + emitSETC; + } // if + genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF); + //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this... + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01)); + pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key)); +#endif + + if (signedCount) { + pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key)); + + pic16_emitpLabel (label_negative->key); + // perform a shift by -1 (shift count is negative) + // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4 ({4,6}c+6 / {5,7}c+8 / {7,9}c+12) + emitCLRC; + pic16_emitpLabel (label_loop_neg->key); + if (sign && (neg_shift == POC_RRCF)) { + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7)); + emitSETC; + } // if + genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF); + //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this... + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01)); + pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key)); + } // if (signedCount) + + pic16_emitpLabel (label_complete->key); + +release: + pic16_freeAsmop (right,NULL,ic,TRUE); + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} + +static void genLeftShift (iCode *ic) { + genGenericShift (ic, 1); +} -release: - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop (right,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); +static void genRightShift (iCode *ic) { + genGenericShift (ic, 0); } +#endif -void pic16_loadFSR0(operand *op) +/* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */ +void pic16_loadFSR0(operand *op, int lit) +{ + 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 (!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))); + } +} + +/*----------------------------------------------------------------*/ +/* pic16_derefPtr - move one byte from the location ptr points to */ +/* to WREG (doWrite == 0) or one byte from WREG */ +/* to the location ptr points to (doWrite != 0) */ +/*----------------------------------------------------------------*/ +static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup) { - pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + if (!IS_PTR(operandType(ptr))) + { + if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0)); + else pic16_mov2w (AOP(ptr), 0); + return; + } + + //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr)))); + /* We might determine pointer type right here: */ + p_type = DCL_TYPE(operandType(ptr)); + + switch (p_type) { + case FPOINTER: + case POINTER: + if (!fsr0_setup || !*fsr0_setup) + { + pic16_loadFSR0( ptr, 0 ); + if (fsr0_setup) *fsr0_setup = 1; + } + if (doWrite) + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + else + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + break; + + case GPOINTER: + if (AOP(ptr)->aopu.aop_reg[2]) { + if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec)); + // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?) + mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1); + pic16_mov2w(AOP(ptr), 2); + pic16_callGenericPointerRW(doWrite, 1); + } else { + // data pointer (just 2 byte given) + if (!fsr0_setup || !*fsr0_setup) + { + pic16_loadFSR0( ptr, 0 ); + if (fsr0_setup) *fsr0_setup = 1; + } + if (doWrite) + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + else + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + } + break; + + default: + assert (0 && "invalid pointer type specified"); + break; + } } /*-----------------------------------------------------------------*/ @@ -10253,192 +10868,124 @@ void pic16_loadFSR0(operand *op) static void genUnpackBits (operand *result, operand *left, char *rname, int ptype) { int shCnt ; - int rlen = 0 ; sym_link *etype, *letype; int blen=0, bstr=0; int lbstr; - int offset = 0 ; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - etype = getSpec(operandType(result)); - letype = getSpec(operandType(left)); - -// if(IS_BITFIELD(etype)) { - blen = SPEC_BLEN(etype); - bstr = SPEC_BSTR(etype); -// } + int same; + pCodeOp *op; - lbstr = SPEC_BSTR( letype ); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + etype = getSpec(operandType(result)); + letype = getSpec(operandType(left)); -#if 1 - if((blen == 1) && (bstr < 8)) { - /* it is a single bit, so use the appropriate bit instructions */ - DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__); + // if(IS_BITFIELD(etype)) { + blen = SPEC_BLEN(etype); + bstr = SPEC_BSTR(etype); + // } - if(IS_BITFIELD(etype)/* && !IS_ITEMP(left)*/) { - pic16_emitpcode(POC_MOVFW, pic16_popGet( AOP(result), 0 )); - pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - } - - if((ptype == POINTER) && (result)) { - /* workaround to reduce the extra lfsr instruction */ - pic16_emitpcode(POC_BTFSC, - pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr)); - } else { - pic16_emitpcode(POC_BTFSC, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); - } - + lbstr = SPEC_BSTR( letype ); - if(IS_BITFIELD(etype)) { - pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); - } + DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__, + SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed"); - pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 )); - return; +#if 1 + if((blen == 1) && (bstr < 8) + && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) { + /* it is a single bit, so use the appropriate bit instructions */ + DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__); + + same = pic16_sameRegs(AOP(left),AOP(result)); + op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0)); + pic16_emitpcode(POC_CLRF, op); + + if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) { + /* workaround to reduce the extra lfsr instruction */ + pic16_emitpcode(POC_BTFSC, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr)); + } else { + assert (PIC_IS_DATA_PTR (operandType(left))); + pic16_loadFSR0 (left, 0); + pic16_emitpcode(POC_BTFSC, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); } -#endif - - /* the following call to pic16_loadFSR0 is temporary until - * optimization to handle single bit assignments is added - * to the function. Until then use the old safe way! -- VR */ - pic16_loadFSR0( left ); - - /* read the first byte */ - switch (ptype) { - case POINTER: - case IPOINTER: - case PPOINTER: - case FPOINTER: - case GPOINTER: - pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); - break; - case CPOINTER: - pic16_emitcode("clr","a"); - pic16_emitcode("movc","a","@a+dptr"); - break; - } - - - /* if we have bitdisplacement then it fits */ - /* into this byte completely or if length is */ - /* less than a byte */ - if ((shCnt = SPEC_BSTR(etype)) || - (SPEC_BLEN(etype) <= 8)) { + if (SPEC_USIGN(OP_SYM_ETYPE(left))) { + /* unsigned bitfields result in either 0 or 1 */ + pic16_emitpcode(POC_INCF, op); + } else { + /* signed bitfields result in either 0 or -1 */ + pic16_emitpcode(POC_DECF, op); + } + if (same) { + pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 )); + } - /* shift right acc */ - AccRsh(shCnt, 0); + pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result))); + return; + } - pic16_emitpcode(POC_ANDLW, pic16_popGetLit( - (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ])); +#endif -/* VR -- normally I would use the following, but since we use the hack, - * to avoid the masking from AccRsh, why not mask it right now? */ + if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) { + // access symbol directly + pic16_mov2w (AOP(left), 0); + } else { + pic16_derefPtr (left, ptype, 0, NULL); + } -/* - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype)))); -*/ + /* if we have bitdisplacement then it fits */ + /* into this byte completely or if length is */ + /* less than a byte */ + if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) { - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - return ; - } + /* shift right acc */ + AccRsh(shCnt, 0); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit( + (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ])); + /* VR -- normally I would use the following, but since we use the hack, + * to avoid the masking from AccRsh, why not mask it right now? */ - 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); + /* + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype)))); + */ - /* bit field did not fit in a byte */ - rlen = SPEC_BLEN(etype) - 8; - pic16_aopPut(AOP(result),"a",offset++); + /* extend signed bitfields to 8 bits */ + if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8)) + { + assert (blen + bstr > 0); + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen))); + } - while (1) { + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - switch (ptype) { - case POINTER: - case IPOINTER: - pic16_emitcode("inc","%s",rname); - pic16_emitcode("mov","a,@%s",rname); - break; - - case PPOINTER: - pic16_emitcode("inc","%s",rname); - pic16_emitcode("movx","a,@%s",rname); - break; + pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result))); + return ; + } - case FPOINTER: - pic16_emitcode("inc","dptr"); - pic16_emitcode("movx","a,@dptr"); - break; - - case CPOINTER: - pic16_emitcode("clr","a"); - pic16_emitcode("inc","dptr"); - pic16_emitcode("movc","a","@a+dptr"); - break; - - case GPOINTER: - pic16_emitcode("inc","dptr"); - pic16_emitcode("lcall","__gptrget"); - break; - } + 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(EXIT_FAILURE); - rlen -= 8; - /* if we are done */ - if ( rlen <= 0 ) - break ; - - pic16_aopPut(AOP(result),"a",offset++); - - } - - if (rlen) { - pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen)); - pic16_aopPut(AOP(result),"a",offset); - } - - return ; + return ; } -static void genDataPointerGet(operand *left, - operand *result, - iCode *ic) +static void genDataPointerGet(operand *left, operand *result, iCode *ic) { int size, offset = 0, leoffset=0 ; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(result, ic, FALSE); + pic16_aopOp(result, ic, TRUE); + + FENTRY; size = AOP_SIZE(result); // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size); -#if 0 - /* The following tests may save a redudant movff instruction when - * accessing unions */ - - /* if they are the same */ - if (operandsEqu (left, result)) { - DEBUGpic16_emitcode("; ***", "left and result operands are equ/same"); - goto release; - } -#endif - -#if 0 - /* if they are the same registers */ - if (pic16_sameRegs(AOP(left),AOP(result))) { - DEBUGpic16_emitcode("; ***", "left and result registers are same"); - goto release; - } -#endif - #if 1 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE), pic16_aopGet(AOP(left), 0, TRUE, FALSE))) { @@ -10447,17 +10994,6 @@ static void genDataPointerGet(operand *left, } #endif - -#if 0 - if ( AOP_TYPE(left) == AOP_PCODE) { - fprintf(stderr,"genDataPointerGet %s, %d\n", - AOP(left)->aopu.pcop->name, - (AOP(left)->aopu.pcop->type == PO_DIR)? - PCOR(AOP(left)->aopu.pcop)->instance: - PCOI(AOP(left)->aopu.pcop)->offset); - } -#endif - if(AOP(left)->aopu.pcop->type == PO_DIR) leoffset=PCOR(AOP(left)->aopu.pcop)->instance; @@ -10466,9 +11002,9 @@ static void genDataPointerGet(operand *left, while (size--) { DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset); - if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE - || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) { - mov2w(AOP(left), offset); // patch 8 +// pic16_DumpOp("(result)",result); + if(is_LitAOp(AOP(result))) { + pic16_mov2w(AOP(left), offset); // patch 8 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); } else { pic16_emitpcode(POC_MOVFF, pic16_popGet2p( @@ -10493,140 +11029,133 @@ static void genNearPointerGet (operand *left, operand *result, iCode *ic) { - asmop *aop = NULL; - //regs *preg = NULL ; - sym_link *rtype, *retype; - sym_link *ltype = operandType(left); +// asmop *aop = NULL; + //regs *preg = NULL ; + sym_link *rtype, *retype; + sym_link *ltype, *letype; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - rtype = operandType(result); - retype= getSpec(rtype); + FENTRY; - pic16_aopOp(left,ic,FALSE); - -// pic16_DumpOp("(left)",left); -// pic16_DumpOp("(result)",result); + rtype = operandType(result); + retype= getSpec(rtype); + ltype = operandType(left); + letype= getSpec(ltype); + + pic16_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_PCODE - && !IS_BITFIELD(retype) - && DCL_TYPE(ltype) == POINTER) { +// pic16_DumpOp("(left)",left); +// pic16_DumpOp("(result)",result); - genDataPointerGet (left,result,ic); - pic16_freeAsmop(left, NULL, ic, TRUE); - return ; - } + /* 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 */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if (AOP_TYPE(left) == AOP_PCODE + && !IS_BITFIELD(retype) + && DCL_TYPE(ltype) == POINTER) { - /* if the value is already in a pointer register - * then don't need anything more */ - if (!AOP_INPREG(AOP(left))) { - /* otherwise get a free pointer register */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - /* VR -- the whole concept is to load FSR0 with the address of the symbol */ - if( (AOP_TYPE(left) == AOP_PCODE) - && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE) - || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10 - { - if(!IS_BITFIELD(retype)) - pic16_loadFSR0( left ); // patch 10 - } else { - if(!IS_BITFIELD(retype)) { - // set up FSR0 with address from left - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10 - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10 - } - } - } -// else -// rname = pic16_aopGet(AOP(left),0,FALSE,FALSE); + genDataPointerGet (left,result,ic); + pic16_freeAsmop(left, NULL, ic, TRUE); + return ; + } - pic16_aopOp (result,ic,FALSE); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_aopOp (result,ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result); - /* if bitfield then unpack the bits */ - if (IS_BITFIELD(retype)) - genUnpackBits (result, left, NULL, POINTER); +#if 1 + if(IS_BITFIELD( retype ) + && (SPEC_BLEN(operandType(result))==1) + ) { + iCode *nextic; + pCodeOp *jop; + int bitstrt, bytestrt; + + /* if this is bitfield of size 1, see if we are checking the value + * of a single bit in an if-statement, + * if yes, then don't generate usual code, but execute the + * genIfx directly -- VR */ + + nextic = ic->next; + + /* CHECK: if next iCode is IFX + * and current result operand is nextic's conditional operand + * and current result operand live ranges ends at nextic's key number + */ + if((nextic->op == IFX) + && (result == IC_COND(nextic)) + && (OP_LIVETO(result) == nextic->seq) + && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)" + ) { + /* everything is ok then */ + /* find a way to optimize the genIfx iCode */ + + bytestrt = SPEC_BSTR(operandType(result))/8; + bitstrt = SPEC_BSTR(operandType(result))%8; + + jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt); + + genIfxpCOpJump(nextic, jop); + + pic16_freeAsmop(left, NULL, ic, TRUE); + pic16_freeAsmop(result, NULL, ic, TRUE); + return; + } + } +#endif + + /* if bitfield then unpack the bits */ + if (IS_BITFIELD(letype)) + genUnpackBits (result, left, NULL, POINTER); else { - /* we have can just get the values */ + /* we have can just get the values */ int size = AOP_SIZE(result); int offset = 0; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_loadFSR0( left, 0 ); - /* fsr0 is loaded already -- VR */ -// pic16_loadFSR0( left ); - -// pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0)); -// pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0)); while(size--) { - - if(size) { - pic16_emitpcode(POC_MOVFF, - pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), - pic16_popGet(AOP(result), offset++))); - } else { - pic16_emitpcode(POC_MOVFF, - pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), - pic16_popGet(AOP(result), offset++))); - } + if(size) { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), + pic16_popGet(AOP(result), offset++))); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), + pic16_popGet(AOP(result), offset++))); + } } -#if 0 -// pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0)); -// pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++)); - if(size) - pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0)); -#endif -/* - while (size--) { - if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) { - - pic16_emitcode("mov","a,@%s",rname); - pic16_aopPut(AOP(result),"a",offset); - } else { - sprintf(buffer,"@%s",rname); - pic16_aopPut(AOP(result),buffer,offset); - } - offset++ ; - if (size) - pic16_emitcode("inc","%s",rname); - } -*/ } +#if 0 /* now some housekeeping stuff */ if (aop) { - /* we had to allocate for this iCode */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_freeAsmop(NULL,aop,ic,TRUE); + /* we had to allocate for this iCode */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_freeAsmop(NULL,aop,ic,TRUE); } else { - /* we did not allocate which means left - already in a pointer register, then - if size > 0 && this could be used again - we have to point it back to where it - belongs */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (AOP_SIZE(result) > 1 && - !OP_SYMBOL(left)->remat && - ( OP_SYMBOL(left)->liveTo > ic->seq || - ic->depth )) { -// int size = AOP_SIZE(result) - 1; -// while (size--) -// pic16_emitcode("dec","%s",rname); + /* we did not allocate which means left + * already in a pointer register, then + * if size > 0 && this could be used again + * we have to point it back to where it + * belongs */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if (AOP_SIZE(result) > 1 + && !OP_SYMBOL(left)->remat + && ( OP_SYMBOL(left)->liveTo > ic->seq + || ic->depth )) { +// int size = AOP_SIZE(result) - 1; +// while (size--) +// pic16_emitcode("dec","%s",rname); } } +#endif /* done */ pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); - } /*-----------------------------------------------------------------*/ @@ -10662,7 +11191,7 @@ static void genPagedPointerGet (operand *left, rname = pic16_aopGet(AOP(left),0,FALSE,FALSE); pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); /* if bitfield then unpack the bits */ if (IS_BITFIELD(retype)) @@ -10710,6 +11239,10 @@ static void genPagedPointerGet (operand *left, } +#if 0 +/* This code is not adjusted to PIC16 and fails utterly. + * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */ + /*-----------------------------------------------------------------*/ /* genFarPointerGet - gget value from far space */ /*-----------------------------------------------------------------*/ @@ -10740,7 +11273,7 @@ static void genFarPointerGet (operand *left, } /* so dptr know contains the address */ pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); /* if bit then unpack */ if (IS_BITFIELD(retype)) @@ -10759,6 +11292,8 @@ static void genFarPointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif + #if 0 /*-----------------------------------------------------------------*/ /* genCodePointerGet - get value from code space */ @@ -10811,6 +11346,7 @@ static void genCodePointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } #endif + #if 0 /*-----------------------------------------------------------------*/ /* genGenPointerGet - gget value from generic pointer space */ @@ -10852,7 +11388,7 @@ static void genGenPointerGet (operand *left, // set up FSR0 with address from left pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); - + offset = 0 ; while(size--) { @@ -10885,15 +11421,20 @@ static void genGenPointerGet (operand *left, operand *result, iCode *ic) { int size, offset, lit; - sym_link *retype = getSpec(operandType(result)); - char fgptrget[32]; + sym_link *letype = getSpec(operandType(left)); DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); size = AOP_SIZE(result); DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); + + /* if bit then unpack */ + if (IS_BITFIELD(letype)) { + genUnpackBits(result,left,"BAD",GPOINTER); + goto release; + } if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!) @@ -10918,41 +11459,16 @@ static void genGenPointerGet (operand *left, } else { /* we need to get it byte by byte */ /* set up WREG:PRODL:FSR0L with address from left */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl))); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2)); - - switch( size ) { - case 1: strcpy(fgptrget, "__gptrget1"); break; - case 2: strcpy(fgptrget, "__gptrget2"); break; - case 3: strcpy(fgptrget, "__gptrget3"); break; - case 4: strcpy(fgptrget, "__gptrget4"); break; - default: - werror(W_POSSBUG2, __FILE__, __LINE__); - abort(); - } + mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1); + pic16_mov2w(AOP(left), 2); + pic16_callGenericPointerRW(0, size); - pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget )); + assignResultValue(result, size, 1); - assignResultValue(result, 1); - - { - symbol *sym; - - sym = newSymbol( fgptrget, 0 ); - strcpy(sym->rname, fgptrget); - checkAddSym(&externs, sym); - -// fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget); - } - goto release; } - /* if bit then unpack */ - if (IS_BITFIELD(retype)) - genUnpackBits(result,left,"BAD",GPOINTER); - release: pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); @@ -10979,29 +11495,11 @@ static void genConstPointerGet (operand *left, DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__); -#if 0 // patch 15 - pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key)); - pic16_emitpLabel(albl->key); - - poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW); - - /* this performs a goto to the specified address -- Why not to use pointer? -- VR */ - pic16_emitpcode(poc,pic16_popGet(AOP(left),1)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath)); - pic16_emitpcode(poc,pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl)); - - pic16_emitpLabel(blbl->key); - - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0)); -#endif // patch 15 - // set up table pointer if( (AOP_TYPE(left) == AOP_PCODE) && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE) - || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ...... + || (AOP(left)->aopu.pcop->type == PO_DIR))) { pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0)); pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); @@ -11009,25 +11507,20 @@ static void genConstPointerGet (operand *left, pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh)); pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2)); pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru)); - } - else - { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru))); - } - + } else { + mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1); + mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2); + } - while(size--) - { - pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset))); - offset++; - } + while(size--) { + pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset))); + offset++; + } pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); - } @@ -11036,12 +11529,12 @@ static void genConstPointerGet (operand *left, /*-----------------------------------------------------------------*/ static void genPointerGet (iCode *ic) { - operand *left, *result ; - sym_link *type, *etype; - int p_type; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + operand *left, *result ; + sym_link *type, *etype; + int p_type; + FENTRY; + left = IC_LEFT(ic); result = IC_RESULT(ic) ; @@ -11058,58 +11551,62 @@ static void genPointerGet (iCode *ic) DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__); /* 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)); - - DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__); - - if (SPEC_OCLS(etype)->codesp ) { - DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__); - //p_type = CPOINTER ; - } - else - if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) - DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__); - /*p_type = FPOINTER ;*/ - else - if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) - DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__); -/* p_type = PPOINTER; */ - else - if (SPEC_OCLS(etype) == idata ) - DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__); -/* p_type = IPOINTER; */ - else - DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__); -/* p_type = POINTER ; */ + 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)); + + DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__); + + if (SPEC_OCLS(etype)->codesp ) { + DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__); + //p_type = CPOINTER ; + } else + if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) { + DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__); + /*p_type = FPOINTER ;*/ + } else + if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) { + DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__); + /* p_type = PPOINTER; */ + } else + if (SPEC_OCLS(etype) == idata ) { + DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__); + /* p_type = IPOINTER; */ + } else { + DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__); + /* p_type = POINTER ; */ + } } /* now that we have the pointer type we assign the pointer values */ switch (p_type) { - - case POINTER: - case IPOINTER: + case POINTER: + case FPOINTER: + case IPOINTER: genNearPointerGet (left,result,ic); break; - case PPOINTER: + case PPOINTER: genPagedPointerGet(left,result,ic); break; - case FPOINTER: +#if 0 + /* PICs do not support FAR pointers... */ + /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */ + case FPOINTER: genFarPointerGet (left,result,ic); break; +#endif - case CPOINTER: + case CPOINTER: genConstPointerGet (left,result,ic); //pic16_emitcodePointerGet (left,result,ic); break; - case GPOINTER: + case GPOINTER: #if 0 if (IS_PTR_CONST(type)) genConstPointerGet (left,result,ic); @@ -11123,7 +11620,6 @@ static void genPointerGet (iCode *ic) "genPointerGet: illegal pointer type"); } - } /*-----------------------------------------------------------------*/ @@ -11137,207 +11633,248 @@ static void genPackBits (sym_link *etype , operand *result, int offset = 0 ; int rLen = 0 ; int blen, bstr ; + int shifted_and_masked = 0; + unsigned long lit = (unsigned long)-1; sym_link *retype; - char *l ; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - blen = SPEC_BLEN(etype); - bstr = SPEC_BSTR(etype); - - retype = getSpec(operandType(right)); - - if(AOP_TYPE(right) == AOP_LIT) { - if((blen == 1) && (bstr < 8)) { - unsigned long lit; - /* it is a single bit, so use the appropriate bit instructions */ - - DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__); - - lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); -// pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); - if((p_type == POINTER) && (result)) { - /* workaround to reduce the extra lfsr instruction */ - if(lit) { - pic16_emitpcode(POC_BSF, - pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); - } else { - pic16_emitpcode(POC_BCF, - pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); - } - } else { - - if(lit) { - pic16_emitpcode(POC_BSF, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); - } else { - pic16_emitpcode(POC_BCF, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); - } - } - - return; - } + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + blen = SPEC_BLEN(etype); + bstr = SPEC_BSTR(etype); - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0)); - offset++; - } else - if(IS_BITFIELD(retype) - && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR) - && (blen == 1)) { - int rblen, rbstr; + retype = getSpec(operandType(right)); - rblen = SPEC_BLEN( retype ); - rbstr = SPEC_BSTR( retype ); - + if(AOP_TYPE(right) == AOP_LIT) { + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + + if((blen == 1) && (bstr < 8)) { + /* it is a single bit, so use the appropriate bit instructions */ - if(IS_BITFIELD(etype)) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0)); - pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - } - - pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr)); - - if(IS_BITFIELD(etype)) { - pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); - } + DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0)); - - return; - } else - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); + if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) { + /* workaround to reduce the extra lfsr instruction */ + if(lit) { + pic16_emitpcode(POC_BSF, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); + } else { + pic16_emitpcode(POC_BCF, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); + } + } else { + if (PIC_IS_DATA_PTR(operandType(result))) { + pic16_loadFSR0(result, 0); + pic16_emitpcode(lit ? POC_BSF : POC_BCF, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); + } else { + /* get old value */ + pic16_derefPtr (result, p_type, 0, NULL); + pic16_emitpcode(lit ? POC_BSF : POC_BCF, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); + /* write back new value */ + pic16_derefPtr (result, p_type, 1, NULL); + } + } - /* if the bit lenth is less than or */ - /* it exactly fits a byte then */ - if((shCnt=SPEC_BSTR(etype)) - || SPEC_BLEN(etype) <= 8 ) { + return; + } + /* IORLW below is more efficient */ + //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr)); + lit = (lit & ((1UL << blen) - 1)) << bstr; + shifted_and_masked = 1; + offset++; + } else + if (IS_DIRECT(result) && !IS_PTR(operandType(result)) + && IS_BITFIELD(retype) + && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR) + && (blen == 1)) { + int rblen, rbstr; - /* shift left acc */ - AccLsh(shCnt); + rblen = SPEC_BLEN( retype ); + rbstr = SPEC_BSTR( retype ); - /* using PRODL as a temporary register here */ - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + if(IS_BITFIELD(etype)) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); + } else { + pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); + } - switch (p_type) { - case FPOINTER: - case POINTER: - pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); -// pic16_emitcode ("mov","b,a"); -// pic16_emitcode("mov","a,@%s",rname); - break; + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr)); - case GPOINTER: - werror(W_POSSBUG2, __FILE__, __LINE__); - break; + if(IS_BITFIELD(etype)) { + pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); + } else { + pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); + } - } -#if 1 - pic16_emitpcode(POC_ANDLW, pic16_popGetLit( - (unsigned char)((unsigned char)(0xff << (blen+bstr)) | - (unsigned char)(0xff >> (8-bstr))) )); - pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); -#endif + pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0)); - return; - } + return; + } else { + /* move right to W */ + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); + } + /* if the bit length is less than or */ + /* it exactly fits a byte then */ + if((shCnt=SPEC_BSTR(etype)) + || SPEC_BLEN(etype) <= 8 ) { + int fsr0_setup = 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); + if (blen != 8 || (bstr % 8) != 0) { + // we need to combine the value with the old value + if(!shifted_and_masked) + { + pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1)); + DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt, + SPEC_BSTR(etype), SPEC_BLEN(etype)); - /* if we r done */ - if ( SPEC_BLEN(etype) <= 8 ) - return ; + /* shift left acc, do NOT mask the result again */ + AccLsh(shCnt, 0); - pic16_emitcode("inc","%s",rname); - rLen = SPEC_BLEN(etype) ; + /* using PRODH as a temporary register here */ + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh)); + } + if ((IS_SYMOP(result) && !IS_PTR(operandType (result))) + || IS_DIRECT(result)) { + /* access symbol directly */ + pic16_mov2w (AOP(result), 0); + } else { + /* get old value */ + pic16_derefPtr (result, p_type, 0, &fsr0_setup); + } +#if 1 + pic16_emitpcode(POC_ANDLW, pic16_popGetLit( + (unsigned char)((unsigned char)(0xff << (blen+bstr)) | + (unsigned char)(0xff >> (8-bstr))) )); + if (!shifted_and_masked) { + pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh)); + } else { + /* We have the shifted and masked (literal) right value in `lit' */ + if (lit != 0) + pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit)); + } + } 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))) + || IS_DIRECT(result)) { + pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0)); + } else { + pic16_derefPtr (result, p_type, 1, &fsr0_setup); + } +#endif - /* now generate for lengths greater than one byte */ - while (1) { + return; + } - l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE); - rLen -= 8 ; - if (rLen <= 0 ) - break ; +#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(EXIT_FAILURE); +#endif - switch (p_type) { - case POINTER: - if (*l == '@') { - MOVA(l); - pic16_emitcode("mov","@%s,a",rname); - } else - pic16_emitcode("mov","@%s,%s",rname,l); - break; - case FPOINTER: - MOVA(l); - pic16_emitcode("movx","@dptr,a"); - break; + pic16_loadFSR0(result, 0); // load FSR0 with address of result + rLen = SPEC_BLEN(etype)-8; - case GPOINTER: - MOVA(l); - DEBUGpic16_emitcode(";lcall","__gptrput"); - break; - } - pic16_emitcode ("inc","%s",rname); + /* now generate for lengths greater than one byte */ + while (1) { + rLen -= 8 ; + if (rLen <= 0 ) { + mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset); + break ; } - MOVA(l); + switch (p_type) { + case POINTER: + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0)); + break; - /* last last was not complete */ - if (rLen) { - /* save the byte & read byte */ - switch (p_type) { - case POINTER: - pic16_emitcode ("mov","b,a"); - pic16_emitcode("mov","a,@%s",rname); - break; + /* + case FPOINTER: + MOVA(l); + pic16_emitcode("movx","@dptr,a"); + break; + + case GPOINTER: + MOVA(l); + DEBUGpic16_emitcode(";lcall","__gptrput"); + break; + */ + default: + assert(0); + } - case FPOINTER: - pic16_emitcode ("mov","b,a"); - pic16_emitcode("movx","a,@dptr"); - break; - case GPOINTER: - pic16_emitcode ("push","b"); - pic16_emitcode ("push","acc"); - pic16_emitcode ("lcall","__gptrget"); - pic16_emitcode ("pop","b"); - break; - } + pic16_mov2w(AOP(right), offset++); + } + + /* last last was not complete */ + if (rLen) { + /* save the byte & read byte */ + switch (p_type) { + case POINTER: + // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + break; - pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) ); - pic16_emitcode ("orl","a,b"); + /* + case FPOINTER: + pic16_emitcode ("mov","b,a"); + pic16_emitcode("movx","a,@dptr"); + break; + + case GPOINTER: + pic16_emitcode ("push","b"); + pic16_emitcode ("push","acc"); + pic16_emitcode ("lcall","__gptrget"); + pic16_emitcode ("pop","b"); + break; + */ + default: + assert(0); } + DEBUGpic16_emitcode(";", "rLen = %i", rLen); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen)); + pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh)); + // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) ); + // pic16_emitcode ("orl","a,b"); + } - if (p_type == GPOINTER) - pic16_emitcode("pop","b"); + // if (p_type == GPOINTER) + // pic16_emitcode("pop","b"); - switch (p_type) { + switch (p_type) { case POINTER: - pic16_emitcode("mov","@%s,a",rname); - break; - - case FPOINTER: - pic16_emitcode("movx","@dptr,a"); - break; - - case GPOINTER: - DEBUGpic16_emitcode(";lcall","__gptrput"); - break; - } + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + // pic16_emitcode("mov","@%s,a",rname); + break; + /* + case FPOINTER: + pic16_emitcode("movx","@dptr,a"); + break; + + case GPOINTER: + DEBUGpic16_emitcode(";lcall","__gptrput"); + break; + */ + default: + assert(0); + } + + // pic16_freeAsmop(right, NULL, ic, TRUE); } + /*-----------------------------------------------------------------*/ /* genDataPointerSet - remat pointer to data space */ /*-----------------------------------------------------------------*/ @@ -11345,7 +11882,7 @@ static void genDataPointerSet(operand *right, operand *result, iCode *ic) { - int size, offset = 0, resoffset=0 ; + int size, offset = 0, resoffset=0 ; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); pic16_aopOp(right,ic,FALSE); @@ -11364,40 +11901,20 @@ static void genDataPointerSet(operand *right, } #endif - if(AOP(result)->aopu.pcop->type == PO_DIR) - resoffset=PCOR(AOP(result)->aopu.pcop)->instance; - - 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; - } + if(AOP(result)->aopu.pcop->type == PO_DIR) + resoffset=PCOR(AOP(result)->aopu.pcop)->instance; - lit = lit >> (8*offset); - if(lit&0xff) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8 - } else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8 - } - } else { - mov2w(AOP(right), offset); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8 - } - offset++; - resoffset++; - } + while (size--) { + if (AOP_TYPE(right) == AOP_LIT) { + 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); } @@ -11412,135 +11929,100 @@ static void genNearPointerSet (operand *right, iCode *ic) { asmop *aop = NULL; - char *l; sym_link *retype; sym_link *ptype = operandType(result); sym_link *resetype; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - retype= getSpec(operandType(right)); - resetype = getSpec(operandType(result)); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + retype= getSpec(operandType(right)); + resetype = getSpec(operandType(result)); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,FALSE); - /* if the result is rematerializable & - * in data space & not a bit variable */ + /* if the result is rematerializable & + * in data space & not a bit variable */ - /* and result is not a bit variable */ - if (AOP_TYPE(result) == AOP_PCODE -// && AOP_TYPE(result) == AOP_IMMD - && DCL_TYPE(ptype) == POINTER - && !IS_BITFIELD(retype) - && !IS_BITFIELD(resetype)) { - - genDataPointerSet (right,result,ic); - pic16_freeAsmop(result,NULL,ic,TRUE); - return; - } - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(right,ic,FALSE); - DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - - /* if the value is already in a pointer register - * then don't need anything more */ - if (!AOP_INPREG(AOP(result))) { - /* otherwise get a free pointer register */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - -// if( (AOP_TYPE(result) == AOP_PCODE) -// && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE) -// || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10 - if(is_LitAOp( AOP(result) )) - { - if(!IS_BITFIELD(resetype)) - pic16_loadFSR0( result ); // patch 10 - } else { - if(!IS_BITFIELD(resetype)) { - // set up FSR0 with address of result - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10 - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10 - } - } - - } -// else -// rname = pic16_aopGet(AOP(result),0,FALSE,FALSE); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - -// pic16_loadFSR0( result ); + /* and result is not a bit variable */ + if (AOP_TYPE(result) == AOP_PCODE +// && AOP_TYPE(result) == AOP_IMMD + && DCL_TYPE(ptype) == POINTER + && !IS_BITFIELD(retype) + && !IS_BITFIELD(resetype)) { + + genDataPointerSet (right,result,ic); + pic16_freeAsmop(result,NULL,ic,TRUE); + return; + } - /* if bitfield then unpack the bits */ - if (IS_BITFIELD(resetype)) { - genPackBits (resetype, result, right, NULL, POINTER); - } else { - /* we have can just get the values */ - int size = AOP_SIZE(right); - int offset = 0 ; + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_aopOp(right,ic,FALSE); + DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - while (size--) { - l = pic16_aopGet(AOP(right),offset,FALSE,TRUE); - if (*l == '@' ) { - //MOVA(l); - //pic16_emitcode("mov","@%s,a",rname); - pic16_emitcode("movf","indf0,w ;1"); - } else { + /* if bitfield then unpack the bits */ + if (IS_BITFIELD(resetype)) { + genPackBits (resetype, result, right, NULL, POINTER); + } else { + /* we have can just get the values */ + int size = AOP_SIZE(right); + int offset = 0 ; - if (AOP_TYPE(right) == AOP_LIT) { // patch 10 - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); // - if (size) { // - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); // - } else { // - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); // - } // - } else { // no literal // - if(size) { // - pic16_emitpcode(POC_MOVFF, // - pic16_popGet2p(pic16_popGet(AOP(right),offset), // - pic16_popCopyReg(&pic16_pc_postinc0))); // - } else { // - pic16_emitpcode(POC_MOVFF, // - pic16_popGet2p(pic16_popGet(AOP(right),offset), // - pic16_popCopyReg(&pic16_pc_indf0))); // - } // - } // patch 10 - } - offset++; - } - } + pic16_loadFSR0(result, 0); + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + while (size--) { + if (AOP_TYPE(right) == AOP_LIT) { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); + if (size) { + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); + } else { + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); + } + } else { // no literal + if(size) { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popGet(AOP(right),offset), + pic16_popCopyReg(&pic16_pc_postinc0))); + } else { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popGet(AOP(right),offset), + pic16_popCopyReg(&pic16_pc_indf0))); + } + } + + offset++; + } + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* now some housekeeping stuff */ - if (aop) { - /* we had to allocate for this iCode */ - pic16_freeAsmop(NULL,aop,ic,TRUE); - } else { - /* we did not allocate which means left - * already in a pointer register, then - * if size > 0 && this could be used again - * we have to point it back to where it - * belongs */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (AOP_SIZE(right) > 1 - && !OP_SYMBOL(result)->remat - && ( OP_SYMBOL(result)->liveTo > ic->seq - || ic->depth )) { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + pic16_freeAsmop(NULL,aop,ic,TRUE); + } else { + /* we did not allocate which means left + * already in a pointer register, then + * if size > 0 && this could be used again + * we have to point it back to where it + * belongs */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if (AOP_SIZE(right) > 1 + && !OP_SYMBOL(result)->remat + && ( OP_SYMBOL(result)->liveTo > ic->seq + || ic->depth )) { - int size = AOP_SIZE(right) - 1; + int size = AOP_SIZE(right) - 1; - while (size--) - pic16_emitcode("decf","fsr0,f"); - //pic16_emitcode("dec","%s",rname); - } - } + while (size--) + pic16_emitcode("decf","fsr0,f"); + //pic16_emitcode("dec","%s",rname); + } + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* done */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* done */ //release: - pic16_freeAsmop(right,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); + pic16_freeAsmop(right,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); } /*-----------------------------------------------------------------*/ @@ -11624,6 +12106,10 @@ static void genPagedPointerSet (operand *right, } +#if 0 +/* This code is not adjusted to PIC16 and fails utterly... + * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */ + /*-----------------------------------------------------------------*/ /* genFarPointerSet - set value from far space */ /*-----------------------------------------------------------------*/ @@ -11673,6 +12159,7 @@ static void genFarPointerSet (operand *right, pic16_freeAsmop(right,NULL,ic,TRUE); } +#endif /*-----------------------------------------------------------------*/ /* genGenPointerSet - set value from generic pointer space */ @@ -11805,8 +12292,7 @@ static void genGenPointerSet (operand *right, operand *result, iCode *ic) { int size; - sym_link *retype = getSpec(operandType(right)); - char fgptrput[32]; + sym_link *retype = getSpec(operandType(result)); DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -11829,11 +12315,10 @@ static void genGenPointerSet (operand *right, DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size); - /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */ /* value of right+0 is placed on stack, which will be retrieved - * by the support function this restoring the stack. The important + * by the support function thus restoring the stack. The important * thing is that there is no need to manually restore stack pointer * here */ pushaop(AOP(right), 0); @@ -11849,27 +12334,7 @@ static void genGenPointerSet (operand *right, pic16_popCopyReg(&pic16_pc_prodl))); pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2)); - - /* put code here */ - switch (size) { - case 1: strcpy(fgptrput, "__gptrput1"); break; - case 2: strcpy(fgptrput, "__gptrput2"); break; - case 3: strcpy(fgptrput, "__gptrput3"); break; - case 4: strcpy(fgptrput, "__gptrput4"); break; - default: - werror(W_POSSBUG2, __FILE__, __LINE__); - abort(); - } - - pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput )); - - { - symbol *sym; - - sym = newSymbol( fgptrput, 0 ); - strcpy(sym->rname, fgptrput); - checkAddSym(&externs, sym); - } + pic16_callGenericPointerRW(1, size); release: pic16_freeAsmop(right,NULL,ic,TRUE); @@ -11881,11 +12346,11 @@ release: /*-----------------------------------------------------------------*/ static void genPointerSet (iCode *ic) { - operand *right, *result ; - sym_link *type, *etype; - int p_type; + operand *right, *result ; + sym_link *type, *etype; + int p_type; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; right = IC_RIGHT(ic); result = IC_RESULT(ic) ; @@ -11894,6 +12359,7 @@ static void genPointerSet (iCode *ic) 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); @@ -11921,27 +12387,30 @@ static void genPointerSet (iCode *ic) /* now that we have the pointer type we assign the pointer values */ switch (p_type) { - - case POINTER: - case IPOINTER: - genNearPointerSet (right,result,ic); - break; - - case PPOINTER: - genPagedPointerSet (right,result,ic); - break; - - case FPOINTER: - genFarPointerSet (right,result,ic); + case POINTER: + case FPOINTER: + case IPOINTER: + genNearPointerSet (right,result,ic); + break; + + case PPOINTER: + genPagedPointerSet (right,result,ic); break; - case GPOINTER: - genGenPointerSet (right,result,ic); - break; +#if 0 + /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */ + case FPOINTER: + genFarPointerSet (right,result,ic); + break; +#endif + + case GPOINTER: + genGenPointerSet (right,result,ic); + break; - default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "genPointerSet: illegal pointer type"); + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "genPointerSet: illegal pointer type"); } } @@ -11953,36 +12422,34 @@ static void genIfx (iCode *ic, iCode *popIc) operand *cond = IC_COND(ic); int isbit =0; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; - pic16_aopOp(cond,ic,FALSE); + pic16_aopOp(cond,ic,FALSE); - /* get the value into acc */ - if (AOP_TYPE(cond) != AOP_CRY) - pic16_toBoolean(cond); - else - isbit = 1; - /* the result is now in the accumulator */ - pic16_freeAsmop(cond,NULL,ic,TRUE); - - /* if there was something to be popped then do it */ - if (popIc) - genIpop(popIc); - - /* if the condition is a bit variable */ - if (isbit && IS_ITEMP(cond) && - SPIL_LOC(cond)) { - genIfxJump(ic,SPIL_LOC(cond)->rname); - DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname); - } - else { - if (isbit && !IS_ITEMP(cond)) - genIfxJump(ic,OP_SYMBOL(cond)->rname); + /* get the value into acc */ + if (AOP_TYPE(cond) != AOP_CRY) + pic16_toBoolean(cond); else - genIfxJump(ic,"a"); - } - ic->generated = 1; - + isbit = 1; + /* the result is now in the accumulator */ + pic16_freeAsmop(cond,NULL,ic,TRUE); + + /* if there was something to be popped then do it */ + if (popIc) + genIpop(popIc); + + /* if the condition is a bit variable */ + if (isbit && IS_ITEMP(cond) && + SPIL_LOC(cond)) { + genIfxJump(ic,"c"); + DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname); + } else { + if (isbit && !IS_ITEMP(cond)) + genIfxJump(ic,OP_SYMBOL(cond)->rname); + else + genIfxJump(ic,"a"); + } + ic->generated = 1; } /*-----------------------------------------------------------------*/ @@ -11995,7 +12462,7 @@ static void genAddrOf (iCode *ic) symbol *sym; // = OP_SYMBOL(IC_LEFT(ic)); pCodeOp *pcop0, *pcop1, *pcop2; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); @@ -12005,21 +12472,29 @@ static void genAddrOf (iCode *ic) /* get address of symbol on stack */ DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name); #if 0 - fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__, - OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack); + fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__, + OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack); #endif - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_fsr2l), - pic16_popGet(AOP(result), 0))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_fsr2h), - pic16_popGet(AOP(result), 1))); - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0)); - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1)); + // operands on stack are accessible via "FSR2 + index" with index + // starting at 2 for arguments and growing from 0 downwards for + // local variables (index == 0 is not assigned so we add one here) + { + int soffs = OP_SYMBOL( IC_LEFT(ic))->stack; + + if (soffs <= 0) { + assert (soffs < 0); + soffs++; + } // if + + DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs); + pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF )); + pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo)); + pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF )); + pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi)); + pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1)); + } goto release; } @@ -12032,10 +12507,6 @@ static void genAddrOf (iCode *ic) pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE); size = AOP_SIZE(IC_RESULT(ic)); - - /* Assume that what we want the address of is in data space - * since there is no stack on the PIC, yet! -- VR */ - pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); @@ -12099,220 +12570,271 @@ static void genFarFarAssign (operand *result, operand *right, iCode *ic) static void genAssign (iCode *ic) { operand *result, *right; + sym_link *restype, *rtype; int size, offset,know_W; unsigned long lit = 0L; - result = IC_RESULT(ic); - right = IC_RIGHT(ic) ; + result = IC_RESULT(ic); + right = IC_RIGHT(ic) ; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; - /* if they are the same */ - if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) - return ; + /* if they are the same */ + if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) + return ; - /* reversed order operands are aopOp'ed so that result operand - * is effective in case right is a stack symbol. This maneauver - * allows to use the _G.resDirect flag later */ - pic16_aopOp(result,ic,TRUE); - pic16_aopOp(right,ic,FALSE); + /* reversed order operands are aopOp'ed so that result operand + * is effective in case right is a stack symbol. This maneauver + * allows to use the _G.resDirect flag later */ + pic16_aopOp(result,ic,TRUE); + pic16_aopOp(right,ic,FALSE); - DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); + DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - /* if they are the same registers */ - if (pic16_sameRegs(AOP(right),AOP(result))) - goto release; + /* if they are the same registers */ + if (pic16_sameRegs(AOP(right),AOP(result))) + goto release; - /* if the result is a bit */ - if (AOP_TYPE(result) == AOP_CRY) { - /* if the right size is a literal then - we know what the value is */ - if (AOP_TYPE(right) == AOP_LIT) { + /* if the result is a bit */ + if (AOP_TYPE(result) == AOP_CRY) { + /* if the right size is a literal then + we know what the value is */ + if (AOP_TYPE(right) == AOP_LIT) { - pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF), - pic16_popGet(AOP(result),0)); + pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF), + pic16_popGet(AOP(result),0)); - if (((int) operandLitValue(right))) - pic16_emitcode("bsf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - else - pic16_emitcode("bcf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - goto release; - } + if (((int) operandLitValue(right))) + pic16_emitcode("bsf","(%s >> 3),(%s & 7)", + AOP(result)->aopu.aop_dir, + AOP(result)->aopu.aop_dir); + else + pic16_emitcode("bcf","(%s >> 3),(%s & 7)", + AOP(result)->aopu.aop_dir, + AOP(result)->aopu.aop_dir); + + goto release; + } - /* the right is also a bit variable */ - if (AOP_TYPE(right) == AOP_CRY) { + /* the right is also a bit variable */ + if (AOP_TYPE(right) == AOP_CRY) { + pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); + + goto release ; + } + + /* we need to or */ pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_toBoolean(right); + emitSKPZ; pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - - pic16_emitcode("bcf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - pic16_emitcode("btfsc","(%s >> 3),(%s & 7)", - AOP(right)->aopu.aop_dir, - AOP(right)->aopu.aop_dir); - pic16_emitcode("bsf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); + //pic16_aopPut(AOP(result),"a",0); goto release ; } - /* we need to or */ - pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_toBoolean(right); - emitSKPZ; - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - //pic16_aopPut(AOP(result),"a",0); - goto release ; - } + /* bit variables done */ + /* general case */ + size = AOP_SIZE(result); + offset = 0 ; /* bit variables done */ /* general case */ size = AOP_SIZE(result); + restype = operandType(result); + rtype = operandType(right); offset = 0 ; if(AOP_TYPE(right) == AOP_LIT) { - if(!IS_FLOAT(operandType( right ))) - lit = (unsigned long)floatFromVal(AOP(right)->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(right)->aopu.aop_lit); - lit = info.lit_int; + if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right)))) + { + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + + /* patch tag for literals that are cast to pointers */ + if (IS_CODEPTR(restype)) { + //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16); + } else { + if (IS_GENPTR(restype)) + { + if (IS_CODEPTR(rtype)) { + //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16); + } else if (PIC_IS_DATA_PTR(rtype)) { + //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16); + } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) { + //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16)); + } else if (IS_PTR(rtype)) { + fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16); + } } + } + } else { + union { + unsigned long lit_int; + float lit_float; + } info; + + + if(IS_FIXED16X16(operandType(right))) { + lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit)); + } else { + /* take care if literal is a float */ + info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit); + lit = info.lit_int; + } + } } // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit, // sizeof(unsigned long int), sizeof(float)); - if(AOP_TYPE(right) != AOP_LIT - && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype)) - && !IS_FUNC(OP_SYM_TYPE(right)) - ) { - DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__); -// fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name); - - // set up table pointer - if( (AOP_TYPE(right) == AOP_PCODE) - && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE) -// || (AOP(right)->aopu.pcop->type == PO_DIR) - ) - ) - { -// fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__); - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh)); - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru)); - } else { -// fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0), - pic16_popCopyReg(&pic16_pc_tblptrl))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1), - pic16_popCopyReg(&pic16_pc_tblptrh))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2), - pic16_popCopyReg(&pic16_pc_tblptru))); - } - size = min(AOP_SIZE(right), AOP_SIZE(result)); - while(size--) { - pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), - pic16_popGet(AOP(result),offset))); - offset++; - } + if (AOP_TYPE(right) == AOP_REG) { + DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__); + while (size--) { + pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++)); + } // while + goto release; + } - if(AOP_SIZE(result) > AOP_SIZE(right)) { - size = AOP_SIZE(result) - AOP_SIZE(right); - while(size--) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset)); - offset++; - } - } - goto release; - } + /* when do we have to read the program memory? + * - if right itself is a symbol in code space + * (we don't care what it points to if it's a pointer) + * - AND right is not a function (we would want its address) + */ + if(AOP_TYPE(right) != AOP_LIT + && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right))) + && !IS_FUNC(OP_SYM_TYPE(right)) + && !IS_ITEMP(right)) { + DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name); + + // set up table pointer + if(is_LitOp(right)) { +// fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1)); + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh)); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2)); + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru)); + } else { +// fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0), + pic16_popCopyReg(&pic16_pc_tblptrl))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1), + pic16_popCopyReg(&pic16_pc_tblptrh))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2), + pic16_popCopyReg(&pic16_pc_tblptru))); + } + /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */ + size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result)); + while(size--) { + pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), + pic16_popGet(AOP(result),offset))); + offset++; + } -#if 0 -/* VR - What is this?! */ - if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(aopIdx(AOP(result),0) == 4) { + /* FIXME: for pointers we need to extend differently (according + * to pointer type DATA/CODE/EEPROM/... :*/ + size = getSize(OP_SYM_TYPE(right)); + if(AOP_SIZE(result) > size) { + size = AOP_SIZE(result) - size; + while(size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset)); + offset++; + } + } + goto release; + } - /* this is a workaround to save value of right into wreg too, - * value of wreg is going to be used later */ +#if 0 + /* VR - What is this?! */ + if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - goto release; - } else + + if(aopIdx(AOP(result),0) == 4) { + /* this is a workaround to save value of right into wreg too, + * value of wreg is going to be used later */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + goto release; + } else // assert(0); DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__); - } + } #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_BTFSS, 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 */ - 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++; } - - offset++; - } + pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right))); - release: +release: pic16_freeAsmop (right,NULL,ic,FALSE); pic16_freeAsmop (result,NULL,ic,TRUE); -} +} /*-----------------------------------------------------------------*/ /* genJumpTab - generates code for jump table */ /*-----------------------------------------------------------------*/ static void genJumpTab (iCode *ic) { - symbol *jtab; - char *l; - pCodeOp *jt_offs; - pCodeOp *jt_offs_hi; - pCodeOp *jt_label; + symbol *jtab; + char *l; + pCodeOp *jt_offs; + pCodeOp *jt_offs_hi; + pCodeOp *jt_label; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp(IC_JTCOND(ic),ic,FALSE); /* get the condition into accumulator */ @@ -12374,10 +12896,12 @@ static void genJumpTab (iCode *ic) pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl)); pic16_emitpLabelFORCE(jtab->key); - #endif + pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE); +// pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); + pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, "")); /* now generate the jump labels */ for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab; jtab = setNextItem(IC_JTLABELS(ic))) { @@ -12385,6 +12909,7 @@ static void genJumpTab (iCode *ic) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key)); } + pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, "")); } @@ -12531,15 +13056,15 @@ static void genCast (iCode *ic) operand *right = IC_RIGHT(ic); int size, offset ; - DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* if they are equivalent then do nothing */ // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic))) // return ; - pic16_aopOp(right,ic,FALSE) ; pic16_aopOp(result,ic,FALSE); + pic16_aopOp(right,ic,FALSE) ; DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); @@ -12611,6 +13136,74 @@ static void genCast (iCode *ic) && IS_BITFIELD(getSpec(rtype))) { DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__); } + + /* port from pic14 to cope with generic pointers */ + if (PIC_IS_TAGGED(restype)) + { + operand *result = IC_RESULT(ic); + //operand *left = IC_LEFT(ic); + operand *right = IC_RIGHT(ic); + int tag = 0xff; + + /* copy common part */ + int max, size = AOP_SIZE(result); + if (size > AOP_SIZE(right)) size = AOP_SIZE(right); + DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); + + max = size; + while (size--) + { + pic16_mov2w (AOP(right), size); + pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size)); + } // while + + /* upcast into generic pointer type? */ + if (IS_GENPTR(restype) + && !PIC_IS_TAGGED(rtype) + && (AOP_SIZE(result) > max)) + { + /* determine appropriate tag for right */ + if (PIC_IS_DATA_PTR(rtype)) + tag = GPTR_TAG_DATA; + else if (IS_CODEPTR(rtype)) + tag = GPTR_TAG_CODE; + else if (PIC_IS_DATA_PTR(ctype)) { + //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno); + tag = GPTR_TAG_DATA; + } else if (IS_CODEPTR(ctype)) { + //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno); + tag = GPTR_TAG_CODE; + } else if (IS_PTR(rtype)) { + PERFORM_ONCE(weirdcast, + fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno); + ); + tag = GPTR_TAG_DATA; + } else { + PERFORM_ONCE(weirdcast, + fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno); + ); + tag = GPTR_TAG_DATA; + } + + assert (AOP_SIZE(result) == 3); + /* zero-extend address... */ + for (size = max; size < AOP_SIZE(result)-1; size++) + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size)); + /* ...and add tag */ + pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag); + } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) { + //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno); + for (size = max; size < AOP_SIZE(result)-1; size++) + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size)); + /* add __code tag */ + pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE); + } else if (AOP_SIZE(result) > max) { + /* extend non-pointers */ + //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno); + pic16_addSign(result, max, 0); + } // if + goto release; + } /* if they are the same size : or less */ if (AOP_SIZE(result) <= AOP_SIZE(right)) { @@ -12669,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); @@ -12726,7 +13322,7 @@ static void genCast (iCode *ic) while (size--) { if(offset < AOP_SIZE(right)) { DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type); - mov2f(AOP(result), AOP(right), offset); + pic16_mov2f(AOP(result), AOP(right), offset); /* if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) { @@ -12747,26 +13343,26 @@ static void genCast (iCode *ic) switch (p_type) { case IPOINTER: case POINTER: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1)); -// pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1)); + case FPOINTER: + pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA); break; case CPOINTER: pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); break; - case FPOINTER: - pic16_emitcode(";BUG!? ","%d",__LINE__); - l = one; - break; case PPOINTER: pic16_emitcode(";BUG!? ","%d",__LINE__); l = "#0x03"; break; case GPOINTER: - pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); + if (GPTRSIZE > AOP_SIZE(right)) { + // assume __data pointer... THIS MIGHT BE WRONG! + pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); + } break; default: @@ -12779,6 +13375,8 @@ static void genCast (iCode *ic) goto release ; } + + assert( 0 ); /* just copy the pointers */ size = AOP_SIZE(result); offset = 0 ; @@ -12806,8 +13404,10 @@ static void genCast (iCode *ic) /* we move to result for the size of source */ size = AOP_SIZE(right); offset = 0 ; + while (size--) { - mov2f(AOP(result), AOP(right), offset); + if(!_G.resDirect) + pic16_mov2f(AOP(result), AOP(right), offset); offset++; } @@ -12824,7 +13424,7 @@ static void genCast (iCode *ic) /* Save one instruction of casting char to int */ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset)); } else { pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg)); @@ -12908,7 +13508,8 @@ static int genDjnz (iCode *ic, iCode *ifx) /*-----------------------------------------------------------------*/ static void genReceive (iCode *ic) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + FENTRY; #if 0 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__, @@ -12941,11 +13542,17 @@ static void genReceive (iCode *ic) } } else { DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) )); - _G.accInUse++; pic16_aopOp(IC_RESULT(ic),ic,FALSE); _G.accInUse--; - assignResultValue(IC_RESULT(ic), 0); + + /* set pseudo stack pointer to where it should be - dw*/ + GpsuedoStkPtr = ic->parmBytes; + + /* setting GpsuedoStkPtr has side effects here: */ + /* 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); @@ -12957,10 +13564,26 @@ static void genReceive (iCode *ic) static void genDummyRead (iCode * ic) { - pic16_emitcode ("; genDummyRead",""); - pic16_emitcode ("; not implemented",""); + operand *op; + int i; - ic = ic; + op = IC_RIGHT(ic); + if (op && IS_SYMOP(op)) { + if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) { + fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__); + return; + } + pic16_aopOp (op, ic, FALSE); + for (i=0; i < AOP_SIZE(op); i++) { + // may need to protect this from the peepholer -- this is not nice but works... + pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN")); + pic16_mov2w (AOP(op),i); + pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END")); + } // for i + pic16_freeAsmop (op, NULL, ic, TRUE); + } else if (op) { + fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__); + } // if } /*-----------------------------------------------------------------*/ @@ -12977,8 +13600,8 @@ genDummyRead (iCode * ic) void genpic16Code (iCode *lic) { - iCode *ic; - int cln = 0; + iCode *ic; + int cln = 0; lineHead = lineCurr = NULL; @@ -12989,244 +13612,242 @@ void genpic16Code (iCode *lic) /* if debug information required */ if (options.debug && currFunc) { if (currFunc) { - cdbSymbol(currFunc,cdbFile,FALSE,TRUE); + cdbSymbol(currFunc,cdbFile,FALSE,TRUE); } } #endif for (ic = lic ; ic ; ic = ic->next ) { - DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op); - if ( cln != ic->lineno ) { - if ( options.debug ) { - debugFile->writeCLine (ic); - } - - if(!options.noCcodeInAsm) { - pic16_addpCode2pBlock(pb, - pic16_newpCodeCSource(ic->lineno, ic->filename, - printCLine(ic->filename, ic->lineno))); - } + DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op)); + if ( cln != ic->lineno ) { + if ( options.debug ) { + debugFile->writeCLine (ic); + } + + if(!options.noCcodeInAsm) { + pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, + printCLine(ic->filename, ic->lineno))); + } - cln = ic->lineno ; - } - - if(options.iCodeInAsm) { - char *l; - /* insert here code to print iCode as comment */ - l = Safe_strdup(printILine(ic)); - pic16_emitpcomment("ic:%d: %s", ic->seq, l); - } + cln = ic->lineno ; + } - /* 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 ; + if(options.iCodeInAsm) { + char *iLine; + + /* insert here code to print iCode as comment */ + iLine = printILine(ic); + pic16_emitpcomment("ic:%d: %s", ic->seq, iLine); + 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 ; - /* depending on the operation */ - switch (ic->op) { - case '!' : - pic16_genNot(ic); - break; - - case '~' : - pic16_genCpl(ic); - break; - - case UNARYMINUS: - genUminus (ic); - break; - - case IPUSH: - genIpush (ic); - break; + /* depending on the operation */ + switch (ic->op) { + case '!' : + pic16_genNot(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 destroy 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 '~' : + pic16_genCpl(ic); + break; - case CALL: - genCall (ic); - break; + case UNARYMINUS: + genUminus (ic); + break; - case PCALL: - genPcall (ic); - break; + case IPUSH: + genIpush (ic); + break; - case FUNCTION: - genFunction (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 destroy 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 ENDFUNCTION: - genEndFunction (ic); - break; + case CALL: + genCall (ic); + break; - case RETURN: - genRet (ic); - break; + case PCALL: + genPcall (ic); + break; - case LABEL: - genLabel (ic); - break; + case FUNCTION: + genFunction (ic); + break; - case GOTO: - genGoto (ic); - break; + case ENDFUNCTION: + genEndFunction (ic); + break; - case '+' : - pic16_genPlus (ic) ; - break; + case RETURN: + genRet (ic); + break; - case '-' : - if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic))) - pic16_genMinus (ic); - break; + case LABEL: + genLabel (ic); + break; - case '*' : - genMult (ic); - break; + case GOTO: + genGoto (ic); + break; - case '/' : - genDiv (ic) ; - break; + case '+' : + pic16_genPlus (ic) ; + break; - case '%' : - genMod (ic); - break; + case '-' : + if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic))) + pic16_genMinus (ic); + break; + + case '*' : + genMult (ic); + break; - case '>' : - genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic)); - break; + case '/' : + genDiv (ic) ; + break; - case '<' : - genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic)); - break; + case '%' : + genMod (ic); + break; - case LE_OP: - case GE_OP: - case NE_OP: + case '>' : + genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic)); + break; - /* 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 '<' : + genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic)); + break; - case EQ_OP: - genCmpEq (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 AND_OP: + genAndOp (ic); + break; - case OR_OP: - genOrOp (ic); - break; + case OR_OP: + genOrOp (ic); + break; - case '^' : - genXor (ic,ifxForOp(IC_RESULT(ic),ic)); - break; + case '^' : + genXor (ic,ifxForOp(IC_RESULT(ic),ic)); + break; - case '|' : - genOr (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 BITWISEAND: + genAnd (ic,ifxForOp(IC_RESULT(ic),ic)); + break; - case INLINEASM: - genInline (ic); - break; + case INLINEASM: + genInline (ic); + break; - case RRC: - genRRC (ic); - break; + case RRC: + genRRC (ic); + break; - case RLC: - genRLC (ic); - break; + case RLC: + genRLC (ic); + break; - case GETHBIT: - genGetHbit (ic); - break; + case GETHBIT: + genGetHbit (ic); + break; - case LEFT_OP: - genLeftShift (ic); - break; + case LEFT_OP: + genLeftShift (ic); + break; - case RIGHT_OP: - genRightShift (ic); - break; + case RIGHT_OP: + genRightShift (ic); + break; - case GET_VALUE_AT_ADDRESS: - genPointerGet(ic); - break; + case GET_VALUE_AT_ADDRESS: + genPointerGet(ic); + break; - case '=' : - if (POINTER_SET(ic)) - genPointerSet(ic); - else - genAssign(ic); - break; + case '=' : + if (POINTER_SET(ic)) + genPointerSet(ic); + else + genAssign(ic); + break; - case IFX: - genIfx (ic,NULL); - break; + case IFX: + genIfx (ic,NULL); + break; - case ADDRESS_OF: - genAddrOf (ic); - break; + case ADDRESS_OF: + genAddrOf (ic); + break; - case JUMPTABLE: - genJumpTab (ic); - break; + case JUMPTABLE: + genJumpTab (ic); + break; - case CAST: - genCast (ic); - break; + case CAST: + genCast (ic); + break; - case RECEIVE: - genReceive(ic); - break; + case RECEIVE: + genReceive(ic); + break; - case SEND: - addSet(&_G.sendSet,ic); - /* create a reversed list of SEND iCodes */ -// addSetHead(&_G.sendSet, ic); - break; + case SEND: + addSet(&_G.sendSet,ic); + break; - case DUMMY_READ_VOLATILE: - genDummyRead (ic); - break; + case DUMMY_READ_VOLATILE: + genDummyRead (ic); + break; - default : - ic = ic; - } + default : + ic = ic; + } } /* now we are ready to call the peep hole optimizer */ - if (!options.nopeep) { + if (!options.nopeep) peepHole (&lineHead); - } + /* now do the actual printing */ - printLine (lineHead, codeOutFile); + printLine (lineHead, codeOutBuf); #ifdef PCODE_DEBUG DFPRINTF((stderr,"printing pBlock\n\n"));