X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=9ca5da162e096bafd4aa27b0db89616edd9d4ece;hb=195ee3f3ee25ce2c5f2a59fbd2779c4cb80527c3;hp=6fbc8173c28fdb599560df018ba1767f3485bedf;hpb=f0914f906af64baca70034066af8fa475ef2c47f;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index 6fbc8173..9ca5da16 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) + - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005) + Bug Fixes - Raphael Neider rneider@web.de (2004,2005) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -47,6 +48,17 @@ #include "device.h" #include "main.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 + 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 *); @@ -57,17 +69,23 @@ 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 int aopIdx (asmop *aop, int offset); +static void mov2fp(pCodeOp *dst, asmop *src, int offset); +static pCodeOp *pic16_popRegFromIdx(int rIdx); -static int labelOffset=0; +//static int aopIdx (asmop *aop, int offset); + +int pic16_labelOffset=0; extern int pic16_debug_verbose; +#if !(USE_GENERIC_SIGNED_SHIFT) static int optimized_for_speed = 0; +#endif /* hack hack */ +extern set *externs; + /* max_key keeps track of the largest label number used in a function. This is then used to adjust the label offset for the next function. @@ -76,6 +94,7 @@ static int max_key=0; 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 ); @@ -89,6 +108,11 @@ static bool is_LitAOp(asmop *aop); #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff) +/* set the following macro to 1 to enable passing the + * first byte of functions parameters via WREG */ +#define USE_WREG_IN_FUNC_PARAMS 0 + + /* this is the down and dirty file with all kinds of kludgy & hacky stuff. This is what it is all about CODE GENERATION for a specific MCU . some of the @@ -96,7 +120,7 @@ static bool is_LitAOp(asmop *aop); static char *zero = "#0x00"; static char *one = "#0x01"; -static char *spname = "sp"; +//static char *spname = "sp"; /* @@ -110,8 +134,8 @@ static char *spname = "sp"; */ -char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" }; -//char *fReturn390[] = {"dpl","dph","dpx", "b","a" }; +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; @@ -122,28 +146,27 @@ static char *accUse[] = {"WREG"}; static struct { short r0Pushed; short r1Pushed; + short fsr0Pushed; short accInUse; short inLine; short debugLine; short nRegsSaved; + short ipushRegs; set *sendSet; - int interruptvector; + set *stackRegSet; + int usefastretfie; + 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; -static void saverbank (int, iCode *,bool); +//static void saverbank (int, iCode *,bool); static lineNode *lineHead = NULL; static lineNode *lineCurr = NULL; @@ -164,7 +187,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) { @@ -211,7 +234,7 @@ void pic16_emitpcomment (char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = lb; va_start(ap,fmt); @@ -237,7 +260,7 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = lb; if(!pic16_debug_verbose) return; @@ -268,27 +291,37 @@ 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+labelOffset)); + pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset)); } void pic16_emitpLabelFORCE(int key) { - pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+labelOffset)); + 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) pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop)); else DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__); - -// fprintf(stderr, "%s\n", pcop->name); } +void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop) +{ + if(pcop) + pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop)); + else + DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__); +} + void pic16_emitpcodeNULLop(PIC_OPCODE poc) { @@ -307,7 +340,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); @@ -357,11 +390,67 @@ pic16_emitDebuggerSymbol (char * debugSym) /*-----------------------------------------------------------------*/ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) { - bool r0iu = FALSE , r1iu = FALSE; - bool r0ou = FALSE , r1ou = FALSE; +// bool r0iu = FALSE , r1iu = FALSE; +// bool r0ou = FALSE , r1ou = FALSE; + 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); + + + fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2); + fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0); + + fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2); + fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0); + + if(bitVectBitValue(ic->rUsed, IDX_WREG)) { + fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__); + DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__); + } + + if(!fsr0iu && !fsr0ou) { + ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0); + (*aopp)->type = AOP_FSR0; + + fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__); + + return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0)); + } + +#if 0 + /* no usage of FSR2 */ + if(!fsr2iu && !fsr2ou) { + ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2); + (*aopp)->type = AOP_FSR2; + + return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2); + } +#endif + + /* now we know they both have usage */ + /* if fsr0 not used in this instruction */ + if (!fsr0iu) { + if (!_G.fsr0Pushed) { + pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) ); + pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) ); + _G.fsr0Pushed++; + } + + ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0); + (*aopp)->type = AOP_FSR0; + +// fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__); + + return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0); + } + - //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op); + fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__); + assert( 0 ); + return NULL; +#if 0 /* the logic: if r0 & r1 used in the instruction then we are in trouble otherwise */ @@ -379,7 +468,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) /* if no usage of r0 then return it */ if (!r0iu && !r0ou) { ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX); - (*aopp)->type = AOP_R0; + (*aopp)->type = AOP_R0; return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX); } @@ -435,6 +524,7 @@ endOfWorld : werror(E_INTERNAL_ERROR,__FILE__,__LINE__, "getFreePtr should never reach here"); exit(0); +#endif } /*-----------------------------------------------------------------*/ @@ -469,8 +559,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; @@ -497,13 +588,17 @@ static void resolveIfx(resolvedIfx *resIfx, iCode *ifx) #if 1 if(IC_TRUE(ifx)) - DEBUGpic16_emitcode("; ***","ifx true is non-null"); + DEBUGpic16_emitcode("; +++","ifx true is non-null"); + else + DEBUGpic16_emitcode("; +++","ifx true is null"); if(IC_FALSE(ifx)) - DEBUGpic16_emitcode("; ***","ifx false is non-null"); + DEBUGpic16_emitcode("; +++","ifx false is non-null"); + else + DEBUGpic16_emitcode("; +++","ifx false is null"); #endif } - DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset); + DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset); } #if 0 @@ -527,8 +622,10 @@ 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); /* if already has one */ @@ -537,28 +634,117 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) return sym->aop; } +#if 0 /* if symbol was initially placed onStack then we must re-place it * to direct memory, since pic16 does not have a specific stack */ if(sym->onStack) { - sym->onStack = 0; - SPEC_OCLS( sym->etype ) = data; - space = data; + fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name); } - +#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 && !options.stack10bit) || sym->iaccess) { - + if (sym->onStack) // || sym->iaccess) + { + pCodeOp *pcop[4]; + int i; + DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d", __FUNCTION__, __LINE__, sym->onStack, sym->iaccess); - sym->aop = aop = newAsmop(0); - aop->aopu.aop_ptr = getFreePtr(ic,&aop,result); + /* acquire a temporary register -- it is saved in function */ + + sym->aop = aop = newAsmop(AOP_STA); + aop->aopu.stk.stk = sym->stack; aop->size = getSize(sym->type); + + 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 { + for(i=0;isize;i++) { + aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 ); + _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx); + } + } + + +// 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) ); + } + + for(i=0;isize;i++) { + + /* initialise for stack access via frame pointer */ + // 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 = 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) ); + } + + return (aop); +#endif + +#if 0 /* now assign the address of the variable to the pointer register */ if (aop->type != AOP_STK) { @@ -585,9 +771,12 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } else aop->aopu.aop_stk = sym->stack; return aop; +#endif + } #endif +#if 0 if (sym->onStack && options.stack10bit) { /* It's on the 10 bit stack, which is located in @@ -618,6 +807,23 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) aop->size = getSize(sym->type); return aop; } +#endif + +#if 1 + /* special case for a function */ + if (IS_FUNC(sym->type)) { + sym->aop = aop = newAsmop(AOP_PCODE); + //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1); + aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0); + PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space); + PCOI(aop->aopu.pcop)->index = 0; + aop->size = FPTRSIZE; + DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname); + return aop; + } +#endif + + //DEBUGpic16_emitcode(";","%d",__LINE__); /* if in bit space */ @@ -638,22 +844,18 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) return aop; } -#if 0 // patch 14 - /* special case for a function */ - if (IS_FUNC(sym->type)) { - sym->aop = aop = newAsmop(AOP_IMMD); - //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1); - aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1); - strcpy(aop->aopu.aop_immd,sym->rname); - aop->size = FPTRSIZE; - DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname); + + if (IN_FARSPACE(space) && !IN_CODESPACE(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; } -#endif // patch 14 /* only remaining is far space */ - /* in which case DPTR gets the address */ sym->aop = aop = newAsmop(AOP_PCODE); /* change the next if to 1 to revert to good old immediate code */ @@ -677,11 +879,17 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) if(IN_DIRSPACE( space )) aop->size = PTRSIZE; - else if(IN_CODESPACE( space )) + 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 { + 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 ); } @@ -700,17 +908,17 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) static asmop *aopForRemat (operand *op) // x symbol *sym) { symbol *sym = OP_SYMBOL(op); + operand *refop; iCode *ic = NULL, *oldic; asmop *aop = newAsmop(AOP_PCODE); int val = 0; 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__); } @@ -731,14 +939,15 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) } offset = OP_SYMBOL(IC_LEFT(ic))->offset; + refop = IC_LEFT(ic); if(!op->isaddr)viaimmd++; else viaimmd=0; /* set the following if to 1 to revert to good old immediate code */ - if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))) + if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop))) || viaimmd) { - DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__); + DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type )); aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val); @@ -749,12 +958,15 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) #endif PCOI(aop->aopu.pcop)->index = val; + + aop->size = getSize( sym->type ); } else { - DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__); + DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type)); aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op); -// aop->size = AOP_SIZE( IC_LEFT(ic) ); + + aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type ); } @@ -776,6 +988,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) return aop; } +#if 0 static int aopIdx (asmop *aop, int offset) { if(!aop) @@ -787,6 +1000,8 @@ static int aopIdx (asmop *aop, int offset) return aop->aopu.aop_reg[offset]->rIdx; } +#endif + /*-----------------------------------------------------------------*/ /* regsInCommon - two operands have some registers in common */ /*-----------------------------------------------------------------*/ @@ -846,7 +1061,8 @@ static bool operandsEqu ( operand *op1, operand *op2) if (sym1 == sym2) return TRUE ; - if (strcmp(sym1->rname,sym2->rname) == 0) + if (sym1->rname[0] && sym2->rname[0] + && strcmp (sym1->rname, sym2->rname) == 0) return TRUE; @@ -877,21 +1093,45 @@ bool pic16_sameRegs (asmop *aop1, asmop *aop2 ) if (aop1 == aop2) return TRUE ; + DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__, + pic16_AopType(aop1->type), pic16_AopType(aop2->type)); + + if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE; + if (aop1->type != AOP_REG || 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++ ) - if (aop1->aopu.aop_reg[i] != - aop2->aopu.aop_reg[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) + if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name )) return FALSE ; + } return TRUE ; } +bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset) +{ + DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__, + pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset); + + if(aop1 == aop2)return TRUE; + if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE; + + if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE; + + return TRUE; +} + + /*-----------------------------------------------------------------*/ /* pic16_aopOp - allocates an asmop for an operand : */ /*-----------------------------------------------------------------*/ @@ -904,7 +1144,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) if (!op) return ; -// DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__); + DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__); /* if this a literal */ if (IS_OP_LITERAL(op)) { @@ -952,7 +1192,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) sym = OP_SYMBOL(op); - DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name); + DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType); /* if the type is a conditional */ if (sym->regType == REG_CND) { aop = op->aop = sym->aop = newAsmop(AOP_CRY); @@ -965,14 +1205,14 @@ 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); - aop->size = getSize(sym->type); - //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd); + sym->aop = op->aop = aop = aopForRemat (op); +// aop->size = getSize(sym->type); +// DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd); return; } @@ -992,7 +1232,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); @@ -1002,10 +1242,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; @@ -1016,16 +1256,26 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) /* force a new aop if sizes differ */ sym->usl.spillLoc->aop = NULL; } + +#if 0 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d", __FUNCTION__,__LINE__, sym->usl.spillLoc->rname, 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); + if (sym->usl.spillLoc && sym->usl.spillLoc->rname) { + aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, + getSize(sym->type), + sym->usl.spillLoc->offset, op); + } else { + fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__); + pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__); + assert (getSize(sym->type) <= 1); + aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg); + } aop->size = getSize(sym->type); return; @@ -1071,8 +1321,24 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) /* depending on the asmop type only three cases need work AOP_RO , AOP_R1 && AOP_STK */ -#if 0 +#if 1 switch (aop->type) { + case AOP_FSR0 : + if (_G.fsr0Pushed ) { + if (pop) { + pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) ); + pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) ); +// pic16_emitcode ("pop","ar0"); + _G.fsr0Pushed--; + } + } + bitVectUnSetBit(ic->rUsed,IDX_FSR0); + break; + + case AOP_FSR2 : + bitVectUnSetBit(ic->rUsed,IDX_FSR2); + break; + case AOP_R0 : if (_G.r0Pushed ) { if (pop) { @@ -1093,6 +1359,44 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) bitVectUnSetBit(ic->rUsed,R1_IDX); break; + case AOP_STA: + { + int i; + + /* 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(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++) { + 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); + } + + } + _G.resDirect = 0; + } + break; +#if 0 case AOP_STK : { int sz = aop->size; @@ -1137,6 +1441,8 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) _G.r1Pushed--; } } +#endif + } #endif @@ -1170,65 +1476,39 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) /* depending on type */ switch (aop->type) { - - case AOP_R0: - case AOP_R1: - DEBUGpic16_emitcode(";","%d",__LINE__); - /* if we need to increment it */ - while (offset > aop->coff) { - pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name); - aop->coff++; - } - - while (offset < aop->coff) { - pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name); - aop->coff--; - } - - aop->coff = offset ; - if (aop->paged) { - pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name); - return (dname ? "acc" : "a"); - } - sprintf(s,"@%s",aop->aopu.aop_ptr->name); - rs = Safe_calloc(1,strlen(s)+1); - strcpy(rs,s); - return rs; - - case AOP_DPTR: - case AOP_DPTR2: - DEBUGpic16_emitcode(";","%d",__LINE__); - if (aop->type == AOP_DPTR2) - { - genSetDPTR(1); - } - - while (offset > aop->coff) { - pic16_emitcode ("inc","dptr"); - aop->coff++; - } - - while (offset < aop->coff) { - pic16_emitcode("lcall","__decdptr"); - aop->coff--; - } - - aop->coff = offset; - if (aop->code) { - pic16_emitcode("clr","a"); - pic16_emitcode("movc","a,@a+dptr"); + + case AOP_FSR0: + case AOP_FSR2: + sprintf(s, "%s", aop->aopu.aop_ptr->name); + rs = Safe_calloc(1, strlen(s)+1); + strcpy(rs, s); + return (rs); + +#if 0 + /* if we need to increment it */ + while (offset > aop->coff) + { + emitcode ("inc", "%s", aop->aopu.aop_ptr->name); + aop->coff++; } - else { - pic16_emitcode("movx","a,@dptr"); - } - - if (aop->type == AOP_DPTR2) - { - genSetDPTR(0); - } - - return (dname ? "acc" : "a"); - + + while (offset < aop->coff) + { + emitcode ("dec", "%s", aop->aopu.aop_ptr->name); + aop->coff--; + } + aop->coff = offset; + if (aop->paged) + { + emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name); + return (dname ? "acc" : "a"); + } + sprintf (s, "@%s", aop->aopu.aop_ptr->name); + rs = Safe_calloc (1, strlen (s) + 1); + strcpy (rs, s); + return rs; +#endif + case AOP_IMMD: if (bit16) @@ -1269,22 +1549,29 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) return aop->aopu.aop_dir; case AOP_ACC: - DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__); + DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset); // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__); // assert( 0 ); - return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug"; +// return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug"; + rs = Safe_strdup("WREG"); + return (rs); case AOP_LIT: - sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset)); + sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset)); rs = Safe_calloc(1,strlen(s)+1); strcpy(rs,s); return rs; 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]; @@ -1296,7 +1583,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); @@ -1305,53 +1596,180 @@ 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); + + case AOP_STK: +// pCodeOp *pcop = aop->aop + break; + } + fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type)); werror(E_INTERNAL_ERROR,__FILE__,__LINE__, "aopget got unsupported aop->type"); exit(0); } + +/* lock has the following meaning: When allocating temporary registers + * for stack variables storage, the value of the temporary register is + * saved on stack. Its value is restored at the end. This procedure is + * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is + * a possibility that before a call to pic16_aopOp, a temporary register + * is allocated for a while and it is freed after some time, this will + * mess the stack and values will not be restored properly. So use lock=1 + * to allocate temporary registers used internally by the programmer, and + * lock=0 to allocate registers for stack use. lock=1 will emit a warning + * to inform the compiler developer about a possible bug. This is an internal + * feature for developing the compiler -- VR */ + +int _TempReg_lock = 0; /*-----------------------------------------------------------------*/ /* pic16_popGetTempReg - create a new temporary pCodeOp */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetTempReg(void) +pCodeOp *pic16_popGetTempReg(int lock) { pCodeOp *pcop; symbol *cfunc; -// DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - cfunc = currFunc; - currFunc = NULL; +// DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if(_TempReg_lock) { +// werror(W_POSSBUG2, __FILE__, __LINE__); + } + + _TempReg_lock += 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; + 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; - /* push value on stack */ - pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); - } + /* push value on stack */ + pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + } - currFunc = cfunc; + currFunc = cfunc; return pcop; } /*-----------------------------------------------------------------*/ -/* pic16_popGetTempReg - create a new temporary pCodeOp */ +/* pic16_popGetTempRegCond - create a new temporary pCodeOp which */ +/* is not part of f, but don't save if */ +/* inside v */ /*-----------------------------------------------------------------*/ -void pic16_popReleaseTempReg(pCodeOp *pcop) +pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { - PCOR(pcop)->r->isFree = 1; - - pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) ); - } + pCodeOp *pcop=NULL; + symbol *cfunc; + int i; + +// DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + if(_TempReg_lock) { +// werror(W_POSSBUG2, __FILE__, __LINE__); + } + + _TempReg_lock += lock; + + cfunc = currFunc; + currFunc = NULL; + + i = bitVectFirstBit(f); + while(i < 128) { + + /* 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; + + return pcop; +} + + +/*-----------------------------------------------------------------*/ +/* pic16_popReleaseTempReg - create a new temporary pCodeOp */ +/*-----------------------------------------------------------------*/ +void pic16_popReleaseTempReg(pCodeOp *pcop, int lock) +{ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + _TempReg_lock -= 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 */ @@ -1359,12 +1777,12 @@ void pic16_popReleaseTempReg(pCodeOp *pcop) pCodeOp *pic16_popGetLabel(unsigned int key) { - DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset); + DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset); if(key>max_key) max_key = key; - return pic16_newpCodeOpLabel(NULL,key+100+labelOffset); + return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset); } /*-----------------------------------------------------------------*/ @@ -1375,16 +1793,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); @@ -1394,7 +1816,7 @@ pCodeOp *pic16_popCopyReg(pCodeOpReg *pc) /*-----------------------------------------------------------------*/ /* pic16_popGetLit - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetLit(unsigned int lit) +pCodeOp *pic16_popGetLit(int lit) { return pic16_newpCodeOpLit(lit); } @@ -1402,7 +1824,7 @@ pCodeOp *pic16_popGetLit(unsigned int lit) /*-----------------------------------------------------------------*/ /* pic16_popGetLit2 - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2) +pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2) { return pic16_newpCodeOpLit2(lit, arg2); } @@ -1456,16 +1878,19 @@ 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); - if(PCOR(pcop)->r == NULL) { + + /* make sure that register doesn't exist, + * and operand isn't NULL + * and symbol isn't in codespace (codespace symbols are handled elsewhere) */ + if((PCOR(pcop)->r == NULL) + && (op) + && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) { // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n", // __FUNCTION__, __LINE__, str, size, offset); - PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op); - //fprintf(stderr, "allocating new register -> %s\n", str); + 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); -// DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset); - } else { -// DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset); } PCOR(pcop)->instance = offset; @@ -1481,6 +1906,7 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx) pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); PCOR(pcop)->rIdx = rIdx; PCOR(pcop)->r = pic16_regWithIdx(rIdx); + PCOR(pcop)->r->isFree = 0; PCOR(pcop)->r->wasUsed = 1; @@ -1557,7 +1983,7 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) char *rs; pCodeOp *pcop; - //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY2; /* offset is greater than size then zero */ @@ -1578,11 +2004,29 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) 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); + case AOP_ACC: { int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx; @@ -1614,29 +2058,41 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__); 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; + 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_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", __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 register idx = %d name = %s",__LINE__,rIdx,rs); return pcop; } case AOP_CRY: DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__); - pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1); + pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER); + PCOR(pcop)->instance = offset; PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir); //if(PCOR(pcop)->r == NULL) //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir); @@ -1665,16 +2121,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; } @@ -1690,6 +2146,8 @@ void pic16_aopPut (asmop *aop, char *s, int offset) char *d = buffer ; symbol *lbl ; + return; + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); if (aop->size && offset > ( aop->size - 1)) { @@ -1906,43 +2364,82 @@ void pic16_aopPut (asmop *aop, char *s, int offset) break; default : - werror(E_INTERNAL_ERROR,__FILE__,__LINE__, - "pic16_aopPut got unsupported aop->type"); - exit(0); + fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type); +// werror(E_INTERNAL_ERROR,__FILE__,__LINE__, +// "pic16_aopPut got unsupported aop->type"); +// exit(0); } } /*-----------------------------------------------------------------*/ -/* 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); -// if(!aop) -// return; - - DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset); + if(is_LitAOp(aop)) + pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset)); + else + pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset)); +} - if(is_LitAOp(aop)) - pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset)); - else - pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset)); +void pic16_mov2f(asmop *dst, asmop *src, int offset) +{ + if(is_LitAOp(src)) { + pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset)); + } else { + if(pic16_sameRegsOfs(src, dst, offset))return; + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset), + pic16_popGet(dst, offset))); + } +} +static void mov2fp(pCodeOp *dst, asmop *src, int offset) +{ + if(is_LitAOp(src)) { + pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset)); + pic16_emitpcode(POC_MOVWF, dst); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst)); + } } +void pic16_testStackOverflow(void) +{ +#define GSTACK_TEST_NAME "_gstack_test" + + pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME )); + + { + symbol *sym; + + sym = newSymbol( GSTACK_TEST_NAME , 0 ); + sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME); +// strcpy(sym->rname, GSTACK_TEST_NAME); + checkAddSym(&externs, sym); + } + +} /* push pcop into stack */ void pic16_pushpCodeOp(pCodeOp *pcop) { // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1))); + if(pic16_options.gstack) + pic16_testStackOverflow(); + } /* 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(); } @@ -1951,8 +2448,10 @@ void pic16_poppCodeOp(pCodeOp *pcop) /*-----------------------------------------------------------------*/ void pushw(void) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1)); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); + if(pic16_options.gstack) + pic16_testStackOverflow(); } @@ -1961,8 +2460,18 @@ void pushw(void) /*-----------------------------------------------------------------*/ void pushaop(asmop *aop, int offset) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0)); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + if(is_LitAOp(aop)) { + pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); + } else { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); + } + + if(pic16_options.gstack) + pic16_testStackOverflow(); } /*-----------------------------------------------------------------*/ @@ -1970,22 +2479,27 @@ 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)); + DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0)); + if(pic16_options.gstack) + pic16_testStackOverflow(); } void popaopidx(asmop *aop, int offset, int index) { int ofs=1; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(STACK_MODEL_LARGE)ofs++; + 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_MOVLW, pic16_popGetLit(index + ofs)); + 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 */ /*-----------------------------------------------------------------*/ @@ -2024,7 +2538,7 @@ static void reAdjustPreg (asmop *aop) } } - +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -2106,6 +2620,7 @@ void pic16_outBitC(operand *result) int i; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* if the result is bit */ if (AOP_TYPE(result) == AOP_CRY) { fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__); @@ -2117,12 +2632,31 @@ void pic16_outBitC(operand *result) pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i)); } pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0)); - -/* - pic16_emitcode("clr","a ; %d", __LINE__); - pic16_emitcode("rlc","a"); - pic16_outAcc(result); -*/ + } +} + +/*-----------------------------------------------------------------*/ +/* pic16_outBitOp - output a bit from Op */ +/* Move to result the value of set/clr op -- VR */ +/*-----------------------------------------------------------------*/ +void pic16_outBitOp(operand *result, pCodeOp *pcop) +{ + int i; + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + /* if the result is bit */ + if (AOP_TYPE(result) == AOP_CRY) { + fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__); + pic16_aopPut(AOP(result),"c",0); + } else { + + i = AOP_SIZE(result); + while(i--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i)); + } + pic16_emitpcode(POC_RRCF, pcop); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0)); } } @@ -2154,7 +2688,7 @@ static void pic16_genNot (iCode *ic) symbol *tlbl; int size; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* assign asmOps to operand & result */ pic16_aopOp (IC_LEFT(ic),ic,FALSE); pic16_aopOp (IC_RESULT(ic),ic,TRUE); @@ -2201,11 +2735,10 @@ static void pic16_genNot (iCode *ic) /*-----------------------------------------------------------------*/ static void pic16_genCpl (iCode *ic) { - int offset = 0; - int size ; - + int offset = 0; + int size ; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* assign asmOps to operand & result */ pic16_aopOp (IC_LEFT(ic),ic,FALSE); pic16_aopOp (IC_RESULT(ic),ic,TRUE); @@ -2252,26 +2785,20 @@ release: /*-----------------------------------------------------------------*/ static void genUminusFloat(operand *op,operand *result) { - int size ,offset =0 ; - char *l; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + 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) - 1; - l = pic16_aopGet(AOP(op),3,FALSE,FALSE); - - MOVA(l); - - pic16_emitcode("cpl","acc.7"); - pic16_aopPut(AOP(result),"a",3); + size = AOP_SIZE(op); while(size--) { - pic16_aopPut(AOP(result), - pic16_aopGet(AOP(op),offset,FALSE,FALSE), - offset); - offset++; - } + pic16_mov2f(AOP(result), AOP(op), offset); + offset++; + } + + /* toggle the MSB's highest bit */ + pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7)); } /*-----------------------------------------------------------------*/ @@ -2281,57 +2808,75 @@ static void genUminus (iCode *ic) { int size, i; sym_link *optype, *rtype; + symbol *label; + int needLabel=0; - 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; - } + FENTRY; + + /* assign asmops */ + pic16_aopOp(IC_LEFT(ic),ic,FALSE); + pic16_aopOp(IC_RESULT(ic),ic,TRUE); - optype = operandType(IC_LEFT(ic)); - rtype = operandType(IC_RESULT(ic)); + /* 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; + } - /* if float then do float stuff */ - if (IS_FLOAT(optype)) { - genUminusFloat(IC_LEFT(ic),IC_RESULT(ic)); - goto release; - } + optype = operandType(IC_LEFT(ic)); + rtype = operandType(IC_RESULT(ic)); - /* 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 /*-----------------------------------------------------------------*/ /* saveRegisters - will look for a call and save the registers */ /*-----------------------------------------------------------------*/ @@ -2433,6 +2978,7 @@ static void unsaveRegisters (iCode *ic) //} } +#endif #if 0 // patch 14 /*-----------------------------------------------------------------*/ @@ -2457,111 +3003,132 @@ static void pushSide(operand * oper, int size) void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) { -// (AOP(left)->aopu.pcop->type == PO_DIR)? - - if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) { - pic16_emitpcode(POC_MOVFW, src); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset)); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - src, pic16_popGet(AOP(op), offset))); - } + 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 { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + src, pic16_popGet(AOP(op), offset))); + } } /*-----------------------------------------------------------------*/ /* assignResultValue - assign results to oper, rescall==1 is */ -/* called from genCall() or genPCall() */ +/* called from genCall() or genPcall() */ /*-----------------------------------------------------------------*/ static void assignResultValue(operand * oper, int rescall) { int size = AOP_SIZE(oper); + int offset=0; + + FENTRY2; +// DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14 + DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL); - DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14 - DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL); - - if(rescall) { - /* assign result from a call/pcall function() */ + if(rescall) { + /* assign result from a call/pcall function() */ - /* function results are stored in a special order, - * see top of file with Function return policy, or manual */ + /* function results are stored in a special order, + * see top of file with Function return policy, or manual */ - if(size <= 4) { - /* 8-bits, result in WREG */ - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0)); + if(size <= 4) { + /* 8-bits, result in WREG */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0)); - if(size>1) { - /* 16-bits, result in PRODL:WREG */ - pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl)); - } + if(size>1) { + /* 16-bits, result in PRODL:WREG */ + pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl)); + } - if(size>2) { - /* 24-bits, result in PRODH:PRODL:WREG */ - pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14 - } + if(size>2) { + /* 24-bits, result in PRODH:PRODL:WREG */ + pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14 + } - if(size>3) { - /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */ - pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14 - } - } else { - /* >32-bits, result on stack, and FSR0 points to beginning. - * Fix stack when done */ - - while (size--) { -// DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr); -// DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2"); + if(size>3) { + /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */ + pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14 + } + + } else { + /* >32-bits, result on stack, and FSR0 points to beginning. + * Fix stack when done */ + /* FIXME FIXME */ +// debugf("WARNING: Possible bug when returning more than 4-bytes\n"); + while (size--) { +// DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr); +// DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2"); - popaopidx(AOP(oper), size, GpsuedoStkPtr); - GpsuedoStkPtr++; - } + popaopidx(AOP(oper), size, GpsuedoStkPtr); + GpsuedoStkPtr++; + } - /* fix stack */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) )); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); - if(STACK_MODEL_LARGE) { - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); - } - } - } else { - if(!GpsuedoStkPtr) { -// DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr); - /* The last byte in the assignment is in W */ - size--; - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size)); - GpsuedoStkPtr++; - } - - while (size--) { -// DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr); -// DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2"); - - popaopidx(AOP(oper), size, GpsuedoStkPtr); - GpsuedoStkPtr++; - -#if 0 -#if STACK_SUPPORT - if(!USE_STACK) - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size)); -#else - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size)); -#endif -#endif - - } + /* fix stack */ + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l )); + if(STACK_MODEL_LARGE) { + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h )); } - + } + } else { + int areg = 0; /* matching argument register */ + +// debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr); + areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1; + + + /* 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); + + /* The last byte in the assignment is in W */ + if(areg <= GpsuedoStkPtr) { + size--; + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/)); + offset++; +// debugf("receive from WREG\n", 0); + } + GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */ + } +// GpsuedoStkPtr++; + _G.stack_lat = AOP_SIZE(oper)-1; + + while (size) { + size--; + GpsuedoStkPtr++; + popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg); +// debugf("receive from STACK\n", 0); + offset++; + } + } } /*-----------------------------------------------------------------*/ -/* genIpush - genrate code for pushing this gets a little complex */ +/* genIpush - generate code for pushing this gets a little complex */ /*-----------------------------------------------------------------*/ static void genIpush (iCode *ic) { +// int size, offset=0; + FENTRY; DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__); + + if(ic->parmPush) { + pic16_aopOp(IC_LEFT(ic), ic, FALSE ); + + /* send to stack as normal */ + addSet(&_G.sendSet,ic); +// addSetHead(&_G.sendSet,ic); + pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); + } + + #if 0 int size, offset = 0 ; char *l; @@ -2589,29 +3156,6 @@ static void genIpush (iCode *ic) return ; } - /* this is a paramter push: in this case we call - the routine to find the call and save those - registers that need to be saved */ - saveRegisters(ic); - - /* then do the push */ - pic16_aopOp(IC_LEFT(ic),ic,FALSE); - - - // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic))); - size = AOP_SIZE(IC_LEFT(ic)); - - while (size--) { - l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE); - if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && - AOP_TYPE(IC_LEFT(ic)) != AOP_DIR && - strcmp(l,"a") ) { - pic16_emitcode("mov","a,%s",l); - pic16_emitcode("push","acc"); - } else - pic16_emitcode("push","%s",l); - } - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); #endif } @@ -2621,6 +3165,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 ; @@ -2641,6 +3186,7 @@ static void genIpop (iCode *ic) #endif } +#if 0 /*-----------------------------------------------------------------*/ /* unsaverbank - restores the resgister bank from stack */ /*-----------------------------------------------------------------*/ @@ -2736,7 +3282,18 @@ static void saverbank (int bank, iCode *ic, bool pushPsw) ic->bankSaved = 1; #endif } +#endif /* 0 */ + + +static int wparamCmp(void *p1, void *p2) +{ + return (!strcmp((char *)p1, (char *)p2)); +} +int inWparamList(char *s) +{ + return isinSetWith(wparamList, s, wparamCmp); +} /*-----------------------------------------------------------------*/ @@ -2744,427 +3301,292 @@ static void saverbank (int bank, iCode *ic, bool pushPsw) /*-----------------------------------------------------------------*/ static void genCall (iCode *ic) { - sym_link *dtype; + sym_link *ftype; int stackParms=0; + int use_wreg=0; + int inwparam=0; + char *fname; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; - /* if caller saves & we have not saved then */ - if (!ic->regsSaved) - saveRegisters(ic); + ftype = OP_SYM_TYPE(IC_LEFT(ic)); + /* if caller saves & we have not saved then */ +// if (!ic->regsSaved) +// saveRegisters(ic); - /* if we are calling a function that is not using - * the same register bank then we need to save the - * destination registers on the stack */ - dtype = operandType(IC_LEFT(ic)); - if (currFunc && dtype && - (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) && - IFFUNC_ISISR(currFunc->type) && - !ic->bankSaved) + /* initialise stackParms for IPUSH pushes */ +// 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)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic)))); - saverbank(FUNC_REGBANK(dtype),ic,TRUE); +#if 0 + gpsimDebug_StackDump(__FILE__, __LINE__, fname ); +#endif - /* if send set is not empty the assign */ - if (_G.sendSet) { - iCode *sic; + /* if send set is not empty the assign */ + if (_G.sendSet) { + iCode *sic; + int psuedoStkPtr=-1; + int firstTimeThruLoop = 1; - /* For the Pic port, there is no data stack. - * So parameters passed to functions are stored - * in registers. (The pCode optimizer will get - * rid of most of these :). */ - int psuedoStkPtr=-1; - int firstTimeThruLoop = 1; + /* reverse sendSet if function is not reentrant */ + if(!IFFUNC_ISREENT(ftype)) + _G.sendSet = reverseSet(_G.sendSet); - _G.sendSet = reverseSet(_G.sendSet); + /* First figure how many parameters are getting passed */ + stackParms = 0; + use_wreg = 0; + + for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) { + int size; +// int offset = 0; - /* First figure how many parameters are getting passed */ - for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) { - pic16_aopOp(IC_LEFT(sic),sic,FALSE); - psuedoStkPtr += AOP_SIZE(IC_LEFT(sic)); - pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE); - } + pic16_aopOp(IC_LEFT(sic),sic,FALSE); + size = AOP_SIZE(IC_LEFT(sic)); - stackParms = psuedoStkPtr; + stackParms += size; - for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) { - int size, offset = 0; + /* pass the last byte through WREG */ + if(inwparam) { - pic16_aopOp(IC_LEFT(sic),sic,FALSE); - size = AOP_SIZE(IC_LEFT(sic)); + while (size--) { + DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, + pic16_AopType(AOP_TYPE(IC_LEFT(sic)))); + DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); - while (size--) { - DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, - pic16_AopType(AOP_TYPE(IC_LEFT(sic)))); - DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); - - if(!firstTimeThruLoop) { - /* If this is not the first time we've been through the loop - * then we need to save the parameter in a temporary - * register. The last byte of the last parameter is - * passed in W. */ - - pushw(); - --psuedoStkPtr; // sanity check - } - - firstTimeThruLoop=0; + if(!firstTimeThruLoop) { + /* If this is not the first time we've been through the loop + * then we need to save the parameter in a temporary + * register. The last byte of the last parameter is + * passed in W. */ - mov2w (AOP(IC_LEFT(sic)), offset); - offset++; - } - pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); - } - _G.sendSet = NULL; - } + pushw(); +// --psuedoStkPtr; // sanity check + use_wreg = 1; + } + + firstTimeThruLoop=0; - /* make the call */ - pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ? - OP_SYMBOL(IC_LEFT(ic))->rname : - OP_SYMBOL(IC_LEFT(ic))->name)); + pic16_mov2w (AOP(IC_LEFT(sic)), size); - GpsuedoStkPtr=0; - /* if we need assign a result value */ - if ((IS_ITEMP(IC_RESULT(ic)) && - (OP_SYMBOL(IC_RESULT(ic))->nRegs || - OP_SYMBOL(IC_RESULT(ic))->spildir )) || - IS_TRUE_SYMOP(IC_RESULT(ic)) ) { +// offset++; + } + } else { + /* all arguments are passed via stack */ + use_wreg = 0; - _G.accInUse++; - pic16_aopOp(IC_RESULT(ic),ic,FALSE); - _G.accInUse--; + while (size--) { + DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, + pic16_AopType(AOP_TYPE(IC_LEFT(sic)))); + DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); - assignResultValue(IC_RESULT(ic), 1); +// pushaop(AOP(IC_LEFT(sic)), size); + pic16_mov2w (AOP(IC_LEFT(sic)), size); - DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, - pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); - - pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE); - } + if(!_G.resDirect) + pushw(); + } + } - if(stackParms>0) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); - if(STACK_MODEL_LARGE) { - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); - } - } + pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); + } - /* adjust the stack for parameters if required */ -// fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes); + if(inwparam) { + if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) { + pushw(); /* save last parameter to stack if functions has varargs */ + use_wreg = 0; + } else + use_wreg = 1; + } else use_wreg = 0; - if (ic->parmBytes) { - int i; + _G.stackRegSet = _G.sendSet; + _G.sendSet = NULL; + } - if (ic->parmBytes > 3) { - pic16_emitcode("mov","a,%s",spname); - pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff); - pic16_emitcode("mov","%s,a",spname); - } else - for ( i = 0 ; i < ic->parmBytes ;i++) - pic16_emitcode("dec","%s",spname); - } + /* make the call */ + pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname)); -#if 0 - /* if register bank was saved then pop them */ - if (ic->bankSaved) - unsaverbank(FUNC_REGBANK(dtype),ic,TRUE); + GpsuedoStkPtr=0; + + /* if we need to assign a result value */ + if ((IS_ITEMP(IC_RESULT(ic)) + && (OP_SYMBOL(IC_RESULT(ic))->nRegs + || OP_SYMBOL(IC_RESULT(ic))->spildir )) + || IS_TRUE_SYMOP(IC_RESULT(ic)) ) { - /* if we hade saved some registers then unsave them */ - if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype)) - unsaveRegisters (ic); -#endif + _G.accInUse++; + pic16_aopOp(IC_RESULT(ic),ic,FALSE); + _G.accInUse--; + + assignResultValue(IC_RESULT(ic), 1); + + DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, + pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); + + pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE); + } + + if(!stackParms && ic->parmBytes) { + stackParms = ic->parmBytes; + } + + stackParms -= use_wreg; + + if(stackParms>0) { + if(stackParms == 1) { + 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_stackpnt_lo )); //&pic16_pc_fsr1l )); + } + if(STACK_MODEL_LARGE) { + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h )); + } + } + +#if 0 + gpsimDebug_StackDump(__FILE__, __LINE__, fname); +#endif + + /* adjust the stack for parameters if required */ +// fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes); + +#if 0 + /* if register bank was saved then pop them */ + if (ic->bankSaved) + unsaverbank(FUNC_REGBANK(dtype),ic,TRUE); + + /* if we hade saved some registers then unsave them */ + if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype)) + unsaveRegisters (ic); +#endif } -/*-----------------------------------------------------------------*/ // patch 14 +/*-----------------------------------------------------------------*/ /* genPcall - generates a call by pointer statement */ +/* new version, created from genCall - HJD */ /*-----------------------------------------------------------------*/ - -// new version, created from genCall - static void genPcall (iCode *ic) { - sym_link *dtype; + sym_link *ftype, *fntype; int stackParms=0; symbol *retlbl = newiTempLabel(NULL); pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - /* if caller saves & we have not saved then */ - if (!ic->regsSaved) - saveRegisters(ic); - - /* if we are calling a function that is not using - * the same register bank then we need to save the - * destination registers on the stack */ - dtype = operandType(IC_LEFT(ic)); - if (currFunc && dtype && - (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) && - IFFUNC_ISISR(currFunc->type) && - !ic->bankSaved) + FENTRY; - saverbank(FUNC_REGBANK(dtype),ic,TRUE); + ftype = OP_SYM_TYPE(IC_LEFT(ic)); + fntype = operandType( IC_LEFT(ic) )->next; - /* if send set is not empty the assign */ - if (_G.sendSet) { - iCode *sic; - - /* For the Pic port, there is no data stack. - * So parameters passed to functions are stored - * in registers. (The pCode optimizer will get - * rid of most of these :). */ + /* if send set is not empty the assign */ + if (_G.sendSet) { + iCode *sic; + int psuedoStkPtr=-1; - int psuedoStkPtr=-1; - int firstTimeThruLoop = 1; + /* reverse sendSet if function is not reentrant */ + if(!IFFUNC_ISREENT(fntype)) + _G.sendSet = reverseSet(_G.sendSet); - _G.sendSet = reverseSet(_G.sendSet); + stackParms = 0; + + for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) { + int size; - /* First figure how many parameters are getting passed */ - for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) { - pic16_aopOp(IC_LEFT(sic),sic,FALSE); - psuedoStkPtr += AOP_SIZE(IC_LEFT(sic)); - pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE); - } + pic16_aopOp(IC_LEFT(sic),sic,FALSE); + size = AOP_SIZE(IC_LEFT(sic)); + stackParms += size; - stackParms = psuedoStkPtr; + /* all parameters are passed via stack, since WREG is clobbered + * by the calling sequence */ + while (size--) { + DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, + pic16_AopType(AOP_TYPE(IC_LEFT(sic)))); + DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); - for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) { - int size, offset = 0; + pic16_mov2w (AOP(IC_LEFT(sic)), size); + pushw(); + } - pic16_aopOp(IC_LEFT(sic),sic,FALSE); - size = AOP_SIZE(IC_LEFT(sic)); + pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); + } - while (size--) { - DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, - pic16_AopType(AOP_TYPE(IC_LEFT(sic)))); - DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); - - if(!firstTimeThruLoop) { - /* If this is not the first time we've been through the loop - * then we need to save the parameter in a temporary - * register. The last byte of the last parameter is - * passed in W. */ - - pushw(); - --psuedoStkPtr; // sanity check - } - - firstTimeThruLoop=0; + _G.stackRegSet = _G.sendSet; + _G.sendSet = NULL; + } - mov2w (AOP(IC_LEFT(sic)), offset); - offset++; - } - pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); - } - _G.sendSet = NULL; - } + pic16_aopOp(IC_LEFT(ic),ic,FALSE); - pic16_aopOp(IC_LEFT(ic),ic,FALSE); + // push return address + // push $ on return stack, then replace with retlbl - // 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_emitpcodeNULLop(POC_PUSH); - pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl)); - pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh)); - pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu)); + pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl)); + pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh)); + pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu)); - /* 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))); - // note: MOVFF to PCL not allowed - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl)); + /* 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))); -// pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key)); -// pic16_emitpcodeNULLop(POC_NOP); -// pic16_emitpcodeNULLop(POC_NOP); + // note: MOVFF to PCL not allowed + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl)); - /* return address is here: (X) */ - pic16_emitpLabelFORCE(retlbl->key); -// pic16_emitpcodeNULLop(POC_NOP); + /* return address is here: (X) */ + pic16_emitpLabelFORCE(retlbl->key); - pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE); + pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE); - GpsuedoStkPtr=0; - /* if we need assign a result value */ - if ((IS_ITEMP(IC_RESULT(ic)) && - (OP_SYMBOL(IC_RESULT(ic))->nRegs || - OP_SYMBOL(IC_RESULT(ic))->spildir )) || - IS_TRUE_SYMOP(IC_RESULT(ic)) ) { + GpsuedoStkPtr=0; + /* if we need assign a result value */ + if ((IS_ITEMP(IC_RESULT(ic)) + && (OP_SYMBOL(IC_RESULT(ic))->nRegs + || OP_SYMBOL(IC_RESULT(ic))->spildir )) + || IS_TRUE_SYMOP(IC_RESULT(ic)) ) { - _G.accInUse++; - pic16_aopOp(IC_RESULT(ic),ic,FALSE); - _G.accInUse--; + _G.accInUse++; + pic16_aopOp(IC_RESULT(ic),ic,FALSE); + _G.accInUse--; - assignResultValue(IC_RESULT(ic), 1); + assignResultValue(IC_RESULT(ic), 1); - DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, - pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); + DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, + pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); - pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE); - } - - if(stackParms>0) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); - if(STACK_MODEL_LARGE) { - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); - } - } - - /* adjust the stack for parameters if required */ -// fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes); - - if (ic->parmBytes) { - int i; - - if (ic->parmBytes > 3) { - pic16_emitcode("mov","a,%s",spname); - pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff); - pic16_emitcode("mov","%s,a",spname); - } else - for ( i = 0 ; i < ic->parmBytes ;i++) - pic16_emitcode("dec","%s",spname); - } - - /* if register bank was saved then pop them */ - if (ic->bankSaved) - unsaverbank(FUNC_REGBANK(dtype),ic,TRUE); - - /* if we hade saved some registers then unsave them */ - if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype)) - unsaveRegisters (ic); -} - - -#if 0 // patch 14 -// old version, kept for reference - -/*-----------------------------------------------------------------*/ -/* genPcall - generates a call by pointer statement */ -/*-----------------------------------------------------------------*/ -static void genPcall (iCode *ic) -{ - sym_link *dtype; - symbol *rlbl = newiTempLabel(NULL); - - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* if caller saves & we have not saved then */ - if (!ic->regsSaved) - saveRegisters(ic); - - /* if we are calling a function that is not using - the same register bank then we need to save the - destination registers on the stack */ - dtype = operandType(IC_LEFT(ic)); - if (currFunc && dtype && - IFFUNC_ISISR(currFunc->type) && - (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype))) - saverbank(FUNC_REGBANK(dtype),ic,TRUE); - - - /* push the return address on to the stack */ - pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100)); - pic16_emitcode("push","acc"); - pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100)); - pic16_emitcode("push","acc"); - - if (options.model == MODEL_FLAT24) - { - pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100)); - pic16_emitcode("push","acc"); + pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE); } - /* now push the calling address */ - pic16_aopOp(IC_LEFT(ic),ic,FALSE); - - pushSide(IC_LEFT(ic), FPTRSIZE); - - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); - - /* if send set is not empty the assign */ - if (_G.sendSet) { - iCode *sic ; - - for (sic = setFirstItem(_G.sendSet) ; sic ; - sic = setNextItem(_G.sendSet)) { - int size, offset = 0; - pic16_aopOp(IC_LEFT(sic),sic,FALSE); - size = AOP_SIZE(IC_LEFT(sic)); - while (size--) { - char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset, - FALSE,FALSE); - if (strcmp(l,fReturn[offset])) - pic16_emitcode("mov","%s,%s", - fReturn[offset], - l); - offset++; - } - pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE); - } - _G.sendSet = NULL; - } - - pic16_emitcode("ret",""); - pic16_emitcode("","%05d_DS_:",(rlbl->key+100)); - - - /* if we need assign a result value */ - if ((IS_ITEMP(IC_RESULT(ic)) && - (OP_SYMBOL(IC_RESULT(ic))->nRegs || - OP_SYMBOL(IC_RESULT(ic))->spildir)) || - IS_TRUE_SYMOP(IC_RESULT(ic)) ) { - - _G.accInUse++; - pic16_aopOp(IC_RESULT(ic),ic,FALSE); - _G.accInUse--; - - assignResultValue(IC_RESULT(ic), 1); - - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); - } - - /* adjust the stack for parameters if - required */ - if (ic->parmBytes) { - int i; - if (ic->parmBytes > 3) { - pic16_emitcode("mov","a,%s",spname); - pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff); - pic16_emitcode("mov","%s,a",spname); - } else - for ( i = 0 ; i < ic->parmBytes ;i++) - pic16_emitcode("dec","%s",spname); - +// stackParms -= use_wreg; + + if(stackParms>0) { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); + if(STACK_MODEL_LARGE) { + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); + } } - - /* if register bank was saved then unsave them */ - if (currFunc && dtype && - (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype))) - unsaverbank(FUNC_REGBANK(dtype),ic,TRUE); - - /* if we hade saved some registers then - unsave them */ - if (ic->regsSaved) - unsaveRegisters (ic); - } -#endif // patch 14 - /*-----------------------------------------------------------------*/ /* resultRemat - result is rematerializable */ @@ -3221,237 +3643,205 @@ static void genFunction (iCode *ic) symbol *sym; sym_link *ftype; - DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key); - - labelOffset += (max_key+4); - max_key=0; - GpsuedoStkPtr=0; - _G.nRegsSaved = 0; - - ftype = operandType(IC_LEFT(ic)); - sym = OP_SYMBOL(IC_LEFT(ic)); - - if(IFFUNC_ISISR(sym->type /*ftype*/)) { - /* create an absolute section at the interrupt vector: - * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */ - symbol *asym; - 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); + FENTRY; + DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key); - apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section")); - pic16_addpBlock( apb ); - - pic16_addpCode2pBlock(apb, - pic16_newpCodeCharP(";-----------------------------------------")); + pic16_labelOffset += (max_key+4); + max_key=0; + GpsuedoStkPtr=0; + _G.nRegsSaved = 0; + + ftype = operandType(IC_LEFT(ic)); + sym = OP_SYMBOL(IC_LEFT(ic)); + if(IFFUNC_ISISR(sym->type /*ftype*/)) { + /* create an absolute section at the interrupt vector: + * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */ + symbol *asym; + char asymname[128]; + pBlock *apb; - pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name)); +// debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type)); - 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)); - - { - absSym *abSym; - - abSym = Safe_calloc(1, sizeof(absSym)); - abSym->name = Safe_strdup( asymname ); - - switch( _G.interruptvector ) { - case 0: abSym->address = 0x000000; break; - case 1: abSym->address = 0x000008; break; - case 2: abSym->address = 0x000018; break; - } - - addSet(&absSymSet, abSym); - } - } - - - /* create the function header */ - pic16_emitcode(";","-----------------------------------------"); - pic16_emitcode(";"," function %s",sym->name); - pic16_emitcode(";","-----------------------------------------"); - - pic16_emitcode("","%s:",sym->rname); - pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname)); - + /* mark the end of this tiny function */ + pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL)); + } else { + sprintf(asymname, "%s", sym->rname); + } { - absSym *ab; + absSym *abSym; + + abSym = Safe_calloc(1, sizeof(absSym)); + strcpy(abSym->name, asymname); + + 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; + } - for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) - if(!strcmp(ab->name, sym->name)) { - pic16_pBlockConvert2Absolute(pb); - break; - } + /* relocate interrupt vectors if needed */ + if(abSym->address != -1) + abSym->address += pic16_options.ivt_loc; - } + addSet(&absSymSet, abSym); + } + } + /* create the function header */ + pic16_emitcode(";","-----------------------------------------"); + pic16_emitcode(";"," function %s",sym->name); + pic16_emitcode(";","-----------------------------------------"); - if(IFFUNC_ISNAKED(ftype)) { - DEBUGpic16_emitcode("; ***", "_naked function, no prologue"); - return; - } - - /* if critical function then turn interrupts off */ - if (IFFUNC_ISCRITICAL(ftype)) - pic16_emitcode("clr","ea"); - - /* if this is an interrupt service routine then - * save acc, b, dpl, dph */ - if (IFFUNC_ISISR(sym->type)) { - int i; - /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */ - if(!(_G.interruptvector == 1)) { - - /* do not save WREG,STATUS,BSR for high priority interrupts - * because they are stored in the hardware shadow registers already */ - - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg )); - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status )); - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr )); - } + pic16_emitcode("","%s:",sym->rname); + pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname)); - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl )); - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l )); - pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); + { + absSym *ab; -// pic16_pBlockConvert2ISR(pb); - - /* if any registers used */ - if (sym->regsUsed) { - /* save the registers used */ - DEBUGpic16_emitcode("; **", "Saving used registers in stack"); - for ( i = 0 ; i < sym->regsUsed->size ; i++) { - if (bitVectBitValue(sym->regsUsed,i)) { -// fprintf(stderr, "%s:%d function %s uses register %s\n", -// __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, -// pic16_regWithIdx(i)->name); - - pic16_pushpCodeOp( pic16_popRegFromIdx(i) ); - _G.nRegsSaved++; - } - } - } - } else { - /* emit code to setup stack frame if user enabled, - * and function is not main() */ - -// fprintf(stderr, "function name: %s\n", sym->name); - if(strcmp(sym->name, "main")) { - if(/*!options.ommitFramePtr || */sym->regsUsed) { - /* setup the stack frame */ - 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)); - if(STACK_MODEL_LARGE) - pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0)); - } - } + for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) { + if(!strcmp(ab->name, sym->rname)) { + pic16_pBlockConvert2Absolute(pb); + break; + } + } + } - /* if callee-save to be used for this function - * then save the registers being used in this function */ -// if (IFFUNC_CALLEESAVES(sym->type)) - { - int i; + if(IFFUNC_ISNAKED(ftype)) { + DEBUGpic16_emitcode("; ***", "_naked function, no prologue"); + return; + } + + /* if critical function then turn interrupts off */ + if (IFFUNC_ISCRITICAL(ftype)) { + //pic16_emitcode("clr","ea"); + } -// fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size); + currFunc = sym; /* update the currFunc symbol */ + _G.fregsUsed = sym->regsUsed; + _G.sregsAlloc = newBitVect(128); + -// pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1); + /* if this is an interrupt service routine then + * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */ + if (IFFUNC_ISISR(sym->type)) { + _G.usefastretfie = 1; /* use shadow registers by default */ + + /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */ + 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; + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr )); + } - /* if any registers used */ - if (sym->regsUsed) { - /* save the registers used */ - DEBUGpic16_emitcode("; **", "Saving used registers in stack"); - for ( i = 0 ; i < sym->regsUsed->size ; i++) { - if (bitVectBitValue(sym->regsUsed,i)) { + /* these should really be optimized somehow, because not all + * interrupt handlers modify them */ + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); + +// pic16_pBlockConvert2ISR(pb); + } -// fprintf(stderr, "%s:%d function %s uses register %s\n", -// __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, -// pic16_regWithIdx(i)->name); + /* emit code to setup stack frame if user enabled, + * and function is not main() */ + +// debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type)); + if(strcmp(sym->name, "main")) { + 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_framepnt_hi)); + pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo)); + + pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0)); + if(STACK_MODEL_LARGE) + pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0)); + } + } - pic16_pushpCodeOp( pic16_popRegFromIdx(i) ); + if ((IFFUNC_ISREENT(sym->type) || options.stackAuto) + && sym->stack) { -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( -// PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), -// &pic16_pc_postdec1, 0)); + if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name); - _G.nRegsSaved++; - } - } - } - } - } + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack)); + 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) || FUNC_ISWPARAM(sym->type)) { + if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type)) + _G.useWreg = 0; + else + _G.useWreg = 1; + } else + _G.useWreg = 0; + /* if callee-save to be used for this function + * then save the registers being used in this function */ +// if (IFFUNC_CALLEESAVES(sym->type)) + { + int i; + /* if any registers used */ + if (sym->regsUsed) { + /* save the registers used */ + 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_END)); + } + } -#if 0 - if (IFFUNC_ISREENT(sym->type) || options.stackAuto) { - - if (options.useXstack) { - pic16_emitcode("mov","r0,%s",spname); - pic16_emitcode("mov","a,_bp"); - pic16_emitcode("movx","@r0,a"); - pic16_emitcode("inc","%s",spname); - } else { - /* set up the stack */ - pic16_emitcode ("push","_bp"); /* save the callers stack */ - } - pic16_emitcode ("mov","_bp,%s",spname); - } -#endif - DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack); - - /* adjust the stack for the function */ - if (sym->stack) { - int i = sym->stack; - - if (i > 127 ) - werror(W_STACK_OVERFLOW,sym->name); - - if (i > 3 && sym->recvSize < 4) { - pic16_emitcode ("mov","a,sp"); - pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff)); - pic16_emitcode ("mov","sp,a"); - } else - while(i--) - pic16_emitcode("inc","sp"); - } - - if (sym->xstack) { - DEBUGpic16_emitcode("; ", "%s", __FUNCTION__); - - pic16_emitcode ("mov","a,_spx"); - pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff)); - pic16_emitcode ("mov","_spx,a"); - } - + DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack); +// fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack); } /*-----------------------------------------------------------------*/ @@ -3459,171 +3849,179 @@ static void genFunction (iCode *ic) /*-----------------------------------------------------------------*/ static void genEndFunction (iCode *ic) { - symbol *sym = OP_SYMBOL(IC_LEFT(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"); - return; + DEBUGpic16_emitcode("; ***", "_naked function, no epilogue"); + return; } -#if 0 - if (IFFUNC_ISREENT(sym->type) || options.stackAuto) - { - pic16_emitcode ("mov","%s,_bp",spname); + _G.stack_lat = 0; + + /* add code for ISCRITICAL */ + if(IFFUNC_ISCRITICAL(sym->type)) { + /* if critical function, turn on interrupts */ + + /* TODO: add code here -- VR */ } -#endif + +// sym->regsUsed = _G.fregsUsed; + + /* now we need to restore the registers */ + /* if any registers used */ - /* if use external stack but some variables were - added to the local stack then decrement the - local stack */ - if (options.useXstack && sym->stack) { - pic16_emitcode("mov","a,sp"); - pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff); - pic16_emitcode("mov","sp,a"); + /* 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 (sym->regsUsed) { + int i; -#if 0 - if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) { - if (options.useXstack) { - pic16_emitcode("mov","r0,%s",spname); - pic16_emitcode("movx","a,@r0"); - pic16_emitcode("mov","_bp,a"); - pic16_emitcode("dec","%s",spname); - } - else - { - pic16_emitcode ("pop","_bp"); - } + pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN)); + /* restore registers used */ + DEBUGpic16_emitcode("; **", "Restoring used registers from stack"); + for ( i = sym->regsUsed->size; i >= 0; i--) { + if (bitVectBitValue(sym->regsUsed,i)) { + pic16_poppCodeOp( pic16_popRegFromIdx(i) ); + _G.nRegsSaved--; + } + } + pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END)); } -#endif - - if (IFFUNC_ISISR(sym->type)) { - /* now we need to restore the registers */ - /* if any registers used */ - if (sym->regsUsed) { - int i; - /* restore registers used */ - DEBUGpic16_emitcode("; **", "Restoring used registers from stack"); - for ( i = sym->regsUsed->size; i >= 0; i--) { - if (bitVectBitValue(sym->regsUsed,i)) { + -// fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n", -// __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, -// pic16_regWithIdx(i)->name); + 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! + } + } - pic16_poppCodeOp( pic16_popRegFromIdx(i) ); + if(strcmp(sym->name, "main")) { + if(0 + || !options.ommitFramePtr +// || sym->regsUsed + || IFFUNC_ARGS(sym->type) + || FUNC_HASSTACKPARM(sym->etype) + ) { + /* restore stack frame */ + if(STACK_MODEL_LARGE) + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi )); + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); + } + } -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( -// &pic16_pc_preinc1, -// PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0)); + _G.useWreg = 0; - } - } - } - - 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)) { - /* 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 */ + if (IFFUNC_ISISR(sym->type)) { + 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 )); -// pic16_pBlockConvert2ISR(pb); + 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 */ - /* if debug then send end of function */ -/* if (options.debug && currFunc) */ - if (currFunc) { - debugFile->writeEndFunction (currFunc, ic, 1); - } - - pic16_emitpcodeNULLop(POC_RETFIE); - } else { - if (IFFUNC_ISCRITICAL(sym->type)) - pic16_emitcode("setb","ea"); + /* if debug then send end of function */ +/* if (options.debug && currFunc) */ + if (currFunc) { + debugFile->writeEndFunction (currFunc, ic, 1); + } + if(_G.usefastretfie) + pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1)); + else + pic16_emitpcodeNULLop(POC_RETFIE); -// pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1); + pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL)); + + _G.usefastretfie = 0; + return; + } - /* if any registers used */ - if (sym->regsUsed) { - int i; - /* save the registers used */ - DEBUGpic16_emitcode("; **", "Restoring used registers from stack"); - for ( i = sym->regsUsed->size; i >= 0; i--) { - if (bitVectBitValue(sym->regsUsed,i)) { - -// fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n", -// __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, -// pic16_regWithIdx(i)->name); - - pic16_poppCodeOp( pic16_popRegFromIdx(i) ); - -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( -// &pic16_pc_preinc1, -// PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0)); + if (IFFUNC_ISCRITICAL(sym->type)) { + pic16_emitcode("setb","ea"); + } - _G.nRegsSaved--; - } - } - } - - pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved); - /* if debug then send end of function */ - if (currFunc) { - debugFile->writeEndFunction (currFunc, ic, 1); - } + /* if debug then send end of function */ + if (currFunc) { + debugFile->writeEndFunction (currFunc, ic, 1); + } - /* insert code to restore stack frame, if user enabled it - * and function is not main() */ + /* insert code to restore stack frame, if user enabled it + * and function is not main() */ - if(strcmp(sym->name, "main")) { - if(/*!options.ommitFramePtr ||*/ sym->regsUsed) { - /* restore stack frame */ - if(STACK_MODEL_LARGE) - pic16_emitpcode(POC_MOVFF, - pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0)); - pic16_emitpcode(POC_MOVFF, - pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0)); - } - } - - pic16_emitcode ("return",""); - pic16_emitpcodeNULLop(POC_RETURN); - - /* Mark the end of a function */ - pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL)); - } + pic16_emitpcodeNULLop(POC_RETURN); + /* Mark the end of a function */ + pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL)); } -void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest) +void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest) { + unsigned long lit=1; + operand *op; - if(is_LitOp(op)) { - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12 + 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 { + 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; + } + } - if(dest->type != PO_WREG) - pic16_emitpcode(POC_MOVWF, dest); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popGet(AOP(op), offset), dest)); - } + if(is_LitOp(op)) { + if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) { + pic16_emitpcode(POC_CLRF, dest); + } else { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); + if(dest->type != PO_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)); + } } /*-----------------------------------------------------------------*/ @@ -3634,7 +4032,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" */ @@ -3647,27 +4045,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))); - } + 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_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12 - - 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 */ @@ -3683,13 +4070,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 )); } } @@ -3745,7 +4132,7 @@ jumpret: && IC_LABEL(ic->next) == returnLabel)) { pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key)); - pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset); + pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset); } } @@ -3754,15 +4141,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 + labelOffset)); + pic16_emitpLabel(IC_LABEL(ic)->key); +// pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset)); } /*-----------------------------------------------------------------*/ @@ -3771,8 +4157,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)+labelOffset); +// pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset); } @@ -3783,7 +4170,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)); @@ -3803,7 +4190,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); @@ -3840,35 +4227,34 @@ 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); } /*-----------------------------------------------------------------*/ @@ -3878,35 +4264,34 @@ 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); } @@ -3920,7 +4305,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); @@ -3977,10 +4362,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); @@ -3999,10 +4383,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, @@ -4012,7 +4396,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 */ @@ -4025,9 +4410,9 @@ static void genDivOneByte (operand *left, /* unsigned is easy */ - pct1 = pic16_popGetTempReg(); - pct2 = pic16_popGetTempReg(); - pct3 = pic16_popGetTempReg(); + pct1 = pic16_popGetTempReg(1); + pct2 = pic16_popGetTempReg(1); + pct3 = pic16_popGetTempReg(1); label1 = newiTempLabel(NULL); label2 = newiTempLabel(NULL); @@ -4077,9 +4462,9 @@ static void genDivOneByte (operand *left, if(AOP_TYPE(result) != AOP_ACC) pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - pic16_popReleaseTempReg( pct3 ); - pic16_popReleaseTempReg( pct2 ); - pic16_popReleaseTempReg( pct1 ); + pic16_popReleaseTempReg( pct3, 1); + pic16_popReleaseTempReg( pct2, 1); + pic16_popReleaseTempReg( pct1, 1); return ; } @@ -4155,7 +4540,8 @@ static void genDiv (iCode *ic) * 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); @@ -4190,10 +4576,12 @@ release : static void genModbits (operand *left, operand *right, operand *result) -{ - - char *l; +{ + 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); @@ -4213,11 +4601,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 */ @@ -4285,11 +4675,12 @@ static void genModOneByte (operand *left, /*-----------------------------------------------------------------*/ static void genMod (iCode *ic) { - operand *left = IC_LEFT(ic); - operand *right = IC_RIGHT(ic); - operand *result= IC_RESULT(ic); + 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); @@ -4327,8 +4718,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) ) { @@ -4336,14 +4727,14 @@ 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)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER)); } pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key)); - pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset); + pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset); } else { @@ -4351,15 +4742,42 @@ 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)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER)); } pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key)); - pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset); + pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset); + + } + + + /* mark the icode as generated */ + 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); } @@ -4396,7 +4814,7 @@ static void genSkip(iCode *ifx,int status_bit) } pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset); + // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); } else { @@ -4415,7 +4833,7 @@ static void genSkip(iCode *ifx,int status_bit) break; } pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset); + // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); } @@ -4433,14 +4851,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 */ /*-----------------------------------------------------------------*/ @@ -4459,6 +4878,7 @@ static void genSkipz2(resolvedIfx *rifx, int invert_condition) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -4480,13 +4900,14 @@ static void genSkipz(iCode *ifx, int condition) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); if ( IC_TRUE(ifx) ) - pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset); + pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); else - pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset); + pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); } #endif +#if !(USE_SIMPLE_GENCMP) /*-----------------------------------------------------------------*/ /* genSkipCond */ /*-----------------------------------------------------------------*/ @@ -4496,14 +4917,15 @@ static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit) return; if(rifx->condition) - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER)); else - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -4534,9 +4956,244 @@ 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 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 (AOP_SIZE(left) == AOP_SIZE(right)); + assert (left && 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 { + 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, operand *result, iCode *ifx, int sign) { @@ -4553,6 +5210,8 @@ static void genCmp (operand *left,operand *right, } */ + FENTRY; + resolveIfx(&rFalseIfx,ifx); truelbl = newiTempLabel(NULL); size = max(AOP_SIZE(left),AOP_SIZE(right)); @@ -4583,6 +5242,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 { @@ -4594,7 +5254,7 @@ static void genCmp (operand *left,operand *right, #if 0 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n", - __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset); + __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset); #endif #ifndef _swapp @@ -4676,7 +5336,7 @@ static void genCmp (operand *left,operand *right, //genSkipCond(&rFalseIfx,left,size,7); //rFalseIfx.condition ^= 1; - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); if(rFalseIfx.condition) pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); else @@ -4746,7 +5406,7 @@ static void genCmp (operand *left,operand *right, //genSkipCond(&rFalseIfx,left,size,7); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); if(rFalseIfx.condition) pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); @@ -4757,7 +5417,7 @@ static void genCmp (operand *left,operand *right, } else { /* lit is positive */ DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); if(rFalseIfx.condition) pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); else @@ -4949,6 +5609,10 @@ static void genCmp (operand *left,operand *right, rFalseIfx.condition ^= 1; genSkipCond(&rFalseIfx,right,size,7); if(ifx) ifx->generated = 1; + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; } @@ -4956,7 +5620,7 @@ static void genCmp (operand *left,operand *right, int s = size; if(rFalseIfx.condition) { - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0)); + 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)); } @@ -4975,6 +5639,10 @@ static void genCmp (operand *left,operand *right, } if(ifx) ifx->generated = 1; + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; } @@ -4985,11 +5653,17 @@ 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 ((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; + } - if(ifx) ifx->generated = 1; return; } @@ -4999,7 +5673,7 @@ static void genCmp (operand *left,operand *right, //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)); + 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) @@ -5018,7 +5692,7 @@ static void genCmp (operand *left,operand *right, //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)); + 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 @@ -5026,7 +5700,6 @@ static void genCmp (operand *left,operand *right, } - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); @@ -5043,6 +5716,11 @@ static void genCmp (operand *left,operand *right, pic16_emitpLabel(truelbl->key); if(ifx) ifx->generated = 1; + + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; // end of if (sign) } else { @@ -5086,6 +5764,10 @@ static void genCmp (operand *left,operand *right, pic16_emitpLabel(truelbl->key); if(ifx) ifx->generated = 1; + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; } @@ -5123,6 +5805,10 @@ static void genCmp (operand *left,operand *right, if(sign) pic16_emitpLabel(truelbl->key); if(ifx) ifx->generated = 1; + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; } } @@ -5134,12 +5820,16 @@ static void genCmp (operand *left,operand *right, 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, 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, pic16_popRegFromIdx(pic16_Gstack_base_addr)); + pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr)); + 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 */ @@ -5154,6 +5844,10 @@ static void genCmp (operand *left,operand *right, genSkipc(&rFalseIfx); if(ifx) ifx->generated = 1; + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; } @@ -5190,6 +5884,10 @@ static void genCmp (operand *left,operand *right, //genSkipc(&rFalseIfx); if(ifx) ifx->generated = 1; + + if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) + goto check_carry; + return; } @@ -5198,7 +5896,8 @@ check_carry: if ((AOP_TYPE(result) != AOP_CRY) && AOP_SIZE(result)) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); -// pic16_emitpLabel( rFalseIfx.lbl->key ); + + if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key ); pic16_outBitC(result); } else { @@ -5215,16 +5914,377 @@ check_carry: } +#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, + operand *result, int offset, int invert_op) +{ + /* add code here */ + + /* check condition, > or < ?? */ + if(rIfx->condition != 0)invert_op ^= 1; + + if(ifx && IC_FALSE(ifx))invert_op ^= 1; + + if(!ifx)invert_op ^= 1; + + DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d", + __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op); + + /* do selection */ + if(!invert_op)return POC_CPFSGT; + else return POC_CPFSLT; +} + +static int compareAopfirstpass=1; + +static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl, + operand *oper, int offset, operand *result, + int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2, + symbol *tlbl) +{ + int op; + symbol *truelbl; + + /* invert if there is a result to be loaded, in order to fit, + * SETC/CLRC sequence */ + if(AOP_SIZE(result))invert_op ^= 1; + +// if(sign && !offset)invert_op ^= 1; + +// if(sign)invert_op ^= 1; + + op = selectCompareOp(resIfx, ifx, result, offset, invert_op); + + if(AOP_SIZE(result) && compareAopfirstpass) { + if(!ifx) { + if(pcop2) + pic16_emitpcode(POC_SETF, pcop2); + else + emitSETC; + } else { + if(pcop2) + pic16_emitpcode(POC_CLRF, pcop2); + else + emitCLRC; + } + } + + compareAopfirstpass = 0; + + /* there is a bug when comparing operands with size > 1, + * because higher bytes can be equal and test should be performed + * to the next lower byte, current algorithm, considers operands + * inequal in these cases! -- VR 20041107 */ + + + if(pcop) + pic16_emitpcode(op, pcop); + else + pic16_emitpcode(op, pic16_popGet(AOP(oper), offset)); + + + if((!sign || !offset) && AOP_SIZE(result)) { + if(!ifx) { + if(pcop2) + pic16_emitpcode(POC_CLRF, pcop2); + else + emitCLRC; + } else { + if(pcop2) + pic16_emitpcode(POC_SETF, pcop2); + else + emitSETC; + } + + /* don't emit final branch (offset == 0) */ + if(offset) { + + if(pcop2) + pic16_emitpcode(POC_RRCF, pcop2); + + pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key)); + } + } else { + if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) { + DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d", + __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset); + + truelbl = newiTempLabel( NULL ); + pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key)); + if((!ifx || !IC_TRUE(ifx)) && (sign && !offset)) + pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key)); + else + pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key)); + pic16_emitpLabel(truelbl->key); + } else { + pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key)); + } + } +} + +static void genCmp (operand *left, operand *right, + operand *result, iCode *ifx, int sign) +{ + int size, cmpop=1; + long lit = 0L; + resolvedIfx rFalseIfx; + symbol *falselbl, *tlbl; + + FENTRY; + + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + + resolveIfx(&rFalseIfx, ifx); + size = max(AOP_SIZE(left), AOP_SIZE(right)); + + /* if left & right are bit variables */ + if(AOP_TYPE(left) == AOP_CRY + && AOP_TYPE(right) == AOP_CRY ) { + + pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); + + werror(W_POSSBUG2, __FILE__, __LINE__); + exit(-1); + } + + /* 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; + + lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit); + +// 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); + } + + /* actual comparing algorithm */ +// size = AOP_SIZE( right ); + + falselbl = newiTempLabel( NULL ); + if(AOP_TYPE(left) == AOP_LIT) { + /* compare to literal */ + DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__); + + if(sign) { + pCodeOp *pct, *pct2; + symbol *tlbl1; + + /* signed compare */ + DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__); + + pct = pic16_popCopyReg(&pic16_pc_prodl); + pct2 = pic16_popCopyReg(&pic16_pc_prodh); + tlbl = newiTempLabel( NULL ); + + /* first compare signs: + * a. if both are positive, compare just like unsigned + * b. if both are negative, invert cmpop, compare just like unsigned + * c. if different signs, determine the result directly */ + + size--; + +#if 1 + /* { */ + tlbl1 = newiTempLabel( NULL ); +// pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */ + + if(lit > 0) { + + /* literal is zero or positive: + * a. if carry is zero, too, continue compare, + * b. if carry is set, then continue depending on cmpop ^ condition: + * 1. '<' return false (literal < variable), + * 2. '>' return true (literal > variable) */ +// pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key )); + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7)); + + + if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key )); + else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key )); + } else + if(lit < 0) { + + /* literal is negative: + * a. if carry is set, too, continue compare, + * b. if carry is zero, then continue depending on cmpop ^ condition: + * 1. '<' return true (literal < variable), + * 2. '>' return false (literal > variable) */ +// pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key )); + pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7)); + + if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key )); + else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key)); + } +#if 1 + else { + /* lit == 0 */ + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7)); + + if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key )); + else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key)); + } +#endif + + + pic16_emitpLabel( tlbl1->key ); +#endif /* } */ + + compareAopfirstpass=1; +// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); +// pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size)); +// pic16_emitpcode(POC_MOVWF, pct); + +// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size))); +// compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); + compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl); + + /* generic case */ + while( size-- ) { +// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); +// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0)); +// pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size)); +// pic16_emitpcode(POC_MOVWF, pct); + +// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0)); + compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl); +// 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; + + if(AOP_SIZE(result)) { + pic16_emitpLabel(tlbl->key); + pic16_emitpLabel(falselbl->key); + pic16_outBitOp( result, pct2 ); + } else { + pic16_emitpLabel(tlbl->key); + } + } else { + + /* unsigned compare */ + DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); + + compareAopfirstpass=1; + while(size--) { + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size))); + 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 ); + } + + } + } else { + /* compare registers */ + DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__); + + + if(sign) { + pCodeOp *pct, *pct2; + + /* signed compare */ + DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__); + + pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */ + pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */ + tlbl = newiTempLabel( NULL ); + + compareAopfirstpass=1; + + size--; + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size)); +// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); + pic16_emitpcode(POC_MOVWF, pct); + + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size)); +// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); + + /* WREG already holds left + 0x80 */ + compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); + + while( size-- ) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size)); +// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); + pic16_emitpcode(POC_MOVWF, pct); + + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size)); +// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); + + /* WREG already holds left + 0x80 */ + 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; + + if(AOP_SIZE(result)) { + pic16_emitpLabel(tlbl->key); + pic16_emitpLabel(falselbl->key); + pic16_outBitOp( result, pct2 ); + } else { + pic16_emitpLabel(tlbl->key); + } + + } else { + /* unsigned compare */ + DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); + + compareAopfirstpass=1; + while(size--) { + + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size)); + 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 ); + } + + } + } +} + +#endif /* } */ + + + /*-----------------------------------------------------------------*/ /* genCmpGt :- greater than comparison */ /*-----------------------------------------------------------------*/ static void genCmpGt (iCode *ic, iCode *ifx) { - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; + left = IC_LEFT(ic); right= IC_RIGHT(ic); result = IC_RESULT(ic); @@ -5249,11 +6309,12 @@ static void genCmpGt (iCode *ic, iCode *ifx) /*-----------------------------------------------------------------*/ static void genCmpLt (iCode *ic, iCode *ifx) { - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; + + FENTRY; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); left = IC_LEFT(ic); right= IC_RIGHT(ic); result = IC_RESULT(ic); @@ -5590,10 +6651,10 @@ static void gencjne(operand *left, operand *right, iCode *ifx) /*-----------------------------------------------------------------*/ static bool is_LitOp(operand *op) { - return (AOP_TYPE(op) == AOP_LIT) + return ((AOP_TYPE(op) == AOP_LIT) || ( (AOP_TYPE(op) == AOP_PCODE) && ( (AOP(op)->aopu.pcop->type == PO_LITERAL) - || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )); + || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ))); } /*-----------------------------------------------------------------*/ @@ -5601,10 +6662,10 @@ static bool is_LitOp(operand *op) /*-----------------------------------------------------------------*/ static bool is_LitAOp(asmop *aop) { - return (aop->type == AOP_LIT) + return ((aop->type == AOP_LIT) || ( (aop->type == AOP_PCODE) && ( (aop->aopu.pcop->type == PO_LITERAL) - || (aop->aopu.pcop->type == PO_IMMEDIATE) )); + || (aop->aopu.pcop->type == PO_IMMEDIATE) ))); } @@ -5621,16 +6682,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; @@ -5643,6 +6707,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; @@ -5664,9 +6732,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)); @@ -5793,7 +6863,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) pic16_emitcode("jc","%05d_DS_",tlbl->key+100); pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100); } - pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset); + pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset); { /* left and right are both bit variables, result is carry */ @@ -5910,11 +6980,11 @@ static void genCmpEq (iCode *ic, iCode *ifx) if ( IC_TRUE(ifx) ) { emitSKPNZ; pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset); + // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); } else { emitSKPZ; pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset); + // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); } } else { @@ -5934,7 +7004,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ"); pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset); + pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset); } else { emitSKPNZ; @@ -5942,7 +7012,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset); + pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); } } else { emitSKPZ; @@ -5950,13 +7020,13 @@ static void genCmpEq (iCode *ic, iCode *ifx) DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ"); pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset); + pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); } offset++; } if(s>1 && IC_TRUE(ifx)) { pic16_emitpLabel(tlbl->key); - pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset); + pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset); } } } @@ -6045,8 +7115,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 ; @@ -6062,12 +7133,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 && @@ -6120,16 +7193,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); @@ -6168,16 +7242,17 @@ static void genAndOp (iCode *ic) static void genOrOp (iCode *ic) { - operand *left,*right, *result; - symbol *tlbl; + operand *left,*right, *result; + symbol *tlbl; - /* note here that || operations that are in an + FENTRY; + + /* 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); @@ -6197,9 +7272,9 @@ static void genOrOp (iCode *ic) tlbl = newiTempLabel(NULL); pic16_toBoolean(left); emitSKPZ; - pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset); + pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset); pic16_toBoolean(right); - pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset); + pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset); pic16_outBitAcc(result); } @@ -6235,10 +7310,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; } /*-----------------------------------------------------------------*/ @@ -6246,10 +7321,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; } /*-----------------------------------------------------------------*/ @@ -6257,20 +7332,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; } /*-----------------------------------------------------------------*/ @@ -6284,8 +7358,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); @@ -6401,9 +7475,9 @@ 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)); + pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER)); } /* @@ -6419,10 +7493,37 @@ static void genAnd (iCode *ic, iCode *ifx) } else { symbol *tlbl = newiTempLabel(NULL); int sizel = AOP_SIZE(left); + if(size) - pic16_emitcode("setb","c"); - while(sizel--){ - if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){ + emitSETC; + + while(sizel--) { + if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) { + + /* patch provided by Aaron Colwell */ + if((posbit = isLiteralBit(bytelit)) != 0) { + pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ), + pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE), + (posbit-1),0, PO_GPR_REGISTER)); + + pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key)); +// pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key)); + } else { + if (bytelit == 0xff) { + /* Aaron had a MOVF instruction here, changed to MOVFW cause + * a peephole could optimize it out -- VR */ + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset)); + } else { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit)); + } + + pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ), + pic16_popGetLabel(tlbl->key)); + } + +#if 0 + /* old code, left here for reference -- VR 09/2004 */ MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE)); // byte == 2^n ? if((posbit = isLiteralBit(bytelit)) != 0) @@ -6432,22 +7533,27 @@ static void genAnd (iCode *ic, iCode *ifx) pic16_emitcode("anl","a,%s", pic16_aopGet(AOP(right),offset,FALSE,TRUE)); pic16_emitcode("jnz","%05d_DS_",tlbl->key+100); - } + } +#endif } offset++; } // bit = left & literal - if(size){ - pic16_emitcode("clr","c"); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); + if(size) { + emitCLRC; + pic16_emitpLabel(tlbl->key); } // if(left & literal) - else{ - if(ifx) - jmpTrueOrFalse(ifx, tlbl); - goto release ; + else { + if(ifx) { + pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key)); + ifx->generated = 1; + } + pic16_emitpLabel(tlbl->key); + goto release; } } + pic16_outBitC(result); goto release ; } @@ -6469,11 +7575,11 @@ 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); - pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0)); + pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER)); } else { pic16_emitcode("movlw","0x%x", (lit & 0xff)); @@ -6773,11 +7879,11 @@ 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, - pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0)); + pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER)); } else { if(know_W != (lit & 0xff)) pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); @@ -7134,8 +8240,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) { @@ -7183,7 +8350,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); @@ -7228,7 +8395,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); @@ -7383,12 +8550,10 @@ static void AccRsh (int shCount, int andmask) return; break; case 1 : pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); -// andmask = 0; /* no need */ break; case 2 : pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); -// andmask = 0; /* no need */ break; case 3 : pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); @@ -7447,6 +8612,7 @@ static void AccSRsh (int shCount) } } #endif + /*-----------------------------------------------------------------*/ /* shiftR1Left2Result - shift right one byte from left to result */ /*-----------------------------------------------------------------*/ @@ -7493,11 +8659,11 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); } - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr)); + //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); @@ -7506,7 +8672,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, case 4: pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); break; @@ -7519,7 +8685,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, } pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); break; @@ -7527,30 +8693,30 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, case 6: if(same) { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); } 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)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0)); - pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + 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)); } break; case 7: if(same) { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); } 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)); - pic16_emitpcode(POC_DECF, 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_SETF, pic16_popGet(AOP(result),offr)); } default: @@ -7609,8 +8775,8 @@ static void shiftR1Left2Result (operand *left, int offl, pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); } - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr)); + //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); break; @@ -7623,19 +8789,19 @@ static void shiftR1Left2Result (operand *left, int offl, case 5: pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - emitCLRC; - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); + //emitCLRC; + pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr)); break; case 6: - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr)); break; case 7: @@ -7849,7 +9015,7 @@ static void shiftL2Left2Result (operand *left, int offl, pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F)); pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); @@ -7968,7 +9134,7 @@ static void shiftR2Left2Result (operand *left, int offl, if(sign) { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 )); pic16_emitpcode(POC_BTFSC, - pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0)); + pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); } @@ -7986,7 +9152,7 @@ static void shiftR2Left2Result (operand *left, int offl, pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03)); if(sign) { pic16_emitpcode(POC_BTFSC, - pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0)); + pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc)); } pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16)); @@ -8004,7 +9170,7 @@ static void shiftR2Left2Result (operand *left, int offl, pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03)); if(sign) { pic16_emitpcode(POC_BTFSC, - pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0)); + pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc)); } pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); @@ -8122,7 +9288,7 @@ static void shiftLLong (operand *left, operand *result, int offr ) pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr)); } - if (size >= LSB+offr ){ + if (size > LSB+offr ){ if (same) { pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr)); } else { @@ -8131,7 +9297,7 @@ static void shiftLLong (operand *left, operand *result, int offr ) } } - if(size >= MSB16+offr){ + if(size > MSB16+offr){ if (same) { pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr)); } else { @@ -8140,7 +9306,7 @@ static void shiftLLong (operand *left, operand *result, int offr ) } } - if(size >= MSB24+offr){ + if(size > MSB24+offr){ if (same) { pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr)); } else { @@ -8233,103 +9399,292 @@ static void genlshFour (operand *result, operand *left, int shCount) } } - /* 1 <= shCount <= 7 */ - else if(shCount <= 3) - { - shiftLLong(left, result, LSB); - while(--shCount >= 1) - shiftLLong(result, result, LSB); - } - /* 3 <= shCount <= 7, optimize */ - else{ - shiftL2Left2Result(left, MSB24, result, MSB24, shCount); - shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount); - shiftL2Left2Result(left, LSB, result, LSB, shCount); - } -} + /* 1 <= shCount <= 7 */ + else if(shCount <= 3) + { + shiftLLong(left, result, LSB); + while(--shCount >= 1) + shiftLLong(result, result, LSB); + } + /* 3 <= shCount <= 7, optimize */ + else{ + shiftL2Left2Result(left, MSB24, result, MSB24, shCount); + shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount); + shiftL2Left2Result(left, LSB, result, LSB, shCount); + } +} + +/*-----------------------------------------------------------------*/ +/* genLeftShiftLiteral - left shifting by known count */ +/*-----------------------------------------------------------------*/ +void pic16_genLeftShiftLiteral (operand *left, + operand *right, + operand *result, + iCode *ic) +{ + int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit)); + int size; + + FENTRY; + DEBUGpic16_emitcode ("; ***","shCount:%d", shCount); + pic16_freeAsmop(right,NULL,ic,TRUE); + + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,TRUE); + + size = getSize(operandType(result)); + +#if VIEW_SIZE + pic16_emitcode("; shift left ","result %d, left %d",size, + AOP_SIZE(left)); +#endif + + /* I suppose that the left size >= result size */ + if(shCount == 0){ + while(size--){ + movLeft2Result(left, size, result, size); + } + } + + else if(shCount >= (size * 8)) + while(size--) + pic16_aopPut(AOP(result),zero,size); + else{ + switch (size) { + case 1: + genlshOne (result,left,shCount); + break; + + case 2: + case 3: + genlshTwo (result,left,shCount); + break; + + case 4: + genlshFour (result,left,shCount); + break; + } + } + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} + +/*-----------------------------------------------------------------* + * genMultiAsm - repeat assembly instruction for size of register. + * if endian == 1, then the high byte (i.e base address + size of + * register) is used first else the low byte is used first; + *-----------------------------------------------------------------*/ +static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian) +{ + + int offset = 0; + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + if(!reg) + return; + + if(!endian) { + endian = 1; + } else { + endian = -1; + offset = size-1; + } + + while(size--) { + pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset)); + offset += endian; + } + +} + +#if !(USE_GENERIC_SIGNED_SHIFT) +/*-----------------------------------------------------------------*/ +/* genLeftShift - generates code for left shifting */ +/*-----------------------------------------------------------------*/ +static void genLeftShift (iCode *ic) +{ + operand *left,*right, *result; + int size, offset; +// char *l; + symbol *tlbl , *tlbl1; + pCodeOp *pctemp; + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + right = IC_RIGHT(ic); + left = IC_LEFT(ic); + result = IC_RESULT(ic); + + pic16_aopOp(right,ic,FALSE); + + /* if the shift count is known then do it + as efficiently as possible */ + if (AOP_TYPE(right) == AOP_LIT) { + pic16_genLeftShiftLiteral (left,right,result,ic); + return ; + } + + /* shift count is unknown then we have to form + * a loop. Get the loop count in WREG : 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 ) */ + + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,FALSE); + + /* now move the left to the result if they are not the + * same, and if size > 1, + * and if right is not same to result (!!!) -- VR */ + if (!pic16_sameRegs(AOP(left),AOP(result)) + && (AOP_SIZE(result) > 1)) { + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + size = AOP_SIZE(result); + offset=0; + while (size--) { + +#if 0 + l = pic16_aopGet(AOP(left),offset,FALSE,TRUE); + if (*l == '@' && (IS_AOP_PREG(result))) { + + pic16_emitcode("mov","a,%s",l); + pic16_aopPut(AOP(result),"a",offset); + } else +#endif + { + /* we don't know if left is a literal or a register, take care -- VR */ + pic16_mov2f(AOP(result), AOP(left), offset); + } + offset++; + } + } + + size = AOP_SIZE(result); + + /* if it is only one byte then */ + if (size == 1) { + if(optimized_for_speed) { + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe)); + pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); + } else { + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + tlbl = newiTempLabel(NULL); + +#if 1 + /* this is already done, why change it? */ + if (!pic16_sameRegs(AOP(left),AOP(result))) { + pic16_mov2f(AOP(result), AOP(left), 0); + } +#endif + + pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); + pic16_emitpLabel(tlbl->key); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); + emitSKPC; + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); + } + goto release ; + } + + if (pic16_sameRegs(AOP(left),AOP(result))) { + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + tlbl = newiTempLabel(NULL); + pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); + genMultiAsm(POC_RRCF, result, size,1); + pic16_emitpLabel(tlbl->key); + genMultiAsm(POC_RLCF, result, size,0); + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); + emitSKPC; + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); + goto release; + } + + //tlbl = newiTempLabel(NULL); + //offset = 0 ; + //tlbl1 = newiTempLabel(NULL); -/*-----------------------------------------------------------------*/ -/* genLeftShiftLiteral - left shifting by known count */ -/*-----------------------------------------------------------------*/ -static void genLeftShiftLiteral (operand *left, - operand *right, - operand *result, - iCode *ic) -{ - int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); - int size; + //reAdjustPreg(AOP(result)); + + //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); + //pic16_emitcode("","%05d_DS_:",tlbl->key+100); + //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); + //MOVA(l); + //pic16_emitcode("add","a,acc"); + //pic16_aopPut(AOP(result),"a",offset++); + //while (--size) { + // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); + // MOVA(l); + // pic16_emitcode("rlc","a"); + // pic16_aopPut(AOP(result),"a",offset++); + //} + //reAdjustPreg(AOP(result)); - DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount); - pic16_freeAsmop(right,NULL,ic,TRUE); + //pic16_emitcode("","%05d_DS_:",tlbl1->key+100); + //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); - size = getSize(operandType(result)); + tlbl = newiTempLabel(NULL); + tlbl1= newiTempLabel(NULL); -#if VIEW_SIZE - pic16_emitcode("; shift left ","result %d, left %d",size, - AOP_SIZE(left)); -#endif + size = AOP_SIZE(result); + offset = 1; - /* I suppose that the left size >= result size */ - if(shCount == 0){ - while(size--){ - movLeft2Result(left, size, result, size); - } - } + pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */ - else if(shCount >= (size * 8)) - while(size--) - pic16_aopPut(AOP(result),zero,size); - else{ - switch (size) { - case 1: - genlshOne (result,left,shCount); - break; + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - case 2: - case 3: - genlshTwo (result,left,shCount); - break; + /* offset should be 0, 1 or 3 */ + + pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1)); + emitSKPNZ; + pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key)); - case 4: - genlshFour (result,left,shCount); - break; - } - } - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); -} + pic16_emitpcode(POC_MOVWF, pctemp); -/*-----------------------------------------------------------------* - * genMultiAsm - repeat assembly instruction for size of register. - * if endian == 1, then the high byte (i.e base address + size of - * register) is used first else the low byte is used first; - *-----------------------------------------------------------------*/ -static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian) -{ - int offset = 0; + pic16_emitpLabel(tlbl->key); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); + while(--size) + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++)); - if(!reg) - return; + pic16_emitpcode(POC_DECFSZ, pctemp); + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); + pic16_emitpLabel(tlbl1->key); - if(!endian) { - endian = 1; - } else { - endian = -1; - offset = size-1; - } + pic16_popReleaseTempReg(pctemp,1); - while(size--) { - pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset)); - offset += endian; - } + release: + pic16_freeAsmop (right,NULL,ic,TRUE); + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif + + +#if 0 +#error old code (left here for reference) /*-----------------------------------------------------------------*/ /* genLeftShift - generates code for left shifting */ /*-----------------------------------------------------------------*/ @@ -8352,7 +9707,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 ; } @@ -8371,6 +9726,8 @@ static void genLeftShift (iCode *ic) if (!pic16_sameRegs(AOP(left),AOP(result)) && AOP_SIZE(result) > 1) { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + size = AOP_SIZE(result); offset=0; while (size--) { @@ -8380,9 +9737,9 @@ static void genLeftShift (iCode *ic) pic16_emitcode("mov","a,%s",l); pic16_aopPut(AOP(result),"a",offset); } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - //pic16_aopPut(AOP(result),l,offset); + + /* we don't know if left is a literal or a register, take care -- VR */ + pic16_mov2f(AOP(result), AOP(left), offset); } offset++; } @@ -8395,22 +9752,26 @@ static void genLeftShift (iCode *ic) if(optimized_for_speed) { pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0)); + pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe)); pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); } else { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + tlbl = newiTempLabel(NULL); if (!pic16_sameRegs(AOP(left),AOP(result))) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),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)); } pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); @@ -8426,6 +9787,8 @@ static void genLeftShift (iCode *ic) if (pic16_sameRegs(AOP(left),AOP(result))) { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + tlbl = newiTempLabel(NULL); pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); genMultiAsm(POC_RRCF, result, size,1); @@ -8467,7 +9830,7 @@ static void genLeftShift (iCode *ic) size = AOP_SIZE(result); offset = 1; - pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */ + pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); @@ -8491,7 +9854,7 @@ static void genLeftShift (iCode *ic) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); pic16_emitpLabel(tlbl1->key); - pic16_popReleaseTempReg(pctemp); + pic16_popReleaseTempReg(pctemp,1); release: @@ -8499,6 +9862,7 @@ static void genLeftShift (iCode *ic) pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif /*-----------------------------------------------------------------*/ /* genrshOne - right shift a one byte quantity by known count */ @@ -8526,12 +9890,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)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16)); - } + pic16_addSign (result, 1, sign); } /* 1 <= shCount <= 7 */ @@ -8668,13 +10027,13 @@ static void genRightShiftLiteral (operand *left, iCode *ic, int sign) { - int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); + int shCount = (int) abs(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)); @@ -8689,8 +10048,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)){ @@ -8698,14 +10059,14 @@ static void genRightShiftLiteral (operand *left, if(res_size == 1) { 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)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB)); + pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB)); } } else { if(sign) { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); while(res_size--) pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size)); @@ -8740,6 +10101,7 @@ static void genRightShiftLiteral (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* genSignedRightShift - right shift of signed number */ /*-----------------------------------------------------------------*/ @@ -8813,7 +10175,7 @@ static void genSignedRightShift (iCode *ic) size = AOP_SIZE(result); offset = size - 1; - pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */ + pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); @@ -8838,7 +10200,7 @@ static void genSignedRightShift (iCode *ic) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); pic16_emitpLabel(tlbl1->key); - pic16_popReleaseTempReg(pctemp); + pic16_popReleaseTempReg(pctemp,1); #if 0 size = AOP_SIZE(result); offset = size - 1; @@ -8880,7 +10242,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 */ /*-----------------------------------------------------------------*/ @@ -8997,35 +10362,284 @@ release: 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); +} + +static void genRightShift (iCode *ic) { + genGenericShift (ic, 0); +} +#endif + + +/* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */ +void pic16_loadFSR0(operand *op, int lit) +{ + if(OP_SYMBOL(op)->remat || is_LitOp( op )) { + pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + } else { + assert (!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) +{ + 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?) + pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl))); + pic16_emitpcode (POC_MOVFW, pic16_popGet(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; + } +} /*-----------------------------------------------------------------*/ /* genUnpackBits - generates code for unpacking bits */ /*-----------------------------------------------------------------*/ -static void genUnpackBits (operand *result, char *rname, int ptype) +static void genUnpackBits (operand *result, operand *left, char *rname, int ptype) { - int shCnt ; - int rlen = 0 ; - sym_link *etype; - int offset = 0 ; + int shCnt ; + sym_link *etype, *letype; + int blen=0, bstr=0; + int lbstr; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - etype = getSpec(operandType(result)); - - /* 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; - } + 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); +// } + + lbstr = SPEC_BSTR( letype ); + +#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__); + + pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); + + // distinguish (p->bitfield) and p.bitfield, remat seems to work... + if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) { + /* workaround to reduce the extra lfsr instruction */ + pic16_emitpcode(POC_BTFSC, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr)); + } else { + pic16_loadFSR0 (left, 0); + pic16_emitpcode(POC_BTFSC, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); + } + pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); + + pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 )); + return; + } + +#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 */ + + if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) { + // access symbol directly + pic16_mov2w (AOP(left), 0); + } else { + pic16_derefPtr (left, ptype, 0, NULL); + } /* if we have bitdisplacement then it fits */ /* into this byte completely or if length is */ @@ -9048,63 +10662,14 @@ static void genUnpackBits (operand *result, char *rname, int ptype) pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); return ; - } - - - - 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); - - /* bit field did not fit in a byte */ - rlen = SPEC_BLEN(etype) - 8; - pic16_aopPut(AOP(result),"a",offset++); - - while (1) { - - 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; + } - 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; - } - 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); - } - + + 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); + return ; } @@ -9116,7 +10681,9 @@ static void genDataPointerGet(operand *left, 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); @@ -9168,9 +10735,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( @@ -9186,10 +10753,6 @@ release: pic16_freeAsmop(result,NULL,ic,TRUE); } -void pic16_loadFSR0(operand *op) -{ - pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); -} /*-----------------------------------------------------------------*/ @@ -9199,135 +10762,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 - { - pic16_loadFSR0( left ); // patch 10 - } else { - // 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); - /* if bitfield then unpack the bits */ - if (IS_BITFIELD(retype)) - genUnpackBits (result, NULL, POINTER); + DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result); + +#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_indf0), - pic16_popGet(AOP(result), offset++))); - } else { - pic16_emitpcode(POC_MOVFF, - pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), - 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); - } /*-----------------------------------------------------------------*/ @@ -9363,11 +10924,11 @@ 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)) - genUnpackBits (result,rname,PPOINTER); + genUnpackBits (result,left,rname,PPOINTER); else { /* we have can just get the values */ int size = AOP_SIZE(result); @@ -9441,11 +11002,11 @@ 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)) - genUnpackBits(result,"dptr",FPOINTER); + genUnpackBits(result,left,"dptr",FPOINTER); else { size = AOP_SIZE(result); offset = 0 ; @@ -9460,6 +11021,7 @@ static void genFarPointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } + #if 0 /*-----------------------------------------------------------------*/ /* genCodePointerGet - get value from code space */ @@ -9495,7 +11057,7 @@ static void genCodePointerGet (operand *left, /* if bit then unpack */ if (IS_BITFIELD(retype)) - genUnpackBits(result,"dptr",CPOINTER); + genUnpackBits(result,left,"dptr",CPOINTER); else { size = AOP_SIZE(result); offset = 0 ; @@ -9512,6 +11074,8 @@ static void genCodePointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } #endif + +#if 0 /*-----------------------------------------------------------------*/ /* genGenPointerGet - gget value from generic pointer space */ /*-----------------------------------------------------------------*/ @@ -9552,7 +11116,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--) { @@ -9568,13 +11132,76 @@ static void genGenPointerGet (operand *left, /* if bit then unpack */ if (IS_BITFIELD(retype)) - genUnpackBits(result,"BAD",GPOINTER); + genUnpackBits(result,left,"BAD",GPOINTER); release: pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif + + +/*-----------------------------------------------------------------*/ +/* genGenPointerGet - gget value from generic pointer space */ +/*-----------------------------------------------------------------*/ +static void genGenPointerGet (operand *left, + operand *result, iCode *ic) +{ + int size, offset, lit; + sym_link *letype = getSpec(operandType(left)); + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_aopOp(left,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!) + + lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit); + // load FSR0 from immediate + pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit))); + + werror(W_POSSBUG2, __FILE__, __LINE__); + + offset = 0; + 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))); + } + offset++; + } + + goto release; + + } 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)); + + pic16_callGenericPointerRW(0, size); + + assignResultValue(result, 1); + + goto release; + } + +release: + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} /*-----------------------------------------------------------------*/ /* genConstPointerGet - get value from const generic pointer space */ @@ -9597,29 +11224,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)); @@ -9627,25 +11236,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 { + 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))); + } - 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); - } @@ -9654,12 +11258,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) ; @@ -9677,57 +11281,56 @@ static void genPointerGet (iCode *ic) /* if left is of type of pointer then it is simple */ if (IS_PTR(type) && !IS_FUNC(type->next)) - p_type = DCL_TYPE(type); + p_type = DCL_TYPE(type); else { - /* we have to go by the storage class */ - p_type = PTR_TYPE(SPEC_OCLS(etype)); + /* we have to go by the storage class */ + p_type = PTR_TYPE(SPEC_OCLS(etype)); - DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__); + 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 (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 IPOINTER: genNearPointerGet (left,result,ic); break; - case PPOINTER: + case PPOINTER: genPagedPointerGet(left,result,ic); break; - case FPOINTER: + case FPOINTER: genFarPointerGet (left,result,ic); break; - 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); @@ -9741,13 +11344,12 @@ static void genPointerGet (iCode *ic) "genPointerGet: illegal pointer type"); } - } /*-----------------------------------------------------------------*/ /* genPackBits - generates code for packed bit storage */ /*-----------------------------------------------------------------*/ -static void genPackBits (sym_link *etype , +static void genPackBits (sym_link *etype , operand *result, operand *right , char *rname, int p_type) { @@ -9755,12 +11357,14 @@ static void genPackBits (sym_link *etype , int offset = 0 ; int rLen = 0 ; int blen, bstr ; - char *l ; + sym_link *retype; 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; @@ -9770,86 +11374,133 @@ static void genPackBits (sym_link *etype , lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); - if(lit) { - pic16_emitpcode(POC_BSF, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); + if(OP_SYMBOL(result)->remat && (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 { - pic16_emitpcode(POC_BCF, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); + pic16_loadFSR0(result, 0); + 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; } - + /* move literal to W */ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0)); offset++; } else - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); + if(IS_BITFIELD(retype) + && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR) + && (blen == 1)) { + int rblen, rbstr; - /* if the bit lenth is less than or */ - /* it exactly fits a byte then */ - if((shCnt=SPEC_BSTR(etype)) - || SPEC_BLEN(etype) <= 8 ) { + rblen = SPEC_BLEN( retype ); + rbstr = SPEC_BSTR( retype ); + - /* shift left acc */ - AccLsh(shCnt); + 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)); + } - /* using PRODL as a temporary register here */ - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0)); + + return; + } else { + /* move right to W */ + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); + } - switch (p_type) { - case FPOINTER: - case POINTER: - case GPOINTER: - pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); -// pic16_emitcode ("mov","b,a"); -// pic16_emitcode("mov","a,@%s",rname); - break; - } + /* 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; + + if (blen != 8 || bstr != 0) { + // we need to combine the value with the old value + 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)); + + /* shift left acc */ + AccLsh(shCnt); + + /* using PRODH as a temporary register here */ + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh)); + + if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) { + /* 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( + 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)); + pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh)); + } // if (blen != 8 || bstr != 0) + + /* write new value back */ + if (IS_SYMOP(result) & !IS_PTR(operandType(result))) { + pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0)); + } else { + pic16_derefPtr (result, p_type, 1, &fsr0_setup); + } #endif return; } +#if 0 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); exit(-1); +#endif - /* if we r done */ - if ( SPEC_BLEN(etype) <= 8 ) - return ; - - pic16_emitcode("inc","%s",rname); - rLen = SPEC_BLEN(etype) ; - - - + pic16_loadFSR0(result, 0); // load FSR0 with address of result + rLen = SPEC_BLEN(etype)-8; + /* now generate for lengths greater than one byte */ while (1) { - - l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE); - rLen -= 8 ; - if (rLen <= 0 ) - break ; + if (rLen <= 0 ) { + mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset); + break ; + } switch (p_type) { case POINTER: - if (*l == '@') { - MOVA(l); - pic16_emitcode("mov","@%s,a",rname); - } else - pic16_emitcode("mov","@%s,%s",rname,l); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0)); break; +/* case FPOINTER: MOVA(l); pic16_emitcode("movx","@dptr,a"); @@ -9859,21 +11510,25 @@ static void genPackBits (sym_link *etype , MOVA(l); DEBUGpic16_emitcode(";lcall","__gptrput"); break; +*/ + default: + assert(0); } - pic16_emitcode ("inc","%s",rname); - } - MOVA(l); + + pic16_mov2w(AOP(right), offset++); + } /* 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); +// pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); break; +/* case FPOINTER: pic16_emitcode ("mov","b,a"); pic16_emitcode("movx","a,@dptr"); @@ -9885,29 +11540,40 @@ static void genPackBits (sym_link *etype , pic16_emitcode ("lcall","__gptrget"); pic16_emitcode ("pop","b"); break; +*/ + default: + assert(0); } - - pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) ); - pic16_emitcode ("orl","a,b"); + 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) { - case POINTER: - pic16_emitcode("mov","@%s,a",rname); + case POINTER: + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); +// pic16_emitcode("mov","@%s,a",rname); break; - - case FPOINTER: +/* + case FPOINTER: pic16_emitcode("movx","@dptr,a"); break; - case GPOINTER: + case GPOINTER: DEBUGpic16_emitcode(";lcall","__gptrput"); break; +*/ + default: + assert(0); } + +// pic16_freeAsmop(right, NULL, ic, TRUE); } /*-----------------------------------------------------------------*/ /* genDataPointerSet - remat pointer to data space */ @@ -9940,19 +11606,32 @@ static void genDataPointerSet(operand *right, while (size--) { if (AOP_TYPE(right) == AOP_LIT) { - unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit); - - 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 - } + unsigned int lit; + + if(!IS_FLOAT(operandType( right ))) + lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + else { + union { + unsigned long lit_int; + float lit_float; + } info; + + /* take care if literal is a float */ + info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + lit = info.lit_int; + } + + lit = lit >> (8*offset); + 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 { + pic16_mov2w(AOP(right), offset); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8 + } offset++; resoffset++; } @@ -9970,7 +11649,6 @@ static void genNearPointerSet (operand *right, iCode *ic) { asmop *aop = NULL; - char *l; sym_link *retype; sym_link *ptype = operandType(result); sym_link *resetype; @@ -9997,102 +11675,73 @@ static void genNearPointerSet (operand *right, } 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 - { - pic16_loadFSR0( result ); // patch 10 - } else { - // 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_aopOp(right,ic,FALSE); + DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); /* if bitfield then unpack the bits */ if (IS_BITFIELD(resetype)) { - genPackBits (resetype, right, NULL, POINTER); + genPackBits (resetype, result, right, NULL, POINTER); } else { /* we have can just get the values */ int size = AOP_SIZE(right); int offset = 0 ; + pic16_loadFSR0(result, 0); + 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 (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 - } + 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); + /* 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; - - while (size--) - pic16_emitcode("decf","fsr0,f"); - //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(right) > 1 + && !OP_SYMBOL(result)->remat + && ( OP_SYMBOL(result)->liveTo > ic->seq + || ic->depth )) { + + int size = AOP_SIZE(right) - 1; + + 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); } /*-----------------------------------------------------------------*/ @@ -10131,7 +11780,7 @@ static void genPagedPointerSet (operand *right, /* if bitfield then unpack the bits */ if (IS_BITFIELD(retype)) - genPackBits (retype,right,rname,PPOINTER); + genPackBits (retype,result,right,rname,PPOINTER); else { /* we have can just get the values */ int size = AOP_SIZE(right); @@ -10209,7 +11858,7 @@ static void genFarPointerSet (operand *right, /* if bit then unpack */ if (IS_BITFIELD(retype)) - genPackBits(retype,right,"dptr",FPOINTER); + genPackBits(retype,result,right,"dptr",FPOINTER); else { size = AOP_SIZE(right); offset = 0 ; @@ -10229,6 +11878,7 @@ static void genFarPointerSet (operand *right, /*-----------------------------------------------------------------*/ /* genGenPointerSet - set value from generic pointer space */ /*-----------------------------------------------------------------*/ +#if 0 static void genGenPointerSet (operand *right, operand *result, iCode *ic) { @@ -10316,7 +11966,7 @@ static void genGenPointerSet (operand *right, /* if bit then unpack */ if (IS_BITFIELD(retype)) - genPackBits(retype,right,"dptr",GPOINTER); + genPackBits(retype,result,right,"dptr",GPOINTER); else { size = AOP_SIZE(right); offset = 0 ; @@ -10350,17 +12000,71 @@ static void genGenPointerSet (operand *right, pic16_freeAsmop(right,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif + +static void genGenPointerSet (operand *right, + operand *result, iCode *ic) +{ + int size; + sym_link *retype = getSpec(operandType(result)); + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + pic16_aopOp(result,ic,FALSE); + pic16_aopOp(right,ic,FALSE); + size = AOP_SIZE(right); + + DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); + + + /* if bit then unpack */ + if (IS_BITFIELD(retype)) { +// pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit))); + genPackBits(retype,result,right,"dptr",GPOINTER); + goto release; + } + + size = AOP_SIZE(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 + * thing is that there is no need to manually restore stack pointer + * here */ + pushaop(AOP(right), 0); +// mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0); + if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1); + if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2); + if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3); + + /* load address to write to in WREG:FSR0H:FSR0L */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0), + pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1), + pic16_popCopyReg(&pic16_pc_prodl))); + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2)); + + pic16_callGenericPointerRW(1, size); + +release: + pic16_freeAsmop(right,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} /*-----------------------------------------------------------------*/ /* genPointerSet - stores the value into a pointer location */ /*-----------------------------------------------------------------*/ 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) ; @@ -10369,6 +12073,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); @@ -10396,27 +12101,26 @@ 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 POINTER: - case IPOINTER: - genNearPointerSet (right,result,ic); - break; - - case PPOINTER: - genPagedPointerSet (right,result,ic); - break; - - case FPOINTER: - genFarPointerSet (right,result,ic); + case PPOINTER: + genPagedPointerSet (right,result,ic); break; - case GPOINTER: - genGenPointerSet (right,result,ic); - break; + case FPOINTER: + genFarPointerSet (right,result,ic); + break; + + 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"); } } @@ -10428,36 +12132,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; } /*-----------------------------------------------------------------*/ @@ -10470,52 +12172,74 @@ 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((left=IC_LEFT(ic)), ic, FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - sym = OP_SYMBOL( left ); + sym = OP_SYMBOL( IC_LEFT(ic) ); + + if(sym->onStack) { + /* 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 %i\n", __FILE__, __LINE__, + OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack); +#endif - size = AOP_SIZE(IC_RESULT(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_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; + } + // if(pic16_debug_verbose) { // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n", // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype))); // } - /* Assume that what we want the address of is in data space - * since there is no stack on the PIC, yet! -- VR */ - /* low */ - pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); + pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE); + size = AOP_SIZE(IC_RESULT(ic)); - /* high */ - pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); - - /* upper */ - pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); + 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)))); + if (size == 3) { + pic16_emitpcode(POC_MOVLW, pcop0); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_MOVLW, pcop1); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); + pic16_emitpcode(POC_MOVLW, pcop2); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2)); + } else + if (size == 2) { + pic16_emitpcode(POC_MOVLW, pcop0); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_MOVLW, pcop1); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); + } else { + pic16_emitpcode(POC_MOVLW, pcop0); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); + } - if (size == 3) { - pic16_emitpcode(POC_MOVLW, pcop0); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - pic16_emitpcode(POC_MOVLW, pcop1); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); - pic16_emitpcode(POC_MOVLW, pcop2); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2)); - } else - if (size == 2) { - pic16_emitpcode(POC_MOVLW, pcop0); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_MOVLW, pcop1); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); - } else { - pic16_emitpcode(POC_MOVLW, pcop0); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - } - - pic16_freeAsmop(result,NULL,ic,TRUE); - pic16_freeAsmop(left, NULL, ic, FALSE); + pic16_freeAsmop(left, NULL, ic, FALSE); +release: + pic16_freeAsmop(result,NULL,ic,TRUE); } @@ -10560,14 +12284,17 @@ static void genAssign (iCode *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 ; - 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); @@ -10628,32 +12355,53 @@ static void genAssign (iCode *ic) offset = 0 ; if(AOP_TYPE(right) == AOP_LIT) { - if(!IS_FLOAT(operandType( right ))) + if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right)))) lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); - else { + 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_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; + } + + /* 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_SYMBOL(right)->etype))) { + && 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( (AOP_TYPE(right) == AOP_PCODE) - && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE) - || (AOP(right)->aopu.pcop->type == PO_DIR))) - { + 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)); @@ -10661,6 +12409,7 @@ static void genAssign (iCode *ic) 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), @@ -10669,7 +12418,8 @@ static void genAssign (iCode *ic) pic16_popCopyReg(&pic16_pc_tblptru))); } - size = min(AOP_SIZE(right), AOP_SIZE(result)); + /* 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), @@ -10677,8 +12427,11 @@ static void genAssign (iCode *ic) offset++; } - if(AOP_SIZE(result) > AOP_SIZE(right)) { - size = AOP_SIZE(result) - AOP_SIZE(right); + /* 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++; @@ -10689,12 +12442,15 @@ static void genAssign (iCode *ic) +#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__); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); if(aopIdx(AOP(result),0) == 4) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - assert(0); + + /* 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; @@ -10702,10 +12458,11 @@ static void genAssign (iCode *ic) // assert(0); DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__); } +#endif know_W=-1; while (size--) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size); if(AOP_TYPE(right) == AOP_LIT) { if(lit&0xff) { if(know_W != (lit&0xff)) @@ -10720,39 +12477,23 @@ static void genAssign (iCode *ic) } else if (AOP_TYPE(right) == AOP_CRY) { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); if(offset == 0) { - pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),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__); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); -#if 1 - /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It - normally should work, but mind that the W register live range - is not checked, so if the code generator assumes that the W - is already loaded after such a pair, wrong code will be generated. - - Checking the live range is the next step. - This is experimental code yet and has not been fully tested yet. - USE WITH CARE. Revert to old code by setting 0 to the condition above. - Vangelis Rokas 030603 (vrokas@otenet.gr) */ - - pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); -#else - /* This is the old code, which is assumed(?!) that works fine(!?) */ - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); -#endif + if(!_G.resDirect) /* use this aopForSym feature */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); } offset++; } - - + release: pic16_freeAsmop (right,NULL,ic,FALSE); pic16_freeAsmop (result,NULL,ic,TRUE); @@ -10763,10 +12504,13 @@ static void genAssign (iCode *ic) /*-----------------------------------------------------------------*/ static void genJumpTab (iCode *ic) { - symbol *jtab; - char *l; + 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 */ @@ -10781,6 +12525,7 @@ static void genJumpTab (iCode *ic) pic16_emitcode("jmp","@a+dptr"); pic16_emitcode("","%05d_DS_:",jtab->key+100); +#if 0 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key)); pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0)); emitSKPNC; @@ -10788,15 +12533,59 @@ static void genJumpTab (iCode *ic) pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl)); pic16_emitpLabel(jtab->key); +#else + + jt_offs = pic16_popGetTempReg(0); + jt_offs_hi = pic16_popGetTempReg(1); + jt_label = pic16_popGetLabel (jtab->key); + //fprintf (stderr, "Creating jump table...\n"); + + // calculate offset into jump table (idx * sizeof (GOTO)) + pic16_emitpcode(POC_CLRF , jt_offs_hi); + pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0)); + pic16_emitpcode(POC_RLCF , jt_offs_hi); + pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RLCF , jt_offs_hi); + pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC)); + pic16_emitpcode(POC_MOVWF , jt_offs); + + // prepare PCLATx (set to first entry in jump table) + pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0)); + pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu)); + pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0)); + pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath)); + pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0)); + + // set PCLATx to selected entry (new PCL is stored in jt_offs) + pic16_emitpcode(POC_ADDWF , jt_offs); + pic16_emitpcode(POC_MOVFW , jt_offs_hi); + pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath)); + emitSKPNC; + pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu)); + + // release temporaries and prepare jump into table (new PCL --> WREG) + pic16_emitpcode(POC_MOVFW , jt_offs); + pic16_popReleaseTempReg (jt_offs_hi, 1); + pic16_popReleaseTempReg (jt_offs, 0); + + // jump into the table + 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))) { - pic16_emitcode("ljmp","%05d_DS_",jtab->key+100); +// pic16_emitcode("ljmp","%05d_DS_",jtab->key+100); pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key)); } + pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, "")); } @@ -10939,19 +12728,23 @@ static void genCast (iCode *ic) operand *result = IC_RESULT(ic); sym_link *ctype = operandType(IC_LEFT(ic)); sym_link *rtype = operandType(IC_RIGHT(ic)); + sym_link *restype = operandType(IC_RESULT(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 ; +// 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); + /* if the result is a bit */ if (AOP_TYPE(result) == AOP_CRY) { @@ -10990,7 +12783,7 @@ static void genCast (iCode *ic) /* we need to or */ if (AOP_TYPE(right) == AOP_REG) { pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); } pic16_toBoolean(right); @@ -11015,6 +12808,11 @@ static void genCast (iCode *ic) goto release; } + if(IS_BITFIELD(getSpec(restype)) + && IS_BITFIELD(getSpec(rtype))) { + DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__); + } + /* if they are the same size : or less */ if (AOP_SIZE(result) <= AOP_SIZE(right)) { @@ -11128,16 +12926,20 @@ static void genCast (iCode *ic) offset = 0 ; while (size--) { if(offset < AOP_SIZE(right)) { - DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__); + DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type); + pic16_mov2f(AOP(result), AOP(right), offset); +/* 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 { + pic16_aopPut(AOP(result), pic16_aopGet(AOP(right),offset,FALSE,FALSE), offset); } +*/ } else pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset)); offset++; @@ -11146,21 +12948,34 @@ static void genCast (iCode *ic) switch (p_type) { case IPOINTER: case POINTER: - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1)); + 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)); 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 CPOINTER: - pic16_emitcode(";BUG!? ","%d",__LINE__); - l = "#0x02"; - break; case PPOINTER: pic16_emitcode(";BUG!? ","%d",__LINE__); l = "#0x03"; break; - + + case GPOINTER: + if (GPTRSIZE > AOP_SIZE(right)) { + // assume data pointer... THIS MIGHT BE WRONG! + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1)); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); + } + break; + default: /* this should never happen */ werror(E_INTERNAL_ERROR,__FILE__,__LINE__, @@ -11171,6 +12986,8 @@ static void genCast (iCode *ic) goto release ; } + + assert( 0 ); /* just copy the pointers */ size = AOP_SIZE(result); offset = 0 ; @@ -11198,9 +13015,10 @@ static void genCast (iCode *ic) /* we move to result for the size of source */ size = AOP_SIZE(right); offset = 0 ; + while (size--) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + if(!_G.resDirect) + pic16_mov2f(AOP(result), AOP(right), offset); offset++; } @@ -11216,15 +13034,15 @@ static void genCast (iCode *ic) if(size == 1) { /* 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)); - pic16_emitpcode(POC_DECF, 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_SETF, pic16_popGet(AOP(result),offset)); } else { pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg)); if(offset) - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); else - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); @@ -11287,14 +13105,9 @@ static int genDjnz (iCode *ic, iCode *ifx) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset); + pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset); } -/* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */ -/* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */ -/* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */ -/* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */ - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); ifx->generated = 1; @@ -11306,40 +13119,52 @@ static int genDjnz (iCode *ic, iCode *ifx) /*-----------------------------------------------------------------*/ static void genReceive (iCode *ic) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (isOperandInFarSpace(IC_RESULT(ic)) && - ( OP_SYMBOL(IC_RESULT(ic))->isspilt || - IS_TRUE_SYMOP(IC_RESULT(ic))) ) { + FENTRY; - int size = getSize(operandType(IC_RESULT(ic))); - int offset = pic16_fReturnSizePic - size; +#if 0 + fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__, + OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack); +#endif +// pic16_DumpOp(__FUNCTION__, IC_RESULT(ic)); - while (size--) { - pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ? - fReturn[pic16_fReturnSizePic - offset - 1] : "acc")); - offset++; - } + if (isOperandInFarSpace(IC_RESULT(ic)) + && ( OP_SYMBOL(IC_RESULT(ic))->isspilt + || IS_TRUE_SYMOP(IC_RESULT(ic))) ) { - DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__); + int size = getSize(operandType(IC_RESULT(ic))); + int offset = pic16_fReturnSizePic - size; - pic16_aopOp(IC_RESULT(ic),ic,FALSE); - size = AOP_SIZE(IC_RESULT(ic)); - offset = 0; - while (size--) { - pic16_emitcode ("pop","acc"); - pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++); - } - } else { - DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__); + assert( 0 ); + while (size--) { + pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ? + fReturn[pic16_fReturnSizePic - offset - 1] : "acc")); + offset++; + } - _G.accInUse++; - pic16_aopOp(IC_RESULT(ic),ic,FALSE); - _G.accInUse--; - assignResultValue(IC_RESULT(ic), 0); - } + DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__); + + pic16_aopOp(IC_RESULT(ic),ic,FALSE); + size = AOP_SIZE(IC_RESULT(ic)); + offset = 0; + while (size--) { + pic16_emitcode ("pop","acc"); + pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++); + } + } 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--; + + /* set pseudo stack pointer to where it should be - dw*/ + GpsuedoStkPtr = ic->parmBytes; - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + /* setting GpsuedoStkPtr has side effects here: */ + assignResultValue(IC_RESULT(ic), 0); + } + + pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); } /*-----------------------------------------------------------------*/ @@ -11348,10 +13173,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 } /*-----------------------------------------------------------------*/ @@ -11368,8 +13209,8 @@ genDummyRead (iCode * ic) void genpic16Code (iCode *lic) { - iCode *ic; - int cln = 0; + iCode *ic; + int cln = 0; lineHead = lineCurr = NULL; @@ -11380,242 +13221,241 @@ 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 ; - } + 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); - } + 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); + } - /* 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 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); - 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, codeOutFile); #ifdef PCODE_DEBUG DFPRINTF((stderr,"printing pBlock\n\n"));