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 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) *
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
5173 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5175 //DEBUGpc ("generate control flow");
5176 rIfx.condition ^= 1;
5185 static void genCmp (operand *left,operand *right,
5186 operand *result, iCode *ifx, int sign)
5188 int size; //, offset = 0 ;
5189 unsigned long lit = 0L,i = 0;
5190 resolvedIfx rFalseIfx;
5191 // resolvedIfx rTrueIfx;
5193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5196 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5197 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5203 resolveIfx(&rFalseIfx,ifx);
5204 truelbl = newiTempLabel(NULL);
5205 size = max(AOP_SIZE(left),AOP_SIZE(right));
5207 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5211 /* if literal is on the right then swap with left */
5212 if ((AOP_TYPE(right) == AOP_LIT)) {
5213 operand *tmp = right ;
5214 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5215 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5218 lit = (lit - 1) & mask;
5221 rFalseIfx.condition ^= 1;
5224 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5225 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5229 //if(IC_TRUE(ifx) == NULL)
5230 /* if left & right are bit variables */
5231 if (AOP_TYPE(left) == AOP_CRY &&
5232 AOP_TYPE(right) == AOP_CRY ) {
5233 assert (0 && "bit variables used in genCmp");
5234 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5235 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5237 /* subtract right from left if at the
5238 end the carry flag is set then we know that
5239 left is greater than right */
5241 symbol *lbl = newiTempLabel(NULL);
5244 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5245 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5249 if(AOP_TYPE(right) == AOP_LIT) {
5251 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5253 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5260 genSkipCond(&rFalseIfx,left,size-1,7);
5262 /* no need to compare to 0...*/
5263 /* NOTE: this is a de-generate compare that most certainly
5264 * creates some dead code. */
5265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5267 if(ifx) ifx->generated = 1;
5274 //i = (lit >> (size*8)) & 0xff;
5275 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5277 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5279 i = ((0-lit) & 0xff);
5282 /* lit is 0x7f, all signed chars are less than
5283 * this except for 0x7f itself */
5284 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5285 genSkipz2(&rFalseIfx,0);
5287 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5288 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5289 genSkipc(&rFalseIfx);
5294 genSkipz2(&rFalseIfx,1);
5296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5297 genSkipc(&rFalseIfx);
5301 if(ifx) ifx->generated = 1;
5305 /* chars are out of the way. now do ints and longs */
5308 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5315 genSkipCond(&rFalseIfx,left,size,7);
5316 if(ifx) ifx->generated = 1;
5321 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5323 //rFalseIfx.condition ^= 1;
5324 //genSkipCond(&rFalseIfx,left,size,7);
5325 //rFalseIfx.condition ^= 1;
5327 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5328 if(rFalseIfx.condition)
5329 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5331 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5333 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5334 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5338 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5340 if(rFalseIfx.condition) {
5342 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5348 genSkipc(&rFalseIfx);
5349 pic16_emitpLabel(truelbl->key);
5350 if(ifx) ifx->generated = 1;
5357 if( (lit & 0xff) == 0) {
5358 /* lower byte is zero */
5359 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5360 i = ((lit >> 8) & 0xff) ^0x80;
5361 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5362 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5363 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5364 genSkipc(&rFalseIfx);
5367 if(ifx) ifx->generated = 1;
5372 /* Special cases for signed longs */
5373 if( (lit & 0xffffff) == 0) {
5374 /* lower byte is zero */
5375 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5376 i = ((lit >> 8*3) & 0xff) ^0x80;
5377 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5378 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5379 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5380 genSkipc(&rFalseIfx);
5383 if(ifx) ifx->generated = 1;
5391 if(lit & (0x80 << (size*8))) {
5392 /* lit is negative */
5393 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5395 //genSkipCond(&rFalseIfx,left,size,7);
5397 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5399 if(rFalseIfx.condition)
5400 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5402 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5406 /* lit is positive */
5407 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5408 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5409 if(rFalseIfx.condition)
5410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5412 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5417 This works, but is only good for ints.
5418 It also requires a "known zero" register.
5419 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5420 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5421 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5422 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5423 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5424 genSkipc(&rFalseIfx);
5426 pic16_emitpLabel(truelbl->key);
5427 if(ifx) ifx->generated = 1;
5431 /* There are no more special cases, so perform a general compare */
5433 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5434 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5438 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5440 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5442 //rFalseIfx.condition ^= 1;
5443 genSkipc(&rFalseIfx);
5445 pic16_emitpLabel(truelbl->key);
5447 if(ifx) ifx->generated = 1;
5454 /* sign is out of the way. So now do an unsigned compare */
5455 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5458 /* General case - compare to an unsigned literal on the right.*/
5460 i = (lit >> (size*8)) & 0xff;
5461 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5462 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5464 i = (lit >> (size*8)) & 0xff;
5467 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5469 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5471 /* this byte of the lit is zero,
5472 *if it's not the last then OR in the variable */
5474 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5479 pic16_emitpLabel(lbl->key);
5480 // pic16_emitpLabel(truelbl->key);
5481 //if(emitFinalCheck)
5482 genSkipc(&rFalseIfx);
5484 pic16_emitpLabel(truelbl->key);
5486 if(ifx) ifx->generated = 1;
5493 if(AOP_TYPE(left) == AOP_LIT) {
5494 //symbol *lbl = newiTempLabel(NULL);
5496 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5499 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5502 if((lit == 0) && (sign == 0)){
5505 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5507 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5509 genSkipz2(&rFalseIfx,0);
5510 if(ifx) ifx->generated = 1;
5517 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5518 /* degenerate compare can never be true */
5519 if(rFalseIfx.condition == 0)
5520 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5522 if(ifx) ifx->generated = 1;
5527 /* signed comparisons to a literal byte */
5529 int lp1 = (lit+1) & 0xff;
5531 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5534 rFalseIfx.condition ^= 1;
5535 genSkipCond(&rFalseIfx,right,0,7);
5538 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5539 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5540 genSkipz2(&rFalseIfx,1);
5543 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5544 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5545 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5546 rFalseIfx.condition ^= 1;
5547 genSkipc(&rFalseIfx);
5551 /* unsigned comparisons to a literal byte */
5553 switch(lit & 0xff ) {
5555 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556 genSkipz2(&rFalseIfx,0);
5559 rFalseIfx.condition ^= 1;
5560 genSkipCond(&rFalseIfx,right,0,7);
5564 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5565 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5566 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5567 rFalseIfx.condition ^= 1;
5568 if (AOP_TYPE(result) == AOP_CRY)
5569 genSkipc(&rFalseIfx);
5571 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5572 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5578 if(ifx) ifx->generated = 1;
5579 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5585 /* Size is greater than 1 */
5593 /* this means lit = 0xffffffff, or -1 */
5596 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5597 rFalseIfx.condition ^= 1;
5598 genSkipCond(&rFalseIfx,right,size,7);
5599 if(ifx) ifx->generated = 1;
5601 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5610 if(rFalseIfx.condition) {
5611 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5612 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5615 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5617 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5621 if(rFalseIfx.condition) {
5622 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5623 pic16_emitpLabel(truelbl->key);
5625 rFalseIfx.condition ^= 1;
5626 genSkipCond(&rFalseIfx,right,s,7);
5629 if(ifx) ifx->generated = 1;
5631 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5637 if((size == 1) && (0 == (lp1&0xff))) {
5638 /* lower byte of signed word is zero */
5639 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5640 i = ((lp1 >> 8) & 0xff) ^0x80;
5641 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5642 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5643 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5645 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5647 if(ifx) ifx->generated = 1;
5650 rFalseIfx.condition ^= 1;
5651 genSkipc(&rFalseIfx);
5652 if(ifx) ifx->generated = 1;
5658 if(lit & (0x80 << (size*8))) {
5659 /* Lit is less than zero */
5660 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5661 //rFalseIfx.condition ^= 1;
5662 //genSkipCond(&rFalseIfx,left,size,7);
5663 //rFalseIfx.condition ^= 1;
5664 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5665 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5667 if(rFalseIfx.condition)
5668 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5670 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5674 /* Lit is greater than or equal to zero */
5675 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5676 //rFalseIfx.condition ^= 1;
5677 //genSkipCond(&rFalseIfx,right,size,7);
5678 //rFalseIfx.condition ^= 1;
5680 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5681 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5683 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5684 if(rFalseIfx.condition)
5685 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5687 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5692 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5698 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5700 rFalseIfx.condition ^= 1;
5701 //rFalseIfx.condition = 1;
5702 genSkipc(&rFalseIfx);
5704 pic16_emitpLabel(truelbl->key);
5706 if(ifx) ifx->generated = 1;
5709 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5716 /* compare word or long to an unsigned literal on the right.*/
5721 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5724 break; /* handled above */
5727 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5729 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5730 genSkipz2(&rFalseIfx,0);
5734 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5736 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5739 if(rFalseIfx.condition)
5740 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5742 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5745 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5746 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5748 rFalseIfx.condition ^= 1;
5749 genSkipc(&rFalseIfx);
5752 pic16_emitpLabel(truelbl->key);
5754 if(ifx) ifx->generated = 1;
5756 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5764 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5765 i = (lit >> (size*8)) & 0xff;
5767 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5768 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5771 i = (lit >> (size*8)) & 0xff;
5774 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5778 /* this byte of the lit is zero,
5779 * if it's not the last then OR in the variable */
5781 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5786 pic16_emitpLabel(lbl->key);
5788 rFalseIfx.condition ^= 1;
5790 genSkipc(&rFalseIfx);
5794 pic16_emitpLabel(truelbl->key);
5795 if(ifx) ifx->generated = 1;
5797 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5803 /* Compare two variables */
5805 DEBUGpic16_emitcode(";sign","%d",sign);
5809 /* Sigh. thus sucks... */
5813 pctemp = pic16_popGetTempReg(1);
5814 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5815 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5816 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5817 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5818 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5819 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5820 pic16_popReleaseTempReg(pctemp, 1);
5822 /* Signed char comparison */
5823 /* Special thanks to Nikolai Golovchenko for this snippet */
5824 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5825 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5826 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5827 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5828 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5829 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5832 genSkipc(&rFalseIfx);
5834 if(ifx) ifx->generated = 1;
5836 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5844 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5845 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5849 /* The rest of the bytes of a multi-byte compare */
5853 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5856 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5862 pic16_emitpLabel(lbl->key);
5864 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5865 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5866 (AOP_TYPE(result) == AOP_REG)) {
5867 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5868 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5870 genSkipc(&rFalseIfx);
5872 //genSkipc(&rFalseIfx);
5873 if(ifx) ifx->generated = 1;
5876 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5884 if ((AOP_TYPE(result) != AOP_CRY)
5885 && AOP_SIZE(result)) {
5886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5888 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5890 pic16_outBitC(result);
5892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5893 /* if the result is used in the next
5894 ifx conditional branch then generate
5895 code a little differently */
5897 genIfxJump (ifx,"c");
5899 pic16_outBitC(result);
5900 /* leave the result in acc */
5905 #elif 0 /* VR version of genCmp() */ /* } else { */
5907 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5908 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5909 operand *result, int offset, int invert_op)
5913 /* check condition, > or < ?? */
5914 if(rIfx->condition != 0)invert_op ^= 1;
5916 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5918 if(!ifx)invert_op ^= 1;
5920 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5921 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5924 if(!invert_op)return POC_CPFSGT;
5925 else return POC_CPFSLT;
5928 static int compareAopfirstpass=1;
5930 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5931 operand *oper, int offset, operand *result,
5932 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5938 /* invert if there is a result to be loaded, in order to fit,
5939 * SETC/CLRC sequence */
5940 if(AOP_SIZE(result))invert_op ^= 1;
5942 // if(sign && !offset)invert_op ^= 1;
5944 // if(sign)invert_op ^= 1;
5946 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5948 if(AOP_SIZE(result) && compareAopfirstpass) {
5951 pic16_emitpcode(POC_SETF, pcop2);
5956 pic16_emitpcode(POC_CLRF, pcop2);
5962 compareAopfirstpass = 0;
5964 /* there is a bug when comparing operands with size > 1,
5965 * because higher bytes can be equal and test should be performed
5966 * to the next lower byte, current algorithm, considers operands
5967 * inequal in these cases! -- VR 20041107 */
5971 pic16_emitpcode(op, pcop);
5973 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5976 if((!sign || !offset) && AOP_SIZE(result)) {
5979 pic16_emitpcode(POC_CLRF, pcop2);
5984 pic16_emitpcode(POC_SETF, pcop2);
5989 /* don't emit final branch (offset == 0) */
5993 pic16_emitpcode(POC_RRCF, pcop2);
5995 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5998 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5999 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6000 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6002 truelbl = newiTempLabel( NULL );
6003 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6004 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6005 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6007 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6008 pic16_emitpLabel(truelbl->key);
6010 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6015 static void genCmp (operand *left, operand *right,
6016 operand *result, iCode *ifx, int sign)
6020 resolvedIfx rFalseIfx;
6021 symbol *falselbl, *tlbl;
6025 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6027 resolveIfx(&rFalseIfx, ifx);
6028 size = max(AOP_SIZE(left), AOP_SIZE(right));
6030 /* if left & right are bit variables */
6031 if(AOP_TYPE(left) == AOP_CRY
6032 && AOP_TYPE(right) == AOP_CRY ) {
6034 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6035 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6037 werror(W_POSSBUG2, __FILE__, __LINE__);
6041 /* if literal is on the right then swap with left */
6042 if((AOP_TYPE(right) == AOP_LIT)) {
6043 operand *tmp = right ;
6044 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6046 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6048 // lit = (lit - 1) & mask;
6051 rFalseIfx.condition ^= 1; /* reverse compare */
6053 if ((AOP_TYPE(left) == AOP_LIT)) {
6054 /* float compares are handled by support functions */
6055 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6058 /* actual comparing algorithm */
6059 // size = AOP_SIZE( right );
6061 falselbl = newiTempLabel( NULL );
6062 if(AOP_TYPE(left) == AOP_LIT) {
6063 /* compare to literal */
6064 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6067 pCodeOp *pct, *pct2;
6070 /* signed compare */
6071 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6073 pct = pic16_popCopyReg(&pic16_pc_prodl);
6074 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6075 tlbl = newiTempLabel( NULL );
6077 /* first compare signs:
6078 * a. if both are positive, compare just like unsigned
6079 * b. if both are negative, invert cmpop, compare just like unsigned
6080 * c. if different signs, determine the result directly */
6086 tlbl1 = newiTempLabel( NULL );
6087 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6091 /* literal is zero or positive:
6092 * a. if carry is zero, too, continue compare,
6093 * b. if carry is set, then continue depending on cmpop ^ condition:
6094 * 1. '<' return false (literal < variable),
6095 * 2. '>' return true (literal > variable) */
6096 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6097 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6100 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6101 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6105 /* literal is negative:
6106 * a. if carry is set, too, continue compare,
6107 * b. if carry is zero, then continue depending on cmpop ^ condition:
6108 * 1. '<' return true (literal < variable),
6109 * 2. '>' return false (literal > variable) */
6110 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6111 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6113 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6119 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6121 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6122 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6127 pic16_emitpLabel( tlbl1->key );
6130 compareAopfirstpass=1;
6131 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6132 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6133 // pic16_emitpcode(POC_MOVWF, pct);
6135 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6136 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6137 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6138 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6142 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6143 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6144 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6145 // pic16_emitpcode(POC_MOVWF, pct);
6147 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6148 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6149 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6150 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6155 if(ifx)ifx->generated = 1;
6157 if(AOP_SIZE(result)) {
6158 pic16_emitpLabel(tlbl->key);
6159 pic16_emitpLabel(falselbl->key);
6160 pic16_outBitOp( result, pct2 );
6162 pic16_emitpLabel(tlbl->key);
6167 /* unsigned compare */
6168 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6170 compareAopfirstpass=1;
6173 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6174 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6178 if(ifx)ifx->generated = 1;
6181 if(AOP_SIZE(result)) {
6182 pic16_emitpLabel(falselbl->key);
6183 pic16_outBitC( result );
6188 /* compare registers */
6189 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6193 pCodeOp *pct, *pct2;
6195 /* signed compare */
6196 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6198 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6199 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6200 tlbl = newiTempLabel( NULL );
6202 compareAopfirstpass=1;
6205 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6206 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6207 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6208 pic16_emitpcode(POC_MOVWF, pct);
6210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6211 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214 /* WREG already holds left + 0x80 */
6215 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6219 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6220 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6221 pic16_emitpcode(POC_MOVWF, pct);
6223 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6224 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6225 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6227 /* WREG already holds left + 0x80 */
6228 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6229 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6232 if(ifx)ifx->generated = 1;
6234 if(AOP_SIZE(result)) {
6235 pic16_emitpLabel(tlbl->key);
6236 pic16_emitpLabel(falselbl->key);
6237 pic16_outBitOp( result, pct2 );
6239 pic16_emitpLabel(tlbl->key);
6243 /* unsigned compare */
6244 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6246 compareAopfirstpass=1;
6249 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6250 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6254 if(ifx)ifx->generated = 1;
6255 if(AOP_SIZE(result)) {
6257 pic16_emitpLabel(falselbl->key);
6258 pic16_outBitC( result );
6269 /*-----------------------------------------------------------------*/
6270 /* genCmpGt :- greater than comparison */
6271 /*-----------------------------------------------------------------*/
6272 static void genCmpGt (iCode *ic, iCode *ifx)
6274 operand *left, *right, *result;
6275 sym_link *letype , *retype;
6281 right= IC_RIGHT(ic);
6282 result = IC_RESULT(ic);
6284 letype = getSpec(operandType(left));
6285 retype =getSpec(operandType(right));
6286 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6287 /* assign the amsops */
6288 pic16_aopOp (left,ic,FALSE);
6289 pic16_aopOp (right,ic,FALSE);
6290 pic16_aopOp (result,ic,TRUE);
6292 genCmp(right, left, result, ifx, sign);
6294 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296 pic16_freeAsmop(result,NULL,ic,TRUE);
6299 /*-----------------------------------------------------------------*/
6300 /* genCmpLt - less than comparisons */
6301 /*-----------------------------------------------------------------*/
6302 static void genCmpLt (iCode *ic, iCode *ifx)
6304 operand *left, *right, *result;
6305 sym_link *letype , *retype;
6311 right= IC_RIGHT(ic);
6312 result = IC_RESULT(ic);
6314 letype = getSpec(operandType(left));
6315 retype =getSpec(operandType(right));
6316 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6318 /* assign the amsops */
6319 pic16_aopOp (left,ic,FALSE);
6320 pic16_aopOp (right,ic,FALSE);
6321 pic16_aopOp (result,ic,TRUE);
6323 genCmp(left, right, result, ifx, sign);
6325 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6327 pic16_freeAsmop(result,NULL,ic,TRUE);
6332 // FIXME reenable literal optimisation when the pic16 port is stable
6334 /*-----------------------------------------------------------------*/
6335 /* genc16bit2lit - compare a 16 bit value to a literal */
6336 /*-----------------------------------------------------------------*/
6337 static void genc16bit2lit(operand *op, int lit, int offset)
6341 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6342 if( (lit&0xff) == 0)
6347 switch( BYTEofLONG(lit,i)) {
6349 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6352 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6355 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6358 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6364 switch( BYTEofLONG(lit,i)) {
6366 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6370 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6374 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6377 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6379 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6388 /*-----------------------------------------------------------------*/
6389 /* gencjneshort - compare and jump if not equal */
6390 /*-----------------------------------------------------------------*/
6391 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6393 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6395 int res_offset = 0; /* the result may be a different size then left or right */
6396 int res_size = AOP_SIZE(result);
6398 symbol *lbl, *lbl_done;
6400 unsigned long lit = 0L;
6401 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6404 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6406 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6407 resolveIfx(&rIfx,ifx);
6408 lbl = newiTempLabel(NULL);
6409 lbl_done = newiTempLabel(NULL);
6412 /* if the left side is a literal or
6413 if the right is in a pointer register and left
6415 if ((AOP_TYPE(left) == AOP_LIT) ||
6416 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6421 if(AOP_TYPE(right) == AOP_LIT)
6422 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6424 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6425 preserve_result = 1;
6427 if(result && !preserve_result)
6430 for(i = 0; i < AOP_SIZE(result); i++)
6431 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6435 /* if the right side is a literal then anything goes */
6436 if (AOP_TYPE(right) == AOP_LIT &&
6437 AOP_TYPE(left) != AOP_DIR ) {
6440 genc16bit2lit(left, lit, 0);
6442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6448 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6451 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6457 if(res_offset < res_size-1)
6465 /* if the right side is in a register or in direct space or
6466 if the left is a pointer register & right is not */
6467 else if (AOP_TYPE(right) == AOP_REG ||
6468 AOP_TYPE(right) == AOP_DIR ||
6469 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6470 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6471 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6472 int lbl_key = lbl->key;
6475 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6476 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6478 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6479 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6480 __FUNCTION__,__LINE__);
6484 /* switch(size) { */
6486 /* genc16bit2lit(left, lit, 0); */
6488 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6493 if((AOP_TYPE(left) == AOP_DIR) &&
6494 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6496 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6499 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6501 switch (lit & 0xff) {
6503 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6507 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6512 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6519 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6525 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6528 if(AOP_TYPE(result) == AOP_CRY) {
6529 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6534 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6536 /* fix me. probably need to check result size too */
6537 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6542 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6543 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6550 if(res_offset < res_size-1)
6555 } else if(AOP_TYPE(right) == AOP_REG &&
6556 AOP_TYPE(left) != AOP_DIR){
6559 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6560 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6561 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6566 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6568 if(res_offset < res_size-1)
6573 /* right is a pointer reg need both a & b */
6575 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6577 pic16_emitcode("mov","b,%s",l);
6578 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6579 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6584 if(result && preserve_result)
6587 for(i = 0; i < AOP_SIZE(result); i++)
6588 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6591 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6593 if(result && preserve_result)
6594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6599 pic16_emitpLabel(lbl->key);
6601 if(result && preserve_result)
6604 for(i = 0; i < AOP_SIZE(result); i++)
6605 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6607 pic16_emitpLabel(lbl_done->key);
6610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6618 /*-----------------------------------------------------------------*/
6619 /* gencjne - compare and jump if not equal */
6620 /*-----------------------------------------------------------------*/
6621 static void gencjne(operand *left, operand *right, iCode *ifx)
6623 symbol *tlbl = newiTempLabel(NULL);
6625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6626 gencjneshort(left, right, lbl);
6628 pic16_emitcode("mov","a,%s",one);
6629 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6630 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6631 pic16_emitcode("clr","a");
6632 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6634 pic16_emitpLabel(lbl->key);
6635 pic16_emitpLabel(tlbl->key);
6641 /*-----------------------------------------------------------------*/
6642 /* is_LitOp - check if operand has to be treated as literal */
6643 /*-----------------------------------------------------------------*/
6644 static bool is_LitOp(operand *op)
6646 return ((AOP_TYPE(op) == AOP_LIT)
6647 || ( (AOP_TYPE(op) == AOP_PCODE)
6648 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6649 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6652 /*-----------------------------------------------------------------*/
6653 /* is_LitAOp - check if operand has to be treated as literal */
6654 /*-----------------------------------------------------------------*/
6655 static bool is_LitAOp(asmop *aop)
6657 return ((aop->type == AOP_LIT)
6658 || ( (aop->type == AOP_PCODE)
6659 && ( (aop->aopu.pcop->type == PO_LITERAL)
6660 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6665 /*-----------------------------------------------------------------*/
6666 /* genCmpEq - generates code for equal to */
6667 /*-----------------------------------------------------------------*/
6668 static void genCmpEq (iCode *ic, iCode *ifx)
6670 operand *left, *right, *result;
6671 symbol *falselbl = newiTempLabel(NULL);
6672 symbol *donelbl = newiTempLabel(NULL);
6674 int preserve_result = 0;
6675 int generate_result = 0;
6677 unsigned long lit = -1;
6681 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6682 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6683 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6685 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6687 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6689 werror(W_POSSBUG2, __FILE__, __LINE__);
6690 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6691 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6695 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6697 operand *tmp = right ;
6702 if (AOP_TYPE(right) == AOP_LIT) {
6703 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6706 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6707 preserve_result = 1;
6709 if(result && AOP_SIZE(result))
6710 generate_result = 1;
6712 if(generate_result && !preserve_result)
6714 for(i = 0; i < AOP_SIZE(result); i++)
6715 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6718 for(i=0; i < AOP_SIZE(left); i++)
6720 if(AOP_TYPE(left) != AOP_ACC)
6723 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6725 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6727 if(is_LitOp(right)) {
6728 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6729 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6732 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6734 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6739 if(generate_result && preserve_result)
6741 for(i = 0; i < AOP_SIZE(result); i++)
6742 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6746 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6748 if(generate_result && preserve_result)
6749 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6751 if(ifx && IC_TRUE(ifx))
6752 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6754 if(ifx && IC_FALSE(ifx))
6755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6757 pic16_emitpLabel(falselbl->key);
6761 if(ifx && IC_FALSE(ifx))
6762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6764 if(generate_result && preserve_result)
6766 for(i = 0; i < AOP_SIZE(result); i++)
6767 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6770 pic16_emitpLabel(donelbl->key);
6776 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6777 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6778 pic16_freeAsmop(result,NULL,ic,TRUE);
6784 // old version kept for reference
6786 /*-----------------------------------------------------------------*/
6787 /* genCmpEq - generates code for equal to */
6788 /*-----------------------------------------------------------------*/
6789 static void genCmpEq (iCode *ic, iCode *ifx)
6791 operand *left, *right, *result;
6792 unsigned long lit = 0L;
6794 symbol *falselbl = newiTempLabel(NULL);
6797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6800 DEBUGpic16_emitcode ("; ifx is non-null","");
6802 DEBUGpic16_emitcode ("; ifx is null","");
6804 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6805 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6806 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6808 size = max(AOP_SIZE(left),AOP_SIZE(right));
6810 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6812 /* if literal, literal on the right or
6813 if the right is in a pointer register and left
6815 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6816 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6817 operand *tmp = right ;
6823 if(ifx && !AOP_SIZE(result)){
6825 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6826 /* if they are both bit variables */
6827 if (AOP_TYPE(left) == AOP_CRY &&
6828 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6829 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6830 if(AOP_TYPE(right) == AOP_LIT){
6831 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6833 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6834 pic16_emitcode("cpl","c");
6835 } else if(lit == 1L) {
6836 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838 pic16_emitcode("clr","c");
6840 /* AOP_TYPE(right) == AOP_CRY */
6842 symbol *lbl = newiTempLabel(NULL);
6843 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6845 pic16_emitcode("cpl","c");
6846 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6848 /* if true label then we jump if condition
6850 tlbl = newiTempLabel(NULL);
6851 if ( IC_TRUE(ifx) ) {
6852 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6853 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6855 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6856 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6858 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6861 /* left and right are both bit variables, result is carry */
6864 resolveIfx(&rIfx,ifx);
6866 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6867 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6868 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6869 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6874 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6876 /* They're not both bit variables. Is the right a literal? */
6877 if(AOP_TYPE(right) == AOP_LIT) {
6878 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6883 switch(lit & 0xff) {
6885 if ( IC_TRUE(ifx) ) {
6886 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6888 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6890 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6895 if ( IC_TRUE(ifx) ) {
6896 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6900 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6905 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6907 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6912 /* end of size == 1 */
6916 genc16bit2lit(left,lit,offset);
6919 /* end of size == 2 */
6924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6925 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6926 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6927 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6930 /* search for patterns that can be optimized */
6932 genc16bit2lit(left,lit,0);
6936 emitSKPZ; // if hi word unequal
6938 emitSKPNZ; // if hi word equal
6940 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6941 genc16bit2lit(left,lit,2);
6944 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6945 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6949 pic16_emitpLabel(falselbl->key);
6958 } else if(AOP_TYPE(right) == AOP_CRY ) {
6959 /* we know the left is not a bit, but that the right is */
6960 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6961 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6962 pic16_popGet(AOP(right),offset));
6963 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6965 /* if the two are equal, then W will be 0 and the Z bit is set
6966 * we could test Z now, or go ahead and check the high order bytes if
6967 * the variable we're comparing is larger than a byte. */
6970 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6972 if ( IC_TRUE(ifx) ) {
6974 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6975 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6978 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6979 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6983 /* They're both variables that are larger than bits */
6986 tlbl = newiTempLabel(NULL);
6989 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6990 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6992 if ( IC_TRUE(ifx) ) {
6996 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6999 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7003 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7006 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7007 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7012 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7015 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7019 if(s>1 && IC_TRUE(ifx)) {
7020 pic16_emitpLabel(tlbl->key);
7021 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7025 /* mark the icode as generated */
7030 /* if they are both bit variables */
7031 if (AOP_TYPE(left) == AOP_CRY &&
7032 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7033 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7034 if(AOP_TYPE(right) == AOP_LIT){
7035 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7037 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7038 pic16_emitcode("cpl","c");
7039 } else if(lit == 1L) {
7040 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042 pic16_emitcode("clr","c");
7044 /* AOP_TYPE(right) == AOP_CRY */
7046 symbol *lbl = newiTempLabel(NULL);
7047 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7049 pic16_emitcode("cpl","c");
7050 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7053 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7054 pic16_outBitC(result);
7058 genIfxJump (ifx,"c");
7061 /* if the result is used in an arithmetic operation
7062 then put the result in place */
7063 pic16_outBitC(result);
7066 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7067 gencjne(left,right,result,ifx);
7070 gencjne(left,right,newiTempLabel(NULL));
7072 if(IC_TRUE(ifx)->key)
7073 gencjne(left,right,IC_TRUE(ifx)->key);
7075 gencjne(left,right,IC_FALSE(ifx)->key);
7079 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7080 pic16_aopPut(AOP(result),"a",0);
7085 genIfxJump (ifx,"a");
7089 /* if the result is used in an arithmetic operation
7090 then put the result in place */
7092 if (AOP_TYPE(result) != AOP_CRY)
7093 pic16_outAcc(result);
7095 /* leave the result in acc */
7099 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101 pic16_freeAsmop(result,NULL,ic,TRUE);
7105 /*-----------------------------------------------------------------*/
7106 /* ifxForOp - returns the icode containing the ifx for operand */
7107 /*-----------------------------------------------------------------*/
7108 static iCode *ifxForOp ( operand *op, iCode *ic )
7112 /* if true symbol then needs to be assigned */
7113 if (IS_TRUE_SYMOP(op))
7116 /* if this has register type condition and
7117 the next instruction is ifx with the same operand
7118 and live to of the operand is upto the ifx only then */
7120 && ic->next->op == IFX
7121 && IC_COND(ic->next)->key == op->key
7122 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7124 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7130 ic->next->op == IFX &&
7131 IC_COND(ic->next)->key == op->key) {
7132 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7137 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7139 ic->next->op == IFX)
7140 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7143 ic->next->op == IFX &&
7144 IC_COND(ic->next)->key == op->key) {
7145 DEBUGpic16_emitcode ("; "," key is okay");
7146 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7147 OP_SYMBOL(op)->liveTo,
7152 /* the code below is completely untested
7153 * it just allows ulong2fs.c compile -- VR */
7156 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7157 __FILE__, __FUNCTION__, __LINE__);
7159 /* if this has register type condition and
7160 the next instruction is ifx with the same operand
7161 and live to of the operand is upto the ifx only then */
7163 ic->next->op == IFX &&
7164 IC_COND(ic->next)->key == op->key &&
7165 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7169 ic->next->op == IFX &&
7170 IC_COND(ic->next)->key == op->key) {
7171 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7175 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7176 __FILE__, __FUNCTION__, __LINE__);
7178 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7183 /*-----------------------------------------------------------------*/
7184 /* genAndOp - for && operation */
7185 /*-----------------------------------------------------------------*/
7186 static void genAndOp (iCode *ic)
7188 operand *left,*right, *result;
7193 /* note here that && operations that are in an
7194 if statement are taken away by backPatchLabels
7195 only those used in arthmetic operations remain */
7196 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7197 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7198 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7200 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7202 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7203 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7204 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7206 /* if both are bit variables */
7207 /* if (AOP_TYPE(left) == AOP_CRY && */
7208 /* AOP_TYPE(right) == AOP_CRY ) { */
7209 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7210 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7211 /* pic16_outBitC(result); */
7213 /* tlbl = newiTempLabel(NULL); */
7214 /* pic16_toBoolean(left); */
7215 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7216 /* pic16_toBoolean(right); */
7217 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7218 /* pic16_outBitAcc(result); */
7221 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7222 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7223 pic16_freeAsmop(result,NULL,ic,TRUE);
7227 /*-----------------------------------------------------------------*/
7228 /* genOrOp - for || operation */
7229 /*-----------------------------------------------------------------*/
7232 modified this code, but it doesn't appear to ever get called
7235 static void genOrOp (iCode *ic)
7237 operand *left,*right, *result;
7242 /* note here that || operations that are in an
7243 if statement are taken away by backPatchLabels
7244 only those used in arthmetic operations remain */
7245 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7246 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7247 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7249 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7251 /* if both are bit variables */
7252 if (AOP_TYPE(left) == AOP_CRY &&
7253 AOP_TYPE(right) == AOP_CRY ) {
7254 pic16_emitcode("clrc","");
7255 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7256 AOP(left)->aopu.aop_dir,
7257 AOP(left)->aopu.aop_dir);
7258 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7259 AOP(right)->aopu.aop_dir,
7260 AOP(right)->aopu.aop_dir);
7261 pic16_emitcode("setc","");
7264 tlbl = newiTempLabel(NULL);
7265 pic16_toBoolean(left);
7267 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7268 pic16_toBoolean(right);
7269 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7271 pic16_outBitAcc(result);
7274 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7275 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7276 pic16_freeAsmop(result,NULL,ic,TRUE);
7279 /*-----------------------------------------------------------------*/
7280 /* isLiteralBit - test if lit == 2^n */
7281 /*-----------------------------------------------------------------*/
7282 static int isLiteralBit(unsigned long lit)
7284 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7285 0x100L,0x200L,0x400L,0x800L,
7286 0x1000L,0x2000L,0x4000L,0x8000L,
7287 0x10000L,0x20000L,0x40000L,0x80000L,
7288 0x100000L,0x200000L,0x400000L,0x800000L,
7289 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7290 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7293 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7294 for(idx = 0; idx < 32; idx++)
7300 /*-----------------------------------------------------------------*/
7301 /* continueIfTrue - */
7302 /*-----------------------------------------------------------------*/
7303 static void continueIfTrue (iCode *ic)
7307 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7311 /*-----------------------------------------------------------------*/
7313 /*-----------------------------------------------------------------*/
7314 static void jumpIfTrue (iCode *ic)
7318 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7322 /*-----------------------------------------------------------------*/
7323 /* jmpTrueOrFalse - */
7324 /*-----------------------------------------------------------------*/
7325 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7327 // ugly but optimized by peephole
7330 symbol *nlbl = newiTempLabel(NULL);
7331 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7332 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7333 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7334 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7336 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7337 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7342 /*-----------------------------------------------------------------*/
7343 /* genAnd - code for and */
7344 /*-----------------------------------------------------------------*/
7345 static void genAnd (iCode *ic, iCode *ifx)
7347 operand *left, *right, *result;
7349 unsigned long lit = 0L;
7355 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7356 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7357 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7359 resolveIfx(&rIfx,ifx);
7361 /* if left is a literal & right is not then exchange them */
7362 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7363 AOP_NEEDSACC(left)) {
7364 operand *tmp = right ;
7369 /* if result = right then exchange them */
7370 if(pic16_sameRegs(AOP(result),AOP(right))){
7371 operand *tmp = right ;
7376 /* if right is bit then exchange them */
7377 if (AOP_TYPE(right) == AOP_CRY &&
7378 AOP_TYPE(left) != AOP_CRY){
7379 operand *tmp = right ;
7383 if(AOP_TYPE(right) == AOP_LIT)
7384 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7386 size = AOP_SIZE(result);
7388 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7391 // result = bit & yy;
7392 if (AOP_TYPE(left) == AOP_CRY){
7393 // c = bit & literal;
7394 if(AOP_TYPE(right) == AOP_LIT){
7396 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7399 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7402 if(size && (AOP_TYPE(result) == AOP_CRY)){
7403 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7406 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7410 pic16_emitcode("clr","c");
7413 if (AOP_TYPE(right) == AOP_CRY){
7415 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7416 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7419 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7421 pic16_emitcode("rrc","a");
7422 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7428 pic16_outBitC(result);
7430 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7431 genIfxJump(ifx, "c");
7435 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7436 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7437 if((AOP_TYPE(right) == AOP_LIT) &&
7438 (AOP_TYPE(result) == AOP_CRY) &&
7439 (AOP_TYPE(left) != AOP_CRY)){
7440 int posbit = isLiteralBit(lit);
7444 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7447 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7453 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7454 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7456 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7460 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7461 size = AOP_SIZE(left);
7464 int bp = posbit, ofs=0;
7471 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7472 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7476 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7477 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7479 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7486 symbol *tlbl = newiTempLabel(NULL);
7487 int sizel = AOP_SIZE(left);
7493 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7495 /* patch provided by Aaron Colwell */
7496 if((posbit = isLiteralBit(bytelit)) != 0) {
7497 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7498 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7499 (posbit-1),0, PO_GPR_REGISTER));
7501 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7502 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7504 if (bytelit == 0xff) {
7505 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7506 * a peephole could optimize it out -- VR */
7507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7509 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7510 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7513 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7514 pic16_popGetLabel(tlbl->key));
7518 /* old code, left here for reference -- VR 09/2004 */
7519 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7521 if((posbit = isLiteralBit(bytelit)) != 0)
7522 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7524 if(bytelit != 0x0FFL)
7525 pic16_emitcode("anl","a,%s",
7526 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7527 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7533 // bit = left & literal
7536 pic16_emitpLabel(tlbl->key);
7538 // if(left & literal)
7541 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7544 pic16_emitpLabel(tlbl->key);
7549 pic16_outBitC(result);
7553 /* if left is same as result */
7554 if(pic16_sameRegs(AOP(result),AOP(left))){
7556 for(;size--; offset++,lit>>=8) {
7557 if(AOP_TYPE(right) == AOP_LIT){
7558 switch(lit & 0xff) {
7560 /* and'ing with 0 has clears the result */
7561 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7562 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7565 /* and'ing with 0xff is a nop when the result and left are the same */
7570 int p = pic16_my_powof2( (~lit) & 0xff );
7572 /* only one bit is set in the literal, so use a bcf instruction */
7573 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7574 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7577 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7578 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7579 if(know_W != (lit&0xff))
7580 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7582 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7587 if (AOP_TYPE(left) == AOP_ACC) {
7588 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7590 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7591 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7598 // left & result in different registers
7599 if(AOP_TYPE(result) == AOP_CRY){
7601 // if(size), result in bit
7602 // if(!size && ifx), conditional oper: if(left & right)
7603 symbol *tlbl = newiTempLabel(NULL);
7604 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7606 pic16_emitcode("setb","c");
7608 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7609 pic16_emitcode("anl","a,%s",
7610 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7611 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7616 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7617 pic16_outBitC(result);
7619 jmpTrueOrFalse(ifx, tlbl);
7621 for(;(size--);offset++) {
7623 // result = left & right
7624 if(AOP_TYPE(right) == AOP_LIT){
7625 int t = (lit >> (offset*8)) & 0x0FFL;
7628 pic16_emitcode("clrf","%s",
7629 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7630 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7633 pic16_emitcode("movf","%s,w",
7634 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7635 pic16_emitcode("movwf","%s",
7636 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7637 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7638 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7641 pic16_emitcode("movlw","0x%x",t);
7642 pic16_emitcode("andwf","%s,w",
7643 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7644 pic16_emitcode("movwf","%s",
7645 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7648 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7649 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7654 if (AOP_TYPE(left) == AOP_ACC) {
7655 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7656 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7658 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7659 pic16_emitcode("andwf","%s,w",
7660 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7661 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7662 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7664 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7665 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7671 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7672 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7673 pic16_freeAsmop(result,NULL,ic,TRUE);
7676 /*-----------------------------------------------------------------*/
7677 /* genOr - code for or */
7678 /*-----------------------------------------------------------------*/
7679 static void genOr (iCode *ic, iCode *ifx)
7681 operand *left, *right, *result;
7683 unsigned long lit = 0L;
7685 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7687 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7688 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7689 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7691 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7693 /* if left is a literal & right is not then exchange them */
7694 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7695 AOP_NEEDSACC(left)) {
7696 operand *tmp = right ;
7701 /* if result = right then exchange them */
7702 if(pic16_sameRegs(AOP(result),AOP(right))){
7703 operand *tmp = right ;
7708 /* if right is bit then exchange them */
7709 if (AOP_TYPE(right) == AOP_CRY &&
7710 AOP_TYPE(left) != AOP_CRY){
7711 operand *tmp = right ;
7716 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7718 if(AOP_TYPE(right) == AOP_LIT)
7719 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7721 size = AOP_SIZE(result);
7725 if (AOP_TYPE(left) == AOP_CRY){
7726 if(AOP_TYPE(right) == AOP_LIT){
7727 // c = bit & literal;
7729 // lit != 0 => result = 1
7730 if(AOP_TYPE(result) == AOP_CRY){
7732 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7733 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7734 // AOP(result)->aopu.aop_dir,
7735 // AOP(result)->aopu.aop_dir);
7737 continueIfTrue(ifx);
7741 // lit == 0 => result = left
7742 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7744 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7747 if (AOP_TYPE(right) == AOP_CRY){
7748 if(pic16_sameRegs(AOP(result),AOP(left))){
7750 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7751 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7752 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7754 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7755 AOP(result)->aopu.aop_dir,
7756 AOP(result)->aopu.aop_dir);
7757 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7758 AOP(right)->aopu.aop_dir,
7759 AOP(right)->aopu.aop_dir);
7760 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7761 AOP(result)->aopu.aop_dir,
7762 AOP(result)->aopu.aop_dir);
7764 if( AOP_TYPE(result) == AOP_ACC) {
7765 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7766 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7767 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7768 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7772 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7773 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7774 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7775 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7777 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7778 AOP(result)->aopu.aop_dir,
7779 AOP(result)->aopu.aop_dir);
7780 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7781 AOP(right)->aopu.aop_dir,
7782 AOP(right)->aopu.aop_dir);
7783 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7784 AOP(left)->aopu.aop_dir,
7785 AOP(left)->aopu.aop_dir);
7786 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7787 AOP(result)->aopu.aop_dir,
7788 AOP(result)->aopu.aop_dir);
7793 symbol *tlbl = newiTempLabel(NULL);
7794 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7797 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7798 if( AOP_TYPE(right) == AOP_ACC) {
7799 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7801 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7802 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7807 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7808 pic16_emitcode(";XXX setb","c");
7809 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7810 AOP(left)->aopu.aop_dir,tlbl->key+100);
7811 pic16_toBoolean(right);
7812 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7813 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7814 jmpTrueOrFalse(ifx, tlbl);
7818 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7825 pic16_outBitC(result);
7827 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7828 genIfxJump(ifx, "c");
7832 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7833 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7834 if((AOP_TYPE(right) == AOP_LIT) &&
7835 (AOP_TYPE(result) == AOP_CRY) &&
7836 (AOP_TYPE(left) != AOP_CRY)){
7838 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7841 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7843 continueIfTrue(ifx);
7846 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847 // lit = 0, result = boolean(left)
7849 pic16_emitcode(";XXX setb","c");
7850 pic16_toBoolean(right);
7852 symbol *tlbl = newiTempLabel(NULL);
7853 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7855 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7857 genIfxJump (ifx,"a");
7861 pic16_outBitC(result);
7865 /* if left is same as result */
7866 if(pic16_sameRegs(AOP(result),AOP(left))){
7868 for(;size--; offset++,lit>>=8) {
7869 if(AOP_TYPE(right) == AOP_LIT){
7870 if((lit & 0xff) == 0)
7871 /* or'ing with 0 has no effect */
7874 int p = pic16_my_powof2(lit & 0xff);
7876 /* only one bit is set in the literal, so use a bsf instruction */
7877 pic16_emitpcode(POC_BSF,
7878 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7880 if(know_W != (lit & 0xff))
7881 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7882 know_W = lit & 0xff;
7883 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7888 if (AOP_TYPE(left) == AOP_ACC) {
7889 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7890 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7892 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7893 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7895 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7896 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7902 // left & result in different registers
7903 if(AOP_TYPE(result) == AOP_CRY){
7905 // if(size), result in bit
7906 // if(!size && ifx), conditional oper: if(left | right)
7907 symbol *tlbl = newiTempLabel(NULL);
7908 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7909 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7913 pic16_emitcode(";XXX setb","c");
7915 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7916 pic16_emitcode(";XXX orl","a,%s",
7917 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7918 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7923 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7924 pic16_outBitC(result);
7926 jmpTrueOrFalse(ifx, tlbl);
7927 } else for(;(size--);offset++){
7929 // result = left & right
7930 if(AOP_TYPE(right) == AOP_LIT){
7931 int t = (lit >> (offset*8)) & 0x0FFL;
7934 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7937 pic16_emitcode("movf","%s,w",
7938 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7939 pic16_emitcode("movwf","%s",
7940 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7943 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7944 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7947 pic16_emitcode("movlw","0x%x",t);
7948 pic16_emitcode("iorwf","%s,w",
7949 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7950 pic16_emitcode("movwf","%s",
7951 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7957 // faster than result <- left, anl result,right
7958 // and better if result is SFR
7959 if (AOP_TYPE(left) == AOP_ACC) {
7960 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7961 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7963 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7964 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7966 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7967 pic16_emitcode("iorwf","%s,w",
7968 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7970 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7971 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7976 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7977 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7978 pic16_freeAsmop(result,NULL,ic,TRUE);
7981 /*-----------------------------------------------------------------*/
7982 /* genXor - code for xclusive or */
7983 /*-----------------------------------------------------------------*/
7984 static void genXor (iCode *ic, iCode *ifx)
7986 operand *left, *right, *result;
7988 unsigned long lit = 0L;
7990 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7992 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7993 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7994 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7996 /* if left is a literal & right is not ||
7997 if left needs acc & right does not */
7998 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7999 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8000 operand *tmp = right ;
8005 /* if result = right then exchange them */
8006 if(pic16_sameRegs(AOP(result),AOP(right))){
8007 operand *tmp = right ;
8012 /* if right is bit then exchange them */
8013 if (AOP_TYPE(right) == AOP_CRY &&
8014 AOP_TYPE(left) != AOP_CRY){
8015 operand *tmp = right ;
8019 if(AOP_TYPE(right) == AOP_LIT)
8020 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8022 size = AOP_SIZE(result);
8026 if (AOP_TYPE(left) == AOP_CRY){
8027 if(AOP_TYPE(right) == AOP_LIT){
8028 // c = bit & literal;
8030 // lit>>1 != 0 => result = 1
8031 if(AOP_TYPE(result) == AOP_CRY){
8033 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8034 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8036 continueIfTrue(ifx);
8039 pic16_emitcode("setb","c");
8043 // lit == 0, result = left
8044 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8046 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8048 // lit == 1, result = not(left)
8049 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8050 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8051 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8052 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8055 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8056 pic16_emitcode("cpl","c");
8063 symbol *tlbl = newiTempLabel(NULL);
8064 if (AOP_TYPE(right) == AOP_CRY){
8066 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8069 int sizer = AOP_SIZE(right);
8071 // if val>>1 != 0, result = 1
8072 pic16_emitcode("setb","c");
8074 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8076 // test the msb of the lsb
8077 pic16_emitcode("anl","a,#0xfe");
8078 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8082 pic16_emitcode("rrc","a");
8084 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8085 pic16_emitcode("cpl","c");
8086 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8091 pic16_outBitC(result);
8093 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8094 genIfxJump(ifx, "c");
8098 if(pic16_sameRegs(AOP(result),AOP(left))){
8099 /* if left is same as result */
8100 for(;size--; offset++) {
8101 if(AOP_TYPE(right) == AOP_LIT){
8102 int t = (lit >> (offset*8)) & 0x0FFL;
8106 if (IS_AOP_PREG(left)) {
8107 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8108 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8109 pic16_aopPut(AOP(result),"a",offset);
8111 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8112 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8113 pic16_emitcode("xrl","%s,%s",
8114 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8115 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118 if (AOP_TYPE(left) == AOP_ACC)
8119 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8121 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8122 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8124 if (IS_AOP_PREG(left)) {
8125 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8126 pic16_aopPut(AOP(result),"a",offset);
8128 pic16_emitcode("xrl","%s,a",
8129 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8135 // left & result in different registers
8136 if(AOP_TYPE(result) == AOP_CRY){
8138 // if(size), result in bit
8139 // if(!size && ifx), conditional oper: if(left ^ right)
8140 symbol *tlbl = newiTempLabel(NULL);
8141 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8143 pic16_emitcode("setb","c");
8145 if((AOP_TYPE(right) == AOP_LIT) &&
8146 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8147 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8149 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8150 pic16_emitcode("xrl","a,%s",
8151 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8158 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8159 pic16_outBitC(result);
8161 jmpTrueOrFalse(ifx, tlbl);
8162 } else for(;(size--);offset++){
8164 // result = left & right
8165 if(AOP_TYPE(right) == AOP_LIT){
8166 int t = (lit >> (offset*8)) & 0x0FFL;
8169 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8170 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8171 pic16_emitcode("movf","%s,w",
8172 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173 pic16_emitcode("movwf","%s",
8174 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8177 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179 pic16_emitcode("comf","%s,w",
8180 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181 pic16_emitcode("movwf","%s",
8182 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8186 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8187 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8188 pic16_emitcode("movlw","0x%x",t);
8189 pic16_emitcode("xorwf","%s,w",
8190 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191 pic16_emitcode("movwf","%s",
8192 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8198 // faster than result <- left, anl result,right
8199 // and better if result is SFR
8200 if (AOP_TYPE(left) == AOP_ACC) {
8201 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8202 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8204 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8205 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8206 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8207 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8209 if ( AOP_TYPE(result) != AOP_ACC){
8210 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8211 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8217 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8218 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8219 pic16_freeAsmop(result,NULL,ic,TRUE);
8222 /*-----------------------------------------------------------------*/
8223 /* genInline - write the inline code out */
8224 /*-----------------------------------------------------------------*/
8225 static void genInline (iCode *ic)
8227 char *buffer, *bp, *bp1;
8230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8232 _G.inLine += (!options.asmpeep);
8234 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8235 strcpy(buffer,IC_INLINE(ic));
8237 while((bp1=strstr(bp, "\\n"))) {
8244 cbuf = Safe_strdup( buffer );
8252 cbuf = Safe_strdup(buffer);
8253 cblen = strlen(buffer)+1;
8254 memset(cbuf, 0, cblen);
8259 if(*bp != '%')*bp1++ = *bp++;
8265 if(i>elementsInSet(asmInlineMap))break;
8268 s = indexSet(asmInlineMap, i);
8269 DEBUGpc("searching symbol s = `%s'", s);
8270 sym = findSym(SymbolTab, NULL, s);
8273 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8275 strcat(bp1, sym->rname);
8281 if(strlen(bp1) > cblen - 16) {
8282 int i = strlen(cbuf);
8284 cbuf = realloc(cbuf, cblen);
8285 memset(cbuf+i, 0, 50);
8291 buffer = Safe_strdup( cbuf );
8297 /* emit each line as a code */
8303 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8311 /* print label, use this special format with NULL directive
8312 * to denote that the argument should not be indented with tab */
8313 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8320 if ((bp1 != bp) && *bp1)
8321 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8326 _G.inLine -= (!options.asmpeep);
8329 /*-----------------------------------------------------------------*/
8330 /* genRRC - rotate right with carry */
8331 /*-----------------------------------------------------------------*/
8332 static void genRRC (iCode *ic)
8334 operand *left , *result ;
8335 int size, offset = 0, same;
8337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8339 /* rotate right with carry */
8341 result=IC_RESULT(ic);
8342 pic16_aopOp (left,ic,FALSE);
8343 pic16_aopOp (result,ic,TRUE);
8345 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8347 same = pic16_sameRegs(AOP(result),AOP(left));
8349 size = AOP_SIZE(result);
8351 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8353 /* get the lsb and put it into the carry */
8354 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8361 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8363 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8364 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8370 pic16_freeAsmop(left,NULL,ic,TRUE);
8371 pic16_freeAsmop(result,NULL,ic,TRUE);
8374 /*-----------------------------------------------------------------*/
8375 /* genRLC - generate code for rotate left with carry */
8376 /*-----------------------------------------------------------------*/
8377 static void genRLC (iCode *ic)
8379 operand *left , *result ;
8380 int size, offset = 0;
8383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8384 /* rotate right with carry */
8386 result=IC_RESULT(ic);
8387 pic16_aopOp (left,ic,FALSE);
8388 pic16_aopOp (result,ic,TRUE);
8390 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8392 same = pic16_sameRegs(AOP(result),AOP(left));
8394 /* move it to the result */
8395 size = AOP_SIZE(result);
8397 /* get the msb and put it into the carry */
8398 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8405 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8407 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8408 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8415 pic16_freeAsmop(left,NULL,ic,TRUE);
8416 pic16_freeAsmop(result,NULL,ic,TRUE);
8420 /* gpasm can get the highest order bit with HIGH/UPPER
8421 * so the following probably is not needed -- VR */
8423 /*-----------------------------------------------------------------*/
8424 /* genGetHbit - generates code get highest order bit */
8425 /*-----------------------------------------------------------------*/
8426 static void genGetHbit (iCode *ic)
8428 operand *left, *result;
8430 result=IC_RESULT(ic);
8431 pic16_aopOp (left,ic,FALSE);
8432 pic16_aopOp (result,ic,FALSE);
8434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8435 /* get the highest order byte into a */
8436 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8437 if(AOP_TYPE(result) == AOP_CRY){
8438 pic16_emitcode("rlc","a");
8439 pic16_outBitC(result);
8442 pic16_emitcode("rl","a");
8443 pic16_emitcode("anl","a,#0x01");
8444 pic16_outAcc(result);
8448 pic16_freeAsmop(left,NULL,ic,TRUE);
8449 pic16_freeAsmop(result,NULL,ic,TRUE);
8453 /*-----------------------------------------------------------------*/
8454 /* AccRol - rotate left accumulator by known count */
8455 /*-----------------------------------------------------------------*/
8456 static void AccRol (int shCount)
8458 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8459 shCount &= 0x0007; // shCount : 0..7
8464 pic16_emitcode("rl","a");
8467 pic16_emitcode("rl","a");
8468 pic16_emitcode("rl","a");
8471 pic16_emitcode("swap","a");
8472 pic16_emitcode("rr","a");
8475 pic16_emitcode("swap","a");
8478 pic16_emitcode("swap","a");
8479 pic16_emitcode("rl","a");
8482 pic16_emitcode("rr","a");
8483 pic16_emitcode("rr","a");
8486 pic16_emitcode("rr","a");
8492 /*-----------------------------------------------------------------*/
8493 /* AccLsh - left shift accumulator by known count */
8494 /*-----------------------------------------------------------------*/
8495 static void AccLsh (int shCount)
8497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8503 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8506 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8507 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8511 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8518 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8532 /*-----------------------------------------------------------------*/
8533 /* AccRsh - right shift accumulator by known count */
8534 /*-----------------------------------------------------------------*/
8535 static void AccRsh (int shCount, int andmask)
8537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8542 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8545 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8546 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8550 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8557 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8560 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8569 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8571 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8575 /*-----------------------------------------------------------------*/
8576 /* AccSRsh - signed right shift accumulator by known count */
8577 /*-----------------------------------------------------------------*/
8578 static void AccSRsh (int shCount)
8581 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8584 pic16_emitcode("mov","c,acc.7");
8585 pic16_emitcode("rrc","a");
8586 } else if(shCount == 2){
8587 pic16_emitcode("mov","c,acc.7");
8588 pic16_emitcode("rrc","a");
8589 pic16_emitcode("mov","c,acc.7");
8590 pic16_emitcode("rrc","a");
8592 tlbl = newiTempLabel(NULL);
8593 /* rotate right accumulator */
8594 AccRol(8 - shCount);
8595 /* and kill the higher order bits */
8596 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8597 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8598 pic16_emitcode("orl","a,#0x%02x",
8599 (unsigned char)~SRMask[shCount]);
8600 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8606 /*-----------------------------------------------------------------*/
8607 /* shiftR1Left2Result - shift right one byte from left to result */
8608 /*-----------------------------------------------------------------*/
8609 static void shiftR1Left2ResultSigned (operand *left, int offl,
8610 operand *result, int offr,
8615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8617 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8621 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8623 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8625 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8626 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8632 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8634 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8636 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8637 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8639 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8640 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8648 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8649 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8653 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8654 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8656 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8657 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8659 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8663 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8664 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8665 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8666 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8667 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8676 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8677 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8678 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8679 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8685 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8686 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8687 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8689 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8690 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8694 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8696 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8703 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8707 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8709 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8717 /*-----------------------------------------------------------------*/
8718 /* shiftR1Left2Result - shift right one byte from left to result */
8719 /*-----------------------------------------------------------------*/
8720 static void shiftR1Left2Result (operand *left, int offl,
8721 operand *result, int offr,
8722 int shCount, int sign)
8726 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8728 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8730 /* Copy the msb into the carry if signed. */
8732 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8742 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8744 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8751 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8753 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8754 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8757 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8764 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8765 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8769 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8775 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8783 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8791 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8793 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8799 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8800 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8801 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8810 /*-----------------------------------------------------------------*/
8811 /* shiftL1Left2Result - shift left one byte from left to result */
8812 /*-----------------------------------------------------------------*/
8813 static void shiftL1Left2Result (operand *left, int offl,
8814 operand *result, int offr, int shCount)
8819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8821 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8822 DEBUGpic16_emitcode ("; ***","same = %d",same);
8823 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8825 /* shift left accumulator */
8826 //AccLsh(shCount); // don't comment out just yet...
8827 // pic16_aopPut(AOP(result),"a",offr);
8831 /* Shift left 1 bit position */
8832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8834 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8836 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8841 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8842 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8843 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8844 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8849 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8851 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8855 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8856 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8859 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8860 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8861 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8867 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8873 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8878 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8883 /*-----------------------------------------------------------------*/
8884 /* movLeft2Result - move byte from left to result */
8885 /*-----------------------------------------------------------------*/
8886 static void movLeft2Result (operand *left, int offl,
8887 operand *result, int offr)
8890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8891 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8892 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8894 if (*l == '@' && (IS_AOP_PREG(result))) {
8895 pic16_emitcode("mov","a,%s",l);
8896 pic16_aopPut(AOP(result),"a",offr);
8898 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8899 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8904 /*-----------------------------------------------------------------*/
8905 /* shiftL2Left2Result - shift left two bytes from left to result */
8906 /*-----------------------------------------------------------------*/
8907 static void shiftL2Left2Result (operand *left, int offl,
8908 operand *result, int offr, int shCount)
8910 int same = pic16_sameRegs(AOP(result), AOP(left));
8913 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8915 if (same && (offl != offr)) { // shift bytes
8918 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8919 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8921 } else { // just treat as different later on
8934 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8936 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8940 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8948 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8949 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
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_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8963 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8966 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8972 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8973 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8976 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8986 /* note, use a mov/add for the shift since the mov has a
8987 chance of getting optimized out */
8988 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8990 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8991 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8996 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8997 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9003 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9004 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9006 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9008 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9009 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9014 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9015 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9019 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9020 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9021 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9028 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9034 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9035 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9036 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9037 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9038 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9043 /*-----------------------------------------------------------------*/
9044 /* shiftR2Left2Result - shift right two bytes from left to result */
9045 /*-----------------------------------------------------------------*/
9046 static void shiftR2Left2Result (operand *left, int offl,
9047 operand *result, int offr,
9048 int shCount, int sign)
9050 int same = pic16_sameRegs(AOP(result), AOP(left));
9052 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9054 if (same && (offl != offr)) { // shift right bytes
9057 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9058 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9060 } else { // just treat as different later on
9072 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9077 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9078 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9080 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9081 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9082 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9083 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9088 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9091 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9092 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9100 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9101 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9104 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9105 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9106 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9108 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9109 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9110 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9113 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9115 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9116 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9120 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9121 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9126 pic16_emitpcode(POC_BTFSC,
9127 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9128 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9136 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9139 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9141 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9142 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9144 pic16_emitpcode(POC_BTFSC,
9145 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9146 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9148 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9149 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9150 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9151 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9153 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9156 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9162 pic16_emitpcode(POC_BTFSC,
9163 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9164 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9167 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9175 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9177 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9180 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9182 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9187 /*-----------------------------------------------------------------*/
9188 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9189 /*-----------------------------------------------------------------*/
9190 static void shiftLLeftOrResult (operand *left, int offl,
9191 operand *result, int offr, int shCount)
9193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9195 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9196 /* shift left accumulator */
9198 /* or with result */
9199 /* back to result */
9200 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9203 /*-----------------------------------------------------------------*/
9204 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9205 /*-----------------------------------------------------------------*/
9206 static void shiftRLeftOrResult (operand *left, int offl,
9207 operand *result, int offr, int shCount)
9209 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9211 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9212 /* shift right accumulator */
9214 /* or with result */
9215 /* back to result */
9216 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9219 /*-----------------------------------------------------------------*/
9220 /* genlshOne - left shift a one byte quantity by known count */
9221 /*-----------------------------------------------------------------*/
9222 static void genlshOne (operand *result, operand *left, int shCount)
9224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9225 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9228 /*-----------------------------------------------------------------*/
9229 /* genlshTwo - left shift two bytes by known amount != 0 */
9230 /*-----------------------------------------------------------------*/
9231 static void genlshTwo (operand *result,operand *left, int shCount)
9235 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9236 size = pic16_getDataSize(result);
9238 /* if shCount >= 8 */
9244 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9246 movLeft2Result(left, LSB, result, MSB16);
9248 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9251 /* 1 <= shCount <= 7 */
9254 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9256 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9260 /*-----------------------------------------------------------------*/
9261 /* shiftLLong - shift left one long from left to result */
9262 /* offr = LSB or MSB16 */
9263 /*-----------------------------------------------------------------*/
9264 static void shiftLLong (operand *left, operand *result, int offr )
9266 int size = AOP_SIZE(result);
9267 int same = pic16_sameRegs(AOP(left),AOP(result));
9270 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9272 if (same && (offr == MSB16)) { //shift one byte
9273 for(i=size-1;i>=MSB16;i--) {
9274 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9275 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9278 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9281 if (size > LSB+offr ){
9283 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9285 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9286 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9290 if(size > MSB16+offr){
9292 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9294 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9295 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9299 if(size > MSB24+offr){
9301 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9303 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9304 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9308 if(size > MSB32+offr){
9310 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9312 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9313 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9317 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9321 /*-----------------------------------------------------------------*/
9322 /* genlshFour - shift four byte by a known amount != 0 */
9323 /*-----------------------------------------------------------------*/
9324 static void genlshFour (operand *result, operand *left, int shCount)
9328 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9329 size = AOP_SIZE(result);
9331 /* if shifting more that 3 bytes */
9332 if (shCount >= 24 ) {
9335 /* lowest order of left goes to the highest
9336 order of the destination */
9337 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9339 movLeft2Result(left, LSB, result, MSB32);
9341 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9342 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9343 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9348 /* more than two bytes */
9349 else if ( shCount >= 16 ) {
9350 /* lower order two bytes goes to higher order two bytes */
9352 /* if some more remaining */
9354 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9356 movLeft2Result(left, MSB16, result, MSB32);
9357 movLeft2Result(left, LSB, result, MSB24);
9359 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9360 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9364 /* if more than 1 byte */
9365 else if ( shCount >= 8 ) {
9366 /* lower order three bytes goes to higher order three bytes */
9370 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9372 movLeft2Result(left, LSB, result, MSB16);
9374 else{ /* size = 4 */
9376 movLeft2Result(left, MSB24, result, MSB32);
9377 movLeft2Result(left, MSB16, result, MSB24);
9378 movLeft2Result(left, LSB, result, MSB16);
9379 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9381 else if(shCount == 1)
9382 shiftLLong(left, result, MSB16);
9384 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9385 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9386 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9387 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9392 /* 1 <= shCount <= 7 */
9393 else if(shCount <= 3)
9395 shiftLLong(left, result, LSB);
9396 while(--shCount >= 1)
9397 shiftLLong(result, result, LSB);
9399 /* 3 <= shCount <= 7, optimize */
9401 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9402 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9403 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9407 /*-----------------------------------------------------------------*/
9408 /* genLeftShiftLiteral - left shifting by known count */
9409 /*-----------------------------------------------------------------*/
9410 void pic16_genLeftShiftLiteral (operand *left,
9415 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9419 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9420 pic16_freeAsmop(right,NULL,ic,TRUE);
9422 pic16_aopOp(left,ic,FALSE);
9423 pic16_aopOp(result,ic,TRUE);
9425 size = getSize(operandType(result));
9428 pic16_emitcode("; shift left ","result %d, left %d",size,
9432 /* I suppose that the left size >= result size */
9435 movLeft2Result(left, size, result, size);
9439 else if(shCount >= (size * 8))
9441 pic16_aopPut(AOP(result),zero,size);
9445 genlshOne (result,left,shCount);
9450 genlshTwo (result,left,shCount);
9454 genlshFour (result,left,shCount);
9458 pic16_freeAsmop(left,NULL,ic,TRUE);
9459 pic16_freeAsmop(result,NULL,ic,TRUE);
9462 /*-----------------------------------------------------------------*
9463 * genMultiAsm - repeat assembly instruction for size of register.
9464 * if endian == 1, then the high byte (i.e base address + size of
9465 * register) is used first else the low byte is used first;
9466 *-----------------------------------------------------------------*/
9467 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9485 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9491 #if !(USE_GENERIC_SIGNED_SHIFT)
9492 /*-----------------------------------------------------------------*/
9493 /* genLeftShift - generates code for left shifting */
9494 /*-----------------------------------------------------------------*/
9495 static void genLeftShift (iCode *ic)
9497 operand *left,*right, *result;
9500 symbol *tlbl , *tlbl1;
9503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9505 right = IC_RIGHT(ic);
9507 result = IC_RESULT(ic);
9509 pic16_aopOp(right,ic,FALSE);
9511 /* if the shift count is known then do it
9512 as efficiently as possible */
9513 if (AOP_TYPE(right) == AOP_LIT) {
9514 pic16_genLeftShiftLiteral (left,right,result,ic);
9518 /* shift count is unknown then we have to form
9519 * a loop. Get the loop count in WREG : Note: we take
9520 * only the lower order byte since shifting
9521 * more than 32 bits make no sense anyway, ( the
9522 * largest size of an object can be only 32 bits ) */
9524 pic16_aopOp(left,ic,FALSE);
9525 pic16_aopOp(result,ic,FALSE);
9527 /* now move the left to the result if they are not the
9528 * same, and if size > 1,
9529 * and if right is not same to result (!!!) -- VR */
9530 if (!pic16_sameRegs(AOP(left),AOP(result))
9531 && (AOP_SIZE(result) > 1)) {
9533 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9535 size = AOP_SIZE(result);
9540 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9541 if (*l == '@' && (IS_AOP_PREG(result))) {
9543 pic16_emitcode("mov","a,%s",l);
9544 pic16_aopPut(AOP(result),"a",offset);
9548 /* we don't know if left is a literal or a register, take care -- VR */
9549 mov2f(AOP(result), AOP(left), offset);
9555 size = AOP_SIZE(result);
9557 /* if it is only one byte then */
9559 if(optimized_for_speed) {
9560 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9561 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9562 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9564 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9565 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9566 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9567 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9568 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9569 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9570 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9571 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9576 tlbl = newiTempLabel(NULL);
9579 /* this is already done, why change it? */
9580 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9581 mov2f(AOP(result), AOP(left), 0);
9585 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9586 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9587 pic16_emitpLabel(tlbl->key);
9588 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9589 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9591 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9596 if (pic16_sameRegs(AOP(left),AOP(result))) {
9598 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9600 tlbl = newiTempLabel(NULL);
9601 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9602 genMultiAsm(POC_RRCF, result, size,1);
9603 pic16_emitpLabel(tlbl->key);
9604 genMultiAsm(POC_RLCF, result, size,0);
9605 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9607 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9611 //tlbl = newiTempLabel(NULL);
9613 //tlbl1 = newiTempLabel(NULL);
9615 //reAdjustPreg(AOP(result));
9617 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9618 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9619 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9621 //pic16_emitcode("add","a,acc");
9622 //pic16_aopPut(AOP(result),"a",offset++);
9624 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9626 // pic16_emitcode("rlc","a");
9627 // pic16_aopPut(AOP(result),"a",offset++);
9629 //reAdjustPreg(AOP(result));
9631 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9632 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9635 tlbl = newiTempLabel(NULL);
9636 tlbl1= newiTempLabel(NULL);
9638 size = AOP_SIZE(result);
9641 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9643 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9645 /* offset should be 0, 1 or 3 */
9647 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9649 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9651 pic16_emitpcode(POC_MOVWF, pctemp);
9654 pic16_emitpLabel(tlbl->key);
9657 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9659 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9661 pic16_emitpcode(POC_DECFSZ, pctemp);
9662 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9663 pic16_emitpLabel(tlbl1->key);
9665 pic16_popReleaseTempReg(pctemp,1);
9669 pic16_freeAsmop (right,NULL,ic,TRUE);
9670 pic16_freeAsmop(left,NULL,ic,TRUE);
9671 pic16_freeAsmop(result,NULL,ic,TRUE);
9677 #error old code (left here for reference)
9678 /*-----------------------------------------------------------------*/
9679 /* genLeftShift - generates code for left shifting */
9680 /*-----------------------------------------------------------------*/
9681 static void genLeftShift (iCode *ic)
9683 operand *left,*right, *result;
9686 symbol *tlbl , *tlbl1;
9689 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9691 right = IC_RIGHT(ic);
9693 result = IC_RESULT(ic);
9695 pic16_aopOp(right,ic,FALSE);
9697 /* if the shift count is known then do it
9698 as efficiently as possible */
9699 if (AOP_TYPE(right) == AOP_LIT) {
9700 pic16_genLeftShiftLiteral (left,right,result,ic);
9704 /* shift count is unknown then we have to form
9705 a loop get the loop count in B : Note: we take
9706 only the lower order byte since shifting
9707 more that 32 bits make no sense anyway, ( the
9708 largest size of an object can be only 32 bits ) */
9711 pic16_aopOp(left,ic,FALSE);
9712 pic16_aopOp(result,ic,FALSE);
9714 /* now move the left to the result if they are not the
9716 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9717 AOP_SIZE(result) > 1) {
9719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9721 size = AOP_SIZE(result);
9724 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9725 if (*l == '@' && (IS_AOP_PREG(result))) {
9727 pic16_emitcode("mov","a,%s",l);
9728 pic16_aopPut(AOP(result),"a",offset);
9731 /* we don't know if left is a literal or a register, take care -- VR */
9732 mov2f(AOP(result), AOP(left), offset);
9738 size = AOP_SIZE(result);
9740 /* if it is only one byte then */
9742 if(optimized_for_speed) {
9743 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9744 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9745 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9748 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9749 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9750 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9751 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9752 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9753 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9754 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9759 tlbl = newiTempLabel(NULL);
9760 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9761 mov2f(AOP(result), AOP(left), 0);
9763 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9764 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9767 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9768 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9769 pic16_emitpLabel(tlbl->key);
9770 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9771 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9773 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9778 if (pic16_sameRegs(AOP(left),AOP(result))) {
9780 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9782 tlbl = newiTempLabel(NULL);
9783 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9784 genMultiAsm(POC_RRCF, result, size,1);
9785 pic16_emitpLabel(tlbl->key);
9786 genMultiAsm(POC_RLCF, result, size,0);
9787 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9789 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9793 //tlbl = newiTempLabel(NULL);
9795 //tlbl1 = newiTempLabel(NULL);
9797 //reAdjustPreg(AOP(result));
9799 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9800 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9801 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9803 //pic16_emitcode("add","a,acc");
9804 //pic16_aopPut(AOP(result),"a",offset++);
9806 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9808 // pic16_emitcode("rlc","a");
9809 // pic16_aopPut(AOP(result),"a",offset++);
9811 //reAdjustPreg(AOP(result));
9813 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9814 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9817 tlbl = newiTempLabel(NULL);
9818 tlbl1= newiTempLabel(NULL);
9820 size = AOP_SIZE(result);
9823 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9825 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9827 /* offset should be 0, 1 or 3 */
9829 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9831 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9833 pic16_emitpcode(POC_MOVWF, pctemp);
9836 pic16_emitpLabel(tlbl->key);
9839 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9841 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9843 pic16_emitpcode(POC_DECFSZ, pctemp);
9844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9845 pic16_emitpLabel(tlbl1->key);
9847 pic16_popReleaseTempReg(pctemp,1);
9851 pic16_freeAsmop (right,NULL,ic,TRUE);
9852 pic16_freeAsmop(left,NULL,ic,TRUE);
9853 pic16_freeAsmop(result,NULL,ic,TRUE);
9857 /*-----------------------------------------------------------------*/
9858 /* genrshOne - right shift a one byte quantity by known count */
9859 /*-----------------------------------------------------------------*/
9860 static void genrshOne (operand *result, operand *left,
9861 int shCount, int sign)
9863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9864 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9867 /*-----------------------------------------------------------------*/
9868 /* genrshTwo - right shift two bytes by known amount != 0 */
9869 /*-----------------------------------------------------------------*/
9870 static void genrshTwo (operand *result,operand *left,
9871 int shCount, int sign)
9873 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9874 /* if shCount >= 8 */
9878 shiftR1Left2Result(left, MSB16, result, LSB,
9881 movLeft2Result(left, MSB16, result, LSB);
9883 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9886 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9887 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9891 /* 1 <= shCount <= 7 */
9893 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9896 /*-----------------------------------------------------------------*/
9897 /* shiftRLong - shift right one long from left to result */
9898 /* offl = LSB or MSB16 */
9899 /*-----------------------------------------------------------------*/
9900 static void shiftRLong (operand *left, int offl,
9901 operand *result, int sign)
9903 int size = AOP_SIZE(result);
9904 int same = pic16_sameRegs(AOP(left),AOP(result));
9906 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9908 if (same && (offl == MSB16)) { //shift one byte right
9909 for(i=MSB16;i<size;i++) {
9910 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9911 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9916 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9922 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9924 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9925 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9929 /* add sign of "a" */
9930 pic16_addSign(result, MSB32, sign);
9934 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9936 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9941 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9943 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9948 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9951 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9957 /*-----------------------------------------------------------------*/
9958 /* genrshFour - shift four byte by a known amount != 0 */
9959 /*-----------------------------------------------------------------*/
9960 static void genrshFour (operand *result, operand *left,
9961 int shCount, int sign)
9963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9964 /* if shifting more that 3 bytes */
9965 if(shCount >= 24 ) {
9968 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9970 movLeft2Result(left, MSB32, result, LSB);
9972 pic16_addSign(result, MSB16, sign);
9974 else if(shCount >= 16){
9977 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9979 movLeft2Result(left, MSB24, result, LSB);
9980 movLeft2Result(left, MSB32, result, MSB16);
9982 pic16_addSign(result, MSB24, sign);
9984 else if(shCount >= 8){
9987 shiftRLong(left, MSB16, result, sign);
9988 else if(shCount == 0){
9989 movLeft2Result(left, MSB16, result, LSB);
9990 movLeft2Result(left, MSB24, result, MSB16);
9991 movLeft2Result(left, MSB32, result, MSB24);
9992 pic16_addSign(result, MSB32, sign);
9994 else{ //shcount >= 2
9995 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9996 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9997 /* the last shift is signed */
9998 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9999 pic16_addSign(result, MSB32, sign);
10002 else{ /* 1 <= shCount <= 7 */
10004 shiftRLong(left, LSB, result, sign);
10006 shiftRLong(result, LSB, result, sign);
10009 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10010 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10011 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10016 /*-----------------------------------------------------------------*/
10017 /* genRightShiftLiteral - right shifting by known count */
10018 /*-----------------------------------------------------------------*/
10019 static void genRightShiftLiteral (operand *left,
10025 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10026 int lsize,res_size;
10028 pic16_freeAsmop(right,NULL,ic,TRUE);
10030 pic16_aopOp(left,ic,FALSE);
10031 pic16_aopOp(result,ic,TRUE);
10033 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10036 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10040 lsize = pic16_getDataSize(left);
10041 res_size = pic16_getDataSize(result);
10042 /* test the LEFT size !!! */
10044 /* I suppose that the left size >= result size */
10046 assert (res_size <= lsize);
10047 while (res_size--) {
10048 mov2f (AOP(result), AOP(left), res_size);
10052 else if(shCount >= (lsize * 8)){
10054 if(res_size == 1) {
10055 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10057 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10058 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10063 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10064 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10072 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10077 switch (res_size) {
10079 genrshOne (result,left,shCount,sign);
10083 genrshTwo (result,left,shCount,sign);
10087 genrshFour (result,left,shCount,sign);
10095 pic16_freeAsmop(left,NULL,ic,TRUE);
10096 pic16_freeAsmop(result,NULL,ic,TRUE);
10099 #if !(USE_GENERIC_SIGNED_SHIFT)
10100 /*-----------------------------------------------------------------*/
10101 /* genSignedRightShift - right shift of signed number */
10102 /*-----------------------------------------------------------------*/
10103 static void genSignedRightShift (iCode *ic)
10105 operand *right, *left, *result;
10108 symbol *tlbl, *tlbl1 ;
10111 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10113 /* we do it the hard way put the shift count in b
10114 and loop thru preserving the sign */
10115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10117 right = IC_RIGHT(ic);
10118 left = IC_LEFT(ic);
10119 result = IC_RESULT(ic);
10121 pic16_aopOp(right,ic,FALSE);
10122 pic16_aopOp(left,ic,FALSE);
10123 pic16_aopOp(result,ic,FALSE);
10126 if ( AOP_TYPE(right) == AOP_LIT) {
10127 genRightShiftLiteral (left,right,result,ic,1);
10130 /* shift count is unknown then we have to form
10131 a loop get the loop count in B : Note: we take
10132 only the lower order byte since shifting
10133 more that 32 bits make no sense anyway, ( the
10134 largest size of an object can be only 32 bits ) */
10136 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10137 //pic16_emitcode("inc","b");
10138 //pic16_freeAsmop (right,NULL,ic,TRUE);
10139 //pic16_aopOp(left,ic,FALSE);
10140 //pic16_aopOp(result,ic,FALSE);
10142 /* now move the left to the result if they are not the
10144 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10145 AOP_SIZE(result) > 1) {
10147 size = AOP_SIZE(result);
10151 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10152 if (*l == '@' && IS_AOP_PREG(result)) {
10154 pic16_emitcode("mov","a,%s",l);
10155 pic16_aopPut(AOP(result),"a",offset);
10157 pic16_aopPut(AOP(result),l,offset);
10159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10160 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10166 /* mov the highest order bit to OVR */
10167 tlbl = newiTempLabel(NULL);
10168 tlbl1= newiTempLabel(NULL);
10170 size = AOP_SIZE(result);
10173 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10175 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10177 /* offset should be 0, 1 or 3 */
10178 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10180 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10182 pic16_emitpcode(POC_MOVWF, pctemp);
10185 pic16_emitpLabel(tlbl->key);
10187 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10188 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10191 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10194 pic16_emitpcode(POC_DECFSZ, pctemp);
10195 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10196 pic16_emitpLabel(tlbl1->key);
10198 pic16_popReleaseTempReg(pctemp,1);
10200 size = AOP_SIZE(result);
10202 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10203 pic16_emitcode("rlc","a");
10204 pic16_emitcode("mov","ov,c");
10205 /* if it is only one byte then */
10207 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10209 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10210 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10211 pic16_emitcode("mov","c,ov");
10212 pic16_emitcode("rrc","a");
10213 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10214 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10215 pic16_aopPut(AOP(result),"a",0);
10219 reAdjustPreg(AOP(result));
10220 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10221 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10222 pic16_emitcode("mov","c,ov");
10224 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10226 pic16_emitcode("rrc","a");
10227 pic16_aopPut(AOP(result),"a",offset--);
10229 reAdjustPreg(AOP(result));
10230 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10231 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10236 pic16_freeAsmop(left,NULL,ic,TRUE);
10237 pic16_freeAsmop(result,NULL,ic,TRUE);
10238 pic16_freeAsmop(right,NULL,ic,TRUE);
10242 #if !(USE_GENERIC_SIGNED_SHIFT)
10243 #warning This implementation of genRightShift() is incomplete!
10244 /*-----------------------------------------------------------------*/
10245 /* genRightShift - generate code for right shifting */
10246 /*-----------------------------------------------------------------*/
10247 static void genRightShift (iCode *ic)
10249 operand *right, *left, *result;
10253 symbol *tlbl, *tlbl1 ;
10255 /* if signed then we do it the hard way preserve the
10256 sign bit moving it inwards */
10257 letype = getSpec(operandType(IC_LEFT(ic)));
10258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10260 if (!SPEC_USIGN(letype)) {
10261 genSignedRightShift (ic);
10265 /* signed & unsigned types are treated the same : i.e. the
10266 signed is NOT propagated inwards : quoting from the
10267 ANSI - standard : "for E1 >> E2, is equivalent to division
10268 by 2**E2 if unsigned or if it has a non-negative value,
10269 otherwise the result is implementation defined ", MY definition
10270 is that the sign does not get propagated */
10272 right = IC_RIGHT(ic);
10273 left = IC_LEFT(ic);
10274 result = IC_RESULT(ic);
10276 pic16_aopOp(right,ic,FALSE);
10278 /* if the shift count is known then do it
10279 as efficiently as possible */
10280 if (AOP_TYPE(right) == AOP_LIT) {
10281 genRightShiftLiteral (left,right,result,ic, 0);
10285 /* shift count is unknown then we have to form
10286 a loop get the loop count in B : Note: we take
10287 only the lower order byte since shifting
10288 more that 32 bits make no sense anyway, ( the
10289 largest size of an object can be only 32 bits ) */
10291 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10292 pic16_emitcode("inc","b");
10293 pic16_aopOp(left,ic,FALSE);
10294 pic16_aopOp(result,ic,FALSE);
10296 /* now move the left to the result if they are not the
10298 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10299 AOP_SIZE(result) > 1) {
10301 size = AOP_SIZE(result);
10304 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10305 if (*l == '@' && IS_AOP_PREG(result)) {
10307 pic16_emitcode("mov","a,%s",l);
10308 pic16_aopPut(AOP(result),"a",offset);
10310 pic16_aopPut(AOP(result),l,offset);
10315 tlbl = newiTempLabel(NULL);
10316 tlbl1= newiTempLabel(NULL);
10317 size = AOP_SIZE(result);
10320 /* if it is only one byte then */
10323 tlbl = newiTempLabel(NULL);
10324 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10325 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10326 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10329 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10330 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10331 pic16_emitpLabel(tlbl->key);
10332 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10333 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10335 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10340 reAdjustPreg(AOP(result));
10341 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10342 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10345 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10347 pic16_emitcode("rrc","a");
10348 pic16_aopPut(AOP(result),"a",offset--);
10350 reAdjustPreg(AOP(result));
10352 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10353 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10356 pic16_freeAsmop(left,NULL,ic,TRUE);
10357 pic16_freeAsmop (right,NULL,ic,TRUE);
10358 pic16_freeAsmop(result,NULL,ic,TRUE);
10362 #if (USE_GENERIC_SIGNED_SHIFT)
10363 /*-----------------------------------------------------------------*/
10364 /* genGenericShift - generates code for left or right shifting */
10365 /*-----------------------------------------------------------------*/
10366 static void genGenericShift (iCode *ic, int isShiftLeft) {
10367 operand *left,*right, *result;
10369 int sign, signedCount;
10370 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10371 PIC_OPCODE pos_shift, neg_shift;
10375 right = IC_RIGHT(ic);
10376 left = IC_LEFT(ic);
10377 result = IC_RESULT(ic);
10379 pic16_aopOp(right,ic,FALSE);
10380 pic16_aopOp(left,ic,FALSE);
10381 pic16_aopOp(result,ic,TRUE);
10383 sign = !SPEC_USIGN(operandType (left));
10384 signedCount = !SPEC_USIGN(operandType (right));
10386 /* if the shift count is known then do it
10387 as efficiently as possible */
10388 if (AOP_TYPE(right) == AOP_LIT) {
10389 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10390 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10391 // we should modify right->aopu.aop_lit here!
10392 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10393 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10395 pic16_genLeftShiftLiteral (left,right,result,ic);
10397 genRightShiftLiteral (left,right,result,ic, sign);
10400 } // if (right is literal)
10402 /* shift count is unknown then we have to form a loop.
10403 * Note: we take only the lower order byte since shifting
10404 * more than 32 bits make no sense anyway, ( the
10405 * largest size of an object can be only 32 bits )
10406 * Note: we perform arithmetic shifts if the left operand is
10407 * signed and we do an (effective) right shift, i. e. we
10408 * shift in the sign bit from the left. */
10410 label_complete = newiTempLabel ( NULL );
10411 label_loop_pos = newiTempLabel ( NULL );
10412 label_loop_neg = NULL;
10413 label_negative = NULL;
10414 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10415 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10418 // additional labels needed
10419 label_loop_neg = newiTempLabel ( NULL );
10420 label_negative = newiTempLabel ( NULL );
10423 // copy source to result -- this will effectively truncate the left operand to the size of result!
10424 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10425 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10426 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10427 mov2f (AOP(result),AOP(left), offset);
10430 // if result is longer than left, fill with zeros (or sign)
10431 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10432 if (sign && AOP_SIZE(left) > 0) {
10433 // shift signed operand -- fill with sign
10434 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10435 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10436 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10437 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10438 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10441 // shift unsigned operand -- fill result with zeros
10442 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10446 } // if (size mismatch)
10448 pic16_mov2w (AOP(right), 0);
10449 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10450 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10453 // perform a shift by one (shift count is positive)
10454 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10455 // 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])
10456 pic16_emitpLabel (label_loop_pos->key);
10458 if (sign && (pos_shift == POC_RRCF)) {
10459 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10462 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10463 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10464 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10466 // perform a shift by one (shift count is positive)
10467 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10468 // 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])
10469 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10470 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10472 pic16_emitpLabel (label_loop_pos->key);
10473 if (sign && (pos_shift == POC_RRCF)) {
10474 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10477 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10478 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10479 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10480 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10484 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10486 pic16_emitpLabel (label_negative->key);
10487 // perform a shift by -1 (shift count is negative)
10488 // 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)
10490 pic16_emitpLabel (label_loop_neg->key);
10491 if (sign && (neg_shift == POC_RRCF)) {
10492 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10495 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10496 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10497 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10498 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10499 } // if (signedCount)
10501 pic16_emitpLabel (label_complete->key);
10504 pic16_freeAsmop (right,NULL,ic,TRUE);
10505 pic16_freeAsmop(left,NULL,ic,TRUE);
10506 pic16_freeAsmop(result,NULL,ic,TRUE);
10509 static void genLeftShift (iCode *ic) {
10510 genGenericShift (ic, 1);
10513 static void genRightShift (iCode *ic) {
10514 genGenericShift (ic, 0);
10519 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10520 void pic16_loadFSR0(operand *op, int lit)
10522 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10523 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10525 assert (!OP_SYMBOL(op)->remat);
10526 // set up FSR0 with address of result
10527 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10528 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10532 /*-----------------------------------------------------------------*/
10533 /* genUnpackBits - generates code for unpacking bits */
10534 /*-----------------------------------------------------------------*/
10535 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10539 sym_link *etype, *letype;
10540 int blen=0, bstr=0;
10544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10545 etype = getSpec(operandType(result));
10546 letype = getSpec(operandType(left));
10548 // if(IS_BITFIELD(etype)) {
10549 blen = SPEC_BLEN(etype);
10550 bstr = SPEC_BSTR(etype);
10553 lbstr = SPEC_BSTR( letype );
10556 if((blen == 1) && (bstr < 8)) {
10557 /* it is a single bit, so use the appropriate bit instructions */
10558 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10560 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10562 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10563 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10564 /* workaround to reduce the extra lfsr instruction */
10565 pic16_emitpcode(POC_BTFSC,
10566 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10568 pic16_loadFSR0 (left, 0);
10569 pic16_emitpcode(POC_BTFSC,
10570 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10573 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10575 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10581 /* the following call to pic16_loadFSR0 is temporary until
10582 * optimization to handle single bit assignments is added
10583 * to the function. Until then use the old safe way! -- VR */
10585 if (OP_SYMBOL(left)->remat) {
10586 // access symbol directly
10587 pic16_mov2w (AOP(left), 0);
10589 pic16_loadFSR0( left, 0 );
10591 /* read the first byte */
10598 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10601 pic16_emitcode("clr","a");
10602 pic16_emitcode("movc","a","@a+dptr");
10608 /* if we have bitdisplacement then it fits */
10609 /* into this byte completely or if length is */
10610 /* less than a byte */
10611 if ((shCnt = SPEC_BSTR(etype)) ||
10612 (SPEC_BLEN(etype) <= 8)) {
10614 /* shift right acc */
10617 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10618 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10620 /* VR -- normally I would use the following, but since we use the hack,
10621 * to avoid the masking from AccRsh, why not mask it right now? */
10624 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10633 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10634 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10637 /* bit field did not fit in a byte */
10638 rlen = SPEC_BLEN(etype) - 8;
10639 pic16_aopPut(AOP(result),"a",offset++);
10646 pic16_emitcode("inc","%s",rname);
10647 pic16_emitcode("mov","a,@%s",rname);
10651 pic16_emitcode("inc","%s",rname);
10652 pic16_emitcode("movx","a,@%s",rname);
10656 pic16_emitcode("inc","dptr");
10657 pic16_emitcode("movx","a,@dptr");
10661 pic16_emitcode("clr","a");
10662 pic16_emitcode("inc","dptr");
10663 pic16_emitcode("movc","a","@a+dptr");
10667 pic16_emitcode("inc","dptr");
10668 pic16_emitcode("lcall","__gptrget");
10673 /* if we are done */
10677 pic16_aopPut(AOP(result),"a",offset++);
10682 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10683 pic16_aopPut(AOP(result),"a",offset);
10690 static void genDataPointerGet(operand *left,
10694 int size, offset = 0, leoffset=0 ;
10696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10697 pic16_aopOp(result, ic, TRUE);
10701 size = AOP_SIZE(result);
10702 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10706 /* The following tests may save a redudant movff instruction when
10707 * accessing unions */
10709 /* if they are the same */
10710 if (operandsEqu (left, result)) {
10711 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10717 /* if they are the same registers */
10718 if (pic16_sameRegs(AOP(left),AOP(result))) {
10719 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10725 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10726 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10727 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10734 if ( AOP_TYPE(left) == AOP_PCODE) {
10735 fprintf(stderr,"genDataPointerGet %s, %d\n",
10736 AOP(left)->aopu.pcop->name,
10737 (AOP(left)->aopu.pcop->type == PO_DIR)?
10738 PCOR(AOP(left)->aopu.pcop)->instance:
10739 PCOI(AOP(left)->aopu.pcop)->offset);
10743 if(AOP(left)->aopu.pcop->type == PO_DIR)
10744 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10746 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10749 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10751 // pic16_DumpOp("(result)",result);
10752 if(is_LitAOp(AOP(result))) {
10753 pic16_mov2w(AOP(left), offset); // patch 8
10754 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10756 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10757 pic16_popGet(AOP(left), offset), //patch 8
10758 pic16_popGet(AOP(result), offset)));
10766 pic16_freeAsmop(result,NULL,ic,TRUE);
10771 /*-----------------------------------------------------------------*/
10772 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10773 /*-----------------------------------------------------------------*/
10774 static void genNearPointerGet (operand *left,
10778 // asmop *aop = NULL;
10779 //regs *preg = NULL ;
10780 sym_link *rtype, *retype;
10781 sym_link *ltype = operandType(left);
10785 rtype = operandType(result);
10786 retype= getSpec(rtype);
10788 pic16_aopOp(left,ic,FALSE);
10790 // pic16_DumpOp("(left)",left);
10791 // pic16_DumpOp("(result)",result);
10793 /* if left is rematerialisable and
10794 * result is not bit variable type and
10795 * the left is pointer to data space i.e
10796 * lower 128 bytes of space */
10798 if (AOP_TYPE(left) == AOP_PCODE
10799 && !IS_BITFIELD(retype)
10800 && DCL_TYPE(ltype) == POINTER) {
10802 genDataPointerGet (left,result,ic);
10803 pic16_freeAsmop(left, NULL, ic, TRUE);
10807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10808 pic16_aopOp (result,ic,TRUE);
10810 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10813 if(IS_BITFIELD( retype )
10814 && (SPEC_BLEN(operandType(result))==1)
10818 int bitstrt, bytestrt;
10820 /* if this is bitfield of size 1, see if we are checking the value
10821 * of a single bit in an if-statement,
10822 * if yes, then don't generate usual code, but execute the
10823 * genIfx directly -- VR */
10827 /* CHECK: if next iCode is IFX
10828 * and current result operand is nextic's conditional operand
10829 * and current result operand live ranges ends at nextic's key number
10831 if((nextic->op == IFX)
10832 && (result == IC_COND(nextic))
10833 && (OP_LIVETO(result) == nextic->seq)
10834 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10836 /* everything is ok then */
10837 /* find a way to optimize the genIfx iCode */
10839 bytestrt = SPEC_BSTR(operandType(result))/8;
10840 bitstrt = SPEC_BSTR(operandType(result))%8;
10842 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10844 genIfxpCOpJump(nextic, jop);
10846 pic16_freeAsmop(left, NULL, ic, TRUE);
10847 pic16_freeAsmop(result, NULL, ic, TRUE);
10854 /* if the value is already in a pointer register
10855 * then don't need anything more */
10856 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10857 /* otherwise get a free pointer register */
10858 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10863 /* if bitfield then unpack the bits */
10864 if (IS_BITFIELD(retype))
10865 genUnpackBits (result, left, NULL, POINTER);
10867 /* we have can just get the values */
10868 int size = AOP_SIZE(result);
10871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10873 pic16_loadFSR0( left, 0 );
10877 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10878 pic16_popGet(AOP(result), offset++)));
10880 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10881 pic16_popGet(AOP(result), offset++)));
10887 /* now some housekeeping stuff */
10889 /* we had to allocate for this iCode */
10890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10891 pic16_freeAsmop(NULL,aop,ic,TRUE);
10893 /* we did not allocate which means left
10894 * already in a pointer register, then
10895 * if size > 0 && this could be used again
10896 * we have to point it back to where it
10898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10899 if (AOP_SIZE(result) > 1
10900 && !OP_SYMBOL(left)->remat
10901 && ( OP_SYMBOL(left)->liveTo > ic->seq
10903 // int size = AOP_SIZE(result) - 1;
10905 // pic16_emitcode("dec","%s",rname);
10911 pic16_freeAsmop(left,NULL,ic,TRUE);
10912 pic16_freeAsmop(result,NULL,ic,TRUE);
10915 /*-----------------------------------------------------------------*/
10916 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10917 /*-----------------------------------------------------------------*/
10918 static void genPagedPointerGet (operand *left,
10923 regs *preg = NULL ;
10925 sym_link *rtype, *retype;
10927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10929 rtype = operandType(result);
10930 retype= getSpec(rtype);
10932 pic16_aopOp(left,ic,FALSE);
10934 /* if the value is already in a pointer register
10935 then don't need anything more */
10936 if (!AOP_INPREG(AOP(left))) {
10937 /* otherwise get a free pointer register */
10939 preg = getFreePtr(ic,&aop,FALSE);
10940 pic16_emitcode("mov","%s,%s",
10942 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10943 rname = preg->name ;
10945 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10947 pic16_freeAsmop(left,NULL,ic,TRUE);
10948 pic16_aopOp (result,ic,TRUE);
10950 /* if bitfield then unpack the bits */
10951 if (IS_BITFIELD(retype))
10952 genUnpackBits (result,left,rname,PPOINTER);
10954 /* we have can just get the values */
10955 int size = AOP_SIZE(result);
10960 pic16_emitcode("movx","a,@%s",rname);
10961 pic16_aopPut(AOP(result),"a",offset);
10966 pic16_emitcode("inc","%s",rname);
10970 /* now some housekeeping stuff */
10972 /* we had to allocate for this iCode */
10973 pic16_freeAsmop(NULL,aop,ic,TRUE);
10975 /* we did not allocate which means left
10976 already in a pointer register, then
10977 if size > 0 && this could be used again
10978 we have to point it back to where it
10980 if (AOP_SIZE(result) > 1 &&
10981 !OP_SYMBOL(left)->remat &&
10982 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10984 int size = AOP_SIZE(result) - 1;
10986 pic16_emitcode("dec","%s",rname);
10991 pic16_freeAsmop(result,NULL,ic,TRUE);
10996 /*-----------------------------------------------------------------*/
10997 /* genFarPointerGet - gget value from far space */
10998 /*-----------------------------------------------------------------*/
10999 static void genFarPointerGet (operand *left,
11000 operand *result, iCode *ic)
11003 sym_link *retype = getSpec(operandType(result));
11005 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11007 pic16_aopOp(left,ic,FALSE);
11009 /* if the operand is already in dptr
11010 then we do nothing else we move the value to dptr */
11011 if (AOP_TYPE(left) != AOP_STR) {
11012 /* if this is remateriazable */
11013 if (AOP_TYPE(left) == AOP_IMMD)
11014 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11015 else { /* we need to get it byte by byte */
11016 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11017 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11018 if (options.model == MODEL_FLAT24)
11020 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11024 /* so dptr know contains the address */
11025 pic16_freeAsmop(left,NULL,ic,TRUE);
11026 pic16_aopOp(result,ic,TRUE);
11028 /* if bit then unpack */
11029 if (IS_BITFIELD(retype))
11030 genUnpackBits(result,left,"dptr",FPOINTER);
11032 size = AOP_SIZE(result);
11036 pic16_emitcode("movx","a,@dptr");
11037 pic16_aopPut(AOP(result),"a",offset++);
11039 pic16_emitcode("inc","dptr");
11043 pic16_freeAsmop(result,NULL,ic,TRUE);
11047 /*-----------------------------------------------------------------*/
11048 /* genCodePointerGet - get value from code space */
11049 /*-----------------------------------------------------------------*/
11050 static void genCodePointerGet (operand *left,
11051 operand *result, iCode *ic)
11054 sym_link *retype = getSpec(operandType(result));
11056 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11058 pic16_aopOp(left,ic,FALSE);
11060 /* if the operand is already in dptr
11061 then we do nothing else we move the value to dptr */
11062 if (AOP_TYPE(left) != AOP_STR) {
11063 /* if this is remateriazable */
11064 if (AOP_TYPE(left) == AOP_IMMD)
11065 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11066 else { /* we need to get it byte by byte */
11067 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11068 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11069 if (options.model == MODEL_FLAT24)
11071 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11075 /* so dptr know contains the address */
11076 pic16_freeAsmop(left,NULL,ic,TRUE);
11077 pic16_aopOp(result,ic,FALSE);
11079 /* if bit then unpack */
11080 if (IS_BITFIELD(retype))
11081 genUnpackBits(result,left,"dptr",CPOINTER);
11083 size = AOP_SIZE(result);
11087 pic16_emitcode("clr","a");
11088 pic16_emitcode("movc","a,@a+dptr");
11089 pic16_aopPut(AOP(result),"a",offset++);
11091 pic16_emitcode("inc","dptr");
11095 pic16_freeAsmop(result,NULL,ic,TRUE);
11100 /*-----------------------------------------------------------------*/
11101 /* genGenPointerGet - gget value from generic pointer space */
11102 /*-----------------------------------------------------------------*/
11103 static void genGenPointerGet (operand *left,
11104 operand *result, iCode *ic)
11106 int size, offset, lit;
11107 sym_link *retype = getSpec(operandType(result));
11109 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11110 pic16_aopOp(left,ic,FALSE);
11111 pic16_aopOp(result,ic,FALSE);
11112 size = AOP_SIZE(result);
11114 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11116 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11118 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11119 // load FSR0 from immediate
11120 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11122 // pic16_loadFSR0( left );
11127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11129 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11136 else { /* we need to get it byte by byte */
11137 // set up FSR0 with address from left
11138 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11139 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11147 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11154 /* if bit then unpack */
11155 if (IS_BITFIELD(retype))
11156 genUnpackBits(result,left,"BAD",GPOINTER);
11159 pic16_freeAsmop(left,NULL,ic,TRUE);
11160 pic16_freeAsmop(result,NULL,ic,TRUE);
11166 /*-----------------------------------------------------------------*/
11167 /* genGenPointerGet - gget value from generic pointer space */
11168 /*-----------------------------------------------------------------*/
11169 static void genGenPointerGet (operand *left,
11170 operand *result, iCode *ic)
11172 int size, offset, lit;
11173 sym_link *retype = getSpec(operandType(result));
11176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11177 pic16_aopOp(left,ic,FALSE);
11178 pic16_aopOp(result,ic,TRUE);
11179 size = AOP_SIZE(result);
11181 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11183 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11185 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11186 // load FSR0 from immediate
11187 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11189 werror(W_POSSBUG2, __FILE__, __LINE__);
11194 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11196 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11203 } else { /* we need to get it byte by byte */
11205 /* set up WREG:PRODL:FSR0L with address from left */
11206 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11208 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11211 case 1: strcpy(fgptrget, "__gptrget1"); break;
11212 case 2: strcpy(fgptrget, "__gptrget2"); break;
11213 case 3: strcpy(fgptrget, "__gptrget3"); break;
11214 case 4: strcpy(fgptrget, "__gptrget4"); break;
11216 werror(W_POSSBUG2, __FILE__, __LINE__);
11220 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11222 assignResultValue(result, 1);
11227 sym = newSymbol( fgptrget, 0 );
11229 strcpy(sym->rname, fgptrget);
11230 checkAddSym(&externs, sym);
11232 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11238 /* if bit then unpack */
11239 if (IS_BITFIELD(retype))
11240 genUnpackBits(result,left,"BAD",GPOINTER);
11243 pic16_freeAsmop(left,NULL,ic,TRUE);
11244 pic16_freeAsmop(result,NULL,ic,TRUE);
11247 /*-----------------------------------------------------------------*/
11248 /* genConstPointerGet - get value from const generic pointer space */
11249 /*-----------------------------------------------------------------*/
11250 static void genConstPointerGet (operand *left,
11251 operand *result, iCode *ic)
11253 //sym_link *retype = getSpec(operandType(result));
11254 // symbol *albl = newiTempLabel(NULL); // patch 15
11255 // symbol *blbl = newiTempLabel(NULL); //
11256 // PIC_OPCODE poc; // patch 15
11260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11261 pic16_aopOp(left,ic,FALSE);
11262 pic16_aopOp(result,ic,TRUE);
11263 size = AOP_SIZE(result);
11265 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11267 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11269 // set up table pointer
11270 if( (AOP_TYPE(left) == AOP_PCODE)
11271 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11272 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11274 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11275 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11276 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11277 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11278 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11279 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11281 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11282 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11283 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11287 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11288 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11292 pic16_freeAsmop(left,NULL,ic,TRUE);
11293 pic16_freeAsmop(result,NULL,ic,TRUE);
11297 /*-----------------------------------------------------------------*/
11298 /* genPointerGet - generate code for pointer get */
11299 /*-----------------------------------------------------------------*/
11300 static void genPointerGet (iCode *ic)
11302 operand *left, *result ;
11303 sym_link *type, *etype;
11308 left = IC_LEFT(ic);
11309 result = IC_RESULT(ic) ;
11311 /* depending on the type of pointer we need to
11312 move it to the correct pointer register */
11313 type = operandType(left);
11314 etype = getSpec(type);
11317 if (IS_PTR_CONST(type))
11319 if (IS_CODEPTR(type))
11321 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11323 /* if left is of type of pointer then it is simple */
11324 if (IS_PTR(type) && !IS_FUNC(type->next))
11325 p_type = DCL_TYPE(type);
11327 /* we have to go by the storage class */
11328 p_type = PTR_TYPE(SPEC_OCLS(etype));
11330 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11332 if (SPEC_OCLS(etype)->codesp ) {
11333 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11334 //p_type = CPOINTER ;
11336 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11337 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11338 /*p_type = FPOINTER ;*/
11340 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11341 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11342 /* p_type = PPOINTER; */
11344 if (SPEC_OCLS(etype) == idata ) {
11345 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11346 /* p_type = IPOINTER; */
11348 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11349 /* p_type = POINTER ; */
11353 /* now that we have the pointer type we assign
11354 the pointer values */
11358 genNearPointerGet (left,result,ic);
11362 genPagedPointerGet(left,result,ic);
11366 genFarPointerGet (left,result,ic);
11370 genConstPointerGet (left,result,ic);
11371 //pic16_emitcodePointerGet (left,result,ic);
11376 if (IS_PTR_CONST(type))
11377 genConstPointerGet (left,result,ic);
11380 genGenPointerGet (left,result,ic);
11384 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11385 "genPointerGet: illegal pointer type");
11390 /*-----------------------------------------------------------------*/
11391 /* genPackBits - generates code for packed bit storage */
11392 /*-----------------------------------------------------------------*/
11393 static void genPackBits (sym_link *etype , operand *result,
11395 char *rname, int p_type)
11403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11404 blen = SPEC_BLEN(etype);
11405 bstr = SPEC_BSTR(etype);
11407 retype = getSpec(operandType(right));
11409 if(AOP_TYPE(right) == AOP_LIT) {
11410 if((blen == 1) && (bstr < 8)) {
11412 /* it is a single bit, so use the appropriate bit instructions */
11414 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11416 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11417 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11418 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11419 /* workaround to reduce the extra lfsr instruction */
11421 pic16_emitpcode(POC_BSF,
11422 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11424 pic16_emitpcode(POC_BCF,
11425 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11428 pic16_loadFSR0(result, 0);
11430 pic16_emitpcode(POC_BSF,
11431 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11433 pic16_emitpcode(POC_BCF,
11434 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11440 /* move literal to W */
11441 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11444 if(IS_BITFIELD(retype)
11445 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11449 rblen = SPEC_BLEN( retype );
11450 rbstr = SPEC_BSTR( retype );
11453 if(IS_BITFIELD(etype)) {
11454 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11455 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11457 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11460 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11462 if(IS_BITFIELD(etype)) {
11463 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11465 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11468 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11472 /* move right to W */
11473 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11476 /* if the bit length is less than or */
11477 /* it exactly fits a byte then */
11478 if((shCnt=SPEC_BSTR(etype))
11479 || SPEC_BLEN(etype) <= 8 ) {
11480 int fsr0_setup = 0;
11482 if (blen != 8 || bstr != 0) {
11483 // we need to combine the value with the old value
11484 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11486 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11487 SPEC_BSTR(etype), SPEC_BLEN(etype));
11489 /* shift left acc */
11492 /* using PRODH as a temporary register here */
11493 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11495 if (OP_SYMBOL(result)->remat) {
11496 // access symbol directly
11497 pic16_mov2w (AOP(result), 0);
11499 /* get old value */
11503 pic16_loadFSR0( result, 0 );
11505 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11506 // pic16_emitcode ("mov","b,a");
11507 // pic16_emitcode("mov","a,@%s",rname);
11511 if (AOP(result)->aopu.aop_reg[2]) {
11512 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11513 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11514 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11515 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11516 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11519 sym = newSymbol( "__gptrget1", 0 );
11520 strcpy(sym->rname, "__gptrget1");
11521 checkAddSym(&externs, sym);
11524 // data pointer (just 2 byte given)
11525 pic16_loadFSR0( result, 0 );
11527 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11530 // warnings will be emitted below
11531 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11532 //werror(W_POSSBUG2, __FILE__, __LINE__);
11536 assert (0 && "invalid pointer type specified");
11541 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11542 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11543 (unsigned char)(0xff >> (8-bstr))) ));
11544 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11545 } // if (blen != 8 || bstr != 0)
11547 /* write new value back */
11548 if (OP_SYMBOL(result)->remat) {
11549 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11554 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11555 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11559 if (AOP(result)->aopu.aop_reg[2]) {
11560 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11561 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11562 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11563 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11564 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11565 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11568 sym = newSymbol( "__gptrput1", 0 );
11569 strcpy(sym->rname, "__gptrput1");
11570 checkAddSym(&externs, sym);
11573 // data pointer (just 2 byte given)
11574 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11575 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11578 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11579 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11580 werror(W_POSSBUG2, __FILE__, __LINE__);
11584 assert (0 && "invalid pointer type specified");
11595 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11596 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11601 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11602 rLen = SPEC_BLEN(etype)-8;
11604 /* now generate for lengths greater than one byte */
11608 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11614 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11620 pic16_emitcode("movx","@dptr,a");
11625 DEBUGpic16_emitcode(";lcall","__gptrput");
11633 pic16_mov2w(AOP(right), offset++);
11636 /* last last was not complete */
11638 /* save the byte & read byte */
11641 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11642 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11647 pic16_emitcode ("mov","b,a");
11648 pic16_emitcode("movx","a,@dptr");
11652 pic16_emitcode ("push","b");
11653 pic16_emitcode ("push","acc");
11654 pic16_emitcode ("lcall","__gptrget");
11655 pic16_emitcode ("pop","b");
11661 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11662 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11663 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11664 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11665 // pic16_emitcode ("orl","a,b");
11668 // if (p_type == GPOINTER)
11669 // pic16_emitcode("pop","b");
11674 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11675 // pic16_emitcode("mov","@%s,a",rname);
11679 pic16_emitcode("movx","@dptr,a");
11683 DEBUGpic16_emitcode(";lcall","__gptrput");
11690 // pic16_freeAsmop(right, NULL, ic, TRUE);
11692 /*-----------------------------------------------------------------*/
11693 /* genDataPointerSet - remat pointer to data space */
11694 /*-----------------------------------------------------------------*/
11695 static void genDataPointerSet(operand *right,
11699 int size, offset = 0, resoffset=0 ;
11701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11702 pic16_aopOp(right,ic,FALSE);
11704 size = AOP_SIZE(right);
11706 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11709 if ( AOP_TYPE(result) == AOP_PCODE) {
11710 fprintf(stderr,"genDataPointerSet %s, %d\n",
11711 AOP(result)->aopu.pcop->name,
11712 (AOP(result)->aopu.pcop->type == PO_DIR)?
11713 PCOR(AOP(result)->aopu.pcop)->instance:
11714 PCOI(AOP(result)->aopu.pcop)->offset);
11718 if(AOP(result)->aopu.pcop->type == PO_DIR)
11719 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11722 if (AOP_TYPE(right) == AOP_LIT) {
11725 if(!IS_FLOAT(operandType( right )))
11726 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11729 unsigned long lit_int;
11733 /* take care if literal is a float */
11734 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11735 lit = info.lit_int;
11738 lit = lit >> (8*offset);
11740 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11741 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11743 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11746 pic16_mov2w(AOP(right), offset);
11747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11753 pic16_freeAsmop(right,NULL,ic,TRUE);
11758 /*-----------------------------------------------------------------*/
11759 /* genNearPointerSet - pic16_emitcode for near pointer put */
11760 /*-----------------------------------------------------------------*/
11761 static void genNearPointerSet (operand *right,
11767 sym_link *ptype = operandType(result);
11768 sym_link *resetype;
11770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11771 retype= getSpec(operandType(right));
11772 resetype = getSpec(operandType(result));
11774 pic16_aopOp(result,ic,FALSE);
11776 /* if the result is rematerializable &
11777 * in data space & not a bit variable */
11779 /* and result is not a bit variable */
11780 if (AOP_TYPE(result) == AOP_PCODE
11781 // && AOP_TYPE(result) == AOP_IMMD
11782 && DCL_TYPE(ptype) == POINTER
11783 && !IS_BITFIELD(retype)
11784 && !IS_BITFIELD(resetype)) {
11786 genDataPointerSet (right,result,ic);
11787 pic16_freeAsmop(result,NULL,ic,TRUE);
11791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11792 pic16_aopOp(right,ic,FALSE);
11793 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11795 /* if the value is already in a pointer register
11796 * then don't need anything more */
11797 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11798 /* otherwise get a free pointer register */
11799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11806 /* if bitfield then unpack the bits */
11807 if (IS_BITFIELD(resetype)) {
11808 genPackBits (resetype, result, right, NULL, POINTER);
11810 /* we have can just get the values */
11811 int size = AOP_SIZE(right);
11814 pic16_loadFSR0(result, 0);
11816 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11818 if (AOP_TYPE(right) == AOP_LIT) {
11819 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11821 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11823 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11825 } else { // no literal
11827 pic16_emitpcode(POC_MOVFF,
11828 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11829 pic16_popCopyReg(&pic16_pc_postinc0)));
11831 pic16_emitpcode(POC_MOVFF,
11832 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11833 pic16_popCopyReg(&pic16_pc_indf0)));
11840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11841 /* now some housekeeping stuff */
11843 /* we had to allocate for this iCode */
11844 pic16_freeAsmop(NULL,aop,ic,TRUE);
11846 /* we did not allocate which means left
11847 * already in a pointer register, then
11848 * if size > 0 && this could be used again
11849 * we have to point it back to where it
11851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11852 if (AOP_SIZE(right) > 1
11853 && !OP_SYMBOL(result)->remat
11854 && ( OP_SYMBOL(result)->liveTo > ic->seq
11857 int size = AOP_SIZE(right) - 1;
11860 pic16_emitcode("decf","fsr0,f");
11861 //pic16_emitcode("dec","%s",rname);
11865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11868 pic16_freeAsmop(right,NULL,ic,TRUE);
11869 pic16_freeAsmop(result,NULL,ic,TRUE);
11872 /*-----------------------------------------------------------------*/
11873 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11874 /*-----------------------------------------------------------------*/
11875 static void genPagedPointerSet (operand *right,
11880 regs *preg = NULL ;
11884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11886 retype= getSpec(operandType(right));
11888 pic16_aopOp(result,ic,FALSE);
11890 /* if the value is already in a pointer register
11891 then don't need anything more */
11892 if (!AOP_INPREG(AOP(result))) {
11893 /* otherwise get a free pointer register */
11895 preg = getFreePtr(ic,&aop,FALSE);
11896 pic16_emitcode("mov","%s,%s",
11898 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11899 rname = preg->name ;
11901 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11903 pic16_freeAsmop(result,NULL,ic,TRUE);
11904 pic16_aopOp (right,ic,FALSE);
11906 /* if bitfield then unpack the bits */
11907 if (IS_BITFIELD(retype))
11908 genPackBits (retype,result,right,rname,PPOINTER);
11910 /* we have can just get the values */
11911 int size = AOP_SIZE(right);
11915 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11918 pic16_emitcode("movx","@%s,a",rname);
11921 pic16_emitcode("inc","%s",rname);
11927 /* now some housekeeping stuff */
11929 /* we had to allocate for this iCode */
11930 pic16_freeAsmop(NULL,aop,ic,TRUE);
11932 /* we did not allocate which means left
11933 already in a pointer register, then
11934 if size > 0 && this could be used again
11935 we have to point it back to where it
11937 if (AOP_SIZE(right) > 1 &&
11938 !OP_SYMBOL(result)->remat &&
11939 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11941 int size = AOP_SIZE(right) - 1;
11943 pic16_emitcode("dec","%s",rname);
11948 pic16_freeAsmop(right,NULL,ic,TRUE);
11953 /*-----------------------------------------------------------------*/
11954 /* genFarPointerSet - set value from far space */
11955 /*-----------------------------------------------------------------*/
11956 static void genFarPointerSet (operand *right,
11957 operand *result, iCode *ic)
11960 sym_link *retype = getSpec(operandType(right));
11962 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11963 pic16_aopOp(result,ic,FALSE);
11965 /* if the operand is already in dptr
11966 then we do nothing else we move the value to dptr */
11967 if (AOP_TYPE(result) != AOP_STR) {
11968 /* if this is remateriazable */
11969 if (AOP_TYPE(result) == AOP_IMMD)
11970 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11971 else { /* we need to get it byte by byte */
11972 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11973 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11974 if (options.model == MODEL_FLAT24)
11976 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11980 /* so dptr know contains the address */
11981 pic16_freeAsmop(result,NULL,ic,TRUE);
11982 pic16_aopOp(right,ic,FALSE);
11984 /* if bit then unpack */
11985 if (IS_BITFIELD(retype))
11986 genPackBits(retype,result,right,"dptr",FPOINTER);
11988 size = AOP_SIZE(right);
11992 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11994 pic16_emitcode("movx","@dptr,a");
11996 pic16_emitcode("inc","dptr");
12000 pic16_freeAsmop(right,NULL,ic,TRUE);
12003 /*-----------------------------------------------------------------*/
12004 /* genGenPointerSet - set value from generic pointer space */
12005 /*-----------------------------------------------------------------*/
12007 static void genGenPointerSet (operand *right,
12008 operand *result, iCode *ic)
12010 int i, size, offset, lit;
12011 sym_link *retype = getSpec(operandType(right));
12013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12015 pic16_aopOp(result,ic,FALSE);
12016 pic16_aopOp(right,ic,FALSE);
12017 size = AOP_SIZE(right);
12020 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12022 /* if the operand is already in dptr
12023 then we do nothing else we move the value to dptr */
12024 if (AOP_TYPE(result) != AOP_STR) {
12025 /* if this is remateriazable */
12026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12027 // WARNING: anythig until "else" is untested!
12028 if (AOP_TYPE(result) == AOP_IMMD) {
12029 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12030 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12031 // load FSR0 from immediate
12032 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12036 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12038 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12044 else { /* we need to get it byte by byte */
12045 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12046 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12048 // set up FSR0 with address of result
12049 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12050 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12052 /* hack hack! see if this the FSR. If so don't load W */
12053 if(AOP_TYPE(right) != AOP_ACC) {
12055 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12057 if(AOP_TYPE(right) == AOP_LIT)
12060 // note: pic16_popGet handles sign extension
12061 for(i=0;i<size;i++) {
12062 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12064 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12066 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12071 for(i=0;i<size;i++) {
12073 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12074 pic16_popCopyReg(&pic16_pc_postinc0)));
12076 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12077 pic16_popCopyReg(&pic16_pc_indf0)));
12083 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12084 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12086 } // if (AOP_TYPE(result) != AOP_IMMD)
12088 } // if (AOP_TYPE(result) != AOP_STR)
12089 /* so dptr know contains the address */
12092 /* if bit then unpack */
12093 if (IS_BITFIELD(retype))
12094 genPackBits(retype,result,right,"dptr",GPOINTER);
12096 size = AOP_SIZE(right);
12099 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12101 // set up FSR0 with address of result
12102 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12103 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12106 if (AOP_TYPE(right) == AOP_LIT) {
12107 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12109 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12111 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12113 } else { // no literal
12115 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12117 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12125 pic16_freeAsmop(right,NULL,ic,TRUE);
12126 pic16_freeAsmop(result,NULL,ic,TRUE);
12130 static void genGenPointerSet (operand *right,
12131 operand *result, iCode *ic)
12134 sym_link *retype = getSpec(operandType(right));
12137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12139 pic16_aopOp(result,ic,FALSE);
12140 pic16_aopOp(right,ic,FALSE);
12141 size = AOP_SIZE(right);
12143 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12146 /* if bit then unpack */
12147 if (IS_BITFIELD(retype)) {
12148 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12149 genPackBits(retype,result,right,"dptr",GPOINTER);
12153 size = AOP_SIZE(right);
12155 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12159 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12161 /* value of right+0 is placed on stack, which will be retrieved
12162 * by the support function this restoring the stack. The important
12163 * thing is that there is no need to manually restore stack pointer
12165 pushaop(AOP(right), 0);
12166 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12167 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12168 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12169 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12171 /* load address to write to in WREG:FSR0H:FSR0L */
12172 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12173 pic16_popCopyReg(&pic16_pc_fsr0l)));
12174 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12175 pic16_popCopyReg(&pic16_pc_prodl)));
12176 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12179 /* put code here */
12181 case 1: strcpy(fgptrput, "__gptrput1"); break;
12182 case 2: strcpy(fgptrput, "__gptrput2"); break;
12183 case 3: strcpy(fgptrput, "__gptrput3"); break;
12184 case 4: strcpy(fgptrput, "__gptrput4"); break;
12186 werror(W_POSSBUG2, __FILE__, __LINE__);
12190 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12195 sym = newSymbol( fgptrput, 0 );
12197 strcpy(sym->rname, fgptrput);
12198 checkAddSym(&externs, sym);
12202 pic16_freeAsmop(right,NULL,ic,TRUE);
12203 pic16_freeAsmop(result,NULL,ic,TRUE);
12206 /*-----------------------------------------------------------------*/
12207 /* genPointerSet - stores the value into a pointer location */
12208 /*-----------------------------------------------------------------*/
12209 static void genPointerSet (iCode *ic)
12211 operand *right, *result ;
12212 sym_link *type, *etype;
12217 right = IC_RIGHT(ic);
12218 result = IC_RESULT(ic) ;
12220 /* depending on the type of pointer we need to
12221 move it to the correct pointer register */
12222 type = operandType(result);
12223 etype = getSpec(type);
12224 /* if left is of type of pointer then it is simple */
12225 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12226 p_type = DCL_TYPE(type);
12229 /* we have to go by the storage class */
12230 p_type = PTR_TYPE(SPEC_OCLS(etype));
12232 /* if (SPEC_OCLS(etype)->codesp ) { */
12233 /* p_type = CPOINTER ; */
12236 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12237 /* p_type = FPOINTER ; */
12239 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12240 /* p_type = PPOINTER ; */
12242 /* if (SPEC_OCLS(etype) == idata ) */
12243 /* p_type = IPOINTER ; */
12245 /* p_type = POINTER ; */
12248 /* now that we have the pointer type we assign
12249 the pointer values */
12253 genNearPointerSet (right,result,ic);
12257 genPagedPointerSet (right,result,ic);
12261 genFarPointerSet (right,result,ic);
12265 genGenPointerSet (right,result,ic);
12269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12270 "genPointerSet: illegal pointer type");
12274 /*-----------------------------------------------------------------*/
12275 /* genIfx - generate code for Ifx statement */
12276 /*-----------------------------------------------------------------*/
12277 static void genIfx (iCode *ic, iCode *popIc)
12279 operand *cond = IC_COND(ic);
12284 pic16_aopOp(cond,ic,FALSE);
12286 /* get the value into acc */
12287 if (AOP_TYPE(cond) != AOP_CRY)
12288 pic16_toBoolean(cond);
12291 /* the result is now in the accumulator */
12292 pic16_freeAsmop(cond,NULL,ic,TRUE);
12294 /* if there was something to be popped then do it */
12298 /* if the condition is a bit variable */
12299 if (isbit && IS_ITEMP(cond) &&
12301 genIfxJump(ic,"c");
12302 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12304 if (isbit && !IS_ITEMP(cond))
12305 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12307 genIfxJump(ic,"a");
12312 /*-----------------------------------------------------------------*/
12313 /* genAddrOf - generates code for address of */
12314 /*-----------------------------------------------------------------*/
12315 static void genAddrOf (iCode *ic)
12317 operand *result, *left;
12319 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12320 pCodeOp *pcop0, *pcop1, *pcop2;
12324 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12326 sym = OP_SYMBOL( IC_LEFT(ic) );
12329 /* get address of symbol on stack */
12330 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12332 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12333 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12336 // operands on stack are accessible via "FSR2 + index" with index
12337 // starting at 2 for arguments and growing from 0 downwards for
12338 // local variables (index == 0 is not assigned so we add one here)
12340 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12342 assert (soffs < 0);
12345 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12346 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12347 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12348 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12349 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12350 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12351 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12357 // if(pic16_debug_verbose) {
12358 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12359 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12362 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12363 size = AOP_SIZE(IC_RESULT(ic));
12365 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12366 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12367 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12370 pic16_emitpcode(POC_MOVLW, pcop0);
12371 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12372 pic16_emitpcode(POC_MOVLW, pcop1);
12373 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12374 pic16_emitpcode(POC_MOVLW, pcop2);
12375 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12378 pic16_emitpcode(POC_MOVLW, pcop0);
12379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12380 pic16_emitpcode(POC_MOVLW, pcop1);
12381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12383 pic16_emitpcode(POC_MOVLW, pcop0);
12384 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12387 pic16_freeAsmop(left, NULL, ic, FALSE);
12389 pic16_freeAsmop(result,NULL,ic,TRUE);
12394 /*-----------------------------------------------------------------*/
12395 /* genFarFarAssign - assignment when both are in far space */
12396 /*-----------------------------------------------------------------*/
12397 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12399 int size = AOP_SIZE(right);
12402 /* first push the right side on to the stack */
12404 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12406 pic16_emitcode ("push","acc");
12409 pic16_freeAsmop(right,NULL,ic,FALSE);
12410 /* now assign DPTR to result */
12411 pic16_aopOp(result,ic,FALSE);
12412 size = AOP_SIZE(result);
12414 pic16_emitcode ("pop","acc");
12415 pic16_aopPut(AOP(result),"a",--offset);
12417 pic16_freeAsmop(result,NULL,ic,FALSE);
12422 /*-----------------------------------------------------------------*/
12423 /* genAssign - generate code for assignment */
12424 /*-----------------------------------------------------------------*/
12425 static void genAssign (iCode *ic)
12427 operand *result, *right;
12428 int size, offset,know_W;
12429 unsigned long lit = 0L;
12431 result = IC_RESULT(ic);
12432 right = IC_RIGHT(ic) ;
12436 /* if they are the same */
12437 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12440 /* reversed order operands are aopOp'ed so that result operand
12441 * is effective in case right is a stack symbol. This maneauver
12442 * allows to use the _G.resDirect flag later */
12443 pic16_aopOp(result,ic,TRUE);
12444 pic16_aopOp(right,ic,FALSE);
12446 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12448 /* if they are the same registers */
12449 if (pic16_sameRegs(AOP(right),AOP(result)))
12452 /* if the result is a bit */
12453 if (AOP_TYPE(result) == AOP_CRY) {
12454 /* if the right size is a literal then
12455 we know what the value is */
12456 if (AOP_TYPE(right) == AOP_LIT) {
12458 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12459 pic16_popGet(AOP(result),0));
12461 if (((int) operandLitValue(right)))
12462 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12463 AOP(result)->aopu.aop_dir,
12464 AOP(result)->aopu.aop_dir);
12466 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12467 AOP(result)->aopu.aop_dir,
12468 AOP(result)->aopu.aop_dir);
12472 /* the right is also a bit variable */
12473 if (AOP_TYPE(right) == AOP_CRY) {
12474 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12475 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12476 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12478 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12479 AOP(result)->aopu.aop_dir,
12480 AOP(result)->aopu.aop_dir);
12481 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12482 AOP(right)->aopu.aop_dir,
12483 AOP(right)->aopu.aop_dir);
12484 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12485 AOP(result)->aopu.aop_dir,
12486 AOP(result)->aopu.aop_dir);
12490 /* we need to or */
12491 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12492 pic16_toBoolean(right);
12494 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12495 //pic16_aopPut(AOP(result),"a",0);
12499 /* bit variables done */
12501 size = AOP_SIZE(result);
12504 if(AOP_TYPE(right) == AOP_LIT) {
12505 if(!IS_FLOAT(operandType( right )))
12506 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12509 unsigned long lit_int;
12513 /* take care if literal is a float */
12514 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12515 lit = info.lit_int;
12519 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12520 // sizeof(unsigned long int), sizeof(float));
12523 if (AOP_TYPE(right) == AOP_REG) {
12524 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12527 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12532 if(AOP_TYPE(right) != AOP_LIT
12533 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12534 && !IS_FUNC(OP_SYM_TYPE(right))
12536 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12537 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12539 // set up table pointer
12540 if(is_LitOp(right)) {
12541 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12542 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12543 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12544 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12545 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12546 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12547 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12549 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12550 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12551 pic16_popCopyReg(&pic16_pc_tblptrl)));
12552 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12553 pic16_popCopyReg(&pic16_pc_tblptrh)));
12554 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12555 pic16_popCopyReg(&pic16_pc_tblptru)));
12558 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12560 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12561 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12562 pic16_popGet(AOP(result),offset)));
12566 size = getSize(OP_SYM_ETYPE(right));
12567 if(AOP_SIZE(result) > size) {
12568 size = AOP_SIZE(result) - size;
12570 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12580 /* VR - What is this?! */
12581 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12582 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12583 if(aopIdx(AOP(result),0) == 4) {
12585 /* this is a workaround to save value of right into wreg too,
12586 * value of wreg is going to be used later */
12587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12588 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12593 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12599 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12600 if(AOP_TYPE(right) == AOP_LIT) {
12602 if(know_W != (lit&0xff))
12603 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12605 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12607 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12611 } else if (AOP_TYPE(right) == AOP_CRY) {
12612 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12614 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12615 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12616 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12618 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12619 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12620 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12624 if(!_G.resDirect) /* use this aopForSym feature */
12625 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12632 pic16_freeAsmop (right,NULL,ic,FALSE);
12633 pic16_freeAsmop (result,NULL,ic,TRUE);
12636 /*-----------------------------------------------------------------*/
12637 /* genJumpTab - generates code for jump table */
12638 /*-----------------------------------------------------------------*/
12639 static void genJumpTab (iCode *ic)
12644 pCodeOp *jt_offs_hi;
12649 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12650 /* get the condition into accumulator */
12651 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12653 /* multiply by three */
12654 pic16_emitcode("add","a,acc");
12655 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12657 jtab = newiTempLabel(NULL);
12658 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12659 pic16_emitcode("jmp","@a+dptr");
12660 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12663 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12664 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12666 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12667 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12668 pic16_emitpLabel(jtab->key);
12672 jt_offs = pic16_popGetTempReg(0);
12673 jt_offs_hi = pic16_popGetTempReg(1);
12674 jt_label = pic16_popGetLabel (jtab->key);
12675 //fprintf (stderr, "Creating jump table...\n");
12677 // calculate offset into jump table (idx * sizeof (GOTO))
12678 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12679 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12680 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12681 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12682 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12683 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12684 pic16_emitpcode(POC_MOVWF , jt_offs);
12686 // prepare PCLATx (set to first entry in jump table)
12687 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12688 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12689 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12690 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12691 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12693 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12694 pic16_emitpcode(POC_ADDWF , jt_offs);
12695 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12696 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12698 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12700 // release temporaries and prepare jump into table (new PCL --> WREG)
12701 pic16_emitpcode(POC_MOVFW , jt_offs);
12702 pic16_popReleaseTempReg (jt_offs_hi, 1);
12703 pic16_popReleaseTempReg (jt_offs, 0);
12705 // jump into the table
12706 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12708 pic16_emitpLabelFORCE(jtab->key);
12711 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12712 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12714 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12715 /* now generate the jump labels */
12716 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12717 jtab = setNextItem(IC_JTLABELS(ic))) {
12718 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12719 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12722 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12726 /*-----------------------------------------------------------------*/
12727 /* genMixedOperation - gen code for operators between mixed types */
12728 /*-----------------------------------------------------------------*/
12730 TSD - Written for the PIC port - but this unfortunately is buggy.
12731 This routine is good in that it is able to efficiently promote
12732 types to different (larger) sizes. Unfortunately, the temporary
12733 variables that are optimized out by this routine are sometimes
12734 used in other places. So until I know how to really parse the
12735 iCode tree, I'm going to not be using this routine :(.
12737 static int genMixedOperation (iCode *ic)
12740 operand *result = IC_RESULT(ic);
12741 sym_link *ctype = operandType(IC_LEFT(ic));
12742 operand *right = IC_RIGHT(ic);
12748 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12750 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12756 nextright = IC_RIGHT(nextic);
12757 nextleft = IC_LEFT(nextic);
12758 nextresult = IC_RESULT(nextic);
12760 pic16_aopOp(right,ic,FALSE);
12761 pic16_aopOp(result,ic,FALSE);
12762 pic16_aopOp(nextright, nextic, FALSE);
12763 pic16_aopOp(nextleft, nextic, FALSE);
12764 pic16_aopOp(nextresult, nextic, FALSE);
12766 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12768 operand *t = right;
12772 pic16_emitcode(";remove right +","");
12774 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12776 operand *t = right;
12780 pic16_emitcode(";remove left +","");
12784 big = AOP_SIZE(nextleft);
12785 small = AOP_SIZE(nextright);
12787 switch(nextic->op) {
12790 pic16_emitcode(";optimize a +","");
12791 /* if unsigned or not an integral type */
12792 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12793 pic16_emitcode(";add a bit to something","");
12796 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12798 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12799 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12800 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12802 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12810 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12811 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12812 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12815 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12817 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12818 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12819 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12820 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12821 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12824 pic16_emitcode("rlf","known_zero,w");
12831 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12832 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12833 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12835 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12845 pic16_freeAsmop(right,NULL,ic,TRUE);
12846 pic16_freeAsmop(result,NULL,ic,TRUE);
12847 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12848 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12850 nextic->generated = 1;
12857 /*-----------------------------------------------------------------*/
12858 /* genCast - gen code for casting */
12859 /*-----------------------------------------------------------------*/
12860 static void genCast (iCode *ic)
12862 operand *result = IC_RESULT(ic);
12863 sym_link *ctype = operandType(IC_LEFT(ic));
12864 sym_link *rtype = operandType(IC_RIGHT(ic));
12865 sym_link *restype = operandType(IC_RESULT(ic));
12866 operand *right = IC_RIGHT(ic);
12872 /* if they are equivalent then do nothing */
12873 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12876 pic16_aopOp(result,ic,FALSE);
12877 pic16_aopOp(right,ic,FALSE) ;
12879 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12882 /* if the result is a bit */
12883 if (AOP_TYPE(result) == AOP_CRY) {
12885 /* if the right size is a literal then
12886 * we know what the value is */
12887 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12889 if (AOP_TYPE(right) == AOP_LIT) {
12890 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12891 pic16_popGet(AOP(result),0));
12893 if (((int) operandLitValue(right)))
12894 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12895 AOP(result)->aopu.aop_dir,
12896 AOP(result)->aopu.aop_dir);
12898 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12899 AOP(result)->aopu.aop_dir,
12900 AOP(result)->aopu.aop_dir);
12904 /* the right is also a bit variable */
12905 if (AOP_TYPE(right) == AOP_CRY) {
12907 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12909 pic16_emitcode("clrc","");
12910 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12911 AOP(right)->aopu.aop_dir,
12912 AOP(right)->aopu.aop_dir);
12913 pic16_aopPut(AOP(result),"c",0);
12917 /* we need to or */
12918 if (AOP_TYPE(right) == AOP_REG) {
12919 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12920 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12921 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12923 pic16_toBoolean(right);
12924 pic16_aopPut(AOP(result),"a",0);
12928 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12931 size = AOP_SIZE(result);
12933 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12935 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12936 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12937 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12940 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12945 if(IS_BITFIELD(getSpec(restype))
12946 && IS_BITFIELD(getSpec(rtype))) {
12947 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12950 /* if they are the same size : or less */
12951 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12953 /* if they are in the same place */
12954 if (pic16_sameRegs(AOP(right),AOP(result)))
12957 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12959 if (IS_PTR_CONST(rtype))
12961 if (IS_CODEPTR(rtype))
12963 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12966 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12968 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12970 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12973 if(AOP_TYPE(right) == AOP_IMMD) {
12974 pCodeOp *pcop0, *pcop1, *pcop2;
12975 symbol *sym = OP_SYMBOL( right );
12977 size = AOP_SIZE(result);
12979 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12981 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12983 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12986 pic16_emitpcode(POC_MOVLW, pcop0);
12987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12988 pic16_emitpcode(POC_MOVLW, pcop1);
12989 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12990 pic16_emitpcode(POC_MOVLW, pcop2);
12991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12994 pic16_emitpcode(POC_MOVLW, pcop0);
12995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12996 pic16_emitpcode(POC_MOVLW, pcop1);
12997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12999 pic16_emitpcode(POC_MOVLW, pcop0);
13000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13004 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13005 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13007 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13009 if(AOP_SIZE(result) <2)
13010 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13012 /* if they in different places then copy */
13013 size = AOP_SIZE(result);
13016 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13024 /* if the result is of type pointer */
13025 if (IS_PTR(ctype)) {
13027 sym_link *type = operandType(right);
13028 sym_link *etype = getSpec(type);
13030 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13032 /* pointer to generic pointer */
13033 if (IS_GENPTR(ctype)) {
13037 p_type = DCL_TYPE(type);
13039 /* we have to go by the storage class */
13040 p_type = PTR_TYPE(SPEC_OCLS(etype));
13042 /* if (SPEC_OCLS(etype)->codesp ) */
13043 /* p_type = CPOINTER ; */
13045 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13046 /* p_type = FPOINTER ; */
13048 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13049 /* p_type = PPOINTER; */
13051 /* if (SPEC_OCLS(etype) == idata ) */
13052 /* p_type = IPOINTER ; */
13054 /* p_type = POINTER ; */
13057 /* the first two bytes are known */
13058 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13059 size = GPTRSIZE - 1;
13062 if(offset < AOP_SIZE(right)) {
13063 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13064 mov2f(AOP(result), AOP(right), offset);
13066 if ((AOP_TYPE(right) == AOP_PCODE) &&
13067 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13068 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13072 pic16_aopPut(AOP(result),
13073 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13078 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13081 /* the last byte depending on type */
13085 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13087 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13091 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13095 pic16_emitcode(";BUG!? ","%d",__LINE__);
13099 pic16_emitcode(";BUG!? ","%d",__LINE__);
13104 if (GPTRSIZE > AOP_SIZE(right)) {
13105 // assume data pointer... THIS MIGHT BE WRONG!
13106 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13107 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13109 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13114 /* this should never happen */
13115 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13116 "got unknown pointer type");
13119 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13125 /* just copy the pointers */
13126 size = AOP_SIZE(result);
13129 pic16_aopPut(AOP(result),
13130 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13139 /* so we now know that the size of destination is greater
13140 than the size of the source.
13141 Now, if the next iCode is an operator then we might be
13142 able to optimize the operation without performing a cast.
13144 if(genMixedOperation(ic))
13147 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13149 /* we move to result for the size of source */
13150 size = AOP_SIZE(right);
13155 mov2f(AOP(result), AOP(right), offset);
13159 /* now depending on the sign of the destination */
13160 size = AOP_SIZE(result) - AOP_SIZE(right);
13161 /* if unsigned or not an integral type */
13162 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13164 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13166 /* we need to extend the sign :( */
13169 /* Save one instruction of casting char to int */
13170 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13171 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13172 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13174 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13177 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13179 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13181 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13184 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13189 pic16_freeAsmop(right,NULL,ic,TRUE);
13190 pic16_freeAsmop(result,NULL,ic,TRUE);
13194 /*-----------------------------------------------------------------*/
13195 /* genDjnz - generate decrement & jump if not zero instrucion */
13196 /*-----------------------------------------------------------------*/
13197 static int genDjnz (iCode *ic, iCode *ifx)
13199 symbol *lbl, *lbl1;
13200 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13205 /* if the if condition has a false label
13206 then we cannot save */
13210 /* if the minus is not of the form
13212 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13213 !IS_OP_LITERAL(IC_RIGHT(ic)))
13216 if (operandLitValue(IC_RIGHT(ic)) != 1)
13219 /* if the size of this greater than one then no
13221 if (getSize(operandType(IC_RESULT(ic))) > 1)
13224 /* otherwise we can save BIG */
13225 lbl = newiTempLabel(NULL);
13226 lbl1= newiTempLabel(NULL);
13228 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13230 if (IS_AOP_PREG(IC_RESULT(ic))) {
13231 pic16_emitcode("dec","%s",
13232 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13233 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13234 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13238 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13239 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13241 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13242 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13246 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13247 ifx->generated = 1;
13251 /*-----------------------------------------------------------------*/
13252 /* genReceive - generate code for a receive iCode */
13253 /*-----------------------------------------------------------------*/
13254 static void genReceive (iCode *ic)
13260 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13261 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13263 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13265 if (isOperandInFarSpace(IC_RESULT(ic))
13266 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13267 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13269 int size = getSize(operandType(IC_RESULT(ic)));
13270 int offset = pic16_fReturnSizePic - size;
13274 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13275 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13279 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13281 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13282 size = AOP_SIZE(IC_RESULT(ic));
13285 pic16_emitcode ("pop","acc");
13286 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13289 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13291 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13294 /* set pseudo stack pointer to where it should be - dw*/
13295 GpsuedoStkPtr = ic->parmBytes;
13297 /* setting GpsuedoStkPtr has side effects here: */
13298 assignResultValue(IC_RESULT(ic), 0);
13301 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13304 /*-----------------------------------------------------------------*/
13305 /* genDummyRead - generate code for dummy read of volatiles */
13306 /*-----------------------------------------------------------------*/
13308 genDummyRead (iCode * ic)
13314 if (op && IS_SYMOP(op)) {
13315 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13316 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13319 pic16_aopOp (op, ic, FALSE);
13320 for (i=0; i < AOP_SIZE(op); i++) {
13321 // may need to protect this from the peepholer -- this is not nice but works...
13322 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13323 pic16_mov2w (AOP(op),i);
13324 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13326 pic16_freeAsmop (op, NULL, ic, TRUE);
13328 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13332 /*-----------------------------------------------------------------*/
13333 /* genpic16Code - generate code for pic16 based controllers */
13334 /*-----------------------------------------------------------------*/
13336 * At this point, ralloc.c has gone through the iCode and attempted
13337 * to optimize in a way suitable for a PIC. Now we've got to generate
13338 * PIC instructions that correspond to the iCode.
13340 * Once the instructions are generated, we'll pass through both the
13341 * peep hole optimizer and the pCode optimizer.
13342 *-----------------------------------------------------------------*/
13344 void genpic16Code (iCode *lic)
13349 lineHead = lineCurr = NULL;
13351 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13352 pic16_addpBlock(pb);
13355 /* if debug information required */
13356 if (options.debug && currFunc) {
13358 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13363 for (ic = lic ; ic ; ic = ic->next ) {
13365 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13366 if ( cln != ic->lineno ) {
13367 if ( options.debug ) {
13368 debugFile->writeCLine (ic);
13371 if(!options.noCcodeInAsm) {
13372 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13373 printCLine(ic->filename, ic->lineno)));
13379 if(options.iCodeInAsm) {
13382 /* insert here code to print iCode as comment */
13383 l = Safe_strdup(printILine(ic));
13384 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13387 /* if the result is marked as
13388 * spilt and rematerializable or code for
13389 * this has already been generated then
13391 if (resultRemat(ic) || ic->generated )
13394 /* depending on the operation */
13413 /* IPOP happens only when trying to restore a
13414 * spilt live range, if there is an ifx statement
13415 * following this pop then the if statement might
13416 * be using some of the registers being popped which
13417 * would destroy the contents of the register so
13418 * we need to check for this condition and handle it */
13420 && ic->next->op == IFX
13421 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13422 genIfx (ic->next,ic);
13440 genEndFunction (ic);
13456 pic16_genPlus (ic) ;
13460 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13461 pic16_genMinus (ic);
13477 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13481 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13487 /* note these two are xlated by algebraic equivalence
13488 * during parsing SDCC.y */
13489 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13490 "got '>=' or '<=' shouldn't have come here");
13494 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13506 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13510 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13514 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13538 genRightShift (ic);
13541 case GET_VALUE_AT_ADDRESS:
13546 if (POINTER_SET(ic))
13573 addSet(&_G.sendSet,ic);
13576 case DUMMY_READ_VOLATILE:
13586 /* now we are ready to call the
13587 peep hole optimizer */
13588 if (!options.nopeep)
13589 peepHole (&lineHead);
13591 /* now do the actual printing */
13592 printLine (lineHead, codeOutFile);
13595 DFPRINTF((stderr,"printing pBlock\n\n"));
13596 pic16_printpBlock(stdout,pb);