1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
142 static char *accUse[] = {"WREG"};
144 //static short rbank = -1;
158 bitVect *fregsUsed; /* registers used in function */
160 set *sregsAllocSet; /* registers used to store stack variables */
161 int stack_lat; /* stack offset latency */
163 int useWreg; /* flag when WREG is used to pass function parameter */
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
174 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
181 /*-----------------------------------------------------------------*/
182 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
183 /* exponent of 2 is returned, otherwise -1 is */
185 /* note that this is similar to the function `powof2' in SDCCsymt */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
193 if( (num & (num-1)) == 0) {
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
208 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
210 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
213 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
215 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216 ((result) ? AOP_SIZE(result) : 0));
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
222 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
224 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
227 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
228 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
229 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
233 void pic16_emitpcomment (char *fmt, ...)
236 char lb[INITIAL_INLINEASM];
242 vsprintf(lb+1,fmt,ap);
244 while (isspace(*lbp)) lbp++;
247 lineCurr = (lineCurr ?
248 connectLine(lineCurr,newLineNode(lb)) :
249 (lineHead = newLineNode(lb)));
250 lineCurr->isInline = _G.inLine;
251 lineCurr->isDebug = _G.debugLine;
253 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
256 // fprintf(stderr, "%s\n", lb);
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
262 char lb[INITIAL_INLINEASM];
265 if(!pic16_debug_verbose)
272 sprintf(lb,"%s\t",inst);
274 sprintf(lb,"%s",inst);
275 vsprintf(lb+(strlen(lb)),fmt,ap);
279 while (isspace(*lbp)) lbp++;
282 lineCurr = (lineCurr ?
283 connectLine(lineCurr,newLineNode(lb)) :
284 (lineHead = newLineNode(lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
288 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
291 // fprintf(stderr, "%s\n", lb);
296 void pic16_emitpLabel(int key)
298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
301 void pic16_emitpLabelFORCE(int key)
303 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
306 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
310 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
312 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
315 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
318 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
320 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
323 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
326 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
332 #define pic16_emitcode DEBUGpic16_emitcode
334 /*-----------------------------------------------------------------*/
335 /* pic16_emitcode - writes the code into a file : for now it is simple */
336 /*-----------------------------------------------------------------*/
337 void pic16_emitcode (char *inst,char *fmt, ...)
340 char lb[INITIAL_INLINEASM];
347 sprintf(lb,"%s\t",inst);
349 sprintf(lb,"%s",inst);
350 vsprintf(lb+(strlen(lb)),fmt,ap);
354 while (isspace(*lbp)) lbp++;
357 lineCurr = (lineCurr ?
358 connectLine(lineCurr,newLineNode(lb)) :
359 (lineHead = newLineNode(lb)));
360 lineCurr->isInline = _G.inLine;
361 lineCurr->isDebug = _G.debugLine;
363 // VR fprintf(stderr, "lb = <%s>\n", lbp);
365 // if(pic16_debug_verbose)
366 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
373 /*-----------------------------------------------------------------*/
374 /* pic16_emitDebuggerSymbol - associate the current code location */
375 /* with a debugger symbol */
376 /*-----------------------------------------------------------------*/
378 pic16_emitDebuggerSymbol (char * debugSym)
381 pic16_emitcode (";", "%s ==.", debugSym);
386 /*-----------------------------------------------------------------*/
387 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
388 /*-----------------------------------------------------------------*/
389 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
391 // bool r0iu = FALSE , r1iu = FALSE;
392 // bool r0ou = FALSE , r1ou = FALSE;
393 bool fsr0iu = FALSE, fsr0ou;
394 bool fsr2iu = FALSE, fsr2ou;
396 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
399 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
400 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
402 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
403 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
405 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
406 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
407 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
410 if(!fsr0iu && !fsr0ou) {
411 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
412 (*aopp)->type = AOP_FSR0;
414 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
416 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
420 /* no usage of FSR2 */
421 if(!fsr2iu && !fsr2ou) {
422 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
423 (*aopp)->type = AOP_FSR2;
425 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
429 /* now we know they both have usage */
430 /* if fsr0 not used in this instruction */
432 if (!_G.fsr0Pushed) {
433 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
434 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
438 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
439 (*aopp)->type = AOP_FSR0;
441 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
443 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
447 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
452 /* the logic: if r0 & r1 used in the instruction
453 then we are in trouble otherwise */
455 /* first check if r0 & r1 are used by this
456 instruction, in which case we are in trouble */
457 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
458 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
463 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
464 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
466 /* if no usage of r0 then return it */
467 if (!r0iu && !r0ou) {
468 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
469 (*aopp)->type = AOP_R0;
471 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
474 /* if no usage of r1 then return it */
475 if (!r1iu && !r1ou) {
476 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477 (*aopp)->type = AOP_R1;
479 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
482 /* now we know they both have usage */
483 /* if r0 not used in this instruction */
485 /* push it if not already pushed */
487 //pic16_emitcode ("push","%s",
488 // pic16_regWithIdx(R0_IDX)->dname);
492 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
493 (*aopp)->type = AOP_R0;
495 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
498 /* if r1 not used then */
501 /* push it if not already pushed */
503 //pic16_emitcode ("push","%s",
504 // pic16_regWithIdx(R1_IDX)->dname);
508 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
509 (*aopp)->type = AOP_R1;
510 return pic16_regWithIdx(R1_IDX);
514 /* I said end of world but not quite end of world yet */
515 /* if this is a result then we can push it on the stack*/
517 (*aopp)->type = AOP_STK;
521 /* other wise this is true end of the world */
522 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
523 "getFreePtr should never reach here");
528 /*-----------------------------------------------------------------*/
529 /* newAsmop - creates a new asmOp */
530 /*-----------------------------------------------------------------*/
531 static asmop *newAsmop (short type)
535 aop = Safe_calloc(1,sizeof(asmop));
540 static void genSetDPTR(int n)
544 pic16_emitcode(";", "Select standard DPTR");
545 pic16_emitcode("mov", "dps, #0x00");
549 pic16_emitcode(";", "Select alternate DPTR");
550 pic16_emitcode("mov", "dps, #0x01");
554 /*-----------------------------------------------------------------*/
555 /* resolveIfx - converts an iCode ifx into a form more useful for */
556 /* generating code */
557 /*-----------------------------------------------------------------*/
558 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
562 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
568 resIfx->condition = 1; /* assume that the ifx is true */
569 resIfx->generated = 0; /* indicate that the ifx has not been used */
572 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
575 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
576 __FUNCTION__,__LINE__,resIfx->lbl->key);
581 resIfx->lbl = IC_TRUE(ifx);
583 resIfx->lbl = IC_FALSE(ifx);
584 resIfx->condition = 0;
589 DEBUGpic16_emitcode("; +++","ifx true is non-null");
591 DEBUGpic16_emitcode("; +++","ifx true is null");
593 DEBUGpic16_emitcode("; +++","ifx false is non-null");
595 DEBUGpic16_emitcode("; +++","ifx false is null");
599 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
603 /*-----------------------------------------------------------------*/
604 /* pointerCode - returns the code for a pointer type */
605 /*-----------------------------------------------------------------*/
606 static int pointerCode (sym_link *etype)
609 return PTR_TYPE(SPEC_OCLS(etype));
614 /*-----------------------------------------------------------------*/
615 /* aopForSym - for a true symbol */
616 /*-----------------------------------------------------------------*/
617 static asmop *aopForSym (iCode *ic, operand *op, bool result)
619 symbol *sym=OP_SYMBOL(op);
621 memmap *space= SPEC_OCLS(sym->etype);
625 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
627 // sym = OP_SYMBOL(op);
629 /* if already has one */
631 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
636 /* if symbol was initially placed onStack then we must re-place it
637 * to direct memory, since pic16 does not have a specific stack */
639 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
647 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
649 sym->aop = aop = newAsmop (AOP_PAGED);
650 aop->aopu.aop_dir = sym->rname ;
651 aop->size = getSize(sym->type);
652 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
653 pic16_allocDirReg( IC_LEFT(ic) );
661 /* assign depending on the storage class */
662 /* if it is on the stack or indirectly addressable */
663 /* space we need to assign either r0 or r1 to it */
664 if (sym->onStack) // || sym->iaccess)
669 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
670 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
672 /* acquire a temporary register -- it is saved in function */
674 sym->aop = aop = newAsmop(AOP_STA);
675 aop->aopu.stk.stk = sym->stack;
676 aop->size = getSize(sym->type);
679 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
680 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
681 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
682 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
684 for(i=0;i<aop->size;i++)
685 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
686 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
688 if(1 && ic->op == SEND) {
690 /* if SEND do the send here */
693 for(i=0;i<aop->size;i++) {
694 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
695 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
700 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
703 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
705 // we do not need to load the value if it is to be defined...
706 if (result) return aop;
709 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
712 for(i=0;i<aop->size;i++) {
714 /* initialise for stack access via frame pointer */
715 // operands on stack are accessible via "FSR2 + index" with index
716 // starting at 2 for arguments and growing from 0 downwards for
717 // local variables (index == 0 is not assigned so we add one here)
719 int soffs = sym->stack;
725 if(1 && ic->op == SEND) {
726 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
727 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
728 pic16_popCopyReg( pic16_frame_plusw ),
729 pic16_popCopyReg(pic16_stack_postdec )));
731 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
733 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
739 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
746 /* now assign the address of the variable to
747 the pointer register */
748 if (aop->type != AOP_STK) {
752 pic16_emitcode("push","acc");
754 pic16_emitcode("mov","a,_bp");
755 pic16_emitcode("add","a,#0x%02x",
757 ((char)(sym->stack - _G.nRegsSaved )) :
758 ((char)sym->stack)) & 0xff);
759 pic16_emitcode("mov","%s,a",
760 aop->aopu.aop_ptr->name);
763 pic16_emitcode("pop","acc");
765 pic16_emitcode("mov","%s,#%s",
766 aop->aopu.aop_ptr->name,
768 aop->paged = space->paged;
770 aop->aopu.aop_stk = sym->stack;
778 if (sym->onStack && options.stack10bit)
780 /* It's on the 10 bit stack, which is located in
784 //DEBUGpic16_emitcode(";","%d",__LINE__);
787 pic16_emitcode("push","acc");
789 pic16_emitcode("mov","a,_bp");
790 pic16_emitcode("add","a,#0x%02x",
792 ((char)(sym->stack - _G.nRegsSaved )) :
793 ((char)sym->stack)) & 0xff);
796 pic16_emitcode ("mov","dpx1,#0x40");
797 pic16_emitcode ("mov","dph1,#0x00");
798 pic16_emitcode ("mov","dpl1, a");
802 pic16_emitcode("pop","acc");
804 sym->aop = aop = newAsmop(AOP_DPTR2);
805 aop->size = getSize(sym->type);
811 /* special case for a function */
812 if (IS_FUNC(sym->type)) {
813 sym->aop = aop = newAsmop(AOP_PCODE);
814 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
815 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
816 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
817 PCOI(aop->aopu.pcop)->index = 0;
818 aop->size = FPTRSIZE;
819 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
826 //DEBUGpic16_emitcode(";","%d",__LINE__);
827 /* if in bit space */
828 if (IN_BITSPACE(space)) {
829 sym->aop = aop = newAsmop (AOP_CRY);
830 aop->aopu.aop_dir = sym->rname ;
831 aop->size = getSize(sym->type);
832 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
835 /* if it is in direct space */
836 if (IN_DIRSPACE(space)) {
837 sym->aop = aop = newAsmop (AOP_DIR);
838 aop->aopu.aop_dir = sym->rname ;
839 aop->size = getSize(sym->type);
840 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841 pic16_allocDirReg( IC_LEFT(ic) );
846 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
847 sym->aop = aop = newAsmop (AOP_DIR);
848 aop->aopu.aop_dir = sym->rname ;
849 aop->size = getSize(sym->type);
850 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851 pic16_allocDirReg( IC_LEFT(ic) );
856 /* only remaining is far space */
857 sym->aop = aop = newAsmop(AOP_PCODE);
859 /* change the next if to 1 to revert to good old immediate code */
860 if(IN_CODESPACE(space)) {
861 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
862 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
863 PCOI(aop->aopu.pcop)->index = 0;
865 /* try to allocate via direct register */
866 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
867 // aop->size = getSize( sym->type );
870 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
871 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
874 if(!pic16_allocDirReg (IC_LEFT(ic)))
878 if(IN_DIRSPACE( space ))
880 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
881 aop->size = FPTRSIZE;
882 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
883 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
884 else if(sym->onStack) {
887 if(SPEC_SCLS(sym->etype) == S_PDATA) {
888 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
889 aop->size = FPTRSIZE;
894 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
896 /* if it is in code space */
897 if (IN_CODESPACE(space))
903 /*-----------------------------------------------------------------*/
904 /* aopForRemat - rematerialzes an object */
905 /*-----------------------------------------------------------------*/
906 static asmop *aopForRemat (operand *op) // x symbol *sym)
908 symbol *sym = OP_SYMBOL(op);
910 iCode *ic = NULL, *oldic;
911 asmop *aop = newAsmop(AOP_PCODE);
918 ic = sym->rematiCode;
920 if(IS_OP_POINTER(op)) {
921 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
927 // pic16_emitpcomment("ic: %s\n", printILine(ic));
930 val += (int) operandLitValue(IC_RIGHT(ic));
931 } else if (ic->op == '-') {
932 val -= (int) operandLitValue(IC_RIGHT(ic));
936 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
939 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
942 if(!op->isaddr)viaimmd++; else viaimmd=0;
944 /* set the following if to 1 to revert to good old immediate code */
945 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
948 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
950 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
953 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
955 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
958 PCOI(aop->aopu.pcop)->index = val;
960 aop->size = getSize( sym->type );
962 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
964 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
965 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
967 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
971 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
972 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
974 val, IS_PTR_CONST(operandType(op)));
976 val, IS_CODEPTR(operandType(op)));
979 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
981 pic16_allocDirReg (IC_LEFT(ic));
983 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
990 static int aopIdx (asmop *aop, int offset)
995 if(aop->type != AOP_REG)
998 return aop->aopu.aop_reg[offset]->rIdx;
1003 /*-----------------------------------------------------------------*/
1004 /* regsInCommon - two operands have some registers in common */
1005 /*-----------------------------------------------------------------*/
1006 static bool regsInCommon (operand *op1, operand *op2)
1008 symbol *sym1, *sym2;
1011 /* if they have registers in common */
1012 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1015 sym1 = OP_SYMBOL(op1);
1016 sym2 = OP_SYMBOL(op2);
1018 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1021 for (i = 0 ; i < sym1->nRegs ; i++) {
1026 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1030 if (sym2->regs[j] == sym1->regs[i])
1038 /*-----------------------------------------------------------------*/
1039 /* operandsEqu - equivalent */
1040 /*-----------------------------------------------------------------*/
1041 static bool operandsEqu ( operand *op1, operand *op2)
1043 symbol *sym1, *sym2;
1045 /* if they not symbols */
1046 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1049 sym1 = OP_SYMBOL(op1);
1050 sym2 = OP_SYMBOL(op2);
1052 /* if both are itemps & one is spilt
1053 and the other is not then false */
1054 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1055 sym1->isspilt != sym2->isspilt )
1058 /* if they are the same */
1062 if (sym1->rname[0] && sym2->rname[0]
1063 && strcmp (sym1->rname, sym2->rname) == 0)
1067 /* if left is a tmp & right is not */
1068 if (IS_ITEMP(op1) &&
1071 (sym1->usl.spillLoc == sym2))
1074 if (IS_ITEMP(op2) &&
1078 (sym2->usl.spillLoc == sym1))
1084 /*-----------------------------------------------------------------*/
1085 /* pic16_sameRegs - two asmops have the same registers */
1086 /*-----------------------------------------------------------------*/
1087 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1094 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1095 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1097 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1099 if (aop1->type != AOP_REG ||
1100 aop2->type != AOP_REG )
1103 /* This is a bit too restrictive if one is a subset of the other...
1104 if (aop1->size != aop2->size )
1108 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1109 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1111 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1112 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1119 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1121 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1122 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1124 if(aop1 == aop2)return TRUE;
1125 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1127 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1133 /*-----------------------------------------------------------------*/
1134 /* pic16_aopOp - allocates an asmop for an operand : */
1135 /*-----------------------------------------------------------------*/
1136 void pic16_aopOp (operand *op, iCode *ic, bool result)
1145 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1147 /* if this a literal */
1148 if (IS_OP_LITERAL(op)) {
1149 op->aop = aop = newAsmop(AOP_LIT);
1150 aop->aopu.aop_lit = op->operand.valOperand;
1151 aop->size = getSize(operandType(op));
1156 sym_link *type = operandType(op);
1158 if(IS_PTR_CONST(type))
1160 if(IS_CODEPTR(type))
1162 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1165 /* if already has a asmop then continue */
1169 /* if the underlying symbol has a aop */
1170 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1171 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1172 op->aop = OP_SYMBOL(op)->aop;
1176 /* if this is a true symbol */
1177 if (IS_TRUE_SYMOP(op)) {
1178 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1179 op->aop = aopForSym(ic, op, result);
1183 /* this is a temporary : this has
1189 e) can be a return use only */
1191 sym = OP_SYMBOL(op);
1193 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1194 /* if the type is a conditional */
1195 if (sym->regType == REG_CND) {
1196 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1201 /* if it is spilt then two situations
1203 b) has a spill location */
1204 if (sym->isspilt || sym->nRegs == 0) {
1206 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1207 DEBUGpic16_emitcode(";","%d",__LINE__);
1208 /* rematerialize it NOW */
1211 sym->aop = op->aop = aop = aopForRemat (op);
1212 // aop->size = getSize(sym->type);
1213 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1220 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1221 aop->size = getSize(sym->type);
1222 for ( i = 0 ; i < 1 ; i++ ) {
1223 aop->aopu.aop_str[i] = accUse[i];
1224 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1226 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1227 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1235 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1236 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1237 //pic16_allocDirReg (IC_LEFT(ic));
1238 aop->size = getSize(sym->type);
1243 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1244 aop->size = getSize(sym->type);
1245 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1246 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1248 DEBUGpic16_emitcode(";","%d",__LINE__);
1252 /* else spill location */
1253 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1254 /* force a new aop if sizes differ */
1255 sym->usl.spillLoc->aop = NULL;
1259 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1260 __FUNCTION__,__LINE__,
1261 sym->usl.spillLoc->rname,
1262 sym->rname, sym->usl.spillLoc->offset);
1265 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1266 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1267 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1268 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1270 sym->usl.spillLoc->offset, op);
1272 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1273 DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1274 assert (getSize(sym->type) <= 1);
1275 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1277 aop->size = getSize(sym->type);
1283 sym_link *type = operandType(op);
1285 if(IS_PTR_CONST(type))
1287 if(IS_CODEPTR(type))
1289 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1292 /* must be in a register */
1293 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1294 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1295 aop->size = sym->nRegs;
1296 for ( i = 0 ; i < sym->nRegs ;i++)
1297 aop->aopu.aop_reg[i] = sym->regs[i];
1300 /*-----------------------------------------------------------------*/
1301 /* pic16_freeAsmop - free up the asmop given to an operand */
1302 /*----------------------------------------------------------------*/
1303 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1320 /* depending on the asmop type only three cases need work AOP_RO
1321 , AOP_R1 && AOP_STK */
1323 switch (aop->type) {
1325 if (_G.fsr0Pushed ) {
1327 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1328 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1329 // pic16_emitcode ("pop","ar0");
1333 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1337 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1343 pic16_emitcode ("pop","ar0");
1347 bitVectUnSetBit(ic->rUsed,R0_IDX);
1353 pic16_emitcode ("pop","ar1");
1357 bitVectUnSetBit(ic->rUsed,R1_IDX);
1364 /* we must store the result on stack */
1365 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1366 // operands on stack are accessible via "FSR2 + index" with index
1367 // starting at 2 for arguments and growing from 0 downwards for
1368 // local variables (index == 0 is not assigned so we add one here)
1369 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1374 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1375 for(i=0;i<aop->size;i++) {
1376 /* initialise for stack access via frame pointer */
1377 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1378 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1379 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1382 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1386 for(i=0;i<aop->size;i++) {
1387 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1389 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1390 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1401 int stk = aop->aopu.aop_stk + aop->size;
1402 bitVectUnSetBit(ic->rUsed,R0_IDX);
1403 bitVectUnSetBit(ic->rUsed,R1_IDX);
1405 getFreePtr(ic,&aop,FALSE);
1407 if (options.stack10bit)
1409 /* I'm not sure what to do here yet... */
1412 "*** Warning: probably generating bad code for "
1413 "10 bit stack mode.\n");
1417 pic16_emitcode ("mov","a,_bp");
1418 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1419 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1421 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1425 pic16_emitcode("pop","acc");
1426 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1428 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1431 pic16_freeAsmop(op,NULL,ic,TRUE);
1433 pic16_emitcode("pop","ar0");
1438 pic16_emitcode("pop","ar1");
1448 /* all other cases just dealloc */
1452 OP_SYMBOL(op)->aop = NULL;
1453 /* if the symbol has a spill */
1455 SPIL_LOC(op)->aop = NULL;
1460 /*-----------------------------------------------------------------*/
1461 /* pic16_aopGet - for fetching value of the aop */
1462 /*-----------------------------------------------------------------*/
1463 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1468 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1470 /* offset is greater than size then zero */
1471 if (offset > (aop->size - 1) &&
1472 aop->type != AOP_LIT)
1475 /* depending on type */
1476 switch (aop->type) {
1480 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1481 rs = Safe_calloc(1, strlen(s)+1);
1486 /* if we need to increment it */
1487 while (offset > aop->coff)
1489 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1493 while (offset < aop->coff)
1495 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1501 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1502 return (dname ? "acc" : "a");
1504 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1505 rs = Safe_calloc (1, strlen (s) + 1);
1513 sprintf (s,"%s",aop->aopu.aop_immd);
1516 sprintf(s,"(%s >> %d)",
1521 aop->aopu.aop_immd);
1522 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1523 rs = Safe_calloc(1,strlen(s)+1);
1529 sprintf(s,"(%s + %d)",
1532 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1534 sprintf(s,"%s",aop->aopu.aop_dir);
1535 rs = Safe_calloc(1,strlen(s)+1);
1541 // return aop->aopu.aop_reg[offset]->dname;
1543 return aop->aopu.aop_reg[offset]->name;
1546 //pic16_emitcode(";","%d",__LINE__);
1547 return aop->aopu.aop_dir;
1550 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1551 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1553 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1554 rs = Safe_strdup("WREG");
1558 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1559 rs = Safe_calloc(1,strlen(s)+1);
1564 aop->coff = offset ;
1566 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1569 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1570 aop->type = AOP_ACC;
1571 return Safe_strdup("WREG");
1573 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1575 return aop->aopu.aop_str[offset];
1579 pCodeOp *pcop = aop->aopu.pcop;
1580 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1582 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1583 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1585 sprintf(s,"(%s + %d)", pcop->name, offset);
1587 sprintf(s,"%s", pcop->name);
1590 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1593 rs = Safe_calloc(1,strlen(s)+1);
1599 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1601 sprintf(s,"(%s + %d)",
1605 sprintf(s,"%s",aop->aopu.aop_dir);
1606 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1607 rs = Safe_calloc(1,strlen(s)+1);
1613 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1617 // pCodeOp *pcop = aop->aop
1622 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1623 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1624 "aopget got unsupported aop->type");
1630 /* lock has the following meaning: When allocating temporary registers
1631 * for stack variables storage, the value of the temporary register is
1632 * saved on stack. Its value is restored at the end. This procedure is
1633 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1634 * a possibility that before a call to pic16_aopOp, a temporary register
1635 * is allocated for a while and it is freed after some time, this will
1636 * mess the stack and values will not be restored properly. So use lock=1
1637 * to allocate temporary registers used internally by the programmer, and
1638 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1639 * to inform the compiler developer about a possible bug. This is an internal
1640 * feature for developing the compiler -- VR */
1642 int _TempReg_lock = 0;
1643 /*-----------------------------------------------------------------*/
1644 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1645 /*-----------------------------------------------------------------*/
1646 pCodeOp *pic16_popGetTempReg(int lock)
1651 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1653 // werror(W_POSSBUG2, __FILE__, __LINE__);
1656 _TempReg_lock += lock;
1661 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1662 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1663 PCOR(pcop)->r->wasUsed=1;
1664 PCOR(pcop)->r->isFree=0;
1666 /* push value on stack */
1667 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1675 /*-----------------------------------------------------------------*/
1676 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1677 /* is not part of f, but don't save if */
1679 /*-----------------------------------------------------------------*/
1680 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1686 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1689 // werror(W_POSSBUG2, __FILE__, __LINE__);
1692 _TempReg_lock += lock;
1697 i = bitVectFirstBit(f);
1700 /* bypass registers that are used by function */
1701 if(!bitVectBitValue(f, i)) {
1703 /* bypass registers that are already allocated for stack access */
1704 if(!bitVectBitValue(v, i)) {
1706 // debugf("getting register rIdx = %d\n", i);
1707 /* ok, get the operand */
1708 pcop = pic16_newpCodeOpReg( i );
1710 /* should never by NULL */
1711 assert( pcop != NULL );
1715 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1718 PCOR(pcop)->r->wasUsed=1;
1719 PCOR(pcop)->r->isFree=0;
1725 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1727 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1728 /* already used in previous steps, break */
1735 /* caller takes care of the following */
1736 // bitVectSetBit(v, i);
1739 /* push value on stack */
1740 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1741 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1757 /*-----------------------------------------------------------------*/
1758 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1759 /*-----------------------------------------------------------------*/
1760 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1762 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1764 _TempReg_lock -= lock;
1766 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1767 PCOR(pcop)->r->isFree = 1;
1769 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1772 /*-----------------------------------------------------------------*/
1773 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1774 /*-----------------------------------------------------------------*/
1775 pCodeOp *pic16_popGetLabel(unsigned int key)
1778 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1783 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1786 /*-----------------------------------------------------------------*/
1787 /* pic16_popCopyReg - copy a pcode operator */
1788 /*-----------------------------------------------------------------*/
1789 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1793 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1794 pcor->pcop.type = pc->pcop.type;
1796 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1797 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1799 pcor->pcop.name = NULL;
1802 pcor->rIdx = pc->rIdx;
1804 pcor->instance = pc->instance;
1806 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1811 /*-----------------------------------------------------------------*/
1812 /* pic16_popGetLit - asm operator to pcode operator conversion */
1813 /*-----------------------------------------------------------------*/
1814 pCodeOp *pic16_popGetLit(int lit)
1816 return pic16_newpCodeOpLit(lit);
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1821 /*-----------------------------------------------------------------*/
1822 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1824 return pic16_newpCodeOpLit2(lit, arg2);
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1833 return pic16_newpCodeOpImmd(name, offset,index, 0);
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGet - asm operator to pcode operator conversion */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetWithString(char *str)
1846 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1850 pcop = pic16_newpCodeOp(str,PO_STR);
1855 /*-----------------------------------------------------------------*/
1856 /* pic16_popRegFromString - */
1857 /*-----------------------------------------------------------------*/
1858 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1861 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862 pcop->type = PO_DIR;
1864 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1865 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1870 pcop->name = Safe_calloc(1,strlen(str)+1);
1871 strcpy(pcop->name,str);
1873 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1875 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1877 /* make sure that register doesn't exist,
1878 * and operand isn't NULL
1879 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1880 if((PCOR(pcop)->r == NULL)
1882 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1883 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1884 // __FUNCTION__, __LINE__, str, size, offset);
1886 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1887 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1890 PCOR(pcop)->instance = offset;
1895 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1899 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1901 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1902 PCOR(pcop)->rIdx = rIdx;
1903 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1905 PCOR(pcop)->r->isFree = 0;
1906 PCOR(pcop)->r->wasUsed = 1;
1908 pcop->type = PCOR(pcop)->r->pc_type;
1913 /*---------------------------------------------------------------------------------*/
1914 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1916 /*---------------------------------------------------------------------------------*/
1917 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1922 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1924 /* comment the following check, so errors to throw up */
1925 // if(!pcop2)return NULL;
1927 temp = pic16_popGet(aop_dst, offset);
1928 pcop2->pcop2 = temp;
1935 /*--------------------------------------------------------------------------------.-*/
1936 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1937 /* VR 030601 , adapted by Hans Dorn */
1938 /*--------------------------------------------------------------------------------.-*/
1939 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1943 pcop2 = (pCodeOpReg2 *)src;
1951 /*---------------------------------------------------------------------------------*/
1952 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1953 /* movff instruction */
1954 /*---------------------------------------------------------------------------------*/
1955 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1960 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1961 pcop2->pcop2 = pic16_popCopyReg(dst);
1963 /* the pCodeOp may be already allocated */
1964 pcop2 = (pCodeOpReg2 *)(src);
1965 pcop2->pcop2 = (pCodeOp *)(dst);
1972 /*-----------------------------------------------------------------*/
1973 /* pic16_popGet - asm operator to pcode operator conversion */
1974 /*-----------------------------------------------------------------*/
1975 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1977 //char *s = buffer ;
1982 /* offset is greater than
1985 // if (offset > (aop->size - 1) &&
1986 // aop->type != AOP_LIT)
1987 // return NULL; //zero;
1989 /* depending on type */
1990 switch (aop->type) {
1996 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1997 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2004 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2005 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2006 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2007 PCOR(pcop)->r->wasUsed = 1;
2008 PCOR(pcop)->r->isFree = 0;
2010 PCOR(pcop)->instance = offset;
2011 pcop->type = PCOR(pcop)->r->pc_type;
2015 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2016 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2019 /* pCodeOp is already allocated from aopForSym */
2020 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2021 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2027 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2029 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2031 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2033 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034 PCOR(pcop)->rIdx = rIdx;
2035 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2036 PCOR(pcop)->r->wasUsed=1;
2037 PCOR(pcop)->r->isFree=0;
2039 PCOR(pcop)->instance = offset;
2040 pcop->type = PCOR(pcop)->r->pc_type;
2041 // rs = aop->aopu.aop_reg[offset]->name;
2042 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2046 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2047 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2053 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2054 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2058 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2065 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2066 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2068 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2070 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2071 // pcop->type = PO_GPR_REGISTER;
2072 PCOR(pcop)->rIdx = rIdx;
2073 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2074 PCOR(pcop)->r->wasUsed=1;
2075 PCOR(pcop)->r->isFree=0;
2077 PCOR(pcop)->instance = offset;
2078 pcop->type = PCOR(pcop)->r->pc_type;
2080 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2081 rs = aop->aopu.aop_reg[offset]->name;
2082 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2087 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2089 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2090 PCOR(pcop)->instance = offset;
2091 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2092 //if(PCOR(pcop)->r == NULL)
2093 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2097 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2098 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2101 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2102 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2105 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2107 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108 pcop->type = PCOR(pcop)->r->pc_type;
2109 pcop->name = PCOR(pcop)->r->name;
2115 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2117 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2118 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2119 switch( aop->aopu.pcop->type ) {
2120 case PO_DIR: PCOR(pcop)->instance += offset; break;
2121 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2126 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2127 assert( 0 ); /* should never reach here */;
2132 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2133 "pic16_popGet got unsupported aop->type");
2136 /*-----------------------------------------------------------------*/
2137 /* pic16_aopPut - puts a string for a aop */
2138 /*-----------------------------------------------------------------*/
2139 void pic16_aopPut (asmop *aop, char *s, int offset)
2146 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2148 if (aop->size && offset > ( aop->size - 1)) {
2149 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2150 "pic16_aopPut got offset > aop->size");
2154 /* will assign value to value */
2155 /* depending on where it is ofcourse */
2156 switch (aop->type) {
2159 sprintf(d,"(%s + %d)",
2160 aop->aopu.aop_dir,offset);
2161 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2164 sprintf(d,"%s",aop->aopu.aop_dir);
2167 DEBUGpic16_emitcode(";","%d",__LINE__);
2169 pic16_emitcode("movf","%s,w",s);
2170 pic16_emitcode("movwf","%s",d);
2173 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2174 if(offset >= aop->size) {
2175 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2178 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2181 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2188 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2189 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2192 strcmp(s,"r0") == 0 ||
2193 strcmp(s,"r1") == 0 ||
2194 strcmp(s,"r2") == 0 ||
2195 strcmp(s,"r3") == 0 ||
2196 strcmp(s,"r4") == 0 ||
2197 strcmp(s,"r5") == 0 ||
2198 strcmp(s,"r6") == 0 ||
2199 strcmp(s,"r7") == 0 )
2200 pic16_emitcode("mov","%s,%s ; %d",
2201 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2205 if(strcmp(s,"W")==0 )
2206 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2208 pic16_emitcode("movwf","%s",
2209 aop->aopu.aop_reg[offset]->name);
2211 if(strcmp(s,zero)==0) {
2212 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2214 } else if(strcmp(s,"W")==0) {
2215 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2216 pcop->type = PO_GPR_REGISTER;
2218 PCOR(pcop)->rIdx = -1;
2219 PCOR(pcop)->r = NULL;
2221 DEBUGpic16_emitcode(";","%d",__LINE__);
2222 pcop->name = Safe_strdup(s);
2223 pic16_emitpcode(POC_MOVFW,pcop);
2224 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2225 } else if(strcmp(s,one)==0) {
2226 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2227 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2229 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2237 if (aop->type == AOP_DPTR2)
2243 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244 "pic16_aopPut writting to code space");
2248 while (offset > aop->coff) {
2250 pic16_emitcode ("inc","dptr");
2253 while (offset < aop->coff) {
2255 pic16_emitcode("lcall","__decdptr");
2260 /* if not in accumulater */
2263 pic16_emitcode ("movx","@dptr,a");
2265 if (aop->type == AOP_DPTR2)
2273 while (offset > aop->coff) {
2275 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2277 while (offset < aop->coff) {
2279 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2285 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2290 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2292 if (strcmp(s,"r0") == 0 ||
2293 strcmp(s,"r1") == 0 ||
2294 strcmp(s,"r2") == 0 ||
2295 strcmp(s,"r3") == 0 ||
2296 strcmp(s,"r4") == 0 ||
2297 strcmp(s,"r5") == 0 ||
2298 strcmp(s,"r6") == 0 ||
2299 strcmp(s,"r7") == 0 ) {
2301 sprintf(buffer,"a%s",s);
2302 pic16_emitcode("mov","@%s,%s",
2303 aop->aopu.aop_ptr->name,buffer);
2305 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2310 if (strcmp(s,"a") == 0)
2311 pic16_emitcode("push","acc");
2313 pic16_emitcode("push","%s",s);
2318 /* if bit variable */
2319 if (!aop->aopu.aop_dir) {
2320 pic16_emitcode("clr","a");
2321 pic16_emitcode("rlc","a");
2324 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2327 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2330 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2332 lbl = newiTempLabel(NULL);
2334 if (strcmp(s,"a")) {
2337 pic16_emitcode("clr","c");
2338 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2339 pic16_emitcode("cpl","c");
2340 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2341 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2348 if (strcmp(aop->aopu.aop_str[offset],s))
2349 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2354 if (!offset && (strcmp(s,"acc") == 0))
2357 if (strcmp(aop->aopu.aop_str[offset],s))
2358 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2362 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2363 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2364 // "pic16_aopPut got unsupported aop->type");
2370 /*-----------------------------------------------------------------*/
2371 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2372 /*-----------------------------------------------------------------*/
2373 void pic16_mov2w (asmop *aop, int offset)
2375 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2378 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2380 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2383 static void mov2f(asmop *dst, asmop *src, int offset)
2385 if(is_LitAOp(src)) {
2386 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2387 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2389 if(pic16_sameRegsOfs(src, dst, offset))return;
2390 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2391 pic16_popGet(dst, offset)));
2395 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2397 if(is_LitAOp(src)) {
2398 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2399 pic16_emitpcode(POC_MOVWF, dst);
2401 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2405 void pic16_testStackOverflow(void)
2407 #define GSTACK_TEST_NAME "__gstack_test"
2409 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2414 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2415 strcpy(sym->rname, GSTACK_TEST_NAME);
2416 checkAddSym(&externs, sym);
2421 /* push pcop into stack */
2422 void pic16_pushpCodeOp(pCodeOp *pcop)
2424 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2425 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2426 if(pic16_options.gstack)
2427 pic16_testStackOverflow();
2431 /* pop pcop from stack */
2432 void pic16_poppCodeOp(pCodeOp *pcop)
2434 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2435 if(pic16_options.gstack)
2436 pic16_testStackOverflow();
2440 /*-----------------------------------------------------------------*/
2441 /* pushw - pushes wreg to stack */
2442 /*-----------------------------------------------------------------*/
2445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2446 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2447 if(pic16_options.gstack)
2448 pic16_testStackOverflow();
2452 /*-----------------------------------------------------------------*/
2453 /* pushaop - pushes aop to stack */
2454 /*-----------------------------------------------------------------*/
2455 void pushaop(asmop *aop, int offset)
2457 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2459 if(is_LitAOp(aop)) {
2460 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2461 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2463 pic16_emitpcode(POC_MOVFF,
2464 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2467 if(pic16_options.gstack)
2468 pic16_testStackOverflow();
2471 /*-----------------------------------------------------------------*/
2472 /* popaop - pops aop from stack */
2473 /*-----------------------------------------------------------------*/
2474 void popaop(asmop *aop, int offset)
2476 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2477 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2478 if(pic16_options.gstack)
2479 pic16_testStackOverflow();
2482 void popaopidx(asmop *aop, int offset, int index)
2486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2488 if(STACK_MODEL_LARGE)ofs++;
2490 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2491 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2492 if(pic16_options.gstack)
2493 pic16_testStackOverflow();
2496 #if !(USE_GENERIC_SIGNED_SHIFT)
2497 /*-----------------------------------------------------------------*/
2498 /* reAdjustPreg - points a register back to where it should */
2499 /*-----------------------------------------------------------------*/
2500 static void reAdjustPreg (asmop *aop)
2504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2506 if ((size = aop->size) <= 1)
2509 switch (aop->type) {
2513 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2517 if (aop->type == AOP_DPTR2)
2523 pic16_emitcode("lcall","__decdptr");
2526 if (aop->type == AOP_DPTR2)
2538 /*-----------------------------------------------------------------*/
2539 /* opIsGptr: returns non-zero if the passed operand is */
2540 /* a generic pointer type. */
2541 /*-----------------------------------------------------------------*/
2542 static int opIsGptr(operand *op)
2544 sym_link *type = operandType(op);
2546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2547 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2555 /*-----------------------------------------------------------------*/
2556 /* pic16_getDataSize - get the operand data size */
2557 /*-----------------------------------------------------------------*/
2558 int pic16_getDataSize(operand *op)
2560 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2563 return AOP_SIZE(op);
2565 // tsd- in the pic port, the genptr size is 1, so this code here
2566 // fails. ( in the 8051 port, the size was 4).
2569 size = AOP_SIZE(op);
2570 if (size == GPTRSIZE)
2572 sym_link *type = operandType(op);
2573 if (IS_GENPTR(type))
2575 /* generic pointer; arithmetic operations
2576 * should ignore the high byte (pointer type).
2579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2586 /*-----------------------------------------------------------------*/
2587 /* pic16_outAcc - output Acc */
2588 /*-----------------------------------------------------------------*/
2589 void pic16_outAcc(operand *result)
2592 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2593 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2596 size = pic16_getDataSize(result);
2598 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2601 /* unsigned or positive */
2603 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2608 /*-----------------------------------------------------------------*/
2609 /* pic16_outBitC - output a bit C */
2610 /* Move to result the value of Carry flag -- VR */
2611 /*-----------------------------------------------------------------*/
2612 void pic16_outBitC(operand *result)
2616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2618 /* if the result is bit */
2619 if (AOP_TYPE(result) == AOP_CRY) {
2620 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2621 pic16_aopPut(AOP(result),"c",0);
2624 i = AOP_SIZE(result);
2626 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2628 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2632 /*-----------------------------------------------------------------*/
2633 /* pic16_outBitOp - output a bit from Op */
2634 /* Move to result the value of set/clr op -- VR */
2635 /*-----------------------------------------------------------------*/
2636 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2640 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2642 /* if the result is bit */
2643 if (AOP_TYPE(result) == AOP_CRY) {
2644 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2645 pic16_aopPut(AOP(result),"c",0);
2648 i = AOP_SIZE(result);
2650 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2652 pic16_emitpcode(POC_RRCF, pcop);
2653 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2657 /*-----------------------------------------------------------------*/
2658 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2659 /*-----------------------------------------------------------------*/
2660 void pic16_toBoolean(operand *oper)
2662 int size = AOP_SIZE(oper) - 1;
2665 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2667 if ( AOP_TYPE(oper) != AOP_ACC) {
2668 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2671 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2676 #if !defined(GEN_Not)
2677 /*-----------------------------------------------------------------*/
2678 /* genNot - generate code for ! operation */
2679 /*-----------------------------------------------------------------*/
2680 static void pic16_genNot (iCode *ic)
2686 /* assign asmOps to operand & result */
2687 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2688 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2690 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2691 /* if in bit space then a special case */
2692 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2693 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2694 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2695 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2697 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2698 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2699 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704 size = AOP_SIZE(IC_LEFT(ic));
2706 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2707 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2708 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2711 pic16_toBoolean(IC_LEFT(ic));
2713 tlbl = newiTempLabel(NULL);
2714 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2715 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2716 pic16_outBitC(IC_RESULT(ic));
2719 /* release the aops */
2720 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2721 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2726 #if !defined(GEN_Cpl)
2727 /*-----------------------------------------------------------------*/
2728 /* genCpl - generate code for complement */
2729 /*-----------------------------------------------------------------*/
2730 static void pic16_genCpl (iCode *ic)
2736 /* assign asmOps to operand & result */
2737 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2738 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2740 /* if both are in bit space then
2742 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2743 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2745 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2746 pic16_emitcode("cpl","c");
2747 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2751 size = AOP_SIZE(IC_RESULT(ic));
2754 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2756 pic16_emitcode("cpl","a");
2757 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2759 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2760 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2762 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2763 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2771 /* release the aops */
2772 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2773 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2777 /*-----------------------------------------------------------------*/
2778 /* genUminusFloat - unary minus for floating points */
2779 /*-----------------------------------------------------------------*/
2780 static void genUminusFloat(operand *op,operand *result)
2782 int size ,offset =0 ;
2785 /* for this we just need to flip the
2786 first it then copy the rest in place */
2787 size = AOP_SIZE(op);
2790 mov2f(AOP(result), AOP(op), offset);
2794 /* toggle the MSB's highest bit */
2795 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2798 /*-----------------------------------------------------------------*/
2799 /* genUminus - unary minus code generation */
2800 /*-----------------------------------------------------------------*/
2801 static void genUminus (iCode *ic)
2804 sym_link *optype, *rtype;
2811 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2812 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2814 /* if both in bit space then special case */
2815 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2816 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2818 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2819 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2820 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2824 optype = operandType(IC_LEFT(ic));
2825 rtype = operandType(IC_RESULT(ic));
2827 /* if float then do float stuff */
2828 if (IS_FLOAT(optype)) {
2829 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2833 /* otherwise subtract from zero by taking the 2's complement */
2834 size = AOP_SIZE(IC_LEFT(ic));
2835 label = newiTempLabel ( NULL );
2837 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2838 for (i=size-1; i > 0; i--) {
2839 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2841 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2842 for (i=1; i < size; i++) {
2843 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2844 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2847 for (i=size-1; i >= 0; i--) {
2848 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2849 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2852 for (i=0; i < size-2; i++) {
2853 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2854 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2856 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2858 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2861 pic16_emitpLabel (label->key);
2864 /* release the aops */
2865 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2866 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2870 /*-----------------------------------------------------------------*/
2871 /* saveRegisters - will look for a call and save the registers */
2872 /*-----------------------------------------------------------------*/
2873 static void saveRegisters(iCode *lic)
2880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2882 for (ic = lic ; ic ; ic = ic->next)
2883 if (ic->op == CALL || ic->op == PCALL)
2887 fprintf(stderr,"found parameter push with no function call\n");
2891 /* if the registers have been saved already then
2893 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2896 /* find the registers in use at this time
2897 and push them away to safety */
2898 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2902 if (options.useXstack) {
2903 if (bitVectBitValue(rsave,R0_IDX))
2904 pic16_emitcode("mov","b,r0");
2905 pic16_emitcode("mov","r0,%s",spname);
2906 for (i = 0 ; i < pic16_nRegs ; i++) {
2907 if (bitVectBitValue(rsave,i)) {
2909 pic16_emitcode("mov","a,b");
2911 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2912 pic16_emitcode("movx","@r0,a");
2913 pic16_emitcode("inc","r0");
2916 pic16_emitcode("mov","%s,r0",spname);
2917 if (bitVectBitValue(rsave,R0_IDX))
2918 pic16_emitcode("mov","r0,b");
2920 //for (i = 0 ; i < pic16_nRegs ; i++) {
2921 // if (bitVectBitValue(rsave,i))
2922 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2925 dtype = operandType(IC_LEFT(ic));
2926 if (currFunc && dtype &&
2927 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2928 IFFUNC_ISISR(currFunc->type) &&
2931 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2934 /*-----------------------------------------------------------------*/
2935 /* unsaveRegisters - pop the pushed registers */
2936 /*-----------------------------------------------------------------*/
2937 static void unsaveRegisters (iCode *ic)
2942 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2943 /* find the registers in use at this time
2944 and push them away to safety */
2945 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2948 if (options.useXstack) {
2949 pic16_emitcode("mov","r0,%s",spname);
2950 for (i = pic16_nRegs ; i >= 0 ; i--) {
2951 if (bitVectBitValue(rsave,i)) {
2952 pic16_emitcode("dec","r0");
2953 pic16_emitcode("movx","a,@r0");
2955 pic16_emitcode("mov","b,a");
2957 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2961 pic16_emitcode("mov","%s,r0",spname);
2962 if (bitVectBitValue(rsave,R0_IDX))
2963 pic16_emitcode("mov","r0,b");
2965 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2966 // if (bitVectBitValue(rsave,i))
2967 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2974 /*-----------------------------------------------------------------*/
2976 /*-----------------------------------------------------------------*/
2977 static void pushSide(operand * oper, int size)
2980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2982 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2983 if (AOP_TYPE(oper) != AOP_REG &&
2984 AOP_TYPE(oper) != AOP_DIR &&
2986 pic16_emitcode("mov","a,%s",l);
2987 pic16_emitcode("push","acc");
2989 pic16_emitcode("push","%s",l);
2994 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2996 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2997 pic16_emitpcode(POC_MOVFW, src);
2998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3000 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3001 src, pic16_popGet(AOP(op), offset)));
3006 /*-----------------------------------------------------------------*/
3007 /* assignResultValue - assign results to oper, rescall==1 is */
3008 /* called from genCall() or genPcall() */
3009 /*-----------------------------------------------------------------*/
3010 static void assignResultValue(operand * oper, int rescall)
3012 int size = AOP_SIZE(oper);
3016 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3017 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3020 /* assign result from a call/pcall function() */
3022 /* function results are stored in a special order,
3023 * see top of file with Function return policy, or manual */
3026 /* 8-bits, result in WREG */
3027 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3030 /* 16-bits, result in PRODL:WREG */
3031 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3035 /* 24-bits, result in PRODH:PRODL:WREG */
3036 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3040 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3041 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3045 /* >32-bits, result on stack, and FSR0 points to beginning.
3046 * Fix stack when done */
3048 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3050 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3051 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3053 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3058 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3059 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3060 if(STACK_MODEL_LARGE) {
3062 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3066 int areg = 0; /* matching argument register */
3068 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3069 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3072 /* its called from genReceive (probably) -- VR */
3073 /* I hope this code will not be called from somewhere else in the future!
3074 * We manually set the pseudo stack pointer in genReceive. - dw
3076 if(!GpsuedoStkPtr && _G.useWreg) {
3077 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3079 /* The last byte in the assignment is in W */
3080 if(areg <= GpsuedoStkPtr) {
3082 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3084 // debugf("receive from WREG\n", 0);
3086 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3089 _G.stack_lat = AOP_SIZE(oper)-1;
3094 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3095 // debugf("receive from STACK\n", 0);
3102 /*-----------------------------------------------------------------*/
3103 /* genIpush - generate code for pushing this gets a little complex */
3104 /*-----------------------------------------------------------------*/
3105 static void genIpush (iCode *ic)
3107 // int size, offset=0;
3110 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3113 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3115 /* send to stack as normal */
3116 addSet(&_G.sendSet,ic);
3117 // addSetHead(&_G.sendSet,ic);
3118 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3123 int size, offset = 0 ;
3127 /* if this is not a parm push : ie. it is spill push
3128 and spill push is always done on the local stack */
3129 if (!ic->parmPush) {
3131 /* and the item is spilt then do nothing */
3132 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3135 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3136 size = AOP_SIZE(IC_LEFT(ic));
3137 /* push it on the stack */
3139 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3144 pic16_emitcode("push","%s",l);
3149 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3153 /*-----------------------------------------------------------------*/
3154 /* genIpop - recover the registers: can happen only for spilling */
3155 /*-----------------------------------------------------------------*/
3156 static void genIpop (iCode *ic)
3159 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3164 /* if the temp was not pushed then */
3165 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3168 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3169 size = AOP_SIZE(IC_LEFT(ic));
3172 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3175 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3180 /*-----------------------------------------------------------------*/
3181 /* unsaverbank - restores the resgister bank from stack */
3182 /*-----------------------------------------------------------------*/
3183 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3185 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3193 if (options.useXstack) {
3195 r = getFreePtr(ic,&aop,FALSE);
3198 pic16_emitcode("mov","%s,_spx",r->name);
3199 pic16_emitcode("movx","a,@%s",r->name);
3200 pic16_emitcode("mov","psw,a");
3201 pic16_emitcode("dec","%s",r->name);
3204 pic16_emitcode ("pop","psw");
3207 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3208 if (options.useXstack) {
3209 pic16_emitcode("movx","a,@%s",r->name);
3210 //pic16_emitcode("mov","(%s+%d),a",
3211 // regspic16[i].base,8*bank+regspic16[i].offset);
3212 pic16_emitcode("dec","%s",r->name);
3215 pic16_emitcode("pop",""); //"(%s+%d)",
3216 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3219 if (options.useXstack) {
3221 pic16_emitcode("mov","_spx,%s",r->name);
3222 pic16_freeAsmop(NULL,aop,ic,TRUE);
3228 /*-----------------------------------------------------------------*/
3229 /* saverbank - saves an entire register bank on the stack */
3230 /*-----------------------------------------------------------------*/
3231 static void saverbank (int bank, iCode *ic, bool pushPsw)
3233 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3240 if (options.useXstack) {
3243 r = getFreePtr(ic,&aop,FALSE);
3244 pic16_emitcode("mov","%s,_spx",r->name);
3248 for (i = 0 ; i < pic16_nRegs ;i++) {
3249 if (options.useXstack) {
3250 pic16_emitcode("inc","%s",r->name);
3251 //pic16_emitcode("mov","a,(%s+%d)",
3252 // regspic16[i].base,8*bank+regspic16[i].offset);
3253 pic16_emitcode("movx","@%s,a",r->name);
3255 pic16_emitcode("push","");// "(%s+%d)",
3256 //regspic16[i].base,8*bank+regspic16[i].offset);
3260 if (options.useXstack) {
3261 pic16_emitcode("mov","a,psw");
3262 pic16_emitcode("movx","@%s,a",r->name);
3263 pic16_emitcode("inc","%s",r->name);
3264 pic16_emitcode("mov","_spx,%s",r->name);
3265 pic16_freeAsmop (NULL,aop,ic,TRUE);
3268 pic16_emitcode("push","psw");
3270 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3278 static int wparamCmp(void *p1, void *p2)
3280 return (!strcmp((char *)p1, (char *)p2));
3283 int inWparamList(char *s)
3285 return isinSetWith(wparamList, s, wparamCmp);
3289 /*-----------------------------------------------------------------*/
3290 /* genCall - generates a call statement */
3291 /*-----------------------------------------------------------------*/
3292 static void genCall (iCode *ic)
3302 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3303 /* if caller saves & we have not saved then */
3304 // if (!ic->regsSaved)
3305 // saveRegisters(ic);
3307 /* initialise stackParms for IPUSH pushes */
3308 // stackParms = psuedoStkPtr;
3309 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3310 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3311 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3314 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3317 /* if send set is not empty the assign */
3320 int psuedoStkPtr=-1;
3321 int firstTimeThruLoop = 1;
3324 /* reverse sendSet if function is not reentrant */
3325 if(!IFFUNC_ISREENT(ftype))
3326 _G.sendSet = reverseSet(_G.sendSet);
3328 /* First figure how many parameters are getting passed */
3332 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3336 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3337 size = AOP_SIZE(IC_LEFT(sic));
3341 /* pass the last byte through WREG */
3345 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3349 if(!firstTimeThruLoop) {
3350 /* If this is not the first time we've been through the loop
3351 * then we need to save the parameter in a temporary
3352 * register. The last byte of the last parameter is
3356 // --psuedoStkPtr; // sanity check
3360 firstTimeThruLoop=0;
3362 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3367 /* all arguments are passed via stack */
3371 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3372 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3373 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3375 // pushaop(AOP(IC_LEFT(sic)), size);
3376 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3383 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3387 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3388 pushw(); /* save last parameter to stack if functions has varargs */
3392 } else use_wreg = 0;
3394 _G.stackRegSet = _G.sendSet;
3399 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3403 /* if we need to assign a result value */
3404 if ((IS_ITEMP(IC_RESULT(ic))
3405 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3406 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3407 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3410 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3413 assignResultValue(IC_RESULT(ic), 1);
3415 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3416 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3418 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3421 if(!stackParms && ic->parmBytes) {
3422 stackParms = ic->parmBytes;
3425 stackParms -= use_wreg;
3428 if(stackParms == 1) {
3429 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3431 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3432 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3434 if(STACK_MODEL_LARGE) {
3436 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3441 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3444 /* adjust the stack for parameters if required */
3445 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3448 /* if register bank was saved then pop them */
3450 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3452 /* if we hade saved some registers then unsave them */
3453 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3454 unsaveRegisters (ic);
3460 /*-----------------------------------------------------------------*/
3461 /* genPcall - generates a call by pointer statement */
3462 /* new version, created from genCall - HJD */
3463 /*-----------------------------------------------------------------*/
3464 static void genPcall (iCode *ic)
3466 sym_link *ftype, *fntype;
3468 symbol *retlbl = newiTempLabel(NULL);
3469 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3473 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3474 fntype = operandType( IC_LEFT(ic) )->next;
3476 /* if send set is not empty the assign */
3479 int psuedoStkPtr=-1;
3481 /* reverse sendSet if function is not reentrant */
3482 if(!IFFUNC_ISREENT(fntype))
3483 _G.sendSet = reverseSet(_G.sendSet);
3487 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3490 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3491 size = AOP_SIZE(IC_LEFT(sic));
3494 /* all parameters are passed via stack, since WREG is clobbered
3495 * by the calling sequence */
3497 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3499 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3501 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3505 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3508 _G.stackRegSet = _G.sendSet;
3512 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3514 // push return address
3515 // push $ on return stack, then replace with retlbl
3517 /* Thanks to Thorsten Klose for pointing out that the following
3518 * snippet should be interrupt safe */
3519 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3520 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3522 pic16_emitpcodeNULLop(POC_PUSH);
3524 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3525 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3526 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3527 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3528 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3529 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3532 /* restore interrupt control register */
3533 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3534 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3536 /* make the call by writing the pointer into pc */
3537 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3538 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3540 // note: MOVFF to PCL not allowed
3541 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3542 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3545 /* return address is here: (X) */
3546 pic16_emitpLabelFORCE(retlbl->key);
3548 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3551 /* if we need assign a result value */
3552 if ((IS_ITEMP(IC_RESULT(ic))
3553 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3554 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3555 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3558 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3561 assignResultValue(IC_RESULT(ic), 1);
3563 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3564 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3566 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3569 // stackParms -= use_wreg;
3572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3573 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3574 if(STACK_MODEL_LARGE) {
3576 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3581 /*-----------------------------------------------------------------*/
3582 /* resultRemat - result is rematerializable */
3583 /*-----------------------------------------------------------------*/
3584 static int resultRemat (iCode *ic)
3586 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3587 if (SKIP_IC(ic) || ic->op == IFX)
3590 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3591 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3592 if (sym->remat && !POINTER_SET(ic))
3599 #if defined(__BORLANDC__) || defined(_MSC_VER)
3600 #define STRCASECMP stricmp
3602 #define STRCASECMP strcasecmp
3606 /*-----------------------------------------------------------------*/
3607 /* inExcludeList - return 1 if the string is in exclude Reg list */
3608 /*-----------------------------------------------------------------*/
3609 static bool inExcludeList(char *s)
3611 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3615 if (options.excludeRegs[i] &&
3616 STRCASECMP(options.excludeRegs[i],"none") == 0)
3619 for ( i = 0 ; options.excludeRegs[i]; i++) {
3620 if (options.excludeRegs[i] &&
3621 STRCASECMP(s,options.excludeRegs[i]) == 0)
3628 /*-----------------------------------------------------------------*/
3629 /* genFunction - generated code for function entry */
3630 /*-----------------------------------------------------------------*/
3631 static void genFunction (iCode *ic)
3637 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3639 pic16_labelOffset += (max_key+4);
3644 ftype = operandType(IC_LEFT(ic));
3645 sym = OP_SYMBOL(IC_LEFT(ic));
3647 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3648 /* create an absolute section at the interrupt vector:
3649 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3654 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3656 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3657 sprintf(asymname, "ivec_%s", sym->name);
3659 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3660 asym = newSymbol(asymname, 0);
3662 /* FIXME: when an interrupt is declared as naked, do not emit the special
3663 * wrapper segment at vector address. The user should take care for this
3666 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3667 pic16_addpBlock( apb );
3669 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3670 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3671 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3673 /* mark the end of this tiny function */
3674 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3679 abSym = Safe_calloc(1, sizeof(absSym));
3680 strcpy(abSym->name, asymname);
3682 switch( FUNC_INTNO(sym->type) ) {
3683 case 0: abSym->address = 0x000000; break;
3684 case 1: abSym->address = 0x000008; break;
3685 case 2: abSym->address = 0x000018; break;
3688 fprintf(stderr, "no interrupt number is given\n");
3689 abSym->address = -1; break;
3692 /* relocate interrupt vectors if needed */
3693 if(abSym->address != -1)
3694 abSym->address += pic16_options.ivt_loc;
3696 addSet(&absSymSet, abSym);
3700 /* create the function header */
3701 pic16_emitcode(";","-----------------------------------------");
3702 pic16_emitcode(";"," function %s",sym->name);
3703 pic16_emitcode(";","-----------------------------------------");
3705 pic16_emitcode("","%s:",sym->rname);
3706 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3712 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3713 if(!strcmp(ab->name, sym->rname)) {
3714 pic16_pBlockConvert2Absolute(pb);
3721 if(IFFUNC_ISNAKED(ftype)) {
3722 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3726 /* if critical function then turn interrupts off */
3727 if (IFFUNC_ISCRITICAL(ftype)) {
3728 //pic16_emitcode("clr","ea");
3731 currFunc = sym; /* update the currFunc symbol */
3732 _G.fregsUsed = sym->regsUsed;
3733 _G.sregsAlloc = newBitVect(128);
3736 /* if this is an interrupt service routine then
3737 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3738 if (IFFUNC_ISISR(sym->type)) {
3739 _G.usefastretfie = 1; /* use shadow registers by default */
3741 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3742 if(!FUNC_ISSHADOWREGS(sym->type)) {
3743 /* do not save WREG,STATUS,BSR for high priority interrupts
3744 * because they are stored in the hardware shadow registers already */
3745 _G.usefastretfie = 0;
3746 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3747 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3748 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3751 /* these should really be optimized somehow, because not all
3752 * interrupt handlers modify them */
3753 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3758 // pic16_pBlockConvert2ISR(pb);
3761 /* emit code to setup stack frame if user enabled,
3762 * and function is not main() */
3764 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3765 if(strcmp(sym->name, "main")) {
3767 || !options.ommitFramePtr
3769 || IFFUNC_ARGS(sym->type)
3770 || FUNC_HASSTACKPARM(sym->etype)
3772 /* setup the stack frame */
3773 if(STACK_MODEL_LARGE)
3774 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3775 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3777 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3778 if(STACK_MODEL_LARGE)
3779 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3783 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3786 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3788 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3789 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3791 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3794 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3795 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3802 /* if callee-save to be used for this function
3803 * then save the registers being used in this function */
3804 // if (IFFUNC_CALLEESAVES(sym->type))
3808 /* if any registers used */
3809 if (sym->regsUsed) {
3810 /* save the registers used */
3811 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3812 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3813 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3814 if (bitVectBitValue(sym->regsUsed,i)) {
3815 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3818 if(!pic16_regWithIdx(i)->wasUsed) {
3819 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3820 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3821 pic16_regWithIdx(i)->wasUsed = 1;
3825 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3829 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3830 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3833 /*-----------------------------------------------------------------*/
3834 /* genEndFunction - generates epilogue for functions */
3835 /*-----------------------------------------------------------------*/
3836 static void genEndFunction (iCode *ic)
3838 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3842 if(IFFUNC_ISNAKED(sym->type)) {
3843 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3849 /* add code for ISCRITICAL */
3850 if(IFFUNC_ISCRITICAL(sym->type)) {
3851 /* if critical function, turn on interrupts */
3853 /* TODO: add code here -- VR */
3856 // sym->regsUsed = _G.fregsUsed;
3858 /* now we need to restore the registers */
3859 /* if any registers used */
3861 /* first restore registers that might be used for stack access */
3862 if(_G.sregsAllocSet) {
3865 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3866 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3867 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3871 if (sym->regsUsed) {
3874 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3875 /* restore registers used */
3876 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3877 for ( i = sym->regsUsed->size; i >= 0; i--) {
3878 if (bitVectBitValue(sym->regsUsed,i)) {
3879 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3883 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3888 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3890 if (sym->stack == 1) {
3891 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3892 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3894 // we have to add more than one...
3895 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3896 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3897 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3899 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3900 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3901 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3905 if(strcmp(sym->name, "main")) {
3907 || !options.ommitFramePtr
3909 || IFFUNC_ARGS(sym->type)
3910 || FUNC_HASSTACKPARM(sym->etype)
3912 /* restore stack frame */
3913 if(STACK_MODEL_LARGE)
3914 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3915 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3921 if (IFFUNC_ISISR(sym->type)) {
3922 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3923 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3924 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3925 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3927 if(!FUNC_ISSHADOWREGS(sym->type)) {
3928 /* do not restore interrupt vector for WREG,STATUS,BSR
3929 * for high priority interrupt, see genFunction */
3930 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3931 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3934 // _G.interruptvector = 0; /* sanity check */
3937 /* if debug then send end of function */
3938 /* if (options.debug && currFunc) */
3940 debugFile->writeEndFunction (currFunc, ic, 1);
3943 if(_G.usefastretfie)
3944 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3946 pic16_emitpcodeNULLop(POC_RETFIE);
3948 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3950 _G.usefastretfie = 0;
3954 if (IFFUNC_ISCRITICAL(sym->type)) {
3955 pic16_emitcode("setb","ea");
3958 /* if debug then send end of function */
3960 debugFile->writeEndFunction (currFunc, ic, 1);
3963 /* insert code to restore stack frame, if user enabled it
3964 * and function is not main() */
3967 pic16_emitpcodeNULLop(POC_RETURN);
3969 /* Mark the end of a function */
3970 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3974 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3976 unsigned long lit=1;
3981 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3982 if(AOP_TYPE(op) == AOP_LIT) {
3983 if(!IS_FLOAT(operandType( op ))) {
3984 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3987 unsigned long lit_int;
3991 /* take care if literal is a float */
3992 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3998 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3999 pic16_emitpcode(POC_CLRF, dest);
4001 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4002 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4005 if(dest->type == PO_WREG && (offset == 0)) {
4006 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4009 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4013 /*-----------------------------------------------------------------*/
4014 /* genRet - generate code for return statement */
4015 /*-----------------------------------------------------------------*/
4016 static void genRet (iCode *ic)
4022 /* if we have no return value then
4023 * just generate the "ret" */
4028 /* we have something to return then
4029 * move the return value into place */
4030 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4031 size = AOP_SIZE(IC_LEFT(ic));
4035 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4038 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4041 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4043 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4046 /* >32-bits, setup stack and FSR0 */
4048 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4049 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4051 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4053 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4058 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4059 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4061 if(STACK_MODEL_LARGE) {
4062 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4063 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4065 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4070 /* old code, left here for reference -- VR */
4074 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4076 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4077 pic16_emitpcomment("push %s",l);
4080 DEBUGpic16_emitcode(";", "%d", __LINE__);
4081 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4082 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4084 if (strcmp(fReturn[offset],l)) {
4085 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4086 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4087 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4089 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4093 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4103 if (strcmp(fReturn[pushed],"a"))
4104 pic16_emitcode("pop",fReturn[pushed]);
4106 pic16_emitcode("pop","acc");
4112 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4115 /* generate a jump to the return label
4116 * if the next is not the return statement */
4117 if (!(ic->next && ic->next->op == LABEL
4118 && IC_LABEL(ic->next) == returnLabel)) {
4120 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4121 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4125 /*-----------------------------------------------------------------*/
4126 /* genLabel - generates a label */
4127 /*-----------------------------------------------------------------*/
4128 static void genLabel (iCode *ic)
4132 /* special case never generate */
4133 if (IC_LABEL(ic) == entryLabel)
4136 pic16_emitpLabel(IC_LABEL(ic)->key);
4137 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4140 /*-----------------------------------------------------------------*/
4141 /* genGoto - generates a goto */
4142 /*-----------------------------------------------------------------*/
4144 static void genGoto (iCode *ic)
4147 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4148 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4152 /*-----------------------------------------------------------------*/
4153 /* genMultbits :- multiplication of bits */
4154 /*-----------------------------------------------------------------*/
4155 static void genMultbits (operand *left,
4161 if(!pic16_sameRegs(AOP(result),AOP(right)))
4162 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4164 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4165 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4166 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4171 /*-----------------------------------------------------------------*/
4172 /* genMultOneByte : 8 bit multiplication & division */
4173 /*-----------------------------------------------------------------*/
4174 static void genMultOneByte (operand *left,
4180 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4181 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4183 /* (if two literals, the value is computed before) */
4184 /* if one literal, literal on the right */
4185 if (AOP_TYPE(left) == AOP_LIT){
4191 /* size is already checked in genMult == 1 */
4192 // size = AOP_SIZE(result);
4194 if (AOP_TYPE(right) == AOP_LIT){
4195 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4196 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4197 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4198 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4200 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4201 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4202 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4203 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4206 pic16_genMult8X8_8 (left, right,result);
4209 /*-----------------------------------------------------------------*/
4210 /* genMultOneWord : 16 bit multiplication */
4211 /*-----------------------------------------------------------------*/
4212 static void genMultOneWord (operand *left,
4217 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4218 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4220 /* (if two literals, the value is computed before)
4221 * if one literal, literal on the right */
4222 if (AOP_TYPE(left) == AOP_LIT){
4228 /* size is checked already == 2 */
4229 // size = AOP_SIZE(result);
4231 if (AOP_TYPE(right) == AOP_LIT) {
4232 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4233 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4234 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4235 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4237 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4238 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4239 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4240 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4243 pic16_genMult16X16_16(left, right,result);
4246 /*-----------------------------------------------------------------*/
4247 /* genMultOneLong : 32 bit multiplication */
4248 /*-----------------------------------------------------------------*/
4249 static void genMultOneLong (operand *left,
4254 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4255 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4257 /* (if two literals, the value is computed before)
4258 * if one literal, literal on the right */
4259 if (AOP_TYPE(left) == AOP_LIT){
4265 /* size is checked already == 4 */
4266 // size = AOP_SIZE(result);
4268 if (AOP_TYPE(right) == AOP_LIT) {
4269 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4270 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4271 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4272 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4274 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4275 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4276 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4277 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4280 pic16_genMult32X32_32(left, right,result);
4285 /*-----------------------------------------------------------------*/
4286 /* genMult - generates code for multiplication */
4287 /*-----------------------------------------------------------------*/
4288 static void genMult (iCode *ic)
4290 operand *left = IC_LEFT(ic);
4291 operand *right = IC_RIGHT(ic);
4292 operand *result= IC_RESULT(ic);
4295 /* assign the amsops */
4296 pic16_aopOp (left,ic,FALSE);
4297 pic16_aopOp (right,ic,FALSE);
4298 pic16_aopOp (result,ic,TRUE);
4300 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4302 /* special cases first *
4304 if (AOP_TYPE(left) == AOP_CRY
4305 && AOP_TYPE(right)== AOP_CRY) {
4306 genMultbits(left,right,result);
4310 /* if both are of size == 1 */
4311 if(AOP_SIZE(left) == 1
4312 && AOP_SIZE(right) == 1) {
4313 genMultOneByte(left,right,result);
4317 /* if both are of size == 2 */
4318 if(AOP_SIZE(left) == 2
4319 && AOP_SIZE(right) == 2) {
4320 genMultOneWord(left, right, result);
4324 /* if both are of size == 4 */
4325 if(AOP_SIZE(left) == 4
4326 && AOP_SIZE(right) == 4) {
4327 genMultOneLong(left, right, result);
4331 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4334 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4335 /* should have been converted to function call */
4339 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4341 pic16_freeAsmop(result,NULL,ic,TRUE);
4344 /*-----------------------------------------------------------------*/
4345 /* genDivbits :- division of bits */
4346 /*-----------------------------------------------------------------*/
4347 static void genDivbits (operand *left,
4354 /* the result must be bit */
4355 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4356 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4360 pic16_emitcode("div","ab");
4361 pic16_emitcode("rrc","a");
4362 pic16_aopPut(AOP(result),"c",0);
4365 /*-----------------------------------------------------------------*/
4366 /* genDivOneByte : 8 bit division */
4367 /*-----------------------------------------------------------------*/
4368 static void genDivOneByte (operand *left,
4372 sym_link *opetype = operandType(result);
4377 /* result = divident / divisor
4378 * - divident may be a register or a literal,
4379 * - divisor may be a register or a literal,
4380 * so there are 3 cases (literal / literal is optimized
4381 * by the front-end) to handle.
4382 * In addition we must handle signed and unsigned, which
4383 * result in 6 final different cases -- VR */
4387 size = AOP_SIZE(result) - 1;
4389 /* signed or unsigned */
4390 if (SPEC_USIGN(opetype)) {
4391 pCodeOp *pct1, /* count */
4394 symbol *label1, *label2, *label3;;
4397 /* unsigned is easy */
4399 pct1 = pic16_popGetTempReg(1);
4400 pct2 = pic16_popGetTempReg(1);
4401 pct3 = pic16_popGetTempReg(1);
4403 label1 = newiTempLabel(NULL);
4404 label2 = newiTempLabel(NULL);
4405 label3 = newiTempLabel(NULL);
4407 /* the following algorithm is extracted from divuint.c */
4409 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4410 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4412 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4414 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4416 pic16_emitpLabel(label1->key);
4419 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4423 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4427 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4429 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4430 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4432 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4433 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4434 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4436 pic16_emitpLabel( label3->key );
4437 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4438 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4442 pic16_emitpLabel(label2->key);
4443 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4444 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4445 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4447 /* result is in wreg */
4448 if(AOP_TYPE(result) != AOP_ACC)
4449 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4451 pic16_popReleaseTempReg( pct3, 1);
4452 pic16_popReleaseTempReg( pct2, 1);
4453 pic16_popReleaseTempReg( pct1, 1);
4458 /* signed is a little bit more difficult */
4460 /* save the signs of the operands */
4461 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4463 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4464 pic16_emitcode("push","acc"); /* save it on the stack */
4466 /* now sign adjust for both left & right */
4467 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4469 lbl = newiTempLabel(NULL);
4470 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4471 pic16_emitcode("cpl","a");
4472 pic16_emitcode("inc","a");
4473 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4474 pic16_emitcode("mov","b,a");
4476 /* sign adjust left side */
4477 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4480 lbl = newiTempLabel(NULL);
4481 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4482 pic16_emitcode("cpl","a");
4483 pic16_emitcode("inc","a");
4484 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4486 /* now the division */
4487 pic16_emitcode("div","ab");
4488 /* we are interested in the lower order
4490 pic16_emitcode("mov","b,a");
4491 lbl = newiTempLabel(NULL);
4492 pic16_emitcode("pop","acc");
4493 /* if there was an over flow we don't
4494 adjust the sign of the result */
4495 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4496 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4498 pic16_emitcode("clr","a");
4499 pic16_emitcode("subb","a,b");
4500 pic16_emitcode("mov","b,a");
4501 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4503 /* now we are done */
4504 pic16_aopPut(AOP(result),"b",0);
4506 pic16_emitcode("mov","c,b.7");
4507 pic16_emitcode("subb","a,acc");
4510 pic16_aopPut(AOP(result),"a",offset++);
4514 /*-----------------------------------------------------------------*/
4515 /* genDiv - generates code for division */
4516 /*-----------------------------------------------------------------*/
4517 static void genDiv (iCode *ic)
4519 operand *left = IC_LEFT(ic);
4520 operand *right = IC_RIGHT(ic);
4521 operand *result= IC_RESULT(ic);
4524 /* Division is a very lengthy algorithm, so it is better
4525 * to call support routines than inlining algorithm.
4526 * Division functions written here just in case someone
4527 * wants to inline and not use the support libraries -- VR */
4531 /* assign the amsops */
4532 pic16_aopOp (left,ic,FALSE);
4533 pic16_aopOp (right,ic,FALSE);
4534 pic16_aopOp (result,ic,TRUE);
4536 /* special cases first */
4538 if (AOP_TYPE(left) == AOP_CRY &&
4539 AOP_TYPE(right)== AOP_CRY) {
4540 genDivbits(left,right,result);
4544 /* if both are of size == 1 */
4545 if (AOP_SIZE(left) == 1 &&
4546 AOP_SIZE(right) == 1 ) {
4547 genDivOneByte(left,right,result);
4551 /* should have been converted to function call */
4554 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4555 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4556 pic16_freeAsmop(result,NULL,ic,TRUE);
4559 /*-----------------------------------------------------------------*/
4560 /* genModbits :- modulus of bits */
4561 /*-----------------------------------------------------------------*/
4562 static void genModbits (operand *left,
4570 werror(W_POSSBUG2, __FILE__, __LINE__);
4571 /* the result must be bit */
4572 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4573 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4577 pic16_emitcode("div","ab");
4578 pic16_emitcode("mov","a,b");
4579 pic16_emitcode("rrc","a");
4580 pic16_aopPut(AOP(result),"c",0);
4583 /*-----------------------------------------------------------------*/
4584 /* genModOneByte : 8 bit modulus */
4585 /*-----------------------------------------------------------------*/
4586 static void genModOneByte (operand *left,
4590 sym_link *opetype = operandType(result);
4595 werror(W_POSSBUG2, __FILE__, __LINE__);
4597 /* signed or unsigned */
4598 if (SPEC_USIGN(opetype)) {
4599 /* unsigned is easy */
4600 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4601 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4603 pic16_emitcode("div","ab");
4604 pic16_aopPut(AOP(result),"b",0);
4608 /* signed is a little bit more difficult */
4610 /* save the signs of the operands */
4611 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4614 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4615 pic16_emitcode("push","acc"); /* save it on the stack */
4617 /* now sign adjust for both left & right */
4618 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4621 lbl = newiTempLabel(NULL);
4622 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4623 pic16_emitcode("cpl","a");
4624 pic16_emitcode("inc","a");
4625 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4626 pic16_emitcode("mov","b,a");
4628 /* sign adjust left side */
4629 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4632 lbl = newiTempLabel(NULL);
4633 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4634 pic16_emitcode("cpl","a");
4635 pic16_emitcode("inc","a");
4636 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4638 /* now the multiplication */
4639 pic16_emitcode("div","ab");
4640 /* we are interested in the lower order
4642 lbl = newiTempLabel(NULL);
4643 pic16_emitcode("pop","acc");
4644 /* if there was an over flow we don't
4645 adjust the sign of the result */
4646 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4647 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4649 pic16_emitcode("clr","a");
4650 pic16_emitcode("subb","a,b");
4651 pic16_emitcode("mov","b,a");
4652 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4654 /* now we are done */
4655 pic16_aopPut(AOP(result),"b",0);
4659 /*-----------------------------------------------------------------*/
4660 /* genMod - generates code for division */
4661 /*-----------------------------------------------------------------*/
4662 static void genMod (iCode *ic)
4664 operand *left = IC_LEFT(ic);
4665 operand *right = IC_RIGHT(ic);
4666 operand *result= IC_RESULT(ic);
4670 /* assign the amsops */
4671 pic16_aopOp (left,ic,FALSE);
4672 pic16_aopOp (right,ic,FALSE);
4673 pic16_aopOp (result,ic,TRUE);
4675 /* special cases first */
4677 if (AOP_TYPE(left) == AOP_CRY &&
4678 AOP_TYPE(right)== AOP_CRY) {
4679 genModbits(left,right,result);
4683 /* if both are of size == 1 */
4684 if (AOP_SIZE(left) == 1 &&
4685 AOP_SIZE(right) == 1 ) {
4686 genModOneByte(left,right,result);
4690 /* should have been converted to function call */
4694 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4695 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4696 pic16_freeAsmop(result,NULL,ic,TRUE);
4699 /*-----------------------------------------------------------------*/
4700 /* genIfxJump :- will create a jump depending on the ifx */
4701 /*-----------------------------------------------------------------*/
4703 note: May need to add parameter to indicate when a variable is in bit space.
4705 static void genIfxJump (iCode *ic, char *jval)
4709 /* if true label then we jump if condition
4711 if ( IC_TRUE(ic) ) {
4713 if(strcmp(jval,"a") == 0)
4715 else if (strcmp(jval,"c") == 0)
4718 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4719 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4722 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4723 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4727 /* false label is present */
4728 if(strcmp(jval,"a") == 0)
4730 else if (strcmp(jval,"c") == 0)
4733 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4734 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4737 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4738 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4743 /* mark the icode as generated */
4747 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4751 /* if true label then we jump if condition
4753 if ( IC_TRUE(ic) ) {
4754 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4755 pic16_emitpcode(POC_BTFSC, jop);
4757 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4758 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4761 /* false label is present */
4762 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4763 pic16_emitpcode(POC_BTFSS, jop);
4765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4766 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4770 /* mark the icode as generated */
4777 /*-----------------------------------------------------------------*/
4779 /*-----------------------------------------------------------------*/
4780 static void genSkip(iCode *ifx,int status_bit)
4782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4786 if ( IC_TRUE(ifx) ) {
4787 switch(status_bit) {
4802 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4803 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4807 switch(status_bit) {
4821 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4822 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4829 /*-----------------------------------------------------------------*/
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipc(resolvedIfx *rifx)
4834 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4844 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4845 rifx->generated = 1;
4848 #if !(USE_SIMPLE_GENCMP)
4849 /*-----------------------------------------------------------------*/
4851 /*-----------------------------------------------------------------*/
4852 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4854 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4859 if( (rifx->condition ^ invert_condition) & 1)
4864 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4865 rifx->generated = 1;
4870 /*-----------------------------------------------------------------*/
4872 /*-----------------------------------------------------------------*/
4873 static void genSkipz(iCode *ifx, int condition)
4884 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4886 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4889 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4891 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4896 #if !(USE_SIMPLE_GENCMP)
4897 /*-----------------------------------------------------------------*/
4899 /*-----------------------------------------------------------------*/
4900 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4906 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4908 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4911 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4912 rifx->generated = 1;
4917 /*-----------------------------------------------------------------*/
4918 /* genChkZeroes :- greater or less than comparison */
4919 /* For each byte in a literal that is zero, inclusive or the */
4920 /* the corresponding byte in the operand with W */
4921 /* returns true if any of the bytes are zero */
4922 /*-----------------------------------------------------------------*/
4923 static int genChkZeroes(operand *op, int lit, int size)
4930 i = (lit >> (size*8)) & 0xff;
4934 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4936 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4946 /*-----------------------------------------------------------------*/
4947 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4948 /* aop (if it's NOT a literal) or from lit (if */
4949 /* aop is a literal) */
4950 /*-----------------------------------------------------------------*/
4951 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4952 if (aop->type == AOP_LIT) {
4953 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4955 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4959 /*-----------------------------------------------------------------*/
4960 /* genCmp :- greater or less than comparison */
4961 /*-----------------------------------------------------------------*/
4963 #if USE_SIMPLE_GENCMP /* { */
4965 /* genCmp performs a left < right comparison, stores
4966 * the outcome in result (if != NULL) and generates
4967 * control flow code for the ifx (if != NULL).
4969 * This version leaves in sequences like
4970 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4971 * which should be optmized by the peephole
4972 * optimizer - RN 2005-01-01 */
4973 static void genCmp (operand *left,operand *right,
4974 operand *result, iCode *ifx, int sign)
4987 assert (AOP_SIZE(left) == AOP_SIZE(right));
4988 assert (left && right);
4990 size = AOP_SIZE(right) - 1;
4991 mask = (0x100UL << (size*8)) - 1;
4992 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4997 resolveIfx (&rIfx, ifx);
4999 /* handle for special cases */
5000 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5003 /**********************************************************************
5004 * handle bits - bit compares are promoted to int compares seemingly! *
5005 **********************************************************************/
5007 // THIS IS COMPLETELY UNTESTED!
5008 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5009 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5010 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5011 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5014 // 1 < {0,1} is false --> clear C by skipping the next instruction
5015 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5016 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5017 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5018 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5019 emitCLRC; // only skipped for left=0 && right=1
5021 goto correct_result_in_carry;
5025 /*************************************************
5026 * make sure that left is register (or the like) *
5027 *************************************************/
5028 if (!isAOP_REGlike(left)) {
5029 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5030 assert (isAOP_LIT(left));
5031 assert (isAOP_REGlike(right));
5032 // swap left and right
5033 // left < right <==> right > left <==> (right >= left + 1)
5034 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5036 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5037 // MAXVALUE < right? always false
5038 if (performedLt) emitCLRC; else emitSETC;
5039 goto correct_result_in_carry;
5042 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5043 // that's why we handled it above.
5050 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5051 } else if (isAOP_LIT(right)) {
5052 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5055 assert (isAOP_REGlike(left)); // left must be register or the like
5056 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5058 /*************************************************
5059 * special cases go here *
5060 *************************************************/
5062 if (isAOP_LIT(right)) {
5064 // unsigned comparison to a literal
5065 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5067 // unsigned left < 0? always false
5068 if (performedLt) emitCLRC; else emitSETC;
5069 goto correct_result_in_carry;
5072 // signed comparison to a literal
5073 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5074 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5075 // signed left < 0x80000000? always false
5076 if (performedLt) emitCLRC; else emitSETC;
5077 goto correct_result_in_carry;
5078 } else if (lit == 0) {
5079 // compare left < 0; set CARRY if SIGNBIT(left) is set
5080 if (performedLt) emitSETC; else emitCLRC;
5081 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5082 if (performedLt) emitCLRC; else emitSETC;
5083 goto correct_result_in_carry;
5086 } // right is literal
5088 /*************************************************
5089 * perform a general case comparison *
5090 * make sure we get CARRY==1 <==> left >= right *
5091 *************************************************/
5092 // compare most significant bytes
5093 //DEBUGpc ("comparing bytes at offset %d", size);
5095 // unsigned comparison
5096 mov2w_regOrLit (AOP(right), lit, size);
5097 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5099 // signed comparison
5100 // (add 2^n to both operands then perform an unsigned comparison)
5101 if (isAOP_LIT(right)) {
5102 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5103 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5105 if (litbyte == 0x80) {
5106 // left >= 0x80 -- always true, but more bytes to come
5107 pic16_mov2w (AOP(left), size);
5108 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5111 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5112 pic16_mov2w (AOP(left), size);
5113 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5114 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5117 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5118 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5119 pic16_mov2w (AOP(left), size);
5120 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5121 pic16_emitpcode (POC_MOVWF, pctemp);
5122 pic16_mov2w (AOP(right), size);
5123 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124 pic16_emitpcode (POC_SUBFW, pctemp);
5125 //pic16_popReleaseTempReg(pctemp, 1);
5129 // compare remaining bytes (treat as unsigned case from above)
5130 templbl = newiTempLabel ( NULL );
5133 //DEBUGpc ("comparing bytes at offset %d", offs);
5134 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5135 mov2w_regOrLit (AOP(right), lit, offs);
5136 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5138 pic16_emitpLabel (templbl->key);
5139 goto result_in_carry;
5143 /****************************************************
5144 * now CARRY contains the result of the comparison: *
5145 * SUBWF sets CARRY iff *
5146 * F-W >= 0 <==> F >= W <==> !(F < W) *
5147 * (F=left, W=right) *
5148 ****************************************************/
5151 if (result && AOP_TYPE(result) != AOP_CRY) {
5152 // value will be stored
5155 // value wil only be used in the following genSkipc()
5156 rIfx.condition ^= 1;
5160 correct_result_in_carry:
5162 // assign result to variable (if neccessary)
5163 if (result && AOP_TYPE(result) != AOP_CRY) {
5164 //DEBUGpc ("assign result");
5165 size = AOP_SIZE(result);
5167 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5169 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5172 // perform conditional jump
5174 //DEBUGpc ("generate control flow");
5183 static void genCmp (operand *left,operand *right,
5184 operand *result, iCode *ifx, int sign)
5186 int size; //, offset = 0 ;
5187 unsigned long lit = 0L,i = 0;
5188 resolvedIfx rFalseIfx;
5189 // resolvedIfx rTrueIfx;
5191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5194 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5195 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5201 resolveIfx(&rFalseIfx,ifx);
5202 truelbl = newiTempLabel(NULL);
5203 size = max(AOP_SIZE(left),AOP_SIZE(right));
5205 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5209 /* if literal is on the right then swap with left */
5210 if ((AOP_TYPE(right) == AOP_LIT)) {
5211 operand *tmp = right ;
5212 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5213 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5216 lit = (lit - 1) & mask;
5219 rFalseIfx.condition ^= 1;
5222 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5223 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5227 //if(IC_TRUE(ifx) == NULL)
5228 /* if left & right are bit variables */
5229 if (AOP_TYPE(left) == AOP_CRY &&
5230 AOP_TYPE(right) == AOP_CRY ) {
5231 assert (0 && "bit variables used in genCmp");
5232 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5233 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5235 /* subtract right from left if at the
5236 end the carry flag is set then we know that
5237 left is greater than right */
5239 symbol *lbl = newiTempLabel(NULL);
5242 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5243 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5247 if(AOP_TYPE(right) == AOP_LIT) {
5249 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5251 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5258 genSkipCond(&rFalseIfx,left,size-1,7);
5260 /* no need to compare to 0...*/
5261 /* NOTE: this is a de-generate compare that most certainly
5262 * creates some dead code. */
5263 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5265 if(ifx) ifx->generated = 1;
5272 //i = (lit >> (size*8)) & 0xff;
5273 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5275 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5277 i = ((0-lit) & 0xff);
5280 /* lit is 0x7f, all signed chars are less than
5281 * this except for 0x7f itself */
5282 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5283 genSkipz2(&rFalseIfx,0);
5285 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5286 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5287 genSkipc(&rFalseIfx);
5292 genSkipz2(&rFalseIfx,1);
5294 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5295 genSkipc(&rFalseIfx);
5299 if(ifx) ifx->generated = 1;
5303 /* chars are out of the way. now do ints and longs */
5306 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5313 genSkipCond(&rFalseIfx,left,size,7);
5314 if(ifx) ifx->generated = 1;
5319 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5321 //rFalseIfx.condition ^= 1;
5322 //genSkipCond(&rFalseIfx,left,size,7);
5323 //rFalseIfx.condition ^= 1;
5325 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5326 if(rFalseIfx.condition)
5327 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5329 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5331 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5332 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5333 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5336 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5338 if(rFalseIfx.condition) {
5340 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5346 genSkipc(&rFalseIfx);
5347 pic16_emitpLabel(truelbl->key);
5348 if(ifx) ifx->generated = 1;
5355 if( (lit & 0xff) == 0) {
5356 /* lower byte is zero */
5357 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5358 i = ((lit >> 8) & 0xff) ^0x80;
5359 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5360 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5361 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5362 genSkipc(&rFalseIfx);
5365 if(ifx) ifx->generated = 1;
5370 /* Special cases for signed longs */
5371 if( (lit & 0xffffff) == 0) {
5372 /* lower byte is zero */
5373 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5374 i = ((lit >> 8*3) & 0xff) ^0x80;
5375 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5376 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5377 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5378 genSkipc(&rFalseIfx);
5381 if(ifx) ifx->generated = 1;
5389 if(lit & (0x80 << (size*8))) {
5390 /* lit is negative */
5391 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5393 //genSkipCond(&rFalseIfx,left,size,7);
5395 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5397 if(rFalseIfx.condition)
5398 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5400 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5404 /* lit is positive */
5405 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5406 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5407 if(rFalseIfx.condition)
5408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5415 This works, but is only good for ints.
5416 It also requires a "known zero" register.
5417 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5418 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5419 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5420 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5421 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5422 genSkipc(&rFalseIfx);
5424 pic16_emitpLabel(truelbl->key);
5425 if(ifx) ifx->generated = 1;
5429 /* There are no more special cases, so perform a general compare */
5431 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5432 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5438 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5440 //rFalseIfx.condition ^= 1;
5441 genSkipc(&rFalseIfx);
5443 pic16_emitpLabel(truelbl->key);
5445 if(ifx) ifx->generated = 1;
5452 /* sign is out of the way. So now do an unsigned compare */
5453 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5456 /* General case - compare to an unsigned literal on the right.*/
5458 i = (lit >> (size*8)) & 0xff;
5459 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5460 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5462 i = (lit >> (size*8)) & 0xff;
5465 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5467 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5469 /* this byte of the lit is zero,
5470 *if it's not the last then OR in the variable */
5472 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5477 pic16_emitpLabel(lbl->key);
5478 // pic16_emitpLabel(truelbl->key);
5479 //if(emitFinalCheck)
5480 genSkipc(&rFalseIfx);
5482 pic16_emitpLabel(truelbl->key);
5484 if(ifx) ifx->generated = 1;
5491 if(AOP_TYPE(left) == AOP_LIT) {
5492 //symbol *lbl = newiTempLabel(NULL);
5494 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5497 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5500 if((lit == 0) && (sign == 0)){
5503 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5505 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5507 genSkipz2(&rFalseIfx,0);
5508 if(ifx) ifx->generated = 1;
5515 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5516 /* degenerate compare can never be true */
5517 if(rFalseIfx.condition == 0)
5518 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5520 if(ifx) ifx->generated = 1;
5525 /* signed comparisons to a literal byte */
5527 int lp1 = (lit+1) & 0xff;
5529 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5532 rFalseIfx.condition ^= 1;
5533 genSkipCond(&rFalseIfx,right,0,7);
5536 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5537 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5538 genSkipz2(&rFalseIfx,1);
5541 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5542 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5543 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5544 rFalseIfx.condition ^= 1;
5545 genSkipc(&rFalseIfx);
5549 /* unsigned comparisons to a literal byte */
5551 switch(lit & 0xff ) {
5553 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5554 genSkipz2(&rFalseIfx,0);
5557 rFalseIfx.condition ^= 1;
5558 genSkipCond(&rFalseIfx,right,0,7);
5562 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5563 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5565 rFalseIfx.condition ^= 1;
5566 if (AOP_TYPE(result) == AOP_CRY)
5567 genSkipc(&rFalseIfx);
5569 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5570 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5576 if(ifx) ifx->generated = 1;
5577 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5583 /* Size is greater than 1 */
5591 /* this means lit = 0xffffffff, or -1 */
5594 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5595 rFalseIfx.condition ^= 1;
5596 genSkipCond(&rFalseIfx,right,size,7);
5597 if(ifx) ifx->generated = 1;
5599 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5608 if(rFalseIfx.condition) {
5609 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5610 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5613 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5615 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5619 if(rFalseIfx.condition) {
5620 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5621 pic16_emitpLabel(truelbl->key);
5623 rFalseIfx.condition ^= 1;
5624 genSkipCond(&rFalseIfx,right,s,7);
5627 if(ifx) ifx->generated = 1;
5629 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5635 if((size == 1) && (0 == (lp1&0xff))) {
5636 /* lower byte of signed word is zero */
5637 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5638 i = ((lp1 >> 8) & 0xff) ^0x80;
5639 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5640 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5641 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5643 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5645 if(ifx) ifx->generated = 1;
5648 rFalseIfx.condition ^= 1;
5649 genSkipc(&rFalseIfx);
5650 if(ifx) ifx->generated = 1;
5656 if(lit & (0x80 << (size*8))) {
5657 /* Lit is less than zero */
5658 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5659 //rFalseIfx.condition ^= 1;
5660 //genSkipCond(&rFalseIfx,left,size,7);
5661 //rFalseIfx.condition ^= 1;
5662 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5663 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5665 if(rFalseIfx.condition)
5666 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5668 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5672 /* Lit is greater than or equal to zero */
5673 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5674 //rFalseIfx.condition ^= 1;
5675 //genSkipCond(&rFalseIfx,right,size,7);
5676 //rFalseIfx.condition ^= 1;
5678 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5679 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5681 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5682 if(rFalseIfx.condition)
5683 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5685 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5689 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5690 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5694 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5696 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5698 rFalseIfx.condition ^= 1;
5699 //rFalseIfx.condition = 1;
5700 genSkipc(&rFalseIfx);
5702 pic16_emitpLabel(truelbl->key);
5704 if(ifx) ifx->generated = 1;
5707 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5714 /* compare word or long to an unsigned literal on the right.*/
5719 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5722 break; /* handled above */
5725 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5727 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5728 genSkipz2(&rFalseIfx,0);
5732 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5734 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5737 if(rFalseIfx.condition)
5738 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5740 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5743 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5744 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5746 rFalseIfx.condition ^= 1;
5747 genSkipc(&rFalseIfx);
5750 pic16_emitpLabel(truelbl->key);
5752 if(ifx) ifx->generated = 1;
5754 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5762 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5763 i = (lit >> (size*8)) & 0xff;
5765 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5766 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5769 i = (lit >> (size*8)) & 0xff;
5772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5774 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5776 /* this byte of the lit is zero,
5777 * if it's not the last then OR in the variable */
5779 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5784 pic16_emitpLabel(lbl->key);
5786 rFalseIfx.condition ^= 1;
5788 genSkipc(&rFalseIfx);
5792 pic16_emitpLabel(truelbl->key);
5793 if(ifx) ifx->generated = 1;
5795 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5801 /* Compare two variables */
5803 DEBUGpic16_emitcode(";sign","%d",sign);
5807 /* Sigh. thus sucks... */
5811 pctemp = pic16_popGetTempReg(1);
5812 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5813 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5814 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5815 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5816 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5817 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5818 pic16_popReleaseTempReg(pctemp, 1);
5820 /* Signed char comparison */
5821 /* Special thanks to Nikolai Golovchenko for this snippet */
5822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5823 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5824 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5825 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5826 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5827 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5830 genSkipc(&rFalseIfx);
5832 if(ifx) ifx->generated = 1;
5834 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5842 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5843 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5847 /* The rest of the bytes of a multi-byte compare */
5851 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5854 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5855 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5860 pic16_emitpLabel(lbl->key);
5862 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5863 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5864 (AOP_TYPE(result) == AOP_REG)) {
5865 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5866 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5868 genSkipc(&rFalseIfx);
5870 //genSkipc(&rFalseIfx);
5871 if(ifx) ifx->generated = 1;
5874 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5882 if ((AOP_TYPE(result) != AOP_CRY)
5883 && AOP_SIZE(result)) {
5884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5886 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5888 pic16_outBitC(result);
5890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5891 /* if the result is used in the next
5892 ifx conditional branch then generate
5893 code a little differently */
5895 genIfxJump (ifx,"c");
5897 pic16_outBitC(result);
5898 /* leave the result in acc */
5903 #elif 0 /* VR version of genCmp() */ /* } else { */
5905 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5906 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5907 operand *result, int offset, int invert_op)
5911 /* check condition, > or < ?? */
5912 if(rIfx->condition != 0)invert_op ^= 1;
5914 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5916 if(!ifx)invert_op ^= 1;
5918 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5919 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5922 if(!invert_op)return POC_CPFSGT;
5923 else return POC_CPFSLT;
5926 static int compareAopfirstpass=1;
5928 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5929 operand *oper, int offset, operand *result,
5930 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5936 /* invert if there is a result to be loaded, in order to fit,
5937 * SETC/CLRC sequence */
5938 if(AOP_SIZE(result))invert_op ^= 1;
5940 // if(sign && !offset)invert_op ^= 1;
5942 // if(sign)invert_op ^= 1;
5944 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5946 if(AOP_SIZE(result) && compareAopfirstpass) {
5949 pic16_emitpcode(POC_SETF, pcop2);
5954 pic16_emitpcode(POC_CLRF, pcop2);
5960 compareAopfirstpass = 0;
5962 /* there is a bug when comparing operands with size > 1,
5963 * because higher bytes can be equal and test should be performed
5964 * to the next lower byte, current algorithm, considers operands
5965 * inequal in these cases! -- VR 20041107 */
5969 pic16_emitpcode(op, pcop);
5971 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5974 if((!sign || !offset) && AOP_SIZE(result)) {
5977 pic16_emitpcode(POC_CLRF, pcop2);
5982 pic16_emitpcode(POC_SETF, pcop2);
5987 /* don't emit final branch (offset == 0) */
5991 pic16_emitpcode(POC_RRCF, pcop2);
5993 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5996 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5997 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5998 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6000 truelbl = newiTempLabel( NULL );
6001 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6002 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6003 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6005 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6006 pic16_emitpLabel(truelbl->key);
6008 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6013 static void genCmp (operand *left, operand *right,
6014 operand *result, iCode *ifx, int sign)
6018 resolvedIfx rFalseIfx;
6019 symbol *falselbl, *tlbl;
6023 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6025 resolveIfx(&rFalseIfx, ifx);
6026 size = max(AOP_SIZE(left), AOP_SIZE(right));
6028 /* if left & right are bit variables */
6029 if(AOP_TYPE(left) == AOP_CRY
6030 && AOP_TYPE(right) == AOP_CRY ) {
6032 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6033 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6035 werror(W_POSSBUG2, __FILE__, __LINE__);
6039 /* if literal is on the right then swap with left */
6040 if((AOP_TYPE(right) == AOP_LIT)) {
6041 operand *tmp = right ;
6042 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6044 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6046 // lit = (lit - 1) & mask;
6049 rFalseIfx.condition ^= 1; /* reverse compare */
6051 if ((AOP_TYPE(left) == AOP_LIT)) {
6052 /* float compares are handled by support functions */
6053 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6056 /* actual comparing algorithm */
6057 // size = AOP_SIZE( right );
6059 falselbl = newiTempLabel( NULL );
6060 if(AOP_TYPE(left) == AOP_LIT) {
6061 /* compare to literal */
6062 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6065 pCodeOp *pct, *pct2;
6068 /* signed compare */
6069 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6071 pct = pic16_popCopyReg(&pic16_pc_prodl);
6072 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6073 tlbl = newiTempLabel( NULL );
6075 /* first compare signs:
6076 * a. if both are positive, compare just like unsigned
6077 * b. if both are negative, invert cmpop, compare just like unsigned
6078 * c. if different signs, determine the result directly */
6084 tlbl1 = newiTempLabel( NULL );
6085 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6089 /* literal is zero or positive:
6090 * a. if carry is zero, too, continue compare,
6091 * b. if carry is set, then continue depending on cmpop ^ condition:
6092 * 1. '<' return false (literal < variable),
6093 * 2. '>' return true (literal > variable) */
6094 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6095 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6098 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6099 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6103 /* literal is negative:
6104 * a. if carry is set, too, continue compare,
6105 * b. if carry is zero, then continue depending on cmpop ^ condition:
6106 * 1. '<' return true (literal < variable),
6107 * 2. '>' return false (literal > variable) */
6108 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6109 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6111 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6112 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6117 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6119 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6120 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6125 pic16_emitpLabel( tlbl1->key );
6128 compareAopfirstpass=1;
6129 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6130 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6131 // pic16_emitpcode(POC_MOVWF, pct);
6133 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6134 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6135 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6136 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6140 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6141 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6142 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6143 // pic16_emitpcode(POC_MOVWF, pct);
6145 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6146 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6147 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6148 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6149 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6153 if(ifx)ifx->generated = 1;
6155 if(AOP_SIZE(result)) {
6156 pic16_emitpLabel(tlbl->key);
6157 pic16_emitpLabel(falselbl->key);
6158 pic16_outBitOp( result, pct2 );
6160 pic16_emitpLabel(tlbl->key);
6165 /* unsigned compare */
6166 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6168 compareAopfirstpass=1;
6171 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6172 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6176 if(ifx)ifx->generated = 1;
6179 if(AOP_SIZE(result)) {
6180 pic16_emitpLabel(falselbl->key);
6181 pic16_outBitC( result );
6186 /* compare registers */
6187 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6191 pCodeOp *pct, *pct2;
6193 /* signed compare */
6194 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6196 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6197 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6198 tlbl = newiTempLabel( NULL );
6200 compareAopfirstpass=1;
6203 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6204 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6206 pic16_emitpcode(POC_MOVWF, pct);
6208 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6209 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6210 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6212 /* WREG already holds left + 0x80 */
6213 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6216 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6217 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219 pic16_emitpcode(POC_MOVWF, pct);
6221 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6222 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6223 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6225 /* WREG already holds left + 0x80 */
6226 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6227 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6230 if(ifx)ifx->generated = 1;
6232 if(AOP_SIZE(result)) {
6233 pic16_emitpLabel(tlbl->key);
6234 pic16_emitpLabel(falselbl->key);
6235 pic16_outBitOp( result, pct2 );
6237 pic16_emitpLabel(tlbl->key);
6241 /* unsigned compare */
6242 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6244 compareAopfirstpass=1;
6247 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6248 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6252 if(ifx)ifx->generated = 1;
6253 if(AOP_SIZE(result)) {
6255 pic16_emitpLabel(falselbl->key);
6256 pic16_outBitC( result );
6267 /*-----------------------------------------------------------------*/
6268 /* genCmpGt :- greater than comparison */
6269 /*-----------------------------------------------------------------*/
6270 static void genCmpGt (iCode *ic, iCode *ifx)
6272 operand *left, *right, *result;
6273 sym_link *letype , *retype;
6279 right= IC_RIGHT(ic);
6280 result = IC_RESULT(ic);
6282 letype = getSpec(operandType(left));
6283 retype =getSpec(operandType(right));
6284 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6285 /* assign the amsops */
6286 pic16_aopOp (left,ic,FALSE);
6287 pic16_aopOp (right,ic,FALSE);
6288 pic16_aopOp (result,ic,TRUE);
6290 genCmp(right, left, result, ifx, sign);
6292 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6293 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6294 pic16_freeAsmop(result,NULL,ic,TRUE);
6297 /*-----------------------------------------------------------------*/
6298 /* genCmpLt - less than comparisons */
6299 /*-----------------------------------------------------------------*/
6300 static void genCmpLt (iCode *ic, iCode *ifx)
6302 operand *left, *right, *result;
6303 sym_link *letype , *retype;
6309 right= IC_RIGHT(ic);
6310 result = IC_RESULT(ic);
6312 letype = getSpec(operandType(left));
6313 retype =getSpec(operandType(right));
6314 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6316 /* assign the amsops */
6317 pic16_aopOp (left,ic,FALSE);
6318 pic16_aopOp (right,ic,FALSE);
6319 pic16_aopOp (result,ic,TRUE);
6321 genCmp(left, right, result, ifx, sign);
6323 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6324 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6325 pic16_freeAsmop(result,NULL,ic,TRUE);
6330 // FIXME reenable literal optimisation when the pic16 port is stable
6332 /*-----------------------------------------------------------------*/
6333 /* genc16bit2lit - compare a 16 bit value to a literal */
6334 /*-----------------------------------------------------------------*/
6335 static void genc16bit2lit(operand *op, int lit, int offset)
6339 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6340 if( (lit&0xff) == 0)
6345 switch( BYTEofLONG(lit,i)) {
6347 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6353 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6356 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6357 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6362 switch( BYTEofLONG(lit,i)) {
6364 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6368 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6372 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6375 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6377 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6386 /*-----------------------------------------------------------------*/
6387 /* gencjneshort - compare and jump if not equal */
6388 /*-----------------------------------------------------------------*/
6389 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6391 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6393 int res_offset = 0; /* the result may be a different size then left or right */
6394 int res_size = AOP_SIZE(result);
6396 symbol *lbl, *lbl_done;
6398 unsigned long lit = 0L;
6399 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6401 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6402 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6404 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6405 resolveIfx(&rIfx,ifx);
6406 lbl = newiTempLabel(NULL);
6407 lbl_done = newiTempLabel(NULL);
6410 /* if the left side is a literal or
6411 if the right is in a pointer register and left
6413 if ((AOP_TYPE(left) == AOP_LIT) ||
6414 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6419 if(AOP_TYPE(right) == AOP_LIT)
6420 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6422 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6423 preserve_result = 1;
6425 if(result && !preserve_result)
6428 for(i = 0; i < AOP_SIZE(result); i++)
6429 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6433 /* if the right side is a literal then anything goes */
6434 if (AOP_TYPE(right) == AOP_LIT &&
6435 AOP_TYPE(left) != AOP_DIR ) {
6438 genc16bit2lit(left, lit, 0);
6440 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6446 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6447 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6449 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6453 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6455 if(res_offset < res_size-1)
6463 /* if the right side is in a register or in direct space or
6464 if the left is a pointer register & right is not */
6465 else if (AOP_TYPE(right) == AOP_REG ||
6466 AOP_TYPE(right) == AOP_DIR ||
6467 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6468 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6469 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6470 int lbl_key = lbl->key;
6473 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6474 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6476 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6477 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6478 __FUNCTION__,__LINE__);
6482 /* switch(size) { */
6484 /* genc16bit2lit(left, lit, 0); */
6486 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6491 if((AOP_TYPE(left) == AOP_DIR) &&
6492 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6494 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6495 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6497 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6499 switch (lit & 0xff) {
6501 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6505 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6506 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6510 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6511 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6517 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6518 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6523 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6526 if(AOP_TYPE(result) == AOP_CRY) {
6527 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6532 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6534 /* fix me. probably need to check result size too */
6535 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6540 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6541 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6548 if(res_offset < res_size-1)
6553 } else if(AOP_TYPE(right) == AOP_REG &&
6554 AOP_TYPE(left) != AOP_DIR){
6557 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6558 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6559 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6564 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6566 if(res_offset < res_size-1)
6571 /* right is a pointer reg need both a & b */
6573 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6575 pic16_emitcode("mov","b,%s",l);
6576 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6577 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6582 if(result && preserve_result)
6585 for(i = 0; i < AOP_SIZE(result); i++)
6586 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6589 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6591 if(result && preserve_result)
6592 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6595 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6597 pic16_emitpLabel(lbl->key);
6599 if(result && preserve_result)
6602 for(i = 0; i < AOP_SIZE(result); i++)
6603 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6605 pic16_emitpLabel(lbl_done->key);
6608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6616 /*-----------------------------------------------------------------*/
6617 /* gencjne - compare and jump if not equal */
6618 /*-----------------------------------------------------------------*/
6619 static void gencjne(operand *left, operand *right, iCode *ifx)
6621 symbol *tlbl = newiTempLabel(NULL);
6623 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6624 gencjneshort(left, right, lbl);
6626 pic16_emitcode("mov","a,%s",one);
6627 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6628 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6629 pic16_emitcode("clr","a");
6630 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6632 pic16_emitpLabel(lbl->key);
6633 pic16_emitpLabel(tlbl->key);
6639 /*-----------------------------------------------------------------*/
6640 /* is_LitOp - check if operand has to be treated as literal */
6641 /*-----------------------------------------------------------------*/
6642 static bool is_LitOp(operand *op)
6644 return ((AOP_TYPE(op) == AOP_LIT)
6645 || ( (AOP_TYPE(op) == AOP_PCODE)
6646 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6647 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitAOp - check if operand has to be treated as literal */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitAOp(asmop *aop)
6655 return ((aop->type == AOP_LIT)
6656 || ( (aop->type == AOP_PCODE)
6657 && ( (aop->aopu.pcop->type == PO_LITERAL)
6658 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6663 /*-----------------------------------------------------------------*/
6664 /* genCmpEq - generates code for equal to */
6665 /*-----------------------------------------------------------------*/
6666 static void genCmpEq (iCode *ic, iCode *ifx)
6668 operand *left, *right, *result;
6669 symbol *falselbl = newiTempLabel(NULL);
6670 symbol *donelbl = newiTempLabel(NULL);
6672 int preserve_result = 0;
6673 int generate_result = 0;
6675 unsigned long lit = -1;
6679 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6680 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6681 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6683 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6685 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6687 werror(W_POSSBUG2, __FILE__, __LINE__);
6688 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6689 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6693 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6695 operand *tmp = right ;
6700 if (AOP_TYPE(right) == AOP_LIT) {
6701 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6704 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6705 preserve_result = 1;
6707 if(result && AOP_SIZE(result))
6708 generate_result = 1;
6710 if(generate_result && !preserve_result)
6712 for(i = 0; i < AOP_SIZE(result); i++)
6713 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6716 for(i=0; i < AOP_SIZE(left); i++)
6718 if(AOP_TYPE(left) != AOP_ACC)
6721 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6723 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6725 if(is_LitOp(right)) {
6726 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6727 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6730 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6732 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6737 if(generate_result && preserve_result)
6739 for(i = 0; i < AOP_SIZE(result); i++)
6740 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6744 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6746 if(generate_result && preserve_result)
6747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6749 if(ifx && IC_TRUE(ifx))
6750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6752 if(ifx && IC_FALSE(ifx))
6753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6755 pic16_emitpLabel(falselbl->key);
6759 if(ifx && IC_FALSE(ifx))
6760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6762 if(generate_result && preserve_result)
6764 for(i = 0; i < AOP_SIZE(result); i++)
6765 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6768 pic16_emitpLabel(donelbl->key);
6774 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6775 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6776 pic16_freeAsmop(result,NULL,ic,TRUE);
6782 // old version kept for reference
6784 /*-----------------------------------------------------------------*/
6785 /* genCmpEq - generates code for equal to */
6786 /*-----------------------------------------------------------------*/
6787 static void genCmpEq (iCode *ic, iCode *ifx)
6789 operand *left, *right, *result;
6790 unsigned long lit = 0L;
6792 symbol *falselbl = newiTempLabel(NULL);
6795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6798 DEBUGpic16_emitcode ("; ifx is non-null","");
6800 DEBUGpic16_emitcode ("; ifx is null","");
6802 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6803 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6804 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6806 size = max(AOP_SIZE(left),AOP_SIZE(right));
6808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6810 /* if literal, literal on the right or
6811 if the right is in a pointer register and left
6813 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6814 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6815 operand *tmp = right ;
6821 if(ifx && !AOP_SIZE(result)){
6823 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6824 /* if they are both bit variables */
6825 if (AOP_TYPE(left) == AOP_CRY &&
6826 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6827 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6828 if(AOP_TYPE(right) == AOP_LIT){
6829 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6831 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832 pic16_emitcode("cpl","c");
6833 } else if(lit == 1L) {
6834 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6836 pic16_emitcode("clr","c");
6838 /* AOP_TYPE(right) == AOP_CRY */
6840 symbol *lbl = newiTempLabel(NULL);
6841 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6843 pic16_emitcode("cpl","c");
6844 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6846 /* if true label then we jump if condition
6848 tlbl = newiTempLabel(NULL);
6849 if ( IC_TRUE(ifx) ) {
6850 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6851 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6853 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6854 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6856 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6859 /* left and right are both bit variables, result is carry */
6862 resolveIfx(&rIfx,ifx);
6864 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6865 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6866 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6867 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6872 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6874 /* They're not both bit variables. Is the right a literal? */
6875 if(AOP_TYPE(right) == AOP_LIT) {
6876 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6881 switch(lit & 0xff) {
6883 if ( IC_TRUE(ifx) ) {
6884 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6886 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6888 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6893 if ( IC_TRUE(ifx) ) {
6894 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6896 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6898 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6905 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6910 /* end of size == 1 */
6914 genc16bit2lit(left,lit,offset);
6917 /* end of size == 2 */
6922 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6923 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6924 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6925 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6928 /* search for patterns that can be optimized */
6930 genc16bit2lit(left,lit,0);
6934 emitSKPZ; // if hi word unequal
6936 emitSKPNZ; // if hi word equal
6938 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6939 genc16bit2lit(left,lit,2);
6942 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6943 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6947 pic16_emitpLabel(falselbl->key);
6956 } else if(AOP_TYPE(right) == AOP_CRY ) {
6957 /* we know the left is not a bit, but that the right is */
6958 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6959 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6960 pic16_popGet(AOP(right),offset));
6961 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6963 /* if the two are equal, then W will be 0 and the Z bit is set
6964 * we could test Z now, or go ahead and check the high order bytes if
6965 * the variable we're comparing is larger than a byte. */
6968 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6970 if ( IC_TRUE(ifx) ) {
6972 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6973 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6977 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6981 /* They're both variables that are larger than bits */
6984 tlbl = newiTempLabel(NULL);
6987 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6988 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6990 if ( IC_TRUE(ifx) ) {
6994 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6996 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6997 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7001 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7005 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7010 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7013 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7017 if(s>1 && IC_TRUE(ifx)) {
7018 pic16_emitpLabel(tlbl->key);
7019 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7023 /* mark the icode as generated */
7028 /* if they are both bit variables */
7029 if (AOP_TYPE(left) == AOP_CRY &&
7030 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7031 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7032 if(AOP_TYPE(right) == AOP_LIT){
7033 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7035 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036 pic16_emitcode("cpl","c");
7037 } else if(lit == 1L) {
7038 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7040 pic16_emitcode("clr","c");
7042 /* AOP_TYPE(right) == AOP_CRY */
7044 symbol *lbl = newiTempLabel(NULL);
7045 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7047 pic16_emitcode("cpl","c");
7048 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7051 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7052 pic16_outBitC(result);
7056 genIfxJump (ifx,"c");
7059 /* if the result is used in an arithmetic operation
7060 then put the result in place */
7061 pic16_outBitC(result);
7064 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7065 gencjne(left,right,result,ifx);
7068 gencjne(left,right,newiTempLabel(NULL));
7070 if(IC_TRUE(ifx)->key)
7071 gencjne(left,right,IC_TRUE(ifx)->key);
7073 gencjne(left,right,IC_FALSE(ifx)->key);
7077 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7078 pic16_aopPut(AOP(result),"a",0);
7083 genIfxJump (ifx,"a");
7087 /* if the result is used in an arithmetic operation
7088 then put the result in place */
7090 if (AOP_TYPE(result) != AOP_CRY)
7091 pic16_outAcc(result);
7093 /* leave the result in acc */
7097 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7098 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7099 pic16_freeAsmop(result,NULL,ic,TRUE);
7103 /*-----------------------------------------------------------------*/
7104 /* ifxForOp - returns the icode containing the ifx for operand */
7105 /*-----------------------------------------------------------------*/
7106 static iCode *ifxForOp ( operand *op, iCode *ic )
7110 /* if true symbol then needs to be assigned */
7111 if (IS_TRUE_SYMOP(op))
7114 /* if this has register type condition and
7115 the next instruction is ifx with the same operand
7116 and live to of the operand is upto the ifx only then */
7118 && ic->next->op == IFX
7119 && IC_COND(ic->next)->key == op->key
7120 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7122 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7128 ic->next->op == IFX &&
7129 IC_COND(ic->next)->key == op->key) {
7130 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7135 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7137 ic->next->op == IFX)
7138 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7141 ic->next->op == IFX &&
7142 IC_COND(ic->next)->key == op->key) {
7143 DEBUGpic16_emitcode ("; "," key is okay");
7144 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7145 OP_SYMBOL(op)->liveTo,
7150 /* the code below is completely untested
7151 * it just allows ulong2fs.c compile -- VR */
7154 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7155 __FILE__, __FUNCTION__, __LINE__);
7157 /* if this has register type condition and
7158 the next instruction is ifx with the same operand
7159 and live to of the operand is upto the ifx only then */
7161 ic->next->op == IFX &&
7162 IC_COND(ic->next)->key == op->key &&
7163 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7167 ic->next->op == IFX &&
7168 IC_COND(ic->next)->key == op->key) {
7169 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7173 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7174 __FILE__, __FUNCTION__, __LINE__);
7176 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7181 /*-----------------------------------------------------------------*/
7182 /* genAndOp - for && operation */
7183 /*-----------------------------------------------------------------*/
7184 static void genAndOp (iCode *ic)
7186 operand *left,*right, *result;
7191 /* note here that && operations that are in an
7192 if statement are taken away by backPatchLabels
7193 only those used in arthmetic operations remain */
7194 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7195 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7196 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7198 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7200 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7201 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7202 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7204 /* if both are bit variables */
7205 /* if (AOP_TYPE(left) == AOP_CRY && */
7206 /* AOP_TYPE(right) == AOP_CRY ) { */
7207 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7208 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7209 /* pic16_outBitC(result); */
7211 /* tlbl = newiTempLabel(NULL); */
7212 /* pic16_toBoolean(left); */
7213 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7214 /* pic16_toBoolean(right); */
7215 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7216 /* pic16_outBitAcc(result); */
7219 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7220 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7221 pic16_freeAsmop(result,NULL,ic,TRUE);
7225 /*-----------------------------------------------------------------*/
7226 /* genOrOp - for || operation */
7227 /*-----------------------------------------------------------------*/
7230 modified this code, but it doesn't appear to ever get called
7233 static void genOrOp (iCode *ic)
7235 operand *left,*right, *result;
7240 /* note here that || operations that are in an
7241 if statement are taken away by backPatchLabels
7242 only those used in arthmetic operations remain */
7243 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7244 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7245 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7247 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7249 /* if both are bit variables */
7250 if (AOP_TYPE(left) == AOP_CRY &&
7251 AOP_TYPE(right) == AOP_CRY ) {
7252 pic16_emitcode("clrc","");
7253 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7254 AOP(left)->aopu.aop_dir,
7255 AOP(left)->aopu.aop_dir);
7256 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7257 AOP(right)->aopu.aop_dir,
7258 AOP(right)->aopu.aop_dir);
7259 pic16_emitcode("setc","");
7262 tlbl = newiTempLabel(NULL);
7263 pic16_toBoolean(left);
7265 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7266 pic16_toBoolean(right);
7267 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7269 pic16_outBitAcc(result);
7272 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7273 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7274 pic16_freeAsmop(result,NULL,ic,TRUE);
7277 /*-----------------------------------------------------------------*/
7278 /* isLiteralBit - test if lit == 2^n */
7279 /*-----------------------------------------------------------------*/
7280 static int isLiteralBit(unsigned long lit)
7282 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7283 0x100L,0x200L,0x400L,0x800L,
7284 0x1000L,0x2000L,0x4000L,0x8000L,
7285 0x10000L,0x20000L,0x40000L,0x80000L,
7286 0x100000L,0x200000L,0x400000L,0x800000L,
7287 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7288 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7291 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7292 for(idx = 0; idx < 32; idx++)
7298 /*-----------------------------------------------------------------*/
7299 /* continueIfTrue - */
7300 /*-----------------------------------------------------------------*/
7301 static void continueIfTrue (iCode *ic)
7305 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7309 /*-----------------------------------------------------------------*/
7311 /*-----------------------------------------------------------------*/
7312 static void jumpIfTrue (iCode *ic)
7316 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7320 /*-----------------------------------------------------------------*/
7321 /* jmpTrueOrFalse - */
7322 /*-----------------------------------------------------------------*/
7323 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7325 // ugly but optimized by peephole
7328 symbol *nlbl = newiTempLabel(NULL);
7329 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7330 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7331 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7332 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7334 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7335 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7340 /*-----------------------------------------------------------------*/
7341 /* genAnd - code for and */
7342 /*-----------------------------------------------------------------*/
7343 static void genAnd (iCode *ic, iCode *ifx)
7345 operand *left, *right, *result;
7347 unsigned long lit = 0L;
7353 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7354 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7355 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7357 resolveIfx(&rIfx,ifx);
7359 /* if left is a literal & right is not then exchange them */
7360 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7361 AOP_NEEDSACC(left)) {
7362 operand *tmp = right ;
7367 /* if result = right then exchange them */
7368 if(pic16_sameRegs(AOP(result),AOP(right))){
7369 operand *tmp = right ;
7374 /* if right is bit then exchange them */
7375 if (AOP_TYPE(right) == AOP_CRY &&
7376 AOP_TYPE(left) != AOP_CRY){
7377 operand *tmp = right ;
7381 if(AOP_TYPE(right) == AOP_LIT)
7382 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7384 size = AOP_SIZE(result);
7386 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7389 // result = bit & yy;
7390 if (AOP_TYPE(left) == AOP_CRY){
7391 // c = bit & literal;
7392 if(AOP_TYPE(right) == AOP_LIT){
7394 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7397 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7400 if(size && (AOP_TYPE(result) == AOP_CRY)){
7401 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7404 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7408 pic16_emitcode("clr","c");
7411 if (AOP_TYPE(right) == AOP_CRY){
7413 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7414 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7417 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7419 pic16_emitcode("rrc","a");
7420 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7426 pic16_outBitC(result);
7428 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7429 genIfxJump(ifx, "c");
7433 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7434 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7435 if((AOP_TYPE(right) == AOP_LIT) &&
7436 (AOP_TYPE(result) == AOP_CRY) &&
7437 (AOP_TYPE(left) != AOP_CRY)){
7438 int posbit = isLiteralBit(lit);
7442 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7445 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7451 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7452 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7454 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7458 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7459 size = AOP_SIZE(left);
7462 int bp = posbit, ofs=0;
7469 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7470 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7474 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7475 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7477 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7484 symbol *tlbl = newiTempLabel(NULL);
7485 int sizel = AOP_SIZE(left);
7491 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7493 /* patch provided by Aaron Colwell */
7494 if((posbit = isLiteralBit(bytelit)) != 0) {
7495 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7496 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7497 (posbit-1),0, PO_GPR_REGISTER));
7499 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7500 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7502 if (bytelit == 0xff) {
7503 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7504 * a peephole could optimize it out -- VR */
7505 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7508 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7511 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7512 pic16_popGetLabel(tlbl->key));
7516 /* old code, left here for reference -- VR 09/2004 */
7517 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7519 if((posbit = isLiteralBit(bytelit)) != 0)
7520 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7522 if(bytelit != 0x0FFL)
7523 pic16_emitcode("anl","a,%s",
7524 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7525 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7531 // bit = left & literal
7534 pic16_emitpLabel(tlbl->key);
7536 // if(left & literal)
7539 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7542 pic16_emitpLabel(tlbl->key);
7547 pic16_outBitC(result);
7551 /* if left is same as result */
7552 if(pic16_sameRegs(AOP(result),AOP(left))){
7554 for(;size--; offset++,lit>>=8) {
7555 if(AOP_TYPE(right) == AOP_LIT){
7556 switch(lit & 0xff) {
7558 /* and'ing with 0 has clears the result */
7559 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7560 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7563 /* and'ing with 0xff is a nop when the result and left are the same */
7568 int p = pic16_my_powof2( (~lit) & 0xff );
7570 /* only one bit is set in the literal, so use a bcf instruction */
7571 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7572 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7575 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7576 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7577 if(know_W != (lit&0xff))
7578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7580 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7585 if (AOP_TYPE(left) == AOP_ACC) {
7586 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7588 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7589 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7596 // left & result in different registers
7597 if(AOP_TYPE(result) == AOP_CRY){
7599 // if(size), result in bit
7600 // if(!size && ifx), conditional oper: if(left & right)
7601 symbol *tlbl = newiTempLabel(NULL);
7602 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7604 pic16_emitcode("setb","c");
7606 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7607 pic16_emitcode("anl","a,%s",
7608 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7609 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7614 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7615 pic16_outBitC(result);
7617 jmpTrueOrFalse(ifx, tlbl);
7619 for(;(size--);offset++) {
7621 // result = left & right
7622 if(AOP_TYPE(right) == AOP_LIT){
7623 int t = (lit >> (offset*8)) & 0x0FFL;
7626 pic16_emitcode("clrf","%s",
7627 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7628 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7631 pic16_emitcode("movf","%s,w",
7632 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7633 pic16_emitcode("movwf","%s",
7634 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7635 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7636 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7639 pic16_emitcode("movlw","0x%x",t);
7640 pic16_emitcode("andwf","%s,w",
7641 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7642 pic16_emitcode("movwf","%s",
7643 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7645 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7646 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7647 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7652 if (AOP_TYPE(left) == AOP_ACC) {
7653 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7654 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7656 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657 pic16_emitcode("andwf","%s,w",
7658 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7659 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7660 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7662 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7663 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7669 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7670 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7671 pic16_freeAsmop(result,NULL,ic,TRUE);
7674 /*-----------------------------------------------------------------*/
7675 /* genOr - code for or */
7676 /*-----------------------------------------------------------------*/
7677 static void genOr (iCode *ic, iCode *ifx)
7679 operand *left, *right, *result;
7681 unsigned long lit = 0L;
7683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7685 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7686 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7687 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7689 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7691 /* if left is a literal & right is not then exchange them */
7692 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7693 AOP_NEEDSACC(left)) {
7694 operand *tmp = right ;
7699 /* if result = right then exchange them */
7700 if(pic16_sameRegs(AOP(result),AOP(right))){
7701 operand *tmp = right ;
7706 /* if right is bit then exchange them */
7707 if (AOP_TYPE(right) == AOP_CRY &&
7708 AOP_TYPE(left) != AOP_CRY){
7709 operand *tmp = right ;
7714 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7716 if(AOP_TYPE(right) == AOP_LIT)
7717 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7719 size = AOP_SIZE(result);
7723 if (AOP_TYPE(left) == AOP_CRY){
7724 if(AOP_TYPE(right) == AOP_LIT){
7725 // c = bit & literal;
7727 // lit != 0 => result = 1
7728 if(AOP_TYPE(result) == AOP_CRY){
7730 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7731 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7732 // AOP(result)->aopu.aop_dir,
7733 // AOP(result)->aopu.aop_dir);
7735 continueIfTrue(ifx);
7739 // lit == 0 => result = left
7740 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7742 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7745 if (AOP_TYPE(right) == AOP_CRY){
7746 if(pic16_sameRegs(AOP(result),AOP(left))){
7748 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7749 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7750 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7752 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7753 AOP(result)->aopu.aop_dir,
7754 AOP(result)->aopu.aop_dir);
7755 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7756 AOP(right)->aopu.aop_dir,
7757 AOP(right)->aopu.aop_dir);
7758 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7759 AOP(result)->aopu.aop_dir,
7760 AOP(result)->aopu.aop_dir);
7762 if( AOP_TYPE(result) == AOP_ACC) {
7763 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7764 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7765 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7766 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7770 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7771 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7772 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7773 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7775 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7776 AOP(result)->aopu.aop_dir,
7777 AOP(result)->aopu.aop_dir);
7778 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7779 AOP(right)->aopu.aop_dir,
7780 AOP(right)->aopu.aop_dir);
7781 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7782 AOP(left)->aopu.aop_dir,
7783 AOP(left)->aopu.aop_dir);
7784 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7785 AOP(result)->aopu.aop_dir,
7786 AOP(result)->aopu.aop_dir);
7791 symbol *tlbl = newiTempLabel(NULL);
7792 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7795 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7796 if( AOP_TYPE(right) == AOP_ACC) {
7797 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7799 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7800 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7805 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7806 pic16_emitcode(";XXX setb","c");
7807 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7808 AOP(left)->aopu.aop_dir,tlbl->key+100);
7809 pic16_toBoolean(right);
7810 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7811 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7812 jmpTrueOrFalse(ifx, tlbl);
7816 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7823 pic16_outBitC(result);
7825 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7826 genIfxJump(ifx, "c");
7830 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7831 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7832 if((AOP_TYPE(right) == AOP_LIT) &&
7833 (AOP_TYPE(result) == AOP_CRY) &&
7834 (AOP_TYPE(left) != AOP_CRY)){
7836 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7839 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7841 continueIfTrue(ifx);
7844 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845 // lit = 0, result = boolean(left)
7847 pic16_emitcode(";XXX setb","c");
7848 pic16_toBoolean(right);
7850 symbol *tlbl = newiTempLabel(NULL);
7851 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7853 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7855 genIfxJump (ifx,"a");
7859 pic16_outBitC(result);
7863 /* if left is same as result */
7864 if(pic16_sameRegs(AOP(result),AOP(left))){
7866 for(;size--; offset++,lit>>=8) {
7867 if(AOP_TYPE(right) == AOP_LIT){
7868 if((lit & 0xff) == 0)
7869 /* or'ing with 0 has no effect */
7872 int p = pic16_my_powof2(lit & 0xff);
7874 /* only one bit is set in the literal, so use a bsf instruction */
7875 pic16_emitpcode(POC_BSF,
7876 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7878 if(know_W != (lit & 0xff))
7879 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7880 know_W = lit & 0xff;
7881 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7886 if (AOP_TYPE(left) == AOP_ACC) {
7887 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7888 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7890 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7891 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7893 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900 // left & result in different registers
7901 if(AOP_TYPE(result) == AOP_CRY){
7903 // if(size), result in bit
7904 // if(!size && ifx), conditional oper: if(left | right)
7905 symbol *tlbl = newiTempLabel(NULL);
7906 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7907 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7911 pic16_emitcode(";XXX setb","c");
7913 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914 pic16_emitcode(";XXX orl","a,%s",
7915 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7916 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7921 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7922 pic16_outBitC(result);
7924 jmpTrueOrFalse(ifx, tlbl);
7925 } else for(;(size--);offset++){
7927 // result = left & right
7928 if(AOP_TYPE(right) == AOP_LIT){
7929 int t = (lit >> (offset*8)) & 0x0FFL;
7932 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7935 pic16_emitcode("movf","%s,w",
7936 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7937 pic16_emitcode("movwf","%s",
7938 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7941 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7942 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7945 pic16_emitcode("movlw","0x%x",t);
7946 pic16_emitcode("iorwf","%s,w",
7947 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7948 pic16_emitcode("movwf","%s",
7949 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7955 // faster than result <- left, anl result,right
7956 // and better if result is SFR
7957 if (AOP_TYPE(left) == AOP_ACC) {
7958 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7959 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7961 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7962 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7964 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965 pic16_emitcode("iorwf","%s,w",
7966 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7969 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7974 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7975 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7976 pic16_freeAsmop(result,NULL,ic,TRUE);
7979 /*-----------------------------------------------------------------*/
7980 /* genXor - code for xclusive or */
7981 /*-----------------------------------------------------------------*/
7982 static void genXor (iCode *ic, iCode *ifx)
7984 operand *left, *right, *result;
7986 unsigned long lit = 0L;
7988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7990 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7991 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7992 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7994 /* if left is a literal & right is not ||
7995 if left needs acc & right does not */
7996 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7997 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7998 operand *tmp = right ;
8003 /* if result = right then exchange them */
8004 if(pic16_sameRegs(AOP(result),AOP(right))){
8005 operand *tmp = right ;
8010 /* if right is bit then exchange them */
8011 if (AOP_TYPE(right) == AOP_CRY &&
8012 AOP_TYPE(left) != AOP_CRY){
8013 operand *tmp = right ;
8017 if(AOP_TYPE(right) == AOP_LIT)
8018 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8020 size = AOP_SIZE(result);
8024 if (AOP_TYPE(left) == AOP_CRY){
8025 if(AOP_TYPE(right) == AOP_LIT){
8026 // c = bit & literal;
8028 // lit>>1 != 0 => result = 1
8029 if(AOP_TYPE(result) == AOP_CRY){
8031 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8032 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8034 continueIfTrue(ifx);
8037 pic16_emitcode("setb","c");
8041 // lit == 0, result = left
8042 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8044 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8046 // lit == 1, result = not(left)
8047 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8048 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8049 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8050 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8053 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8054 pic16_emitcode("cpl","c");
8061 symbol *tlbl = newiTempLabel(NULL);
8062 if (AOP_TYPE(right) == AOP_CRY){
8064 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8067 int sizer = AOP_SIZE(right);
8069 // if val>>1 != 0, result = 1
8070 pic16_emitcode("setb","c");
8072 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8074 // test the msb of the lsb
8075 pic16_emitcode("anl","a,#0xfe");
8076 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8080 pic16_emitcode("rrc","a");
8082 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8083 pic16_emitcode("cpl","c");
8084 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8089 pic16_outBitC(result);
8091 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8092 genIfxJump(ifx, "c");
8096 if(pic16_sameRegs(AOP(result),AOP(left))){
8097 /* if left is same as result */
8098 for(;size--; offset++) {
8099 if(AOP_TYPE(right) == AOP_LIT){
8100 int t = (lit >> (offset*8)) & 0x0FFL;
8104 if (IS_AOP_PREG(left)) {
8105 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8106 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8107 pic16_aopPut(AOP(result),"a",offset);
8109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8110 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8111 pic16_emitcode("xrl","%s,%s",
8112 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8113 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116 if (AOP_TYPE(left) == AOP_ACC)
8117 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8119 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8120 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8122 if (IS_AOP_PREG(left)) {
8123 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8124 pic16_aopPut(AOP(result),"a",offset);
8126 pic16_emitcode("xrl","%s,a",
8127 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8133 // left & result in different registers
8134 if(AOP_TYPE(result) == AOP_CRY){
8136 // if(size), result in bit
8137 // if(!size && ifx), conditional oper: if(left ^ right)
8138 symbol *tlbl = newiTempLabel(NULL);
8139 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8141 pic16_emitcode("setb","c");
8143 if((AOP_TYPE(right) == AOP_LIT) &&
8144 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8145 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8147 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148 pic16_emitcode("xrl","a,%s",
8149 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8151 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8156 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8157 pic16_outBitC(result);
8159 jmpTrueOrFalse(ifx, tlbl);
8160 } else for(;(size--);offset++){
8162 // result = left & right
8163 if(AOP_TYPE(right) == AOP_LIT){
8164 int t = (lit >> (offset*8)) & 0x0FFL;
8167 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8168 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8169 pic16_emitcode("movf","%s,w",
8170 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8171 pic16_emitcode("movwf","%s",
8172 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8175 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177 pic16_emitcode("comf","%s,w",
8178 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179 pic16_emitcode("movwf","%s",
8180 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8184 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8185 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8186 pic16_emitcode("movlw","0x%x",t);
8187 pic16_emitcode("xorwf","%s,w",
8188 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189 pic16_emitcode("movwf","%s",
8190 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8196 // faster than result <- left, anl result,right
8197 // and better if result is SFR
8198 if (AOP_TYPE(left) == AOP_ACC) {
8199 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8200 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8202 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8203 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8204 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8205 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8207 if ( AOP_TYPE(result) != AOP_ACC){
8208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8209 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8215 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8216 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8217 pic16_freeAsmop(result,NULL,ic,TRUE);
8220 /*-----------------------------------------------------------------*/
8221 /* genInline - write the inline code out */
8222 /*-----------------------------------------------------------------*/
8223 static void genInline (iCode *ic)
8225 char *buffer, *bp, *bp1;
8228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8230 _G.inLine += (!options.asmpeep);
8232 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8233 strcpy(buffer,IC_INLINE(ic));
8235 while((bp1=strstr(bp, "\\n"))) {
8242 cbuf = Safe_strdup( buffer );
8250 cbuf = Safe_strdup(buffer);
8251 cblen = strlen(buffer)+1;
8252 memset(cbuf, 0, cblen);
8257 if(*bp != '%')*bp1++ = *bp++;
8263 if(i>elementsInSet(asmInlineMap))break;
8266 s = indexSet(asmInlineMap, i);
8267 DEBUGpc("searching symbol s = `%s'", s);
8268 sym = findSym(SymbolTab, NULL, s);
8271 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8273 strcat(bp1, sym->rname);
8279 if(strlen(bp1) > cblen - 16) {
8280 int i = strlen(cbuf);
8282 cbuf = realloc(cbuf, cblen);
8283 memset(cbuf+i, 0, 50);
8289 buffer = Safe_strdup( cbuf );
8295 /* emit each line as a code */
8301 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8309 /* print label, use this special format with NULL directive
8310 * to denote that the argument should not be indented with tab */
8311 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8318 if ((bp1 != bp) && *bp1)
8319 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8324 _G.inLine -= (!options.asmpeep);
8327 /*-----------------------------------------------------------------*/
8328 /* genRRC - rotate right with carry */
8329 /*-----------------------------------------------------------------*/
8330 static void genRRC (iCode *ic)
8332 operand *left , *result ;
8333 int size, offset = 0, same;
8335 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8337 /* rotate right with carry */
8339 result=IC_RESULT(ic);
8340 pic16_aopOp (left,ic,FALSE);
8341 pic16_aopOp (result,ic,TRUE);
8343 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8345 same = pic16_sameRegs(AOP(result),AOP(left));
8347 size = AOP_SIZE(result);
8349 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8351 /* get the lsb and put it into the carry */
8352 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8359 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8361 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8362 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8368 pic16_freeAsmop(left,NULL,ic,TRUE);
8369 pic16_freeAsmop(result,NULL,ic,TRUE);
8372 /*-----------------------------------------------------------------*/
8373 /* genRLC - generate code for rotate left with carry */
8374 /*-----------------------------------------------------------------*/
8375 static void genRLC (iCode *ic)
8377 operand *left , *result ;
8378 int size, offset = 0;
8381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8382 /* rotate right with carry */
8384 result=IC_RESULT(ic);
8385 pic16_aopOp (left,ic,FALSE);
8386 pic16_aopOp (result,ic,TRUE);
8388 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8390 same = pic16_sameRegs(AOP(result),AOP(left));
8392 /* move it to the result */
8393 size = AOP_SIZE(result);
8395 /* get the msb and put it into the carry */
8396 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8403 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8405 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8413 pic16_freeAsmop(left,NULL,ic,TRUE);
8414 pic16_freeAsmop(result,NULL,ic,TRUE);
8418 /* gpasm can get the highest order bit with HIGH/UPPER
8419 * so the following probably is not needed -- VR */
8421 /*-----------------------------------------------------------------*/
8422 /* genGetHbit - generates code get highest order bit */
8423 /*-----------------------------------------------------------------*/
8424 static void genGetHbit (iCode *ic)
8426 operand *left, *result;
8428 result=IC_RESULT(ic);
8429 pic16_aopOp (left,ic,FALSE);
8430 pic16_aopOp (result,ic,FALSE);
8432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8433 /* get the highest order byte into a */
8434 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8435 if(AOP_TYPE(result) == AOP_CRY){
8436 pic16_emitcode("rlc","a");
8437 pic16_outBitC(result);
8440 pic16_emitcode("rl","a");
8441 pic16_emitcode("anl","a,#0x01");
8442 pic16_outAcc(result);
8446 pic16_freeAsmop(left,NULL,ic,TRUE);
8447 pic16_freeAsmop(result,NULL,ic,TRUE);
8451 /*-----------------------------------------------------------------*/
8452 /* AccRol - rotate left accumulator by known count */
8453 /*-----------------------------------------------------------------*/
8454 static void AccRol (int shCount)
8456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8457 shCount &= 0x0007; // shCount : 0..7
8462 pic16_emitcode("rl","a");
8465 pic16_emitcode("rl","a");
8466 pic16_emitcode("rl","a");
8469 pic16_emitcode("swap","a");
8470 pic16_emitcode("rr","a");
8473 pic16_emitcode("swap","a");
8476 pic16_emitcode("swap","a");
8477 pic16_emitcode("rl","a");
8480 pic16_emitcode("rr","a");
8481 pic16_emitcode("rr","a");
8484 pic16_emitcode("rr","a");
8490 /*-----------------------------------------------------------------*/
8491 /* AccLsh - left shift accumulator by known count */
8492 /*-----------------------------------------------------------------*/
8493 static void AccLsh (int shCount)
8495 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8501 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8504 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8509 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8515 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8530 /*-----------------------------------------------------------------*/
8531 /* AccRsh - right shift accumulator by known count */
8532 /*-----------------------------------------------------------------*/
8533 static void AccRsh (int shCount, int andmask)
8535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8540 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8547 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8548 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8569 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8573 /*-----------------------------------------------------------------*/
8574 /* AccSRsh - signed right shift accumulator by known count */
8575 /*-----------------------------------------------------------------*/
8576 static void AccSRsh (int shCount)
8579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8582 pic16_emitcode("mov","c,acc.7");
8583 pic16_emitcode("rrc","a");
8584 } else if(shCount == 2){
8585 pic16_emitcode("mov","c,acc.7");
8586 pic16_emitcode("rrc","a");
8587 pic16_emitcode("mov","c,acc.7");
8588 pic16_emitcode("rrc","a");
8590 tlbl = newiTempLabel(NULL);
8591 /* rotate right accumulator */
8592 AccRol(8 - shCount);
8593 /* and kill the higher order bits */
8594 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8595 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8596 pic16_emitcode("orl","a,#0x%02x",
8597 (unsigned char)~SRMask[shCount]);
8598 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8604 /*-----------------------------------------------------------------*/
8605 /* shiftR1Left2Result - shift right one byte from left to result */
8606 /*-----------------------------------------------------------------*/
8607 static void shiftR1Left2ResultSigned (operand *left, int offl,
8608 operand *result, int offr,
8613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8615 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8619 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8621 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8623 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8630 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8632 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8634 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8635 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8637 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8638 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8644 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8647 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8650 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8651 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8654 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8655 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8657 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8661 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8662 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8663 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8664 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8674 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8676 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8677 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8686 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8687 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8692 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8694 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8700 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8701 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8703 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8706 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8707 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8715 /*-----------------------------------------------------------------*/
8716 /* shiftR1Left2Result - shift right one byte from left to result */
8717 /*-----------------------------------------------------------------*/
8718 static void shiftR1Left2Result (operand *left, int offl,
8719 operand *result, int offr,
8720 int shCount, int sign)
8724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8726 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8728 /* Copy the msb into the carry if signed. */
8730 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8740 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8742 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8749 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8751 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8755 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8760 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8762 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8763 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8767 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8774 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8779 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8789 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8797 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8798 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8799 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8808 /*-----------------------------------------------------------------*/
8809 /* shiftL1Left2Result - shift left one byte from left to result */
8810 /*-----------------------------------------------------------------*/
8811 static void shiftL1Left2Result (operand *left, int offl,
8812 operand *result, int offr, int shCount)
8817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8819 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8820 DEBUGpic16_emitcode ("; ***","same = %d",same);
8821 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8823 /* shift left accumulator */
8824 //AccLsh(shCount); // don't comment out just yet...
8825 // pic16_aopPut(AOP(result),"a",offr);
8829 /* Shift left 1 bit position */
8830 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8832 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8834 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8835 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8839 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8841 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8842 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8845 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8846 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8847 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8848 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8849 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8854 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8864 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8865 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8871 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8876 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8881 /*-----------------------------------------------------------------*/
8882 /* movLeft2Result - move byte from left to result */
8883 /*-----------------------------------------------------------------*/
8884 static void movLeft2Result (operand *left, int offl,
8885 operand *result, int offr)
8888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8889 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8890 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8892 if (*l == '@' && (IS_AOP_PREG(result))) {
8893 pic16_emitcode("mov","a,%s",l);
8894 pic16_aopPut(AOP(result),"a",offr);
8896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8897 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8902 /*-----------------------------------------------------------------*/
8903 /* shiftL2Left2Result - shift left two bytes from left to result */
8904 /*-----------------------------------------------------------------*/
8905 static void shiftL2Left2Result (operand *left, int offl,
8906 operand *result, int offr, int shCount)
8908 int same = pic16_sameRegs(AOP(result), AOP(left));
8911 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8913 if (same && (offl != offr)) { // shift bytes
8916 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8917 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8919 } else { // just treat as different later on
8932 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8934 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8945 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8946 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8948 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8958 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8963 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8964 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8984 /* note, use a mov/add for the shift since the mov has a
8985 chance of getting optimized out */
8986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8994 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9001 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9002 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9004 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9007 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9008 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9012 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9017 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9018 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9019 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9026 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9033 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9034 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9035 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9041 /*-----------------------------------------------------------------*/
9042 /* shiftR2Left2Result - shift right two bytes from left to result */
9043 /*-----------------------------------------------------------------*/
9044 static void shiftR2Left2Result (operand *left, int offl,
9045 operand *result, int offr,
9046 int shCount, int sign)
9048 int same = pic16_sameRegs(AOP(result), AOP(left));
9050 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9052 if (same && (offl != offr)) { // shift right bytes
9055 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9056 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9058 } else { // just treat as different later on
9070 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9075 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9076 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9078 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9079 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9081 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9090 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9098 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9099 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9101 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9103 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9104 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9107 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9108 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9110 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9111 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9112 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9113 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9119 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9123 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9124 pic16_emitpcode(POC_BTFSC,
9125 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9126 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9134 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9137 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9138 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9139 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9142 pic16_emitpcode(POC_BTFSC,
9143 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9144 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9146 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9148 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9149 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9151 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9152 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9160 pic16_emitpcode(POC_BTFSC,
9161 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9162 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9174 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9175 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9178 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9180 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9185 /*-----------------------------------------------------------------*/
9186 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9187 /*-----------------------------------------------------------------*/
9188 static void shiftLLeftOrResult (operand *left, int offl,
9189 operand *result, int offr, int shCount)
9191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9193 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9194 /* shift left accumulator */
9196 /* or with result */
9197 /* back to result */
9198 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9201 /*-----------------------------------------------------------------*/
9202 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9203 /*-----------------------------------------------------------------*/
9204 static void shiftRLeftOrResult (operand *left, int offl,
9205 operand *result, int offr, int shCount)
9207 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9209 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9210 /* shift right accumulator */
9212 /* or with result */
9213 /* back to result */
9214 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9217 /*-----------------------------------------------------------------*/
9218 /* genlshOne - left shift a one byte quantity by known count */
9219 /*-----------------------------------------------------------------*/
9220 static void genlshOne (operand *result, operand *left, int shCount)
9222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9223 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9226 /*-----------------------------------------------------------------*/
9227 /* genlshTwo - left shift two bytes by known amount != 0 */
9228 /*-----------------------------------------------------------------*/
9229 static void genlshTwo (operand *result,operand *left, int shCount)
9233 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9234 size = pic16_getDataSize(result);
9236 /* if shCount >= 8 */
9242 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9244 movLeft2Result(left, LSB, result, MSB16);
9246 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9249 /* 1 <= shCount <= 7 */
9252 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9254 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9258 /*-----------------------------------------------------------------*/
9259 /* shiftLLong - shift left one long from left to result */
9260 /* offr = LSB or MSB16 */
9261 /*-----------------------------------------------------------------*/
9262 static void shiftLLong (operand *left, operand *result, int offr )
9264 int size = AOP_SIZE(result);
9265 int same = pic16_sameRegs(AOP(left),AOP(result));
9268 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9270 if (same && (offr == MSB16)) { //shift one byte
9271 for(i=size-1;i>=MSB16;i--) {
9272 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9273 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9276 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9279 if (size > LSB+offr ){
9281 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9283 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9284 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9288 if(size > MSB16+offr){
9290 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9292 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9293 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9297 if(size > MSB24+offr){
9299 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9301 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9302 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9306 if(size > MSB32+offr){
9308 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9310 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9311 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9315 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9319 /*-----------------------------------------------------------------*/
9320 /* genlshFour - shift four byte by a known amount != 0 */
9321 /*-----------------------------------------------------------------*/
9322 static void genlshFour (operand *result, operand *left, int shCount)
9326 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9327 size = AOP_SIZE(result);
9329 /* if shifting more that 3 bytes */
9330 if (shCount >= 24 ) {
9333 /* lowest order of left goes to the highest
9334 order of the destination */
9335 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9337 movLeft2Result(left, LSB, result, MSB32);
9339 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9340 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9341 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9346 /* more than two bytes */
9347 else if ( shCount >= 16 ) {
9348 /* lower order two bytes goes to higher order two bytes */
9350 /* if some more remaining */
9352 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9354 movLeft2Result(left, MSB16, result, MSB32);
9355 movLeft2Result(left, LSB, result, MSB24);
9357 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9358 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9362 /* if more than 1 byte */
9363 else if ( shCount >= 8 ) {
9364 /* lower order three bytes goes to higher order three bytes */
9368 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9370 movLeft2Result(left, LSB, result, MSB16);
9372 else{ /* size = 4 */
9374 movLeft2Result(left, MSB24, result, MSB32);
9375 movLeft2Result(left, MSB16, result, MSB24);
9376 movLeft2Result(left, LSB, result, MSB16);
9377 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9379 else if(shCount == 1)
9380 shiftLLong(left, result, MSB16);
9382 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9383 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9384 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9385 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9390 /* 1 <= shCount <= 7 */
9391 else if(shCount <= 3)
9393 shiftLLong(left, result, LSB);
9394 while(--shCount >= 1)
9395 shiftLLong(result, result, LSB);
9397 /* 3 <= shCount <= 7, optimize */
9399 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9400 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9401 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9405 /*-----------------------------------------------------------------*/
9406 /* genLeftShiftLiteral - left shifting by known count */
9407 /*-----------------------------------------------------------------*/
9408 void pic16_genLeftShiftLiteral (operand *left,
9413 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9417 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9418 pic16_freeAsmop(right,NULL,ic,TRUE);
9420 pic16_aopOp(left,ic,FALSE);
9421 pic16_aopOp(result,ic,TRUE);
9423 size = getSize(operandType(result));
9426 pic16_emitcode("; shift left ","result %d, left %d",size,
9430 /* I suppose that the left size >= result size */
9433 movLeft2Result(left, size, result, size);
9437 else if(shCount >= (size * 8))
9439 pic16_aopPut(AOP(result),zero,size);
9443 genlshOne (result,left,shCount);
9448 genlshTwo (result,left,shCount);
9452 genlshFour (result,left,shCount);
9456 pic16_freeAsmop(left,NULL,ic,TRUE);
9457 pic16_freeAsmop(result,NULL,ic,TRUE);
9460 /*-----------------------------------------------------------------*
9461 * genMultiAsm - repeat assembly instruction for size of register.
9462 * if endian == 1, then the high byte (i.e base address + size of
9463 * register) is used first else the low byte is used first;
9464 *-----------------------------------------------------------------*/
9465 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9483 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9489 #if !(USE_GENERIC_SIGNED_SHIFT)
9490 /*-----------------------------------------------------------------*/
9491 /* genLeftShift - generates code for left shifting */
9492 /*-----------------------------------------------------------------*/
9493 static void genLeftShift (iCode *ic)
9495 operand *left,*right, *result;
9498 symbol *tlbl , *tlbl1;
9501 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9503 right = IC_RIGHT(ic);
9505 result = IC_RESULT(ic);
9507 pic16_aopOp(right,ic,FALSE);
9509 /* if the shift count is known then do it
9510 as efficiently as possible */
9511 if (AOP_TYPE(right) == AOP_LIT) {
9512 pic16_genLeftShiftLiteral (left,right,result,ic);
9516 /* shift count is unknown then we have to form
9517 * a loop. Get the loop count in WREG : Note: we take
9518 * only the lower order byte since shifting
9519 * more than 32 bits make no sense anyway, ( the
9520 * largest size of an object can be only 32 bits ) */
9522 pic16_aopOp(left,ic,FALSE);
9523 pic16_aopOp(result,ic,FALSE);
9525 /* now move the left to the result if they are not the
9526 * same, and if size > 1,
9527 * and if right is not same to result (!!!) -- VR */
9528 if (!pic16_sameRegs(AOP(left),AOP(result))
9529 && (AOP_SIZE(result) > 1)) {
9531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 size = AOP_SIZE(result);
9538 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9539 if (*l == '@' && (IS_AOP_PREG(result))) {
9541 pic16_emitcode("mov","a,%s",l);
9542 pic16_aopPut(AOP(result),"a",offset);
9546 /* we don't know if left is a literal or a register, take care -- VR */
9547 mov2f(AOP(result), AOP(left), offset);
9553 size = AOP_SIZE(result);
9555 /* if it is only one byte then */
9557 if(optimized_for_speed) {
9558 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9559 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9560 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9561 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9562 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9563 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9564 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9565 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9566 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9567 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9568 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9569 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9574 tlbl = newiTempLabel(NULL);
9577 /* this is already done, why change it? */
9578 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9579 mov2f(AOP(result), AOP(left), 0);
9583 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9584 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9585 pic16_emitpLabel(tlbl->key);
9586 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9587 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9589 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9594 if (pic16_sameRegs(AOP(left),AOP(result))) {
9596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9598 tlbl = newiTempLabel(NULL);
9599 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9600 genMultiAsm(POC_RRCF, result, size,1);
9601 pic16_emitpLabel(tlbl->key);
9602 genMultiAsm(POC_RLCF, result, size,0);
9603 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9605 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9609 //tlbl = newiTempLabel(NULL);
9611 //tlbl1 = newiTempLabel(NULL);
9613 //reAdjustPreg(AOP(result));
9615 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9616 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9617 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9619 //pic16_emitcode("add","a,acc");
9620 //pic16_aopPut(AOP(result),"a",offset++);
9622 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9624 // pic16_emitcode("rlc","a");
9625 // pic16_aopPut(AOP(result),"a",offset++);
9627 //reAdjustPreg(AOP(result));
9629 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9630 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9633 tlbl = newiTempLabel(NULL);
9634 tlbl1= newiTempLabel(NULL);
9636 size = AOP_SIZE(result);
9639 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9641 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9643 /* offset should be 0, 1 or 3 */
9645 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9647 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9649 pic16_emitpcode(POC_MOVWF, pctemp);
9652 pic16_emitpLabel(tlbl->key);
9655 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9657 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9659 pic16_emitpcode(POC_DECFSZ, pctemp);
9660 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9661 pic16_emitpLabel(tlbl1->key);
9663 pic16_popReleaseTempReg(pctemp,1);
9667 pic16_freeAsmop (right,NULL,ic,TRUE);
9668 pic16_freeAsmop(left,NULL,ic,TRUE);
9669 pic16_freeAsmop(result,NULL,ic,TRUE);
9675 #error old code (left here for reference)
9676 /*-----------------------------------------------------------------*/
9677 /* genLeftShift - generates code for left shifting */
9678 /*-----------------------------------------------------------------*/
9679 static void genLeftShift (iCode *ic)
9681 operand *left,*right, *result;
9684 symbol *tlbl , *tlbl1;
9687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9689 right = IC_RIGHT(ic);
9691 result = IC_RESULT(ic);
9693 pic16_aopOp(right,ic,FALSE);
9695 /* if the shift count is known then do it
9696 as efficiently as possible */
9697 if (AOP_TYPE(right) == AOP_LIT) {
9698 pic16_genLeftShiftLiteral (left,right,result,ic);
9702 /* shift count is unknown then we have to form
9703 a loop get the loop count in B : Note: we take
9704 only the lower order byte since shifting
9705 more that 32 bits make no sense anyway, ( the
9706 largest size of an object can be only 32 bits ) */
9709 pic16_aopOp(left,ic,FALSE);
9710 pic16_aopOp(result,ic,FALSE);
9712 /* now move the left to the result if they are not the
9714 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9715 AOP_SIZE(result) > 1) {
9717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9719 size = AOP_SIZE(result);
9722 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9723 if (*l == '@' && (IS_AOP_PREG(result))) {
9725 pic16_emitcode("mov","a,%s",l);
9726 pic16_aopPut(AOP(result),"a",offset);
9729 /* we don't know if left is a literal or a register, take care -- VR */
9730 mov2f(AOP(result), AOP(left), offset);
9736 size = AOP_SIZE(result);
9738 /* if it is only one byte then */
9740 if(optimized_for_speed) {
9741 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9742 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9743 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9744 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9746 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9747 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9748 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9749 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9750 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9751 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9752 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9757 tlbl = newiTempLabel(NULL);
9758 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9759 mov2f(AOP(result), AOP(left), 0);
9761 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9762 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9765 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9766 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9767 pic16_emitpLabel(tlbl->key);
9768 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9769 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9771 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9776 if (pic16_sameRegs(AOP(left),AOP(result))) {
9778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9780 tlbl = newiTempLabel(NULL);
9781 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9782 genMultiAsm(POC_RRCF, result, size,1);
9783 pic16_emitpLabel(tlbl->key);
9784 genMultiAsm(POC_RLCF, result, size,0);
9785 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9787 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9791 //tlbl = newiTempLabel(NULL);
9793 //tlbl1 = newiTempLabel(NULL);
9795 //reAdjustPreg(AOP(result));
9797 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9798 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9799 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9801 //pic16_emitcode("add","a,acc");
9802 //pic16_aopPut(AOP(result),"a",offset++);
9804 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9806 // pic16_emitcode("rlc","a");
9807 // pic16_aopPut(AOP(result),"a",offset++);
9809 //reAdjustPreg(AOP(result));
9811 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9812 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9815 tlbl = newiTempLabel(NULL);
9816 tlbl1= newiTempLabel(NULL);
9818 size = AOP_SIZE(result);
9821 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9823 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9825 /* offset should be 0, 1 or 3 */
9827 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9829 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9831 pic16_emitpcode(POC_MOVWF, pctemp);
9834 pic16_emitpLabel(tlbl->key);
9837 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9839 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9841 pic16_emitpcode(POC_DECFSZ, pctemp);
9842 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9843 pic16_emitpLabel(tlbl1->key);
9845 pic16_popReleaseTempReg(pctemp,1);
9849 pic16_freeAsmop (right,NULL,ic,TRUE);
9850 pic16_freeAsmop(left,NULL,ic,TRUE);
9851 pic16_freeAsmop(result,NULL,ic,TRUE);
9855 /*-----------------------------------------------------------------*/
9856 /* genrshOne - right shift a one byte quantity by known count */
9857 /*-----------------------------------------------------------------*/
9858 static void genrshOne (operand *result, operand *left,
9859 int shCount, int sign)
9861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9862 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9865 /*-----------------------------------------------------------------*/
9866 /* genrshTwo - right shift two bytes by known amount != 0 */
9867 /*-----------------------------------------------------------------*/
9868 static void genrshTwo (operand *result,operand *left,
9869 int shCount, int sign)
9871 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9872 /* if shCount >= 8 */
9876 shiftR1Left2Result(left, MSB16, result, LSB,
9879 movLeft2Result(left, MSB16, result, LSB);
9881 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9884 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9885 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9889 /* 1 <= shCount <= 7 */
9891 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9894 /*-----------------------------------------------------------------*/
9895 /* shiftRLong - shift right one long from left to result */
9896 /* offl = LSB or MSB16 */
9897 /*-----------------------------------------------------------------*/
9898 static void shiftRLong (operand *left, int offl,
9899 operand *result, int sign)
9901 int size = AOP_SIZE(result);
9902 int same = pic16_sameRegs(AOP(left),AOP(result));
9904 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9906 if (same && (offl == MSB16)) { //shift one byte right
9907 for(i=MSB16;i<size;i++) {
9908 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9909 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9914 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9920 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9922 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9927 /* add sign of "a" */
9928 pic16_addSign(result, MSB32, sign);
9932 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9934 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9955 /*-----------------------------------------------------------------*/
9956 /* genrshFour - shift four byte by a known amount != 0 */
9957 /*-----------------------------------------------------------------*/
9958 static void genrshFour (operand *result, operand *left,
9959 int shCount, int sign)
9961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9962 /* if shifting more that 3 bytes */
9963 if(shCount >= 24 ) {
9966 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9968 movLeft2Result(left, MSB32, result, LSB);
9970 pic16_addSign(result, MSB16, sign);
9972 else if(shCount >= 16){
9975 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9977 movLeft2Result(left, MSB24, result, LSB);
9978 movLeft2Result(left, MSB32, result, MSB16);
9980 pic16_addSign(result, MSB24, sign);
9982 else if(shCount >= 8){
9985 shiftRLong(left, MSB16, result, sign);
9986 else if(shCount == 0){
9987 movLeft2Result(left, MSB16, result, LSB);
9988 movLeft2Result(left, MSB24, result, MSB16);
9989 movLeft2Result(left, MSB32, result, MSB24);
9990 pic16_addSign(result, MSB32, sign);
9992 else{ //shcount >= 2
9993 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9994 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9995 /* the last shift is signed */
9996 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9997 pic16_addSign(result, MSB32, sign);
10000 else{ /* 1 <= shCount <= 7 */
10002 shiftRLong(left, LSB, result, sign);
10004 shiftRLong(result, LSB, result, sign);
10007 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10008 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10009 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10014 /*-----------------------------------------------------------------*/
10015 /* genRightShiftLiteral - right shifting by known count */
10016 /*-----------------------------------------------------------------*/
10017 static void genRightShiftLiteral (operand *left,
10023 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10024 int lsize,res_size;
10026 pic16_freeAsmop(right,NULL,ic,TRUE);
10028 pic16_aopOp(left,ic,FALSE);
10029 pic16_aopOp(result,ic,TRUE);
10031 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10034 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10038 lsize = pic16_getDataSize(left);
10039 res_size = pic16_getDataSize(result);
10040 /* test the LEFT size !!! */
10042 /* I suppose that the left size >= result size */
10044 assert (res_size <= lsize);
10045 while (res_size--) {
10046 mov2f (AOP(result), AOP(left), res_size);
10050 else if(shCount >= (lsize * 8)){
10052 if(res_size == 1) {
10053 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10055 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10056 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10062 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10070 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10075 switch (res_size) {
10077 genrshOne (result,left,shCount,sign);
10081 genrshTwo (result,left,shCount,sign);
10085 genrshFour (result,left,shCount,sign);
10093 pic16_freeAsmop(left,NULL,ic,TRUE);
10094 pic16_freeAsmop(result,NULL,ic,TRUE);
10097 #if !(USE_GENERIC_SIGNED_SHIFT)
10098 /*-----------------------------------------------------------------*/
10099 /* genSignedRightShift - right shift of signed number */
10100 /*-----------------------------------------------------------------*/
10101 static void genSignedRightShift (iCode *ic)
10103 operand *right, *left, *result;
10106 symbol *tlbl, *tlbl1 ;
10109 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10111 /* we do it the hard way put the shift count in b
10112 and loop thru preserving the sign */
10113 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10115 right = IC_RIGHT(ic);
10116 left = IC_LEFT(ic);
10117 result = IC_RESULT(ic);
10119 pic16_aopOp(right,ic,FALSE);
10120 pic16_aopOp(left,ic,FALSE);
10121 pic16_aopOp(result,ic,FALSE);
10124 if ( AOP_TYPE(right) == AOP_LIT) {
10125 genRightShiftLiteral (left,right,result,ic,1);
10128 /* shift count is unknown then we have to form
10129 a loop get the loop count in B : Note: we take
10130 only the lower order byte since shifting
10131 more that 32 bits make no sense anyway, ( the
10132 largest size of an object can be only 32 bits ) */
10134 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10135 //pic16_emitcode("inc","b");
10136 //pic16_freeAsmop (right,NULL,ic,TRUE);
10137 //pic16_aopOp(left,ic,FALSE);
10138 //pic16_aopOp(result,ic,FALSE);
10140 /* now move the left to the result if they are not the
10142 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10143 AOP_SIZE(result) > 1) {
10145 size = AOP_SIZE(result);
10149 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10150 if (*l == '@' && IS_AOP_PREG(result)) {
10152 pic16_emitcode("mov","a,%s",l);
10153 pic16_aopPut(AOP(result),"a",offset);
10155 pic16_aopPut(AOP(result),l,offset);
10157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10158 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10164 /* mov the highest order bit to OVR */
10165 tlbl = newiTempLabel(NULL);
10166 tlbl1= newiTempLabel(NULL);
10168 size = AOP_SIZE(result);
10171 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10173 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10175 /* offset should be 0, 1 or 3 */
10176 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10178 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10180 pic16_emitpcode(POC_MOVWF, pctemp);
10183 pic16_emitpLabel(tlbl->key);
10185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10186 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10189 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10192 pic16_emitpcode(POC_DECFSZ, pctemp);
10193 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10194 pic16_emitpLabel(tlbl1->key);
10196 pic16_popReleaseTempReg(pctemp,1);
10198 size = AOP_SIZE(result);
10200 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10201 pic16_emitcode("rlc","a");
10202 pic16_emitcode("mov","ov,c");
10203 /* if it is only one byte then */
10205 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10207 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10208 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10209 pic16_emitcode("mov","c,ov");
10210 pic16_emitcode("rrc","a");
10211 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10212 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10213 pic16_aopPut(AOP(result),"a",0);
10217 reAdjustPreg(AOP(result));
10218 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10219 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10220 pic16_emitcode("mov","c,ov");
10222 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10224 pic16_emitcode("rrc","a");
10225 pic16_aopPut(AOP(result),"a",offset--);
10227 reAdjustPreg(AOP(result));
10228 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10229 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10234 pic16_freeAsmop(left,NULL,ic,TRUE);
10235 pic16_freeAsmop(result,NULL,ic,TRUE);
10236 pic16_freeAsmop(right,NULL,ic,TRUE);
10240 #if !(USE_GENERIC_SIGNED_SHIFT)
10241 #warning This implementation of genRightShift() is incomplete!
10242 /*-----------------------------------------------------------------*/
10243 /* genRightShift - generate code for right shifting */
10244 /*-----------------------------------------------------------------*/
10245 static void genRightShift (iCode *ic)
10247 operand *right, *left, *result;
10251 symbol *tlbl, *tlbl1 ;
10253 /* if signed then we do it the hard way preserve the
10254 sign bit moving it inwards */
10255 letype = getSpec(operandType(IC_LEFT(ic)));
10256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10258 if (!SPEC_USIGN(letype)) {
10259 genSignedRightShift (ic);
10263 /* signed & unsigned types are treated the same : i.e. the
10264 signed is NOT propagated inwards : quoting from the
10265 ANSI - standard : "for E1 >> E2, is equivalent to division
10266 by 2**E2 if unsigned or if it has a non-negative value,
10267 otherwise the result is implementation defined ", MY definition
10268 is that the sign does not get propagated */
10270 right = IC_RIGHT(ic);
10271 left = IC_LEFT(ic);
10272 result = IC_RESULT(ic);
10274 pic16_aopOp(right,ic,FALSE);
10276 /* if the shift count is known then do it
10277 as efficiently as possible */
10278 if (AOP_TYPE(right) == AOP_LIT) {
10279 genRightShiftLiteral (left,right,result,ic, 0);
10283 /* shift count is unknown then we have to form
10284 a loop get the loop count in B : Note: we take
10285 only the lower order byte since shifting
10286 more that 32 bits make no sense anyway, ( the
10287 largest size of an object can be only 32 bits ) */
10289 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10290 pic16_emitcode("inc","b");
10291 pic16_aopOp(left,ic,FALSE);
10292 pic16_aopOp(result,ic,FALSE);
10294 /* now move the left to the result if they are not the
10296 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10297 AOP_SIZE(result) > 1) {
10299 size = AOP_SIZE(result);
10302 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10303 if (*l == '@' && IS_AOP_PREG(result)) {
10305 pic16_emitcode("mov","a,%s",l);
10306 pic16_aopPut(AOP(result),"a",offset);
10308 pic16_aopPut(AOP(result),l,offset);
10313 tlbl = newiTempLabel(NULL);
10314 tlbl1= newiTempLabel(NULL);
10315 size = AOP_SIZE(result);
10318 /* if it is only one byte then */
10321 tlbl = newiTempLabel(NULL);
10322 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10323 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10327 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10328 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10329 pic16_emitpLabel(tlbl->key);
10330 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10331 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10333 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10338 reAdjustPreg(AOP(result));
10339 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10340 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10343 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10345 pic16_emitcode("rrc","a");
10346 pic16_aopPut(AOP(result),"a",offset--);
10348 reAdjustPreg(AOP(result));
10350 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10351 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10354 pic16_freeAsmop(left,NULL,ic,TRUE);
10355 pic16_freeAsmop (right,NULL,ic,TRUE);
10356 pic16_freeAsmop(result,NULL,ic,TRUE);
10360 #if (USE_GENERIC_SIGNED_SHIFT)
10361 /*-----------------------------------------------------------------*/
10362 /* genGenericShift - generates code for left or right shifting */
10363 /*-----------------------------------------------------------------*/
10364 static void genGenericShift (iCode *ic, int isShiftLeft) {
10365 operand *left,*right, *result;
10367 int sign, signedCount;
10368 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10369 PIC_OPCODE pos_shift, neg_shift;
10373 right = IC_RIGHT(ic);
10374 left = IC_LEFT(ic);
10375 result = IC_RESULT(ic);
10377 pic16_aopOp(right,ic,FALSE);
10378 pic16_aopOp(left,ic,FALSE);
10379 pic16_aopOp(result,ic,TRUE);
10381 sign = !SPEC_USIGN(operandType (left));
10382 signedCount = !SPEC_USIGN(operandType (right));
10384 /* if the shift count is known then do it
10385 as efficiently as possible */
10386 if (AOP_TYPE(right) == AOP_LIT) {
10387 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10388 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10389 // we should modify right->aopu.aop_lit here!
10390 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10391 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10393 pic16_genLeftShiftLiteral (left,right,result,ic);
10395 genRightShiftLiteral (left,right,result,ic, sign);
10398 } // if (right is literal)
10400 /* shift count is unknown then we have to form a loop.
10401 * Note: we take only the lower order byte since shifting
10402 * more than 32 bits make no sense anyway, ( the
10403 * largest size of an object can be only 32 bits )
10404 * Note: we perform arithmetic shifts if the left operand is
10405 * signed and we do an (effective) right shift, i. e. we
10406 * shift in the sign bit from the left. */
10408 label_complete = newiTempLabel ( NULL );
10409 label_loop_pos = newiTempLabel ( NULL );
10410 label_loop_neg = NULL;
10411 label_negative = NULL;
10412 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10413 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10416 // additional labels needed
10417 label_loop_neg = newiTempLabel ( NULL );
10418 label_negative = newiTempLabel ( NULL );
10421 // copy source to result -- this will effectively truncate the left operand to the size of result!
10422 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10423 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10424 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10425 mov2f (AOP(result),AOP(left), offset);
10428 // if result is longer than left, fill with zeros (or sign)
10429 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10430 if (sign && AOP_SIZE(left) > 0) {
10431 // shift signed operand -- fill with sign
10432 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10433 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10434 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10435 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10436 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10439 // shift unsigned operand -- fill result with zeros
10440 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10441 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10444 } // if (size mismatch)
10446 pic16_mov2w (AOP(right), 0);
10447 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10448 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10451 // perform a shift by one (shift count is positive)
10452 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10453 // 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])
10454 pic16_emitpLabel (label_loop_pos->key);
10456 if (sign && (pos_shift == POC_RRCF)) {
10457 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10460 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10461 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10462 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10464 // perform a shift by one (shift count is positive)
10465 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10466 // 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])
10467 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10468 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10470 pic16_emitpLabel (label_loop_pos->key);
10471 if (sign && (pos_shift == POC_RRCF)) {
10472 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10475 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10476 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10477 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10478 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10482 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10484 pic16_emitpLabel (label_negative->key);
10485 // perform a shift by -1 (shift count is negative)
10486 // 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)
10488 pic16_emitpLabel (label_loop_neg->key);
10489 if (sign && (neg_shift == POC_RRCF)) {
10490 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10493 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10494 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10497 } // if (signedCount)
10499 pic16_emitpLabel (label_complete->key);
10502 pic16_freeAsmop (right,NULL,ic,TRUE);
10503 pic16_freeAsmop(left,NULL,ic,TRUE);
10504 pic16_freeAsmop(result,NULL,ic,TRUE);
10507 static void genLeftShift (iCode *ic) {
10508 genGenericShift (ic, 1);
10511 static void genRightShift (iCode *ic) {
10512 genGenericShift (ic, 0);
10517 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10518 void pic16_loadFSR0(operand *op, int lit)
10520 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10521 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10523 assert (!OP_SYMBOL(op)->remat);
10524 // set up FSR0 with address of result
10525 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10526 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10530 /*-----------------------------------------------------------------*/
10531 /* genUnpackBits - generates code for unpacking bits */
10532 /*-----------------------------------------------------------------*/
10533 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10537 sym_link *etype, *letype;
10538 int blen=0, bstr=0;
10542 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10543 etype = getSpec(operandType(result));
10544 letype = getSpec(operandType(left));
10546 // if(IS_BITFIELD(etype)) {
10547 blen = SPEC_BLEN(etype);
10548 bstr = SPEC_BSTR(etype);
10551 lbstr = SPEC_BSTR( letype );
10554 if((blen == 1) && (bstr < 8)) {
10555 /* it is a single bit, so use the appropriate bit instructions */
10556 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10558 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10560 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10561 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10562 /* workaround to reduce the extra lfsr instruction */
10563 pic16_emitpcode(POC_BTFSC,
10564 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10566 pic16_loadFSR0 (left, 0);
10567 pic16_emitpcode(POC_BTFSC,
10568 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10571 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10573 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10579 /* the following call to pic16_loadFSR0 is temporary until
10580 * optimization to handle single bit assignments is added
10581 * to the function. Until then use the old safe way! -- VR */
10583 if (OP_SYMBOL(left)->remat) {
10584 // access symbol directly
10585 pic16_mov2w (AOP(left), 0);
10587 pic16_loadFSR0( left, 0 );
10589 /* read the first byte */
10596 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10599 pic16_emitcode("clr","a");
10600 pic16_emitcode("movc","a","@a+dptr");
10606 /* if we have bitdisplacement then it fits */
10607 /* into this byte completely or if length is */
10608 /* less than a byte */
10609 if ((shCnt = SPEC_BSTR(etype)) ||
10610 (SPEC_BLEN(etype) <= 8)) {
10612 /* shift right acc */
10615 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10616 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10618 /* VR -- normally I would use the following, but since we use the hack,
10619 * to avoid the masking from AccRsh, why not mask it right now? */
10622 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10625 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10631 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10632 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10635 /* bit field did not fit in a byte */
10636 rlen = SPEC_BLEN(etype) - 8;
10637 pic16_aopPut(AOP(result),"a",offset++);
10644 pic16_emitcode("inc","%s",rname);
10645 pic16_emitcode("mov","a,@%s",rname);
10649 pic16_emitcode("inc","%s",rname);
10650 pic16_emitcode("movx","a,@%s",rname);
10654 pic16_emitcode("inc","dptr");
10655 pic16_emitcode("movx","a,@dptr");
10659 pic16_emitcode("clr","a");
10660 pic16_emitcode("inc","dptr");
10661 pic16_emitcode("movc","a","@a+dptr");
10665 pic16_emitcode("inc","dptr");
10666 pic16_emitcode("lcall","__gptrget");
10671 /* if we are done */
10675 pic16_aopPut(AOP(result),"a",offset++);
10680 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10681 pic16_aopPut(AOP(result),"a",offset);
10688 static void genDataPointerGet(operand *left,
10692 int size, offset = 0, leoffset=0 ;
10694 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10695 pic16_aopOp(result, ic, TRUE);
10699 size = AOP_SIZE(result);
10700 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10704 /* The following tests may save a redudant movff instruction when
10705 * accessing unions */
10707 /* if they are the same */
10708 if (operandsEqu (left, result)) {
10709 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10715 /* if they are the same registers */
10716 if (pic16_sameRegs(AOP(left),AOP(result))) {
10717 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10723 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10724 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10725 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10732 if ( AOP_TYPE(left) == AOP_PCODE) {
10733 fprintf(stderr,"genDataPointerGet %s, %d\n",
10734 AOP(left)->aopu.pcop->name,
10735 (AOP(left)->aopu.pcop->type == PO_DIR)?
10736 PCOR(AOP(left)->aopu.pcop)->instance:
10737 PCOI(AOP(left)->aopu.pcop)->offset);
10741 if(AOP(left)->aopu.pcop->type == PO_DIR)
10742 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10744 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10747 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10749 // pic16_DumpOp("(result)",result);
10750 if(is_LitAOp(AOP(result))) {
10751 pic16_mov2w(AOP(left), offset); // patch 8
10752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10754 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10755 pic16_popGet(AOP(left), offset), //patch 8
10756 pic16_popGet(AOP(result), offset)));
10764 pic16_freeAsmop(result,NULL,ic,TRUE);
10769 /*-----------------------------------------------------------------*/
10770 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10771 /*-----------------------------------------------------------------*/
10772 static void genNearPointerGet (operand *left,
10776 // asmop *aop = NULL;
10777 //regs *preg = NULL ;
10778 sym_link *rtype, *retype;
10779 sym_link *ltype = operandType(left);
10783 rtype = operandType(result);
10784 retype= getSpec(rtype);
10786 pic16_aopOp(left,ic,FALSE);
10788 // pic16_DumpOp("(left)",left);
10789 // pic16_DumpOp("(result)",result);
10791 /* if left is rematerialisable and
10792 * result is not bit variable type and
10793 * the left is pointer to data space i.e
10794 * lower 128 bytes of space */
10796 if (AOP_TYPE(left) == AOP_PCODE
10797 && !IS_BITFIELD(retype)
10798 && DCL_TYPE(ltype) == POINTER) {
10800 genDataPointerGet (left,result,ic);
10801 pic16_freeAsmop(left, NULL, ic, TRUE);
10805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10806 pic16_aopOp (result,ic,TRUE);
10808 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10811 if(IS_BITFIELD( retype )
10812 && (SPEC_BLEN(operandType(result))==1)
10816 int bitstrt, bytestrt;
10818 /* if this is bitfield of size 1, see if we are checking the value
10819 * of a single bit in an if-statement,
10820 * if yes, then don't generate usual code, but execute the
10821 * genIfx directly -- VR */
10825 /* CHECK: if next iCode is IFX
10826 * and current result operand is nextic's conditional operand
10827 * and current result operand live ranges ends at nextic's key number
10829 if((nextic->op == IFX)
10830 && (result == IC_COND(nextic))
10831 && (OP_LIVETO(result) == nextic->seq)
10832 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10834 /* everything is ok then */
10835 /* find a way to optimize the genIfx iCode */
10837 bytestrt = SPEC_BSTR(operandType(result))/8;
10838 bitstrt = SPEC_BSTR(operandType(result))%8;
10840 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10842 genIfxpCOpJump(nextic, jop);
10844 pic16_freeAsmop(left, NULL, ic, TRUE);
10845 pic16_freeAsmop(result, NULL, ic, TRUE);
10852 /* if the value is already in a pointer register
10853 * then don't need anything more */
10854 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10855 /* otherwise get a free pointer register */
10856 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10861 /* if bitfield then unpack the bits */
10862 if (IS_BITFIELD(retype))
10863 genUnpackBits (result, left, NULL, POINTER);
10865 /* we have can just get the values */
10866 int size = AOP_SIZE(result);
10869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10871 pic16_loadFSR0( left, 0 );
10875 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876 pic16_popGet(AOP(result), offset++)));
10878 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879 pic16_popGet(AOP(result), offset++)));
10885 /* now some housekeeping stuff */
10887 /* we had to allocate for this iCode */
10888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10889 pic16_freeAsmop(NULL,aop,ic,TRUE);
10891 /* we did not allocate which means left
10892 * already in a pointer register, then
10893 * if size > 0 && this could be used again
10894 * we have to point it back to where it
10896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10897 if (AOP_SIZE(result) > 1
10898 && !OP_SYMBOL(left)->remat
10899 && ( OP_SYMBOL(left)->liveTo > ic->seq
10901 // int size = AOP_SIZE(result) - 1;
10903 // pic16_emitcode("dec","%s",rname);
10909 pic16_freeAsmop(left,NULL,ic,TRUE);
10910 pic16_freeAsmop(result,NULL,ic,TRUE);
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left,
10921 regs *preg = NULL ;
10923 sym_link *rtype, *retype;
10925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10927 rtype = operandType(result);
10928 retype= getSpec(rtype);
10930 pic16_aopOp(left,ic,FALSE);
10932 /* if the value is already in a pointer register
10933 then don't need anything more */
10934 if (!AOP_INPREG(AOP(left))) {
10935 /* otherwise get a free pointer register */
10937 preg = getFreePtr(ic,&aop,FALSE);
10938 pic16_emitcode("mov","%s,%s",
10940 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941 rname = preg->name ;
10943 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10945 pic16_freeAsmop(left,NULL,ic,TRUE);
10946 pic16_aopOp (result,ic,TRUE);
10948 /* if bitfield then unpack the bits */
10949 if (IS_BITFIELD(retype))
10950 genUnpackBits (result,left,rname,PPOINTER);
10952 /* we have can just get the values */
10953 int size = AOP_SIZE(result);
10958 pic16_emitcode("movx","a,@%s",rname);
10959 pic16_aopPut(AOP(result),"a",offset);
10964 pic16_emitcode("inc","%s",rname);
10968 /* now some housekeeping stuff */
10970 /* we had to allocate for this iCode */
10971 pic16_freeAsmop(NULL,aop,ic,TRUE);
10973 /* we did not allocate which means left
10974 already in a pointer register, then
10975 if size > 0 && this could be used again
10976 we have to point it back to where it
10978 if (AOP_SIZE(result) > 1 &&
10979 !OP_SYMBOL(left)->remat &&
10980 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10982 int size = AOP_SIZE(result) - 1;
10984 pic16_emitcode("dec","%s",rname);
10989 pic16_freeAsmop(result,NULL,ic,TRUE);
10994 /*-----------------------------------------------------------------*/
10995 /* genFarPointerGet - gget value from far space */
10996 /*-----------------------------------------------------------------*/
10997 static void genFarPointerGet (operand *left,
10998 operand *result, iCode *ic)
11001 sym_link *retype = getSpec(operandType(result));
11003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11005 pic16_aopOp(left,ic,FALSE);
11007 /* if the operand is already in dptr
11008 then we do nothing else we move the value to dptr */
11009 if (AOP_TYPE(left) != AOP_STR) {
11010 /* if this is remateriazable */
11011 if (AOP_TYPE(left) == AOP_IMMD)
11012 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11013 else { /* we need to get it byte by byte */
11014 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11015 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11016 if (options.model == MODEL_FLAT24)
11018 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11022 /* so dptr know contains the address */
11023 pic16_freeAsmop(left,NULL,ic,TRUE);
11024 pic16_aopOp(result,ic,TRUE);
11026 /* if bit then unpack */
11027 if (IS_BITFIELD(retype))
11028 genUnpackBits(result,left,"dptr",FPOINTER);
11030 size = AOP_SIZE(result);
11034 pic16_emitcode("movx","a,@dptr");
11035 pic16_aopPut(AOP(result),"a",offset++);
11037 pic16_emitcode("inc","dptr");
11041 pic16_freeAsmop(result,NULL,ic,TRUE);
11045 /*-----------------------------------------------------------------*/
11046 /* genCodePointerGet - get value from code space */
11047 /*-----------------------------------------------------------------*/
11048 static void genCodePointerGet (operand *left,
11049 operand *result, iCode *ic)
11052 sym_link *retype = getSpec(operandType(result));
11054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11056 pic16_aopOp(left,ic,FALSE);
11058 /* if the operand is already in dptr
11059 then we do nothing else we move the value to dptr */
11060 if (AOP_TYPE(left) != AOP_STR) {
11061 /* if this is remateriazable */
11062 if (AOP_TYPE(left) == AOP_IMMD)
11063 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11064 else { /* we need to get it byte by byte */
11065 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11066 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11067 if (options.model == MODEL_FLAT24)
11069 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11073 /* so dptr know contains the address */
11074 pic16_freeAsmop(left,NULL,ic,TRUE);
11075 pic16_aopOp(result,ic,FALSE);
11077 /* if bit then unpack */
11078 if (IS_BITFIELD(retype))
11079 genUnpackBits(result,left,"dptr",CPOINTER);
11081 size = AOP_SIZE(result);
11085 pic16_emitcode("clr","a");
11086 pic16_emitcode("movc","a,@a+dptr");
11087 pic16_aopPut(AOP(result),"a",offset++);
11089 pic16_emitcode("inc","dptr");
11093 pic16_freeAsmop(result,NULL,ic,TRUE);
11098 /*-----------------------------------------------------------------*/
11099 /* genGenPointerGet - gget value from generic pointer space */
11100 /*-----------------------------------------------------------------*/
11101 static void genGenPointerGet (operand *left,
11102 operand *result, iCode *ic)
11104 int size, offset, lit;
11105 sym_link *retype = getSpec(operandType(result));
11107 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11108 pic16_aopOp(left,ic,FALSE);
11109 pic16_aopOp(result,ic,FALSE);
11110 size = AOP_SIZE(result);
11112 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11114 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11116 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11117 // load FSR0 from immediate
11118 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11120 // pic16_loadFSR0( left );
11125 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11134 else { /* we need to get it byte by byte */
11135 // set up FSR0 with address from left
11136 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11137 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11152 /* if bit then unpack */
11153 if (IS_BITFIELD(retype))
11154 genUnpackBits(result,left,"BAD",GPOINTER);
11157 pic16_freeAsmop(left,NULL,ic,TRUE);
11158 pic16_freeAsmop(result,NULL,ic,TRUE);
11164 /*-----------------------------------------------------------------*/
11165 /* genGenPointerGet - gget value from generic pointer space */
11166 /*-----------------------------------------------------------------*/
11167 static void genGenPointerGet (operand *left,
11168 operand *result, iCode *ic)
11170 int size, offset, lit;
11171 sym_link *retype = getSpec(operandType(result));
11174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11175 pic16_aopOp(left,ic,FALSE);
11176 pic16_aopOp(result,ic,TRUE);
11177 size = AOP_SIZE(result);
11179 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11181 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11183 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11184 // load FSR0 from immediate
11185 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11187 werror(W_POSSBUG2, __FILE__, __LINE__);
11192 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11194 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11201 } else { /* we need to get it byte by byte */
11203 /* set up WREG:PRODL:FSR0L with address from left */
11204 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11205 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11206 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11209 case 1: strcpy(fgptrget, "__gptrget1"); break;
11210 case 2: strcpy(fgptrget, "__gptrget2"); break;
11211 case 3: strcpy(fgptrget, "__gptrget3"); break;
11212 case 4: strcpy(fgptrget, "__gptrget4"); break;
11214 werror(W_POSSBUG2, __FILE__, __LINE__);
11218 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11220 assignResultValue(result, 1);
11225 sym = newSymbol( fgptrget, 0 );
11227 strcpy(sym->rname, fgptrget);
11228 checkAddSym(&externs, sym);
11230 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11236 /* if bit then unpack */
11237 if (IS_BITFIELD(retype))
11238 genUnpackBits(result,left,"BAD",GPOINTER);
11241 pic16_freeAsmop(left,NULL,ic,TRUE);
11242 pic16_freeAsmop(result,NULL,ic,TRUE);
11245 /*-----------------------------------------------------------------*/
11246 /* genConstPointerGet - get value from const generic pointer space */
11247 /*-----------------------------------------------------------------*/
11248 static void genConstPointerGet (operand *left,
11249 operand *result, iCode *ic)
11251 //sym_link *retype = getSpec(operandType(result));
11252 // symbol *albl = newiTempLabel(NULL); // patch 15
11253 // symbol *blbl = newiTempLabel(NULL); //
11254 // PIC_OPCODE poc; // patch 15
11258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11259 pic16_aopOp(left,ic,FALSE);
11260 pic16_aopOp(result,ic,TRUE);
11261 size = AOP_SIZE(result);
11263 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11265 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11267 // set up table pointer
11268 if( (AOP_TYPE(left) == AOP_PCODE)
11269 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11270 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11272 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11273 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11274 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11275 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11276 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11277 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11279 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11280 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11281 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11285 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11286 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11290 pic16_freeAsmop(left,NULL,ic,TRUE);
11291 pic16_freeAsmop(result,NULL,ic,TRUE);
11295 /*-----------------------------------------------------------------*/
11296 /* genPointerGet - generate code for pointer get */
11297 /*-----------------------------------------------------------------*/
11298 static void genPointerGet (iCode *ic)
11300 operand *left, *result ;
11301 sym_link *type, *etype;
11306 left = IC_LEFT(ic);
11307 result = IC_RESULT(ic) ;
11309 /* depending on the type of pointer we need to
11310 move it to the correct pointer register */
11311 type = operandType(left);
11312 etype = getSpec(type);
11315 if (IS_PTR_CONST(type))
11317 if (IS_CODEPTR(type))
11319 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11321 /* if left is of type of pointer then it is simple */
11322 if (IS_PTR(type) && !IS_FUNC(type->next))
11323 p_type = DCL_TYPE(type);
11325 /* we have to go by the storage class */
11326 p_type = PTR_TYPE(SPEC_OCLS(etype));
11328 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11330 if (SPEC_OCLS(etype)->codesp ) {
11331 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11332 //p_type = CPOINTER ;
11334 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11335 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11336 /*p_type = FPOINTER ;*/
11338 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11339 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11340 /* p_type = PPOINTER; */
11342 if (SPEC_OCLS(etype) == idata ) {
11343 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11344 /* p_type = IPOINTER; */
11346 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11347 /* p_type = POINTER ; */
11351 /* now that we have the pointer type we assign
11352 the pointer values */
11356 genNearPointerGet (left,result,ic);
11360 genPagedPointerGet(left,result,ic);
11364 genFarPointerGet (left,result,ic);
11368 genConstPointerGet (left,result,ic);
11369 //pic16_emitcodePointerGet (left,result,ic);
11374 if (IS_PTR_CONST(type))
11375 genConstPointerGet (left,result,ic);
11378 genGenPointerGet (left,result,ic);
11382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11383 "genPointerGet: illegal pointer type");
11388 /*-----------------------------------------------------------------*/
11389 /* genPackBits - generates code for packed bit storage */
11390 /*-----------------------------------------------------------------*/
11391 static void genPackBits (sym_link *etype , operand *result,
11393 char *rname, int p_type)
11401 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11402 blen = SPEC_BLEN(etype);
11403 bstr = SPEC_BSTR(etype);
11405 retype = getSpec(operandType(right));
11407 if(AOP_TYPE(right) == AOP_LIT) {
11408 if((blen == 1) && (bstr < 8)) {
11410 /* it is a single bit, so use the appropriate bit instructions */
11412 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11414 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11415 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11416 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11417 /* workaround to reduce the extra lfsr instruction */
11419 pic16_emitpcode(POC_BSF,
11420 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11422 pic16_emitpcode(POC_BCF,
11423 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11426 pic16_loadFSR0(result, 0);
11428 pic16_emitpcode(POC_BSF,
11429 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11431 pic16_emitpcode(POC_BCF,
11432 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11438 /* move literal to W */
11439 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11442 if(IS_BITFIELD(retype)
11443 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11447 rblen = SPEC_BLEN( retype );
11448 rbstr = SPEC_BSTR( retype );
11451 if(IS_BITFIELD(etype)) {
11452 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11453 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11455 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11458 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11460 if(IS_BITFIELD(etype)) {
11461 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11463 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11466 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11470 /* move right to W */
11471 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11474 /* if the bit length is less than or */
11475 /* it exactly fits a byte then */
11476 if((shCnt=SPEC_BSTR(etype))
11477 || SPEC_BLEN(etype) <= 8 ) {
11478 int fsr0_setup = 0;
11480 if (blen != 8 || bstr != 0) {
11481 // we need to combine the value with the old value
11482 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11484 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11485 SPEC_BSTR(etype), SPEC_BLEN(etype));
11487 /* shift left acc */
11490 /* using PRODH as a temporary register here */
11491 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11493 if (OP_SYMBOL(result)->remat) {
11494 // access symbol directly
11495 pic16_mov2w (AOP(result), 0);
11497 /* get old value */
11501 pic16_loadFSR0( result, 0 );
11503 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11504 // pic16_emitcode ("mov","b,a");
11505 // pic16_emitcode("mov","a,@%s",rname);
11509 if (AOP(result)->aopu.aop_reg[2]) {
11510 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11511 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11512 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11513 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11514 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11517 sym = newSymbol( "__gptrget1", 0 );
11518 strcpy(sym->rname, "__gptrget1");
11519 checkAddSym(&externs, sym);
11522 // data pointer (just 2 byte given)
11523 pic16_loadFSR0( result, 0 );
11525 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11528 // warnings will be emitted below
11529 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11530 //werror(W_POSSBUG2, __FILE__, __LINE__);
11534 assert (0 && "invalid pointer type specified");
11539 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11540 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11541 (unsigned char)(0xff >> (8-bstr))) ));
11542 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11543 } // if (blen != 8 || bstr != 0)
11545 /* write new value back */
11546 if (OP_SYMBOL(result)->remat) {
11547 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11552 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11553 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11557 if (AOP(result)->aopu.aop_reg[2]) {
11558 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11559 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11560 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11561 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11562 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11563 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11566 sym = newSymbol( "__gptrput1", 0 );
11567 strcpy(sym->rname, "__gptrput1");
11568 checkAddSym(&externs, sym);
11571 // data pointer (just 2 byte given)
11572 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11573 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11576 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11577 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11578 werror(W_POSSBUG2, __FILE__, __LINE__);
11582 assert (0 && "invalid pointer type specified");
11593 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11594 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11599 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11600 rLen = SPEC_BLEN(etype)-8;
11602 /* now generate for lengths greater than one byte */
11606 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11612 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11618 pic16_emitcode("movx","@dptr,a");
11623 DEBUGpic16_emitcode(";lcall","__gptrput");
11631 pic16_mov2w(AOP(right), offset++);
11634 /* last last was not complete */
11636 /* save the byte & read byte */
11639 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11640 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11645 pic16_emitcode ("mov","b,a");
11646 pic16_emitcode("movx","a,@dptr");
11650 pic16_emitcode ("push","b");
11651 pic16_emitcode ("push","acc");
11652 pic16_emitcode ("lcall","__gptrget");
11653 pic16_emitcode ("pop","b");
11659 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11661 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11662 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11663 // pic16_emitcode ("orl","a,b");
11666 // if (p_type == GPOINTER)
11667 // pic16_emitcode("pop","b");
11672 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11673 // pic16_emitcode("mov","@%s,a",rname);
11677 pic16_emitcode("movx","@dptr,a");
11681 DEBUGpic16_emitcode(";lcall","__gptrput");
11688 // pic16_freeAsmop(right, NULL, ic, TRUE);
11690 /*-----------------------------------------------------------------*/
11691 /* genDataPointerSet - remat pointer to data space */
11692 /*-----------------------------------------------------------------*/
11693 static void genDataPointerSet(operand *right,
11697 int size, offset = 0, resoffset=0 ;
11699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11700 pic16_aopOp(right,ic,FALSE);
11702 size = AOP_SIZE(right);
11704 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11707 if ( AOP_TYPE(result) == AOP_PCODE) {
11708 fprintf(stderr,"genDataPointerSet %s, %d\n",
11709 AOP(result)->aopu.pcop->name,
11710 (AOP(result)->aopu.pcop->type == PO_DIR)?
11711 PCOR(AOP(result)->aopu.pcop)->instance:
11712 PCOI(AOP(result)->aopu.pcop)->offset);
11716 if(AOP(result)->aopu.pcop->type == PO_DIR)
11717 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11720 if (AOP_TYPE(right) == AOP_LIT) {
11723 if(!IS_FLOAT(operandType( right )))
11724 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11727 unsigned long lit_int;
11731 /* take care if literal is a float */
11732 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11733 lit = info.lit_int;
11736 lit = lit >> (8*offset);
11738 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11739 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11741 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11744 pic16_mov2w(AOP(right), offset);
11745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11751 pic16_freeAsmop(right,NULL,ic,TRUE);
11756 /*-----------------------------------------------------------------*/
11757 /* genNearPointerSet - pic16_emitcode for near pointer put */
11758 /*-----------------------------------------------------------------*/
11759 static void genNearPointerSet (operand *right,
11765 sym_link *ptype = operandType(result);
11766 sym_link *resetype;
11768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11769 retype= getSpec(operandType(right));
11770 resetype = getSpec(operandType(result));
11772 pic16_aopOp(result,ic,FALSE);
11774 /* if the result is rematerializable &
11775 * in data space & not a bit variable */
11777 /* and result is not a bit variable */
11778 if (AOP_TYPE(result) == AOP_PCODE
11779 // && AOP_TYPE(result) == AOP_IMMD
11780 && DCL_TYPE(ptype) == POINTER
11781 && !IS_BITFIELD(retype)
11782 && !IS_BITFIELD(resetype)) {
11784 genDataPointerSet (right,result,ic);
11785 pic16_freeAsmop(result,NULL,ic,TRUE);
11789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11790 pic16_aopOp(right,ic,FALSE);
11791 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11793 /* if the value is already in a pointer register
11794 * then don't need anything more */
11795 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11796 /* otherwise get a free pointer register */
11797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11804 /* if bitfield then unpack the bits */
11805 if (IS_BITFIELD(resetype)) {
11806 genPackBits (resetype, result, right, NULL, POINTER);
11808 /* we have can just get the values */
11809 int size = AOP_SIZE(right);
11812 pic16_loadFSR0(result, 0);
11814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11816 if (AOP_TYPE(right) == AOP_LIT) {
11817 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11819 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11821 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11823 } else { // no literal
11825 pic16_emitpcode(POC_MOVFF,
11826 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11827 pic16_popCopyReg(&pic16_pc_postinc0)));
11829 pic16_emitpcode(POC_MOVFF,
11830 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11831 pic16_popCopyReg(&pic16_pc_indf0)));
11838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11839 /* now some housekeeping stuff */
11841 /* we had to allocate for this iCode */
11842 pic16_freeAsmop(NULL,aop,ic,TRUE);
11844 /* we did not allocate which means left
11845 * already in a pointer register, then
11846 * if size > 0 && this could be used again
11847 * we have to point it back to where it
11849 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11850 if (AOP_SIZE(right) > 1
11851 && !OP_SYMBOL(result)->remat
11852 && ( OP_SYMBOL(result)->liveTo > ic->seq
11855 int size = AOP_SIZE(right) - 1;
11858 pic16_emitcode("decf","fsr0,f");
11859 //pic16_emitcode("dec","%s",rname);
11863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11866 pic16_freeAsmop(right,NULL,ic,TRUE);
11867 pic16_freeAsmop(result,NULL,ic,TRUE);
11870 /*-----------------------------------------------------------------*/
11871 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11872 /*-----------------------------------------------------------------*/
11873 static void genPagedPointerSet (operand *right,
11878 regs *preg = NULL ;
11882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11884 retype= getSpec(operandType(right));
11886 pic16_aopOp(result,ic,FALSE);
11888 /* if the value is already in a pointer register
11889 then don't need anything more */
11890 if (!AOP_INPREG(AOP(result))) {
11891 /* otherwise get a free pointer register */
11893 preg = getFreePtr(ic,&aop,FALSE);
11894 pic16_emitcode("mov","%s,%s",
11896 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11897 rname = preg->name ;
11899 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11901 pic16_freeAsmop(result,NULL,ic,TRUE);
11902 pic16_aopOp (right,ic,FALSE);
11904 /* if bitfield then unpack the bits */
11905 if (IS_BITFIELD(retype))
11906 genPackBits (retype,result,right,rname,PPOINTER);
11908 /* we have can just get the values */
11909 int size = AOP_SIZE(right);
11913 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11916 pic16_emitcode("movx","@%s,a",rname);
11919 pic16_emitcode("inc","%s",rname);
11925 /* now some housekeeping stuff */
11927 /* we had to allocate for this iCode */
11928 pic16_freeAsmop(NULL,aop,ic,TRUE);
11930 /* we did not allocate which means left
11931 already in a pointer register, then
11932 if size > 0 && this could be used again
11933 we have to point it back to where it
11935 if (AOP_SIZE(right) > 1 &&
11936 !OP_SYMBOL(result)->remat &&
11937 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11939 int size = AOP_SIZE(right) - 1;
11941 pic16_emitcode("dec","%s",rname);
11946 pic16_freeAsmop(right,NULL,ic,TRUE);
11951 /*-----------------------------------------------------------------*/
11952 /* genFarPointerSet - set value from far space */
11953 /*-----------------------------------------------------------------*/
11954 static void genFarPointerSet (operand *right,
11955 operand *result, iCode *ic)
11958 sym_link *retype = getSpec(operandType(right));
11960 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11961 pic16_aopOp(result,ic,FALSE);
11963 /* if the operand is already in dptr
11964 then we do nothing else we move the value to dptr */
11965 if (AOP_TYPE(result) != AOP_STR) {
11966 /* if this is remateriazable */
11967 if (AOP_TYPE(result) == AOP_IMMD)
11968 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11969 else { /* we need to get it byte by byte */
11970 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11971 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11972 if (options.model == MODEL_FLAT24)
11974 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11978 /* so dptr know contains the address */
11979 pic16_freeAsmop(result,NULL,ic,TRUE);
11980 pic16_aopOp(right,ic,FALSE);
11982 /* if bit then unpack */
11983 if (IS_BITFIELD(retype))
11984 genPackBits(retype,result,right,"dptr",FPOINTER);
11986 size = AOP_SIZE(right);
11990 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11992 pic16_emitcode("movx","@dptr,a");
11994 pic16_emitcode("inc","dptr");
11998 pic16_freeAsmop(right,NULL,ic,TRUE);
12001 /*-----------------------------------------------------------------*/
12002 /* genGenPointerSet - set value from generic pointer space */
12003 /*-----------------------------------------------------------------*/
12005 static void genGenPointerSet (operand *right,
12006 operand *result, iCode *ic)
12008 int i, size, offset, lit;
12009 sym_link *retype = getSpec(operandType(right));
12011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12013 pic16_aopOp(result,ic,FALSE);
12014 pic16_aopOp(right,ic,FALSE);
12015 size = AOP_SIZE(right);
12018 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12020 /* if the operand is already in dptr
12021 then we do nothing else we move the value to dptr */
12022 if (AOP_TYPE(result) != AOP_STR) {
12023 /* if this is remateriazable */
12024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12025 // WARNING: anythig until "else" is untested!
12026 if (AOP_TYPE(result) == AOP_IMMD) {
12027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12028 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12029 // load FSR0 from immediate
12030 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12034 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12036 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12042 else { /* we need to get it byte by byte */
12043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12044 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12046 // set up FSR0 with address of result
12047 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12048 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12050 /* hack hack! see if this the FSR. If so don't load W */
12051 if(AOP_TYPE(right) != AOP_ACC) {
12053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12055 if(AOP_TYPE(right) == AOP_LIT)
12058 // note: pic16_popGet handles sign extension
12059 for(i=0;i<size;i++) {
12060 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12062 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12064 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12069 for(i=0;i<size;i++) {
12071 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12072 pic16_popCopyReg(&pic16_pc_postinc0)));
12074 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12075 pic16_popCopyReg(&pic16_pc_indf0)));
12081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12082 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12084 } // if (AOP_TYPE(result) != AOP_IMMD)
12086 } // if (AOP_TYPE(result) != AOP_STR)
12087 /* so dptr know contains the address */
12090 /* if bit then unpack */
12091 if (IS_BITFIELD(retype))
12092 genPackBits(retype,result,right,"dptr",GPOINTER);
12094 size = AOP_SIZE(right);
12097 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12099 // set up FSR0 with address of result
12100 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12101 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12104 if (AOP_TYPE(right) == AOP_LIT) {
12105 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12107 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12109 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12111 } else { // no literal
12113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12115 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12123 pic16_freeAsmop(right,NULL,ic,TRUE);
12124 pic16_freeAsmop(result,NULL,ic,TRUE);
12128 static void genGenPointerSet (operand *right,
12129 operand *result, iCode *ic)
12132 sym_link *retype = getSpec(operandType(right));
12135 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12137 pic16_aopOp(result,ic,FALSE);
12138 pic16_aopOp(right,ic,FALSE);
12139 size = AOP_SIZE(right);
12141 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12144 /* if bit then unpack */
12145 if (IS_BITFIELD(retype)) {
12146 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12147 genPackBits(retype,result,right,"dptr",GPOINTER);
12151 size = AOP_SIZE(right);
12153 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12157 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12159 /* value of right+0 is placed on stack, which will be retrieved
12160 * by the support function this restoring the stack. The important
12161 * thing is that there is no need to manually restore stack pointer
12163 pushaop(AOP(right), 0);
12164 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12165 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12166 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12167 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12169 /* load address to write to in WREG:FSR0H:FSR0L */
12170 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12171 pic16_popCopyReg(&pic16_pc_fsr0l)));
12172 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12173 pic16_popCopyReg(&pic16_pc_prodl)));
12174 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12177 /* put code here */
12179 case 1: strcpy(fgptrput, "__gptrput1"); break;
12180 case 2: strcpy(fgptrput, "__gptrput2"); break;
12181 case 3: strcpy(fgptrput, "__gptrput3"); break;
12182 case 4: strcpy(fgptrput, "__gptrput4"); break;
12184 werror(W_POSSBUG2, __FILE__, __LINE__);
12188 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12193 sym = newSymbol( fgptrput, 0 );
12195 strcpy(sym->rname, fgptrput);
12196 checkAddSym(&externs, sym);
12200 pic16_freeAsmop(right,NULL,ic,TRUE);
12201 pic16_freeAsmop(result,NULL,ic,TRUE);
12204 /*-----------------------------------------------------------------*/
12205 /* genPointerSet - stores the value into a pointer location */
12206 /*-----------------------------------------------------------------*/
12207 static void genPointerSet (iCode *ic)
12209 operand *right, *result ;
12210 sym_link *type, *etype;
12215 right = IC_RIGHT(ic);
12216 result = IC_RESULT(ic) ;
12218 /* depending on the type of pointer we need to
12219 move it to the correct pointer register */
12220 type = operandType(result);
12221 etype = getSpec(type);
12222 /* if left is of type of pointer then it is simple */
12223 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12224 p_type = DCL_TYPE(type);
12227 /* we have to go by the storage class */
12228 p_type = PTR_TYPE(SPEC_OCLS(etype));
12230 /* if (SPEC_OCLS(etype)->codesp ) { */
12231 /* p_type = CPOINTER ; */
12234 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12235 /* p_type = FPOINTER ; */
12237 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12238 /* p_type = PPOINTER ; */
12240 /* if (SPEC_OCLS(etype) == idata ) */
12241 /* p_type = IPOINTER ; */
12243 /* p_type = POINTER ; */
12246 /* now that we have the pointer type we assign
12247 the pointer values */
12251 genNearPointerSet (right,result,ic);
12255 genPagedPointerSet (right,result,ic);
12259 genFarPointerSet (right,result,ic);
12263 genGenPointerSet (right,result,ic);
12267 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12268 "genPointerSet: illegal pointer type");
12272 /*-----------------------------------------------------------------*/
12273 /* genIfx - generate code for Ifx statement */
12274 /*-----------------------------------------------------------------*/
12275 static void genIfx (iCode *ic, iCode *popIc)
12277 operand *cond = IC_COND(ic);
12282 pic16_aopOp(cond,ic,FALSE);
12284 /* get the value into acc */
12285 if (AOP_TYPE(cond) != AOP_CRY)
12286 pic16_toBoolean(cond);
12289 /* the result is now in the accumulator */
12290 pic16_freeAsmop(cond,NULL,ic,TRUE);
12292 /* if there was something to be popped then do it */
12296 /* if the condition is a bit variable */
12297 if (isbit && IS_ITEMP(cond) &&
12299 genIfxJump(ic,"c");
12300 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12302 if (isbit && !IS_ITEMP(cond))
12303 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12305 genIfxJump(ic,"a");
12310 /*-----------------------------------------------------------------*/
12311 /* genAddrOf - generates code for address of */
12312 /*-----------------------------------------------------------------*/
12313 static void genAddrOf (iCode *ic)
12315 operand *result, *left;
12317 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12318 pCodeOp *pcop0, *pcop1, *pcop2;
12322 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12324 sym = OP_SYMBOL( IC_LEFT(ic) );
12327 /* get address of symbol on stack */
12328 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12330 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12331 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12334 // operands on stack are accessible via "FSR2 + index" with index
12335 // starting at 2 for arguments and growing from 0 downwards for
12336 // local variables (index == 0 is not assigned so we add one here)
12338 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12340 assert (soffs < 0);
12343 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12344 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12345 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12346 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12347 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12348 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12349 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12355 // if(pic16_debug_verbose) {
12356 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12357 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12360 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12361 size = AOP_SIZE(IC_RESULT(ic));
12363 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12364 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12365 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12368 pic16_emitpcode(POC_MOVLW, pcop0);
12369 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12370 pic16_emitpcode(POC_MOVLW, pcop1);
12371 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12372 pic16_emitpcode(POC_MOVLW, pcop2);
12373 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12376 pic16_emitpcode(POC_MOVLW, pcop0);
12377 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12378 pic16_emitpcode(POC_MOVLW, pcop1);
12379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12381 pic16_emitpcode(POC_MOVLW, pcop0);
12382 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12385 pic16_freeAsmop(left, NULL, ic, FALSE);
12387 pic16_freeAsmop(result,NULL,ic,TRUE);
12392 /*-----------------------------------------------------------------*/
12393 /* genFarFarAssign - assignment when both are in far space */
12394 /*-----------------------------------------------------------------*/
12395 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12397 int size = AOP_SIZE(right);
12400 /* first push the right side on to the stack */
12402 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12404 pic16_emitcode ("push","acc");
12407 pic16_freeAsmop(right,NULL,ic,FALSE);
12408 /* now assign DPTR to result */
12409 pic16_aopOp(result,ic,FALSE);
12410 size = AOP_SIZE(result);
12412 pic16_emitcode ("pop","acc");
12413 pic16_aopPut(AOP(result),"a",--offset);
12415 pic16_freeAsmop(result,NULL,ic,FALSE);
12420 /*-----------------------------------------------------------------*/
12421 /* genAssign - generate code for assignment */
12422 /*-----------------------------------------------------------------*/
12423 static void genAssign (iCode *ic)
12425 operand *result, *right;
12426 int size, offset,know_W;
12427 unsigned long lit = 0L;
12429 result = IC_RESULT(ic);
12430 right = IC_RIGHT(ic) ;
12434 /* if they are the same */
12435 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12438 /* reversed order operands are aopOp'ed so that result operand
12439 * is effective in case right is a stack symbol. This maneauver
12440 * allows to use the _G.resDirect flag later */
12441 pic16_aopOp(result,ic,TRUE);
12442 pic16_aopOp(right,ic,FALSE);
12444 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12446 /* if they are the same registers */
12447 if (pic16_sameRegs(AOP(right),AOP(result)))
12450 /* if the result is a bit */
12451 if (AOP_TYPE(result) == AOP_CRY) {
12452 /* if the right size is a literal then
12453 we know what the value is */
12454 if (AOP_TYPE(right) == AOP_LIT) {
12456 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12457 pic16_popGet(AOP(result),0));
12459 if (((int) operandLitValue(right)))
12460 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12461 AOP(result)->aopu.aop_dir,
12462 AOP(result)->aopu.aop_dir);
12464 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12465 AOP(result)->aopu.aop_dir,
12466 AOP(result)->aopu.aop_dir);
12470 /* the right is also a bit variable */
12471 if (AOP_TYPE(right) == AOP_CRY) {
12472 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12473 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12474 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12476 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12477 AOP(result)->aopu.aop_dir,
12478 AOP(result)->aopu.aop_dir);
12479 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12480 AOP(right)->aopu.aop_dir,
12481 AOP(right)->aopu.aop_dir);
12482 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12483 AOP(result)->aopu.aop_dir,
12484 AOP(result)->aopu.aop_dir);
12488 /* we need to or */
12489 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12490 pic16_toBoolean(right);
12492 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12493 //pic16_aopPut(AOP(result),"a",0);
12497 /* bit variables done */
12499 size = AOP_SIZE(result);
12502 if(AOP_TYPE(right) == AOP_LIT) {
12503 if(!IS_FLOAT(operandType( right )))
12504 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12507 unsigned long lit_int;
12511 /* take care if literal is a float */
12512 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12513 lit = info.lit_int;
12517 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12518 // sizeof(unsigned long int), sizeof(float));
12521 if (AOP_TYPE(right) == AOP_REG) {
12522 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12525 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12530 if(AOP_TYPE(right) != AOP_LIT
12531 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12532 && !IS_FUNC(OP_SYM_TYPE(right))
12534 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12535 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12537 // set up table pointer
12538 if(is_LitOp(right)) {
12539 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12540 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12541 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12542 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12543 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12544 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12545 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12547 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12548 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12549 pic16_popCopyReg(&pic16_pc_tblptrl)));
12550 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12551 pic16_popCopyReg(&pic16_pc_tblptrh)));
12552 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12553 pic16_popCopyReg(&pic16_pc_tblptru)));
12556 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12558 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12560 pic16_popGet(AOP(result),offset)));
12564 size = getSize(OP_SYM_ETYPE(right));
12565 if(AOP_SIZE(result) > size) {
12566 size = AOP_SIZE(result) - size;
12568 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12578 /* VR - What is this?! */
12579 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12581 if(aopIdx(AOP(result),0) == 4) {
12583 /* this is a workaround to save value of right into wreg too,
12584 * value of wreg is going to be used later */
12585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12586 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12587 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12591 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12597 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12598 if(AOP_TYPE(right) == AOP_LIT) {
12600 if(know_W != (lit&0xff))
12601 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12603 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12605 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12609 } else if (AOP_TYPE(right) == AOP_CRY) {
12610 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12612 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12613 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12614 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12616 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12617 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12618 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12622 if(!_G.resDirect) /* use this aopForSym feature */
12623 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12630 pic16_freeAsmop (right,NULL,ic,FALSE);
12631 pic16_freeAsmop (result,NULL,ic,TRUE);
12634 /*-----------------------------------------------------------------*/
12635 /* genJumpTab - generates code for jump table */
12636 /*-----------------------------------------------------------------*/
12637 static void genJumpTab (iCode *ic)
12642 pCodeOp *jt_offs_hi;
12647 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12648 /* get the condition into accumulator */
12649 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12651 /* multiply by three */
12652 pic16_emitcode("add","a,acc");
12653 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12655 jtab = newiTempLabel(NULL);
12656 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12657 pic16_emitcode("jmp","@a+dptr");
12658 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12661 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12662 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12664 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12665 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12666 pic16_emitpLabel(jtab->key);
12670 jt_offs = pic16_popGetTempReg(0);
12671 jt_offs_hi = pic16_popGetTempReg(1);
12672 jt_label = pic16_popGetLabel (jtab->key);
12673 //fprintf (stderr, "Creating jump table...\n");
12675 // calculate offset into jump table (idx * sizeof (GOTO))
12676 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12677 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12678 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12679 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12680 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12681 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12682 pic16_emitpcode(POC_MOVWF , jt_offs);
12684 // prepare PCLATx (set to first entry in jump table)
12685 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12686 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12687 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12688 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12689 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12691 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12692 pic16_emitpcode(POC_ADDWF , jt_offs);
12693 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12694 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12696 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12698 // release temporaries and prepare jump into table (new PCL --> WREG)
12699 pic16_emitpcode(POC_MOVFW , jt_offs);
12700 pic16_popReleaseTempReg (jt_offs_hi, 1);
12701 pic16_popReleaseTempReg (jt_offs, 0);
12703 // jump into the table
12704 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12706 pic16_emitpLabelFORCE(jtab->key);
12709 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12710 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12712 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12713 /* now generate the jump labels */
12714 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12715 jtab = setNextItem(IC_JTLABELS(ic))) {
12716 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12717 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12720 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12724 /*-----------------------------------------------------------------*/
12725 /* genMixedOperation - gen code for operators between mixed types */
12726 /*-----------------------------------------------------------------*/
12728 TSD - Written for the PIC port - but this unfortunately is buggy.
12729 This routine is good in that it is able to efficiently promote
12730 types to different (larger) sizes. Unfortunately, the temporary
12731 variables that are optimized out by this routine are sometimes
12732 used in other places. So until I know how to really parse the
12733 iCode tree, I'm going to not be using this routine :(.
12735 static int genMixedOperation (iCode *ic)
12738 operand *result = IC_RESULT(ic);
12739 sym_link *ctype = operandType(IC_LEFT(ic));
12740 operand *right = IC_RIGHT(ic);
12746 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12748 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12754 nextright = IC_RIGHT(nextic);
12755 nextleft = IC_LEFT(nextic);
12756 nextresult = IC_RESULT(nextic);
12758 pic16_aopOp(right,ic,FALSE);
12759 pic16_aopOp(result,ic,FALSE);
12760 pic16_aopOp(nextright, nextic, FALSE);
12761 pic16_aopOp(nextleft, nextic, FALSE);
12762 pic16_aopOp(nextresult, nextic, FALSE);
12764 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12766 operand *t = right;
12770 pic16_emitcode(";remove right +","");
12772 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12774 operand *t = right;
12778 pic16_emitcode(";remove left +","");
12782 big = AOP_SIZE(nextleft);
12783 small = AOP_SIZE(nextright);
12785 switch(nextic->op) {
12788 pic16_emitcode(";optimize a +","");
12789 /* if unsigned or not an integral type */
12790 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12791 pic16_emitcode(";add a bit to something","");
12794 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12796 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12797 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12798 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12800 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12808 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12809 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12810 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12813 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12815 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12816 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12817 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12818 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12819 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12822 pic16_emitcode("rlf","known_zero,w");
12829 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12830 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12831 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12833 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12843 pic16_freeAsmop(right,NULL,ic,TRUE);
12844 pic16_freeAsmop(result,NULL,ic,TRUE);
12845 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12846 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12848 nextic->generated = 1;
12855 /*-----------------------------------------------------------------*/
12856 /* genCast - gen code for casting */
12857 /*-----------------------------------------------------------------*/
12858 static void genCast (iCode *ic)
12860 operand *result = IC_RESULT(ic);
12861 sym_link *ctype = operandType(IC_LEFT(ic));
12862 sym_link *rtype = operandType(IC_RIGHT(ic));
12863 sym_link *restype = operandType(IC_RESULT(ic));
12864 operand *right = IC_RIGHT(ic);
12870 /* if they are equivalent then do nothing */
12871 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12874 pic16_aopOp(result,ic,FALSE);
12875 pic16_aopOp(right,ic,FALSE) ;
12877 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12880 /* if the result is a bit */
12881 if (AOP_TYPE(result) == AOP_CRY) {
12883 /* if the right size is a literal then
12884 * we know what the value is */
12885 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12887 if (AOP_TYPE(right) == AOP_LIT) {
12888 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12889 pic16_popGet(AOP(result),0));
12891 if (((int) operandLitValue(right)))
12892 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12893 AOP(result)->aopu.aop_dir,
12894 AOP(result)->aopu.aop_dir);
12896 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12897 AOP(result)->aopu.aop_dir,
12898 AOP(result)->aopu.aop_dir);
12902 /* the right is also a bit variable */
12903 if (AOP_TYPE(right) == AOP_CRY) {
12905 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12907 pic16_emitcode("clrc","");
12908 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12909 AOP(right)->aopu.aop_dir,
12910 AOP(right)->aopu.aop_dir);
12911 pic16_aopPut(AOP(result),"c",0);
12915 /* we need to or */
12916 if (AOP_TYPE(right) == AOP_REG) {
12917 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12918 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12919 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12921 pic16_toBoolean(right);
12922 pic16_aopPut(AOP(result),"a",0);
12926 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12929 size = AOP_SIZE(result);
12931 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12933 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12934 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12935 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12938 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12943 if(IS_BITFIELD(getSpec(restype))
12944 && IS_BITFIELD(getSpec(rtype))) {
12945 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12948 /* if they are the same size : or less */
12949 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12951 /* if they are in the same place */
12952 if (pic16_sameRegs(AOP(right),AOP(result)))
12955 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12957 if (IS_PTR_CONST(rtype))
12959 if (IS_CODEPTR(rtype))
12961 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12964 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12966 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12968 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12971 if(AOP_TYPE(right) == AOP_IMMD) {
12972 pCodeOp *pcop0, *pcop1, *pcop2;
12973 symbol *sym = OP_SYMBOL( right );
12975 size = AOP_SIZE(result);
12977 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12979 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12981 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12984 pic16_emitpcode(POC_MOVLW, pcop0);
12985 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12986 pic16_emitpcode(POC_MOVLW, pcop1);
12987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12988 pic16_emitpcode(POC_MOVLW, pcop2);
12989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12992 pic16_emitpcode(POC_MOVLW, pcop0);
12993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12994 pic16_emitpcode(POC_MOVLW, pcop1);
12995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12997 pic16_emitpcode(POC_MOVLW, pcop0);
12998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13002 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13003 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13005 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13007 if(AOP_SIZE(result) <2)
13008 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13010 /* if they in different places then copy */
13011 size = AOP_SIZE(result);
13014 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13022 /* if the result is of type pointer */
13023 if (IS_PTR(ctype)) {
13025 sym_link *type = operandType(right);
13026 sym_link *etype = getSpec(type);
13028 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13030 /* pointer to generic pointer */
13031 if (IS_GENPTR(ctype)) {
13035 p_type = DCL_TYPE(type);
13037 /* we have to go by the storage class */
13038 p_type = PTR_TYPE(SPEC_OCLS(etype));
13040 /* if (SPEC_OCLS(etype)->codesp ) */
13041 /* p_type = CPOINTER ; */
13043 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13044 /* p_type = FPOINTER ; */
13046 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13047 /* p_type = PPOINTER; */
13049 /* if (SPEC_OCLS(etype) == idata ) */
13050 /* p_type = IPOINTER ; */
13052 /* p_type = POINTER ; */
13055 /* the first two bytes are known */
13056 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13057 size = GPTRSIZE - 1;
13060 if(offset < AOP_SIZE(right)) {
13061 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13062 mov2f(AOP(result), AOP(right), offset);
13064 if ((AOP_TYPE(right) == AOP_PCODE) &&
13065 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13066 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13070 pic16_aopPut(AOP(result),
13071 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13076 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13079 /* the last byte depending on type */
13083 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13084 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13085 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13089 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13093 pic16_emitcode(";BUG!? ","%d",__LINE__);
13097 pic16_emitcode(";BUG!? ","%d",__LINE__);
13102 if (GPTRSIZE > AOP_SIZE(right)) {
13103 // assume data pointer... THIS MIGHT BE WRONG!
13104 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13105 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13107 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13112 /* this should never happen */
13113 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13114 "got unknown pointer type");
13117 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13123 /* just copy the pointers */
13124 size = AOP_SIZE(result);
13127 pic16_aopPut(AOP(result),
13128 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13137 /* so we now know that the size of destination is greater
13138 than the size of the source.
13139 Now, if the next iCode is an operator then we might be
13140 able to optimize the operation without performing a cast.
13142 if(genMixedOperation(ic))
13145 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13147 /* we move to result for the size of source */
13148 size = AOP_SIZE(right);
13153 mov2f(AOP(result), AOP(right), offset);
13157 /* now depending on the sign of the destination */
13158 size = AOP_SIZE(result) - AOP_SIZE(right);
13159 /* if unsigned or not an integral type */
13160 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13162 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13164 /* we need to extend the sign :( */
13167 /* Save one instruction of casting char to int */
13168 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13169 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13170 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13172 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13175 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13177 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13179 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13182 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13187 pic16_freeAsmop(right,NULL,ic,TRUE);
13188 pic16_freeAsmop(result,NULL,ic,TRUE);
13192 /*-----------------------------------------------------------------*/
13193 /* genDjnz - generate decrement & jump if not zero instrucion */
13194 /*-----------------------------------------------------------------*/
13195 static int genDjnz (iCode *ic, iCode *ifx)
13197 symbol *lbl, *lbl1;
13198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13203 /* if the if condition has a false label
13204 then we cannot save */
13208 /* if the minus is not of the form
13210 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13211 !IS_OP_LITERAL(IC_RIGHT(ic)))
13214 if (operandLitValue(IC_RIGHT(ic)) != 1)
13217 /* if the size of this greater than one then no
13219 if (getSize(operandType(IC_RESULT(ic))) > 1)
13222 /* otherwise we can save BIG */
13223 lbl = newiTempLabel(NULL);
13224 lbl1= newiTempLabel(NULL);
13226 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13228 if (IS_AOP_PREG(IC_RESULT(ic))) {
13229 pic16_emitcode("dec","%s",
13230 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13231 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13232 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13236 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13237 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13239 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13240 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13244 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13245 ifx->generated = 1;
13249 /*-----------------------------------------------------------------*/
13250 /* genReceive - generate code for a receive iCode */
13251 /*-----------------------------------------------------------------*/
13252 static void genReceive (iCode *ic)
13258 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13259 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13261 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13263 if (isOperandInFarSpace(IC_RESULT(ic))
13264 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13265 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13267 int size = getSize(operandType(IC_RESULT(ic)));
13268 int offset = pic16_fReturnSizePic - size;
13272 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13273 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13277 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13279 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13280 size = AOP_SIZE(IC_RESULT(ic));
13283 pic16_emitcode ("pop","acc");
13284 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13287 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13289 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13292 /* set pseudo stack pointer to where it should be - dw*/
13293 GpsuedoStkPtr = ic->parmBytes;
13295 /* setting GpsuedoStkPtr has side effects here: */
13296 assignResultValue(IC_RESULT(ic), 0);
13299 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13302 /*-----------------------------------------------------------------*/
13303 /* genDummyRead - generate code for dummy read of volatiles */
13304 /*-----------------------------------------------------------------*/
13306 genDummyRead (iCode * ic)
13312 if (op && IS_SYMOP(op)) {
13313 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13314 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13317 pic16_aopOp (op, ic, FALSE);
13318 for (i=0; i < AOP_SIZE(op); i++) {
13319 // may need to protect this from the peepholer -- this is not nice but works...
13320 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13321 pic16_mov2w (AOP(op),i);
13322 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13324 pic16_freeAsmop (op, NULL, ic, TRUE);
13326 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13330 /*-----------------------------------------------------------------*/
13331 /* genpic16Code - generate code for pic16 based controllers */
13332 /*-----------------------------------------------------------------*/
13334 * At this point, ralloc.c has gone through the iCode and attempted
13335 * to optimize in a way suitable for a PIC. Now we've got to generate
13336 * PIC instructions that correspond to the iCode.
13338 * Once the instructions are generated, we'll pass through both the
13339 * peep hole optimizer and the pCode optimizer.
13340 *-----------------------------------------------------------------*/
13342 void genpic16Code (iCode *lic)
13347 lineHead = lineCurr = NULL;
13349 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13350 pic16_addpBlock(pb);
13353 /* if debug information required */
13354 if (options.debug && currFunc) {
13356 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13361 for (ic = lic ; ic ; ic = ic->next ) {
13363 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13364 if ( cln != ic->lineno ) {
13365 if ( options.debug ) {
13366 debugFile->writeCLine (ic);
13369 if(!options.noCcodeInAsm) {
13370 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13371 printCLine(ic->filename, ic->lineno)));
13377 if(options.iCodeInAsm) {
13380 /* insert here code to print iCode as comment */
13381 l = Safe_strdup(printILine(ic));
13382 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13385 /* if the result is marked as
13386 * spilt and rematerializable or code for
13387 * this has already been generated then
13389 if (resultRemat(ic) || ic->generated )
13392 /* depending on the operation */
13411 /* IPOP happens only when trying to restore a
13412 * spilt live range, if there is an ifx statement
13413 * following this pop then the if statement might
13414 * be using some of the registers being popped which
13415 * would destroy the contents of the register so
13416 * we need to check for this condition and handle it */
13418 && ic->next->op == IFX
13419 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13420 genIfx (ic->next,ic);
13438 genEndFunction (ic);
13454 pic16_genPlus (ic) ;
13458 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13459 pic16_genMinus (ic);
13475 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13479 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13485 /* note these two are xlated by algebraic equivalence
13486 * during parsing SDCC.y */
13487 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13488 "got '>=' or '<=' shouldn't have come here");
13492 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13504 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13508 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13512 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13536 genRightShift (ic);
13539 case GET_VALUE_AT_ADDRESS:
13544 if (POINTER_SET(ic))
13571 addSet(&_G.sendSet,ic);
13574 case DUMMY_READ_VOLATILE:
13584 /* now we are ready to call the
13585 peep hole optimizer */
13586 if (!options.nopeep)
13587 peepHole (&lineHead);
13589 /* now do the actual printing */
13590 printLine (lineHead, codeOutFile);
13593 DFPRINTF((stderr,"printing pBlock\n\n"));
13594 pic16_printpBlock(stdout,pb);