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 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5030 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5032 assert (isAOP_LIT(left));
5033 assert (isAOP_REGlike(right));
5034 // swap left and right
5035 // left < right <==> right > left <==> (right >= left + 1)
5036 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5038 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5039 // MAXVALUE < right? always false
5040 if (performedLt) emitCLRC; else emitSETC;
5041 goto correct_result_in_carry;
5044 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5045 // that's we handled it above.
5052 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5053 } else if (isAOP_LIT(right)) {
5054 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5057 assert (isAOP_REGlike(left)); // left must be register or the like
5058 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5060 /*************************************************
5061 * special cases go here *
5062 *************************************************/
5064 if (isAOP_LIT(right)) {
5066 // unsigned comparison to a literal
5067 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5068 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5071 // unsigned left < 0? always false
5072 if (performedLt) emitCLRC; else emitSETC;
5073 goto correct_result_in_carry;
5076 // signed comparison to a literal
5077 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5078 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5080 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5081 // signed left < 0x80000000? always false
5082 if (performedLt) emitCLRC; else emitSETC;
5083 goto correct_result_in_carry;
5084 } else if (lit == 0) {
5085 // compare left < 0; set CARRY if SIGNBIT(left) is set
5086 if (performedLt) emitSETC; else emitCLRC;
5087 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5088 if (performedLt) emitCLRC; else emitSETC;
5089 goto correct_result_in_carry;
5092 } // right is literal
5094 /*************************************************
5095 * perform a general case comparison *
5096 * make sure we get CARRY==1 <==> left >= right *
5097 *************************************************/
5098 // compare most significant bytes
5099 //DEBUGpc ("comparing bytes at offset %d", size);
5101 // unsigned comparison
5102 mov2w_regOrLit (AOP(right), lit, size);
5103 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5105 // signed comparison
5106 // (add 2^n to both operands then perform an unsigned comparison)
5107 if (isAOP_LIT(right)) {
5108 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5109 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5111 if (litbyte == 0x80) {
5112 // left >= 0x80 -- always true, but more bytes to come
5113 pic16_mov2w (AOP(left), size);
5114 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5117 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5118 pic16_mov2w (AOP(left), size);
5119 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5120 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5123 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5124 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5125 pic16_mov2w (AOP(left), size);
5126 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127 pic16_emitpcode (POC_MOVWF, pctemp);
5128 pic16_mov2w (AOP(right), size);
5129 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5130 pic16_emitpcode (POC_SUBFW, pctemp);
5131 //pic16_popReleaseTempReg(pctemp, 1);
5135 // compare remaining bytes (treat as unsigned case from above)
5136 templbl = newiTempLabel ( NULL );
5139 //DEBUGpc ("comparing bytes at offset %d", offs);
5140 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5141 mov2w_regOrLit (AOP(right), lit, offs);
5142 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5144 pic16_emitpLabel (templbl->key);
5145 goto result_in_carry;
5149 /****************************************************
5150 * now CARRY contains the result of the comparison: *
5151 * SUBWF sets CARRY iff *
5152 * F-W >= 0 <==> F >= W <==> !(F < W) *
5154 ****************************************************/
5157 if (result && AOP_TYPE(result) != AOP_CRY) {
5158 // value will be stored
5161 // value wil only be used in the following genSkipc()
5162 rIfx.condition ^= 1;
5166 correct_result_in_carry:
5168 // assign result to variable (if neccessary)
5169 if (result && AOP_TYPE(result) != AOP_CRY) {
5170 //DEBUGpc ("assign result");
5171 size = AOP_SIZE(result);
5173 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5175 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5178 // perform conditional jump
5179 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5181 //DEBUGpc ("generate control flow");
5182 rIfx.condition ^= 1;
5191 static void genCmp (operand *left,operand *right,
5192 operand *result, iCode *ifx, int sign)
5194 int size; //, offset = 0 ;
5195 unsigned long lit = 0L,i = 0;
5196 resolvedIfx rFalseIfx;
5197 // resolvedIfx rTrueIfx;
5199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5202 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5203 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5209 resolveIfx(&rFalseIfx,ifx);
5210 truelbl = newiTempLabel(NULL);
5211 size = max(AOP_SIZE(left),AOP_SIZE(right));
5213 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5217 /* if literal is on the right then swap with left */
5218 if ((AOP_TYPE(right) == AOP_LIT)) {
5219 operand *tmp = right ;
5220 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5221 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5224 lit = (lit - 1) & mask;
5227 rFalseIfx.condition ^= 1;
5230 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5231 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5235 //if(IC_TRUE(ifx) == NULL)
5236 /* if left & right are bit variables */
5237 if (AOP_TYPE(left) == AOP_CRY &&
5238 AOP_TYPE(right) == AOP_CRY ) {
5239 assert (0 && "bit variables used in genCmp");
5240 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5241 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5243 /* subtract right from left if at the
5244 end the carry flag is set then we know that
5245 left is greater than right */
5247 symbol *lbl = newiTempLabel(NULL);
5250 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5251 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5255 if(AOP_TYPE(right) == AOP_LIT) {
5257 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5259 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5266 genSkipCond(&rFalseIfx,left,size-1,7);
5268 /* no need to compare to 0...*/
5269 /* NOTE: this is a de-generate compare that most certainly
5270 * creates some dead code. */
5271 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5273 if(ifx) ifx->generated = 1;
5280 //i = (lit >> (size*8)) & 0xff;
5281 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5283 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5285 i = ((0-lit) & 0xff);
5288 /* lit is 0x7f, all signed chars are less than
5289 * this except for 0x7f itself */
5290 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5291 genSkipz2(&rFalseIfx,0);
5293 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5294 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5295 genSkipc(&rFalseIfx);
5300 genSkipz2(&rFalseIfx,1);
5302 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5303 genSkipc(&rFalseIfx);
5307 if(ifx) ifx->generated = 1;
5311 /* chars are out of the way. now do ints and longs */
5314 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5321 genSkipCond(&rFalseIfx,left,size,7);
5322 if(ifx) ifx->generated = 1;
5327 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5329 //rFalseIfx.condition ^= 1;
5330 //genSkipCond(&rFalseIfx,left,size,7);
5331 //rFalseIfx.condition ^= 1;
5333 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5334 if(rFalseIfx.condition)
5335 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5337 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5339 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5340 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5341 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5344 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5346 if(rFalseIfx.condition) {
5348 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5354 genSkipc(&rFalseIfx);
5355 pic16_emitpLabel(truelbl->key);
5356 if(ifx) ifx->generated = 1;
5363 if( (lit & 0xff) == 0) {
5364 /* lower byte is zero */
5365 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5366 i = ((lit >> 8) & 0xff) ^0x80;
5367 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5368 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5369 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5370 genSkipc(&rFalseIfx);
5373 if(ifx) ifx->generated = 1;
5378 /* Special cases for signed longs */
5379 if( (lit & 0xffffff) == 0) {
5380 /* lower byte is zero */
5381 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5382 i = ((lit >> 8*3) & 0xff) ^0x80;
5383 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5384 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5385 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5386 genSkipc(&rFalseIfx);
5389 if(ifx) ifx->generated = 1;
5397 if(lit & (0x80 << (size*8))) {
5398 /* lit is negative */
5399 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5401 //genSkipCond(&rFalseIfx,left,size,7);
5403 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5405 if(rFalseIfx.condition)
5406 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5412 /* lit is positive */
5413 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5414 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5415 if(rFalseIfx.condition)
5416 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5418 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5423 This works, but is only good for ints.
5424 It also requires a "known zero" register.
5425 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5426 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5427 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5428 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5429 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5430 genSkipc(&rFalseIfx);
5432 pic16_emitpLabel(truelbl->key);
5433 if(ifx) ifx->generated = 1;
5437 /* There are no more special cases, so perform a general compare */
5439 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5440 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5444 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5448 //rFalseIfx.condition ^= 1;
5449 genSkipc(&rFalseIfx);
5451 pic16_emitpLabel(truelbl->key);
5453 if(ifx) ifx->generated = 1;
5460 /* sign is out of the way. So now do an unsigned compare */
5461 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5464 /* General case - compare to an unsigned literal on the right.*/
5466 i = (lit >> (size*8)) & 0xff;
5467 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5468 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5470 i = (lit >> (size*8)) & 0xff;
5473 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5475 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5477 /* this byte of the lit is zero,
5478 *if it's not the last then OR in the variable */
5480 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5485 pic16_emitpLabel(lbl->key);
5486 // pic16_emitpLabel(truelbl->key);
5487 //if(emitFinalCheck)
5488 genSkipc(&rFalseIfx);
5490 pic16_emitpLabel(truelbl->key);
5492 if(ifx) ifx->generated = 1;
5499 if(AOP_TYPE(left) == AOP_LIT) {
5500 //symbol *lbl = newiTempLabel(NULL);
5502 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5505 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5508 if((lit == 0) && (sign == 0)){
5511 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5513 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5515 genSkipz2(&rFalseIfx,0);
5516 if(ifx) ifx->generated = 1;
5523 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5524 /* degenerate compare can never be true */
5525 if(rFalseIfx.condition == 0)
5526 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5528 if(ifx) ifx->generated = 1;
5533 /* signed comparisons to a literal byte */
5535 int lp1 = (lit+1) & 0xff;
5537 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5540 rFalseIfx.condition ^= 1;
5541 genSkipCond(&rFalseIfx,right,0,7);
5544 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5545 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5546 genSkipz2(&rFalseIfx,1);
5549 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5550 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5551 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5552 rFalseIfx.condition ^= 1;
5553 genSkipc(&rFalseIfx);
5557 /* unsigned comparisons to a literal byte */
5559 switch(lit & 0xff ) {
5561 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5562 genSkipz2(&rFalseIfx,0);
5565 rFalseIfx.condition ^= 1;
5566 genSkipCond(&rFalseIfx,right,0,7);
5570 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5571 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5573 rFalseIfx.condition ^= 1;
5574 if (AOP_TYPE(result) == AOP_CRY)
5575 genSkipc(&rFalseIfx);
5577 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5578 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5584 if(ifx) ifx->generated = 1;
5585 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5591 /* Size is greater than 1 */
5599 /* this means lit = 0xffffffff, or -1 */
5602 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5603 rFalseIfx.condition ^= 1;
5604 genSkipCond(&rFalseIfx,right,size,7);
5605 if(ifx) ifx->generated = 1;
5607 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5616 if(rFalseIfx.condition) {
5617 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5618 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5621 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5623 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5627 if(rFalseIfx.condition) {
5628 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5629 pic16_emitpLabel(truelbl->key);
5631 rFalseIfx.condition ^= 1;
5632 genSkipCond(&rFalseIfx,right,s,7);
5635 if(ifx) ifx->generated = 1;
5637 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5643 if((size == 1) && (0 == (lp1&0xff))) {
5644 /* lower byte of signed word is zero */
5645 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5646 i = ((lp1 >> 8) & 0xff) ^0x80;
5647 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5648 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5649 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5651 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5653 if(ifx) ifx->generated = 1;
5656 rFalseIfx.condition ^= 1;
5657 genSkipc(&rFalseIfx);
5658 if(ifx) ifx->generated = 1;
5664 if(lit & (0x80 << (size*8))) {
5665 /* Lit is less than zero */
5666 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5667 //rFalseIfx.condition ^= 1;
5668 //genSkipCond(&rFalseIfx,left,size,7);
5669 //rFalseIfx.condition ^= 1;
5670 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5671 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5673 if(rFalseIfx.condition)
5674 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5676 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5680 /* Lit is greater than or equal to zero */
5681 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5682 //rFalseIfx.condition ^= 1;
5683 //genSkipCond(&rFalseIfx,right,size,7);
5684 //rFalseIfx.condition ^= 1;
5686 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5687 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5689 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5690 if(rFalseIfx.condition)
5691 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5693 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5697 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5698 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5706 rFalseIfx.condition ^= 1;
5707 //rFalseIfx.condition = 1;
5708 genSkipc(&rFalseIfx);
5710 pic16_emitpLabel(truelbl->key);
5712 if(ifx) ifx->generated = 1;
5715 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5722 /* compare word or long to an unsigned literal on the right.*/
5727 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5730 break; /* handled above */
5733 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5735 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5736 genSkipz2(&rFalseIfx,0);
5740 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5742 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5745 if(rFalseIfx.condition)
5746 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5748 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5751 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5752 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5754 rFalseIfx.condition ^= 1;
5755 genSkipc(&rFalseIfx);
5758 pic16_emitpLabel(truelbl->key);
5760 if(ifx) ifx->generated = 1;
5762 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5770 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5771 i = (lit >> (size*8)) & 0xff;
5773 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5774 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5777 i = (lit >> (size*8)) & 0xff;
5780 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5782 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5784 /* this byte of the lit is zero,
5785 * if it's not the last then OR in the variable */
5787 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5792 pic16_emitpLabel(lbl->key);
5794 rFalseIfx.condition ^= 1;
5796 genSkipc(&rFalseIfx);
5800 pic16_emitpLabel(truelbl->key);
5801 if(ifx) ifx->generated = 1;
5803 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5809 /* Compare two variables */
5811 DEBUGpic16_emitcode(";sign","%d",sign);
5815 /* Sigh. thus sucks... */
5819 pctemp = pic16_popGetTempReg(1);
5820 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5821 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5822 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5823 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5825 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826 pic16_popReleaseTempReg(pctemp, 1);
5828 /* Signed char comparison */
5829 /* Special thanks to Nikolai Golovchenko for this snippet */
5830 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5831 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5832 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5833 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5834 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5835 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5838 genSkipc(&rFalseIfx);
5840 if(ifx) ifx->generated = 1;
5842 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5850 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5851 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5855 /* The rest of the bytes of a multi-byte compare */
5859 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5862 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5863 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5868 pic16_emitpLabel(lbl->key);
5870 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5871 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5872 (AOP_TYPE(result) == AOP_REG)) {
5873 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5874 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5876 genSkipc(&rFalseIfx);
5878 //genSkipc(&rFalseIfx);
5879 if(ifx) ifx->generated = 1;
5882 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5890 if ((AOP_TYPE(result) != AOP_CRY)
5891 && AOP_SIZE(result)) {
5892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5894 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5896 pic16_outBitC(result);
5898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5899 /* if the result is used in the next
5900 ifx conditional branch then generate
5901 code a little differently */
5903 genIfxJump (ifx,"c");
5905 pic16_outBitC(result);
5906 /* leave the result in acc */
5911 #elif 0 /* VR version of genCmp() */ /* } else { */
5913 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5914 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5915 operand *result, int offset, int invert_op)
5919 /* check condition, > or < ?? */
5920 if(rIfx->condition != 0)invert_op ^= 1;
5922 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5924 if(!ifx)invert_op ^= 1;
5926 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5927 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5930 if(!invert_op)return POC_CPFSGT;
5931 else return POC_CPFSLT;
5934 static int compareAopfirstpass=1;
5936 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5937 operand *oper, int offset, operand *result,
5938 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5944 /* invert if there is a result to be loaded, in order to fit,
5945 * SETC/CLRC sequence */
5946 if(AOP_SIZE(result))invert_op ^= 1;
5948 // if(sign && !offset)invert_op ^= 1;
5950 // if(sign)invert_op ^= 1;
5952 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5954 if(AOP_SIZE(result) && compareAopfirstpass) {
5957 pic16_emitpcode(POC_SETF, pcop2);
5962 pic16_emitpcode(POC_CLRF, pcop2);
5968 compareAopfirstpass = 0;
5970 /* there is a bug when comparing operands with size > 1,
5971 * because higher bytes can be equal and test should be performed
5972 * to the next lower byte, current algorithm, considers operands
5973 * inequal in these cases! -- VR 20041107 */
5977 pic16_emitpcode(op, pcop);
5979 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5982 if((!sign || !offset) && AOP_SIZE(result)) {
5985 pic16_emitpcode(POC_CLRF, pcop2);
5990 pic16_emitpcode(POC_SETF, pcop2);
5995 /* don't emit final branch (offset == 0) */
5999 pic16_emitpcode(POC_RRCF, pcop2);
6001 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6004 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6005 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6006 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6008 truelbl = newiTempLabel( NULL );
6009 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6010 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6011 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6013 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6014 pic16_emitpLabel(truelbl->key);
6016 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6021 static void genCmp (operand *left, operand *right,
6022 operand *result, iCode *ifx, int sign)
6026 resolvedIfx rFalseIfx;
6027 symbol *falselbl, *tlbl;
6031 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6033 resolveIfx(&rFalseIfx, ifx);
6034 size = max(AOP_SIZE(left), AOP_SIZE(right));
6036 /* if left & right are bit variables */
6037 if(AOP_TYPE(left) == AOP_CRY
6038 && AOP_TYPE(right) == AOP_CRY ) {
6040 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6041 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6043 werror(W_POSSBUG2, __FILE__, __LINE__);
6047 /* if literal is on the right then swap with left */
6048 if((AOP_TYPE(right) == AOP_LIT)) {
6049 operand *tmp = right ;
6050 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6052 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6054 // lit = (lit - 1) & mask;
6057 rFalseIfx.condition ^= 1; /* reverse compare */
6059 if ((AOP_TYPE(left) == AOP_LIT)) {
6060 /* float compares are handled by support functions */
6061 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6064 /* actual comparing algorithm */
6065 // size = AOP_SIZE( right );
6067 falselbl = newiTempLabel( NULL );
6068 if(AOP_TYPE(left) == AOP_LIT) {
6069 /* compare to literal */
6070 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6073 pCodeOp *pct, *pct2;
6076 /* signed compare */
6077 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6079 pct = pic16_popCopyReg(&pic16_pc_prodl);
6080 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6081 tlbl = newiTempLabel( NULL );
6083 /* first compare signs:
6084 * a. if both are positive, compare just like unsigned
6085 * b. if both are negative, invert cmpop, compare just like unsigned
6086 * c. if different signs, determine the result directly */
6092 tlbl1 = newiTempLabel( NULL );
6093 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6097 /* literal is zero or positive:
6098 * a. if carry is zero, too, continue compare,
6099 * b. if carry is set, then continue depending on cmpop ^ condition:
6100 * 1. '<' return false (literal < variable),
6101 * 2. '>' return true (literal > variable) */
6102 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6103 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6106 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6107 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6111 /* literal is negative:
6112 * a. if carry is set, too, continue compare,
6113 * b. if carry is zero, then continue depending on cmpop ^ condition:
6114 * 1. '<' return true (literal < variable),
6115 * 2. '>' return false (literal > variable) */
6116 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6117 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6119 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6120 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6125 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6127 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6128 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6133 pic16_emitpLabel( tlbl1->key );
6136 compareAopfirstpass=1;
6137 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6138 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6139 // pic16_emitpcode(POC_MOVWF, pct);
6141 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6142 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6143 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6144 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6148 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6149 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6150 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6151 // pic16_emitpcode(POC_MOVWF, pct);
6153 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6154 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6155 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6156 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6157 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6161 if(ifx)ifx->generated = 1;
6163 if(AOP_SIZE(result)) {
6164 pic16_emitpLabel(tlbl->key);
6165 pic16_emitpLabel(falselbl->key);
6166 pic16_outBitOp( result, pct2 );
6168 pic16_emitpLabel(tlbl->key);
6173 /* unsigned compare */
6174 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6176 compareAopfirstpass=1;
6179 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6180 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6184 if(ifx)ifx->generated = 1;
6187 if(AOP_SIZE(result)) {
6188 pic16_emitpLabel(falselbl->key);
6189 pic16_outBitC( result );
6194 /* compare registers */
6195 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6199 pCodeOp *pct, *pct2;
6201 /* signed compare */
6202 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6204 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6205 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6206 tlbl = newiTempLabel( NULL );
6208 compareAopfirstpass=1;
6211 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6212 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6213 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214 pic16_emitpcode(POC_MOVWF, pct);
6216 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6217 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6220 /* WREG already holds left + 0x80 */
6221 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6224 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6225 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6226 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6227 pic16_emitpcode(POC_MOVWF, pct);
6229 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6230 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6231 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6233 /* WREG already holds left + 0x80 */
6234 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6235 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6238 if(ifx)ifx->generated = 1;
6240 if(AOP_SIZE(result)) {
6241 pic16_emitpLabel(tlbl->key);
6242 pic16_emitpLabel(falselbl->key);
6243 pic16_outBitOp( result, pct2 );
6245 pic16_emitpLabel(tlbl->key);
6249 /* unsigned compare */
6250 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6252 compareAopfirstpass=1;
6255 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6256 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6260 if(ifx)ifx->generated = 1;
6261 if(AOP_SIZE(result)) {
6263 pic16_emitpLabel(falselbl->key);
6264 pic16_outBitC( result );
6275 /*-----------------------------------------------------------------*/
6276 /* genCmpGt :- greater than comparison */
6277 /*-----------------------------------------------------------------*/
6278 static void genCmpGt (iCode *ic, iCode *ifx)
6280 operand *left, *right, *result;
6281 sym_link *letype , *retype;
6287 right= IC_RIGHT(ic);
6288 result = IC_RESULT(ic);
6290 letype = getSpec(operandType(left));
6291 retype =getSpec(operandType(right));
6292 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6293 /* assign the amsops */
6294 pic16_aopOp (left,ic,FALSE);
6295 pic16_aopOp (right,ic,FALSE);
6296 pic16_aopOp (result,ic,TRUE);
6298 genCmp(right, left, result, ifx, sign);
6300 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6301 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6302 pic16_freeAsmop(result,NULL,ic,TRUE);
6305 /*-----------------------------------------------------------------*/
6306 /* genCmpLt - less than comparisons */
6307 /*-----------------------------------------------------------------*/
6308 static void genCmpLt (iCode *ic, iCode *ifx)
6310 operand *left, *right, *result;
6311 sym_link *letype , *retype;
6317 right= IC_RIGHT(ic);
6318 result = IC_RESULT(ic);
6320 letype = getSpec(operandType(left));
6321 retype =getSpec(operandType(right));
6322 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6324 /* assign the amsops */
6325 pic16_aopOp (left,ic,FALSE);
6326 pic16_aopOp (right,ic,FALSE);
6327 pic16_aopOp (result,ic,TRUE);
6329 genCmp(left, right, result, ifx, sign);
6331 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6332 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6333 pic16_freeAsmop(result,NULL,ic,TRUE);
6338 // FIXME reenable literal optimisation when the pic16 port is stable
6340 /*-----------------------------------------------------------------*/
6341 /* genc16bit2lit - compare a 16 bit value to a literal */
6342 /*-----------------------------------------------------------------*/
6343 static void genc16bit2lit(operand *op, int lit, int offset)
6347 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6348 if( (lit&0xff) == 0)
6353 switch( BYTEofLONG(lit,i)) {
6355 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6358 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6364 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6365 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6370 switch( BYTEofLONG(lit,i)) {
6372 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6376 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6380 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6383 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6385 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6394 /*-----------------------------------------------------------------*/
6395 /* gencjneshort - compare and jump if not equal */
6396 /*-----------------------------------------------------------------*/
6397 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6399 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6401 int res_offset = 0; /* the result may be a different size then left or right */
6402 int res_size = AOP_SIZE(result);
6404 symbol *lbl, *lbl_done;
6406 unsigned long lit = 0L;
6407 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6410 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6412 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6413 resolveIfx(&rIfx,ifx);
6414 lbl = newiTempLabel(NULL);
6415 lbl_done = newiTempLabel(NULL);
6418 /* if the left side is a literal or
6419 if the right is in a pointer register and left
6421 if ((AOP_TYPE(left) == AOP_LIT) ||
6422 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6427 if(AOP_TYPE(right) == AOP_LIT)
6428 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6430 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6431 preserve_result = 1;
6433 if(result && !preserve_result)
6436 for(i = 0; i < AOP_SIZE(result); i++)
6437 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6441 /* if the right side is a literal then anything goes */
6442 if (AOP_TYPE(right) == AOP_LIT &&
6443 AOP_TYPE(left) != AOP_DIR ) {
6446 genc16bit2lit(left, lit, 0);
6448 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6454 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6455 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6457 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6463 if(res_offset < res_size-1)
6471 /* if the right side is in a register or in direct space or
6472 if the left is a pointer register & right is not */
6473 else if (AOP_TYPE(right) == AOP_REG ||
6474 AOP_TYPE(right) == AOP_DIR ||
6475 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6476 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6477 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6478 int lbl_key = lbl->key;
6481 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6482 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6484 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6485 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6486 __FUNCTION__,__LINE__);
6490 /* switch(size) { */
6492 /* genc16bit2lit(left, lit, 0); */
6494 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6499 if((AOP_TYPE(left) == AOP_DIR) &&
6500 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6502 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6503 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6505 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6507 switch (lit & 0xff) {
6509 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6512 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6513 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6518 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6519 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6520 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6521 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6525 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6526 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6531 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6534 if(AOP_TYPE(result) == AOP_CRY) {
6535 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6540 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6542 /* fix me. probably need to check result size too */
6543 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6548 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6549 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6556 if(res_offset < res_size-1)
6561 } else if(AOP_TYPE(right) == AOP_REG &&
6562 AOP_TYPE(left) != AOP_DIR){
6565 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6566 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6567 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6572 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6574 if(res_offset < res_size-1)
6579 /* right is a pointer reg need both a & b */
6581 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6583 pic16_emitcode("mov","b,%s",l);
6584 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6585 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6590 if(result && preserve_result)
6593 for(i = 0; i < AOP_SIZE(result); i++)
6594 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6597 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6599 if(result && preserve_result)
6600 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6605 pic16_emitpLabel(lbl->key);
6607 if(result && preserve_result)
6610 for(i = 0; i < AOP_SIZE(result); i++)
6611 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6613 pic16_emitpLabel(lbl_done->key);
6616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6624 /*-----------------------------------------------------------------*/
6625 /* gencjne - compare and jump if not equal */
6626 /*-----------------------------------------------------------------*/
6627 static void gencjne(operand *left, operand *right, iCode *ifx)
6629 symbol *tlbl = newiTempLabel(NULL);
6631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6632 gencjneshort(left, right, lbl);
6634 pic16_emitcode("mov","a,%s",one);
6635 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6636 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6637 pic16_emitcode("clr","a");
6638 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6640 pic16_emitpLabel(lbl->key);
6641 pic16_emitpLabel(tlbl->key);
6647 /*-----------------------------------------------------------------*/
6648 /* is_LitOp - check if operand has to be treated as literal */
6649 /*-----------------------------------------------------------------*/
6650 static bool is_LitOp(operand *op)
6652 return ((AOP_TYPE(op) == AOP_LIT)
6653 || ( (AOP_TYPE(op) == AOP_PCODE)
6654 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6655 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6658 /*-----------------------------------------------------------------*/
6659 /* is_LitAOp - check if operand has to be treated as literal */
6660 /*-----------------------------------------------------------------*/
6661 static bool is_LitAOp(asmop *aop)
6663 return ((aop->type == AOP_LIT)
6664 || ( (aop->type == AOP_PCODE)
6665 && ( (aop->aopu.pcop->type == PO_LITERAL)
6666 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6671 /*-----------------------------------------------------------------*/
6672 /* genCmpEq - generates code for equal to */
6673 /*-----------------------------------------------------------------*/
6674 static void genCmpEq (iCode *ic, iCode *ifx)
6676 operand *left, *right, *result;
6677 symbol *falselbl = newiTempLabel(NULL);
6678 symbol *donelbl = newiTempLabel(NULL);
6680 int preserve_result = 0;
6681 int generate_result = 0;
6683 unsigned long lit = -1;
6687 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6688 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6689 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6691 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6693 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6695 werror(W_POSSBUG2, __FILE__, __LINE__);
6696 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6697 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6701 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6703 operand *tmp = right ;
6708 if (AOP_TYPE(right) == AOP_LIT) {
6709 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6712 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6713 preserve_result = 1;
6715 if(result && AOP_SIZE(result))
6716 generate_result = 1;
6718 if(generate_result && !preserve_result)
6720 for(i = 0; i < AOP_SIZE(result); i++)
6721 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6724 for(i=0; i < AOP_SIZE(left); i++)
6726 if(AOP_TYPE(left) != AOP_ACC)
6729 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6731 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6733 if(is_LitOp(right)) {
6734 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6735 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6738 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6740 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6745 if(generate_result && preserve_result)
6747 for(i = 0; i < AOP_SIZE(result); i++)
6748 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6752 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6754 if(generate_result && preserve_result)
6755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6757 if(ifx && IC_TRUE(ifx))
6758 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6760 if(ifx && IC_FALSE(ifx))
6761 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6763 pic16_emitpLabel(falselbl->key);
6767 if(ifx && IC_FALSE(ifx))
6768 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6770 if(generate_result && preserve_result)
6772 for(i = 0; i < AOP_SIZE(result); i++)
6773 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6776 pic16_emitpLabel(donelbl->key);
6782 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6783 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6784 pic16_freeAsmop(result,NULL,ic,TRUE);
6790 // old version kept for reference
6792 /*-----------------------------------------------------------------*/
6793 /* genCmpEq - generates code for equal to */
6794 /*-----------------------------------------------------------------*/
6795 static void genCmpEq (iCode *ic, iCode *ifx)
6797 operand *left, *right, *result;
6798 unsigned long lit = 0L;
6800 symbol *falselbl = newiTempLabel(NULL);
6803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6806 DEBUGpic16_emitcode ("; ifx is non-null","");
6808 DEBUGpic16_emitcode ("; ifx is null","");
6810 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6811 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6812 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6814 size = max(AOP_SIZE(left),AOP_SIZE(right));
6816 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6818 /* if literal, literal on the right or
6819 if the right is in a pointer register and left
6821 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6822 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6823 operand *tmp = right ;
6829 if(ifx && !AOP_SIZE(result)){
6831 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6832 /* if they are both bit variables */
6833 if (AOP_TYPE(left) == AOP_CRY &&
6834 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6835 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6836 if(AOP_TYPE(right) == AOP_LIT){
6837 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6839 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840 pic16_emitcode("cpl","c");
6841 } else if(lit == 1L) {
6842 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844 pic16_emitcode("clr","c");
6846 /* AOP_TYPE(right) == AOP_CRY */
6848 symbol *lbl = newiTempLabel(NULL);
6849 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6850 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6851 pic16_emitcode("cpl","c");
6852 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6854 /* if true label then we jump if condition
6856 tlbl = newiTempLabel(NULL);
6857 if ( IC_TRUE(ifx) ) {
6858 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6859 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6861 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6862 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6864 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6867 /* left and right are both bit variables, result is carry */
6870 resolveIfx(&rIfx,ifx);
6872 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6873 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6874 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6875 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6880 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6882 /* They're not both bit variables. Is the right a literal? */
6883 if(AOP_TYPE(right) == AOP_LIT) {
6884 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6889 switch(lit & 0xff) {
6891 if ( IC_TRUE(ifx) ) {
6892 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6896 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6897 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6901 if ( IC_TRUE(ifx) ) {
6902 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6904 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6906 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6907 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6911 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6913 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6918 /* end of size == 1 */
6922 genc16bit2lit(left,lit,offset);
6925 /* end of size == 2 */
6930 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6931 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6932 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6933 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6936 /* search for patterns that can be optimized */
6938 genc16bit2lit(left,lit,0);
6942 emitSKPZ; // if hi word unequal
6944 emitSKPNZ; // if hi word equal
6946 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6947 genc16bit2lit(left,lit,2);
6950 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6951 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6955 pic16_emitpLabel(falselbl->key);
6964 } else if(AOP_TYPE(right) == AOP_CRY ) {
6965 /* we know the left is not a bit, but that the right is */
6966 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6967 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6968 pic16_popGet(AOP(right),offset));
6969 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6971 /* if the two are equal, then W will be 0 and the Z bit is set
6972 * we could test Z now, or go ahead and check the high order bytes if
6973 * the variable we're comparing is larger than a byte. */
6976 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6978 if ( IC_TRUE(ifx) ) {
6980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6981 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6984 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6985 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6989 /* They're both variables that are larger than bits */
6992 tlbl = newiTempLabel(NULL);
6995 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6996 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6998 if ( IC_TRUE(ifx) ) {
7002 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7005 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7009 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7013 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7018 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7020 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7021 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7025 if(s>1 && IC_TRUE(ifx)) {
7026 pic16_emitpLabel(tlbl->key);
7027 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7031 /* mark the icode as generated */
7036 /* if they are both bit variables */
7037 if (AOP_TYPE(left) == AOP_CRY &&
7038 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7039 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7040 if(AOP_TYPE(right) == AOP_LIT){
7041 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7043 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044 pic16_emitcode("cpl","c");
7045 } else if(lit == 1L) {
7046 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048 pic16_emitcode("clr","c");
7050 /* AOP_TYPE(right) == AOP_CRY */
7052 symbol *lbl = newiTempLabel(NULL);
7053 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7054 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7055 pic16_emitcode("cpl","c");
7056 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7059 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7060 pic16_outBitC(result);
7064 genIfxJump (ifx,"c");
7067 /* if the result is used in an arithmetic operation
7068 then put the result in place */
7069 pic16_outBitC(result);
7072 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7073 gencjne(left,right,result,ifx);
7076 gencjne(left,right,newiTempLabel(NULL));
7078 if(IC_TRUE(ifx)->key)
7079 gencjne(left,right,IC_TRUE(ifx)->key);
7081 gencjne(left,right,IC_FALSE(ifx)->key);
7085 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7086 pic16_aopPut(AOP(result),"a",0);
7091 genIfxJump (ifx,"a");
7095 /* if the result is used in an arithmetic operation
7096 then put the result in place */
7098 if (AOP_TYPE(result) != AOP_CRY)
7099 pic16_outAcc(result);
7101 /* leave the result in acc */
7105 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7106 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7107 pic16_freeAsmop(result,NULL,ic,TRUE);
7111 /*-----------------------------------------------------------------*/
7112 /* ifxForOp - returns the icode containing the ifx for operand */
7113 /*-----------------------------------------------------------------*/
7114 static iCode *ifxForOp ( operand *op, iCode *ic )
7118 /* if true symbol then needs to be assigned */
7119 if (IS_TRUE_SYMOP(op))
7122 /* if this has register type condition and
7123 the next instruction is ifx with the same operand
7124 and live to of the operand is upto the ifx only then */
7126 && ic->next->op == IFX
7127 && IC_COND(ic->next)->key == op->key
7128 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7130 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7136 ic->next->op == IFX &&
7137 IC_COND(ic->next)->key == op->key) {
7138 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7143 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7145 ic->next->op == IFX)
7146 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7149 ic->next->op == IFX &&
7150 IC_COND(ic->next)->key == op->key) {
7151 DEBUGpic16_emitcode ("; "," key is okay");
7152 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7153 OP_SYMBOL(op)->liveTo,
7158 /* the code below is completely untested
7159 * it just allows ulong2fs.c compile -- VR */
7162 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7163 __FILE__, __FUNCTION__, __LINE__);
7165 /* if this has register type condition and
7166 the next instruction is ifx with the same operand
7167 and live to of the operand is upto the ifx only then */
7169 ic->next->op == IFX &&
7170 IC_COND(ic->next)->key == op->key &&
7171 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7175 ic->next->op == IFX &&
7176 IC_COND(ic->next)->key == op->key) {
7177 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7181 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7182 __FILE__, __FUNCTION__, __LINE__);
7184 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7189 /*-----------------------------------------------------------------*/
7190 /* genAndOp - for && operation */
7191 /*-----------------------------------------------------------------*/
7192 static void genAndOp (iCode *ic)
7194 operand *left,*right, *result;
7199 /* note here that && operations that are in an
7200 if statement are taken away by backPatchLabels
7201 only those used in arthmetic operations remain */
7202 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7203 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7204 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7206 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7209 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7210 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7212 /* if both are bit variables */
7213 /* if (AOP_TYPE(left) == AOP_CRY && */
7214 /* AOP_TYPE(right) == AOP_CRY ) { */
7215 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7216 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7217 /* pic16_outBitC(result); */
7219 /* tlbl = newiTempLabel(NULL); */
7220 /* pic16_toBoolean(left); */
7221 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7222 /* pic16_toBoolean(right); */
7223 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7224 /* pic16_outBitAcc(result); */
7227 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7228 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7229 pic16_freeAsmop(result,NULL,ic,TRUE);
7233 /*-----------------------------------------------------------------*/
7234 /* genOrOp - for || operation */
7235 /*-----------------------------------------------------------------*/
7238 modified this code, but it doesn't appear to ever get called
7241 static void genOrOp (iCode *ic)
7243 operand *left,*right, *result;
7248 /* note here that || operations that are in an
7249 if statement are taken away by backPatchLabels
7250 only those used in arthmetic operations remain */
7251 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7252 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7253 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7255 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7257 /* if both are bit variables */
7258 if (AOP_TYPE(left) == AOP_CRY &&
7259 AOP_TYPE(right) == AOP_CRY ) {
7260 pic16_emitcode("clrc","");
7261 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7262 AOP(left)->aopu.aop_dir,
7263 AOP(left)->aopu.aop_dir);
7264 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7265 AOP(right)->aopu.aop_dir,
7266 AOP(right)->aopu.aop_dir);
7267 pic16_emitcode("setc","");
7270 tlbl = newiTempLabel(NULL);
7271 pic16_toBoolean(left);
7273 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7274 pic16_toBoolean(right);
7275 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7277 pic16_outBitAcc(result);
7280 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7281 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7282 pic16_freeAsmop(result,NULL,ic,TRUE);
7285 /*-----------------------------------------------------------------*/
7286 /* isLiteralBit - test if lit == 2^n */
7287 /*-----------------------------------------------------------------*/
7288 static int isLiteralBit(unsigned long lit)
7290 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7291 0x100L,0x200L,0x400L,0x800L,
7292 0x1000L,0x2000L,0x4000L,0x8000L,
7293 0x10000L,0x20000L,0x40000L,0x80000L,
7294 0x100000L,0x200000L,0x400000L,0x800000L,
7295 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7296 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7300 for(idx = 0; idx < 32; idx++)
7306 /*-----------------------------------------------------------------*/
7307 /* continueIfTrue - */
7308 /*-----------------------------------------------------------------*/
7309 static void continueIfTrue (iCode *ic)
7313 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7317 /*-----------------------------------------------------------------*/
7319 /*-----------------------------------------------------------------*/
7320 static void jumpIfTrue (iCode *ic)
7324 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7328 /*-----------------------------------------------------------------*/
7329 /* jmpTrueOrFalse - */
7330 /*-----------------------------------------------------------------*/
7331 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7333 // ugly but optimized by peephole
7336 symbol *nlbl = newiTempLabel(NULL);
7337 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7338 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7339 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7340 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7342 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7343 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7348 /*-----------------------------------------------------------------*/
7349 /* genAnd - code for and */
7350 /*-----------------------------------------------------------------*/
7351 static void genAnd (iCode *ic, iCode *ifx)
7353 operand *left, *right, *result;
7355 unsigned long lit = 0L;
7361 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7362 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7363 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7365 resolveIfx(&rIfx,ifx);
7367 /* if left is a literal & right is not then exchange them */
7368 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7369 AOP_NEEDSACC(left)) {
7370 operand *tmp = right ;
7375 /* if result = right then exchange them */
7376 if(pic16_sameRegs(AOP(result),AOP(right))){
7377 operand *tmp = right ;
7382 /* if right is bit then exchange them */
7383 if (AOP_TYPE(right) == AOP_CRY &&
7384 AOP_TYPE(left) != AOP_CRY){
7385 operand *tmp = right ;
7389 if(AOP_TYPE(right) == AOP_LIT)
7390 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7392 size = AOP_SIZE(result);
7394 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7397 // result = bit & yy;
7398 if (AOP_TYPE(left) == AOP_CRY){
7399 // c = bit & literal;
7400 if(AOP_TYPE(right) == AOP_LIT){
7402 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7405 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7408 if(size && (AOP_TYPE(result) == AOP_CRY)){
7409 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7412 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7416 pic16_emitcode("clr","c");
7419 if (AOP_TYPE(right) == AOP_CRY){
7421 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7422 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7425 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7427 pic16_emitcode("rrc","a");
7428 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7434 pic16_outBitC(result);
7436 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7437 genIfxJump(ifx, "c");
7441 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7442 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7443 if((AOP_TYPE(right) == AOP_LIT) &&
7444 (AOP_TYPE(result) == AOP_CRY) &&
7445 (AOP_TYPE(left) != AOP_CRY)){
7446 int posbit = isLiteralBit(lit);
7450 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7453 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7459 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7462 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7466 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7467 size = AOP_SIZE(left);
7470 int bp = posbit, ofs=0;
7477 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7478 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7482 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7483 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7485 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7492 symbol *tlbl = newiTempLabel(NULL);
7493 int sizel = AOP_SIZE(left);
7499 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7501 /* patch provided by Aaron Colwell */
7502 if((posbit = isLiteralBit(bytelit)) != 0) {
7503 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7504 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7505 (posbit-1),0, PO_GPR_REGISTER));
7507 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7508 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7510 if (bytelit == 0xff) {
7511 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7512 * a peephole could optimize it out -- VR */
7513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7516 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7519 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7520 pic16_popGetLabel(tlbl->key));
7524 /* old code, left here for reference -- VR 09/2004 */
7525 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7527 if((posbit = isLiteralBit(bytelit)) != 0)
7528 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7530 if(bytelit != 0x0FFL)
7531 pic16_emitcode("anl","a,%s",
7532 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7533 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7539 // bit = left & literal
7542 pic16_emitpLabel(tlbl->key);
7544 // if(left & literal)
7547 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7550 pic16_emitpLabel(tlbl->key);
7555 pic16_outBitC(result);
7559 /* if left is same as result */
7560 if(pic16_sameRegs(AOP(result),AOP(left))){
7562 for(;size--; offset++,lit>>=8) {
7563 if(AOP_TYPE(right) == AOP_LIT){
7564 switch(lit & 0xff) {
7566 /* and'ing with 0 has clears the result */
7567 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7568 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7571 /* and'ing with 0xff is a nop when the result and left are the same */
7576 int p = pic16_my_powof2( (~lit) & 0xff );
7578 /* only one bit is set in the literal, so use a bcf instruction */
7579 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7580 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7583 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7584 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7585 if(know_W != (lit&0xff))
7586 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7588 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7593 if (AOP_TYPE(left) == AOP_ACC) {
7594 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7596 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7597 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7604 // left & result in different registers
7605 if(AOP_TYPE(result) == AOP_CRY){
7607 // if(size), result in bit
7608 // if(!size && ifx), conditional oper: if(left & right)
7609 symbol *tlbl = newiTempLabel(NULL);
7610 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7612 pic16_emitcode("setb","c");
7614 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7615 pic16_emitcode("anl","a,%s",
7616 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7617 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7622 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7623 pic16_outBitC(result);
7625 jmpTrueOrFalse(ifx, tlbl);
7627 for(;(size--);offset++) {
7629 // result = left & right
7630 if(AOP_TYPE(right) == AOP_LIT){
7631 int t = (lit >> (offset*8)) & 0x0FFL;
7634 pic16_emitcode("clrf","%s",
7635 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7636 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7639 pic16_emitcode("movf","%s,w",
7640 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7641 pic16_emitcode("movwf","%s",
7642 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7643 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7644 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7647 pic16_emitcode("movlw","0x%x",t);
7648 pic16_emitcode("andwf","%s,w",
7649 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7650 pic16_emitcode("movwf","%s",
7651 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7653 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7654 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7655 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7660 if (AOP_TYPE(left) == AOP_ACC) {
7661 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7662 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7664 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7665 pic16_emitcode("andwf","%s,w",
7666 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7667 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7668 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7670 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7671 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7677 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7678 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679 pic16_freeAsmop(result,NULL,ic,TRUE);
7682 /*-----------------------------------------------------------------*/
7683 /* genOr - code for or */
7684 /*-----------------------------------------------------------------*/
7685 static void genOr (iCode *ic, iCode *ifx)
7687 operand *left, *right, *result;
7689 unsigned long lit = 0L;
7691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7693 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7694 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7695 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7697 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7699 /* if left is a literal & right is not then exchange them */
7700 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7701 AOP_NEEDSACC(left)) {
7702 operand *tmp = right ;
7707 /* if result = right then exchange them */
7708 if(pic16_sameRegs(AOP(result),AOP(right))){
7709 operand *tmp = right ;
7714 /* if right is bit then exchange them */
7715 if (AOP_TYPE(right) == AOP_CRY &&
7716 AOP_TYPE(left) != AOP_CRY){
7717 operand *tmp = right ;
7722 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7724 if(AOP_TYPE(right) == AOP_LIT)
7725 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7727 size = AOP_SIZE(result);
7731 if (AOP_TYPE(left) == AOP_CRY){
7732 if(AOP_TYPE(right) == AOP_LIT){
7733 // c = bit & literal;
7735 // lit != 0 => result = 1
7736 if(AOP_TYPE(result) == AOP_CRY){
7738 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7739 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7740 // AOP(result)->aopu.aop_dir,
7741 // AOP(result)->aopu.aop_dir);
7743 continueIfTrue(ifx);
7747 // lit == 0 => result = left
7748 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7750 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7753 if (AOP_TYPE(right) == AOP_CRY){
7754 if(pic16_sameRegs(AOP(result),AOP(left))){
7756 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7757 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7758 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7760 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7761 AOP(result)->aopu.aop_dir,
7762 AOP(result)->aopu.aop_dir);
7763 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7764 AOP(right)->aopu.aop_dir,
7765 AOP(right)->aopu.aop_dir);
7766 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7767 AOP(result)->aopu.aop_dir,
7768 AOP(result)->aopu.aop_dir);
7770 if( AOP_TYPE(result) == AOP_ACC) {
7771 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7772 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7773 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7774 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7778 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7779 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7780 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7781 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7783 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7784 AOP(result)->aopu.aop_dir,
7785 AOP(result)->aopu.aop_dir);
7786 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7787 AOP(right)->aopu.aop_dir,
7788 AOP(right)->aopu.aop_dir);
7789 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7790 AOP(left)->aopu.aop_dir,
7791 AOP(left)->aopu.aop_dir);
7792 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7793 AOP(result)->aopu.aop_dir,
7794 AOP(result)->aopu.aop_dir);
7799 symbol *tlbl = newiTempLabel(NULL);
7800 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7803 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7804 if( AOP_TYPE(right) == AOP_ACC) {
7805 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7807 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7808 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7813 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7814 pic16_emitcode(";XXX setb","c");
7815 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7816 AOP(left)->aopu.aop_dir,tlbl->key+100);
7817 pic16_toBoolean(right);
7818 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7819 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7820 jmpTrueOrFalse(ifx, tlbl);
7824 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7831 pic16_outBitC(result);
7833 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7834 genIfxJump(ifx, "c");
7838 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7839 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7840 if((AOP_TYPE(right) == AOP_LIT) &&
7841 (AOP_TYPE(result) == AOP_CRY) &&
7842 (AOP_TYPE(left) != AOP_CRY)){
7844 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7849 continueIfTrue(ifx);
7852 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7853 // lit = 0, result = boolean(left)
7855 pic16_emitcode(";XXX setb","c");
7856 pic16_toBoolean(right);
7858 symbol *tlbl = newiTempLabel(NULL);
7859 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7861 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7863 genIfxJump (ifx,"a");
7867 pic16_outBitC(result);
7871 /* if left is same as result */
7872 if(pic16_sameRegs(AOP(result),AOP(left))){
7874 for(;size--; offset++,lit>>=8) {
7875 if(AOP_TYPE(right) == AOP_LIT){
7876 if((lit & 0xff) == 0)
7877 /* or'ing with 0 has no effect */
7880 int p = pic16_my_powof2(lit & 0xff);
7882 /* only one bit is set in the literal, so use a bsf instruction */
7883 pic16_emitpcode(POC_BSF,
7884 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7886 if(know_W != (lit & 0xff))
7887 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7888 know_W = lit & 0xff;
7889 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7894 if (AOP_TYPE(left) == AOP_ACC) {
7895 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7896 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7899 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7901 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7908 // left & result in different registers
7909 if(AOP_TYPE(result) == AOP_CRY){
7911 // if(size), result in bit
7912 // if(!size && ifx), conditional oper: if(left | right)
7913 symbol *tlbl = newiTempLabel(NULL);
7914 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7915 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7919 pic16_emitcode(";XXX setb","c");
7921 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7922 pic16_emitcode(";XXX orl","a,%s",
7923 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7929 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7930 pic16_outBitC(result);
7932 jmpTrueOrFalse(ifx, tlbl);
7933 } else for(;(size--);offset++){
7935 // result = left & right
7936 if(AOP_TYPE(right) == AOP_LIT){
7937 int t = (lit >> (offset*8)) & 0x0FFL;
7940 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7943 pic16_emitcode("movf","%s,w",
7944 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7945 pic16_emitcode("movwf","%s",
7946 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7950 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7953 pic16_emitcode("movlw","0x%x",t);
7954 pic16_emitcode("iorwf","%s,w",
7955 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7956 pic16_emitcode("movwf","%s",
7957 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7963 // faster than result <- left, anl result,right
7964 // and better if result is SFR
7965 if (AOP_TYPE(left) == AOP_ACC) {
7966 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7967 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7969 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7970 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7972 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7973 pic16_emitcode("iorwf","%s,w",
7974 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7977 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7982 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7983 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7984 pic16_freeAsmop(result,NULL,ic,TRUE);
7987 /*-----------------------------------------------------------------*/
7988 /* genXor - code for xclusive or */
7989 /*-----------------------------------------------------------------*/
7990 static void genXor (iCode *ic, iCode *ifx)
7992 operand *left, *right, *result;
7994 unsigned long lit = 0L;
7996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7998 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7999 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8000 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8002 /* if left is a literal & right is not ||
8003 if left needs acc & right does not */
8004 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8005 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8006 operand *tmp = right ;
8011 /* if result = right then exchange them */
8012 if(pic16_sameRegs(AOP(result),AOP(right))){
8013 operand *tmp = right ;
8018 /* if right is bit then exchange them */
8019 if (AOP_TYPE(right) == AOP_CRY &&
8020 AOP_TYPE(left) != AOP_CRY){
8021 operand *tmp = right ;
8025 if(AOP_TYPE(right) == AOP_LIT)
8026 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8028 size = AOP_SIZE(result);
8032 if (AOP_TYPE(left) == AOP_CRY){
8033 if(AOP_TYPE(right) == AOP_LIT){
8034 // c = bit & literal;
8036 // lit>>1 != 0 => result = 1
8037 if(AOP_TYPE(result) == AOP_CRY){
8039 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8040 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8042 continueIfTrue(ifx);
8045 pic16_emitcode("setb","c");
8049 // lit == 0, result = left
8050 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8052 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8054 // lit == 1, result = not(left)
8055 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8056 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8057 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8058 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8061 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8062 pic16_emitcode("cpl","c");
8069 symbol *tlbl = newiTempLabel(NULL);
8070 if (AOP_TYPE(right) == AOP_CRY){
8072 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8075 int sizer = AOP_SIZE(right);
8077 // if val>>1 != 0, result = 1
8078 pic16_emitcode("setb","c");
8080 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8082 // test the msb of the lsb
8083 pic16_emitcode("anl","a,#0xfe");
8084 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8088 pic16_emitcode("rrc","a");
8090 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8091 pic16_emitcode("cpl","c");
8092 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8097 pic16_outBitC(result);
8099 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8100 genIfxJump(ifx, "c");
8104 if(pic16_sameRegs(AOP(result),AOP(left))){
8105 /* if left is same as result */
8106 for(;size--; offset++) {
8107 if(AOP_TYPE(right) == AOP_LIT){
8108 int t = (lit >> (offset*8)) & 0x0FFL;
8112 if (IS_AOP_PREG(left)) {
8113 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8115 pic16_aopPut(AOP(result),"a",offset);
8117 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8118 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8119 pic16_emitcode("xrl","%s,%s",
8120 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8121 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124 if (AOP_TYPE(left) == AOP_ACC)
8125 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8127 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8128 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8130 if (IS_AOP_PREG(left)) {
8131 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132 pic16_aopPut(AOP(result),"a",offset);
8134 pic16_emitcode("xrl","%s,a",
8135 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8141 // left & result in different registers
8142 if(AOP_TYPE(result) == AOP_CRY){
8144 // if(size), result in bit
8145 // if(!size && ifx), conditional oper: if(left ^ right)
8146 symbol *tlbl = newiTempLabel(NULL);
8147 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8149 pic16_emitcode("setb","c");
8151 if((AOP_TYPE(right) == AOP_LIT) &&
8152 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8153 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8156 pic16_emitcode("xrl","a,%s",
8157 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8164 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8165 pic16_outBitC(result);
8167 jmpTrueOrFalse(ifx, tlbl);
8168 } else for(;(size--);offset++){
8170 // result = left & right
8171 if(AOP_TYPE(right) == AOP_LIT){
8172 int t = (lit >> (offset*8)) & 0x0FFL;
8175 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177 pic16_emitcode("movf","%s,w",
8178 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179 pic16_emitcode("movwf","%s",
8180 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8184 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8185 pic16_emitcode("comf","%s,w",
8186 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8187 pic16_emitcode("movwf","%s",
8188 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8192 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8193 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8194 pic16_emitcode("movlw","0x%x",t);
8195 pic16_emitcode("xorwf","%s,w",
8196 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8197 pic16_emitcode("movwf","%s",
8198 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8204 // faster than result <- left, anl result,right
8205 // and better if result is SFR
8206 if (AOP_TYPE(left) == AOP_ACC) {
8207 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8208 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8210 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8211 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8212 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8215 if ( AOP_TYPE(result) != AOP_ACC){
8216 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8217 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8223 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8224 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8225 pic16_freeAsmop(result,NULL,ic,TRUE);
8228 /*-----------------------------------------------------------------*/
8229 /* genInline - write the inline code out */
8230 /*-----------------------------------------------------------------*/
8231 static void genInline (iCode *ic)
8233 char *buffer, *bp, *bp1;
8236 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8238 _G.inLine += (!options.asmpeep);
8240 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8241 strcpy(buffer,IC_INLINE(ic));
8243 while((bp1=strstr(bp, "\\n"))) {
8250 cbuf = Safe_strdup( buffer );
8258 cbuf = Safe_strdup(buffer);
8259 cblen = strlen(buffer)+1;
8260 memset(cbuf, 0, cblen);
8265 if(*bp != '%')*bp1++ = *bp++;
8271 if(i>elementsInSet(asmInlineMap))break;
8274 s = indexSet(asmInlineMap, i);
8275 DEBUGpc("searching symbol s = `%s'", s);
8276 sym = findSym(SymbolTab, NULL, s);
8279 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8281 strcat(bp1, sym->rname);
8287 if(strlen(bp1) > cblen - 16) {
8288 int i = strlen(cbuf);
8290 cbuf = realloc(cbuf, cblen);
8291 memset(cbuf+i, 0, 50);
8297 buffer = Safe_strdup( cbuf );
8303 /* emit each line as a code */
8309 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8317 /* print label, use this special format with NULL directive
8318 * to denote that the argument should not be indented with tab */
8319 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326 if ((bp1 != bp) && *bp1)
8327 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8332 _G.inLine -= (!options.asmpeep);
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry */
8337 /*-----------------------------------------------------------------*/
8338 static void genRRC (iCode *ic)
8340 operand *left , *result ;
8341 int size, offset = 0, same;
8343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8345 /* rotate right with carry */
8347 result=IC_RESULT(ic);
8348 pic16_aopOp (left,ic,FALSE);
8349 pic16_aopOp (result,ic,TRUE);
8351 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8353 same = pic16_sameRegs(AOP(result),AOP(left));
8355 size = AOP_SIZE(result);
8357 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8359 /* get the lsb and put it into the carry */
8360 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8367 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8370 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8376 pic16_freeAsmop(left,NULL,ic,TRUE);
8377 pic16_freeAsmop(result,NULL,ic,TRUE);
8380 /*-----------------------------------------------------------------*/
8381 /* genRLC - generate code for rotate left with carry */
8382 /*-----------------------------------------------------------------*/
8383 static void genRLC (iCode *ic)
8385 operand *left , *result ;
8386 int size, offset = 0;
8389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8390 /* rotate right with carry */
8392 result=IC_RESULT(ic);
8393 pic16_aopOp (left,ic,FALSE);
8394 pic16_aopOp (result,ic,TRUE);
8396 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8398 same = pic16_sameRegs(AOP(result),AOP(left));
8400 /* move it to the result */
8401 size = AOP_SIZE(result);
8403 /* get the msb and put it into the carry */
8404 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8411 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8413 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8414 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8421 pic16_freeAsmop(left,NULL,ic,TRUE);
8422 pic16_freeAsmop(result,NULL,ic,TRUE);
8426 /* gpasm can get the highest order bit with HIGH/UPPER
8427 * so the following probably is not needed -- VR */
8429 /*-----------------------------------------------------------------*/
8430 /* genGetHbit - generates code get highest order bit */
8431 /*-----------------------------------------------------------------*/
8432 static void genGetHbit (iCode *ic)
8434 operand *left, *result;
8436 result=IC_RESULT(ic);
8437 pic16_aopOp (left,ic,FALSE);
8438 pic16_aopOp (result,ic,FALSE);
8440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8441 /* get the highest order byte into a */
8442 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8443 if(AOP_TYPE(result) == AOP_CRY){
8444 pic16_emitcode("rlc","a");
8445 pic16_outBitC(result);
8448 pic16_emitcode("rl","a");
8449 pic16_emitcode("anl","a,#0x01");
8450 pic16_outAcc(result);
8454 pic16_freeAsmop(left,NULL,ic,TRUE);
8455 pic16_freeAsmop(result,NULL,ic,TRUE);
8459 /*-----------------------------------------------------------------*/
8460 /* AccRol - rotate left accumulator by known count */
8461 /*-----------------------------------------------------------------*/
8462 static void AccRol (int shCount)
8464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8465 shCount &= 0x0007; // shCount : 0..7
8470 pic16_emitcode("rl","a");
8473 pic16_emitcode("rl","a");
8474 pic16_emitcode("rl","a");
8477 pic16_emitcode("swap","a");
8478 pic16_emitcode("rr","a");
8481 pic16_emitcode("swap","a");
8484 pic16_emitcode("swap","a");
8485 pic16_emitcode("rl","a");
8488 pic16_emitcode("rr","a");
8489 pic16_emitcode("rr","a");
8492 pic16_emitcode("rr","a");
8498 /*-----------------------------------------------------------------*/
8499 /* AccLsh - left shift accumulator by known count */
8500 /*-----------------------------------------------------------------*/
8501 static void AccLsh (int shCount)
8503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8509 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8538 /*-----------------------------------------------------------------*/
8539 /* AccRsh - right shift accumulator by known count */
8540 /*-----------------------------------------------------------------*/
8541 static void AccRsh (int shCount, int andmask)
8543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8548 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8577 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8581 /*-----------------------------------------------------------------*/
8582 /* AccSRsh - signed right shift accumulator by known count */
8583 /*-----------------------------------------------------------------*/
8584 static void AccSRsh (int shCount)
8587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8590 pic16_emitcode("mov","c,acc.7");
8591 pic16_emitcode("rrc","a");
8592 } else if(shCount == 2){
8593 pic16_emitcode("mov","c,acc.7");
8594 pic16_emitcode("rrc","a");
8595 pic16_emitcode("mov","c,acc.7");
8596 pic16_emitcode("rrc","a");
8598 tlbl = newiTempLabel(NULL);
8599 /* rotate right accumulator */
8600 AccRol(8 - shCount);
8601 /* and kill the higher order bits */
8602 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8603 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8604 pic16_emitcode("orl","a,#0x%02x",
8605 (unsigned char)~SRMask[shCount]);
8606 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8612 /*-----------------------------------------------------------------*/
8613 /* shiftR1Left2Result - shift right one byte from left to result */
8614 /*-----------------------------------------------------------------*/
8615 static void shiftR1Left2ResultSigned (operand *left, int offl,
8616 operand *result, int offr,
8621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8623 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8627 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8629 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8631 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8638 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8640 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8645 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8654 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8655 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8659 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8662 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8663 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8670 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8671 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8672 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8673 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8692 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8693 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8694 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8695 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8696 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8699 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8700 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8709 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8713 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8723 /*-----------------------------------------------------------------*/
8724 /* shiftR1Left2Result - shift right one byte from left to result */
8725 /*-----------------------------------------------------------------*/
8726 static void shiftR1Left2Result (operand *left, int offl,
8727 operand *result, int offr,
8728 int shCount, int sign)
8732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8734 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8736 /* Copy the msb into the carry if signed. */
8738 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8748 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8750 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8757 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8775 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
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(0x0f));
8783 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8788 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8789 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8797 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8798 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8805 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8806 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8807 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8816 /*-----------------------------------------------------------------*/
8817 /* shiftL1Left2Result - shift left one byte from left to result */
8818 /*-----------------------------------------------------------------*/
8819 static void shiftL1Left2Result (operand *left, int offl,
8820 operand *result, int offr, int shCount)
8825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8827 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8828 DEBUGpic16_emitcode ("; ***","same = %d",same);
8829 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8831 /* shift left accumulator */
8832 //AccLsh(shCount); // don't comment out just yet...
8833 // pic16_aopPut(AOP(result),"a",offr);
8837 /* Shift left 1 bit position */
8838 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8842 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8849 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8853 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8854 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8855 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8861 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8862 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8867 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8873 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8884 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8889 /*-----------------------------------------------------------------*/
8890 /* movLeft2Result - move byte from left to result */
8891 /*-----------------------------------------------------------------*/
8892 static void movLeft2Result (operand *left, int offl,
8893 operand *result, int offr)
8896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8897 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8898 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8900 if (*l == '@' && (IS_AOP_PREG(result))) {
8901 pic16_emitcode("mov","a,%s",l);
8902 pic16_aopPut(AOP(result),"a",offr);
8904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910 /*-----------------------------------------------------------------*/
8911 /* shiftL2Left2Result - shift left two bytes from left to result */
8912 /*-----------------------------------------------------------------*/
8913 static void shiftL2Left2Result (operand *left, int offl,
8914 operand *result, int offr, int shCount)
8916 int same = pic16_sameRegs(AOP(result), AOP(left));
8919 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8921 if (same && (offl != offr)) { // shift bytes
8924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8927 } else { // just treat as different later on
8940 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8954 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8956 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8979 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8992 /* note, use a mov/add for the shift since the mov has a
8993 chance of getting optimized out */
8994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8997 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9009 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9010 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9015 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9020 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9026 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9033 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9034 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9041 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9042 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9043 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9049 /*-----------------------------------------------------------------*/
9050 /* shiftR2Left2Result - shift right two bytes from left to result */
9051 /*-----------------------------------------------------------------*/
9052 static void shiftR2Left2Result (operand *left, int offl,
9053 operand *result, int offr,
9054 int shCount, int sign)
9056 int same = pic16_sameRegs(AOP(result), AOP(left));
9058 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9060 if (same && (offl != offr)) { // shift right bytes
9063 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9064 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9066 } else { // just treat as different later on
9078 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9084 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9087 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9106 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9111 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9112 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9115 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9116 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9119 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9122 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9126 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9127 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9132 pic16_emitpcode(POC_BTFSC,
9133 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9134 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9145 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9148 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9150 pic16_emitpcode(POC_BTFSC,
9151 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9152 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9154 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9164 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9165 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9166 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9168 pic16_emitpcode(POC_BTFSC,
9169 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9170 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9173 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9181 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9183 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9186 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9188 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9195 /*-----------------------------------------------------------------*/
9196 static void shiftLLeftOrResult (operand *left, int offl,
9197 operand *result, int offr, int shCount)
9199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9201 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9202 /* shift left accumulator */
9204 /* or with result */
9205 /* back to result */
9206 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9211 /*-----------------------------------------------------------------*/
9212 static void shiftRLeftOrResult (operand *left, int offl,
9213 operand *result, int offr, int shCount)
9215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9217 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9218 /* shift right accumulator */
9220 /* or with result */
9221 /* back to result */
9222 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9225 /*-----------------------------------------------------------------*/
9226 /* genlshOne - left shift a one byte quantity by known count */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshOne (operand *result, operand *left, int shCount)
9230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9231 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9234 /*-----------------------------------------------------------------*/
9235 /* genlshTwo - left shift two bytes by known amount != 0 */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshTwo (operand *result,operand *left, int shCount)
9241 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9242 size = pic16_getDataSize(result);
9244 /* if shCount >= 8 */
9250 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9252 movLeft2Result(left, LSB, result, MSB16);
9254 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9257 /* 1 <= shCount <= 7 */
9260 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9262 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9266 /*-----------------------------------------------------------------*/
9267 /* shiftLLong - shift left one long from left to result */
9268 /* offr = LSB or MSB16 */
9269 /*-----------------------------------------------------------------*/
9270 static void shiftLLong (operand *left, operand *result, int offr )
9272 int size = AOP_SIZE(result);
9273 int same = pic16_sameRegs(AOP(left),AOP(result));
9276 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9278 if (same && (offr == MSB16)) { //shift one byte
9279 for(i=size-1;i>=MSB16;i--) {
9280 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9281 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9284 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9287 if (size > LSB+offr ){
9289 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9291 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9296 if(size > MSB16+offr){
9298 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9300 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9305 if(size > MSB24+offr){
9307 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9309 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9314 if(size > MSB32+offr){
9316 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9318 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9319 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9323 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9327 /*-----------------------------------------------------------------*/
9328 /* genlshFour - shift four byte by a known amount != 0 */
9329 /*-----------------------------------------------------------------*/
9330 static void genlshFour (operand *result, operand *left, int shCount)
9334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9335 size = AOP_SIZE(result);
9337 /* if shifting more that 3 bytes */
9338 if (shCount >= 24 ) {
9341 /* lowest order of left goes to the highest
9342 order of the destination */
9343 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9345 movLeft2Result(left, LSB, result, MSB32);
9347 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9348 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9349 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9354 /* more than two bytes */
9355 else if ( shCount >= 16 ) {
9356 /* lower order two bytes goes to higher order two bytes */
9358 /* if some more remaining */
9360 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9362 movLeft2Result(left, MSB16, result, MSB32);
9363 movLeft2Result(left, LSB, result, MSB24);
9365 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9366 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9370 /* if more than 1 byte */
9371 else if ( shCount >= 8 ) {
9372 /* lower order three bytes goes to higher order three bytes */
9376 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9378 movLeft2Result(left, LSB, result, MSB16);
9380 else{ /* size = 4 */
9382 movLeft2Result(left, MSB24, result, MSB32);
9383 movLeft2Result(left, MSB16, result, MSB24);
9384 movLeft2Result(left, LSB, result, MSB16);
9385 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9387 else if(shCount == 1)
9388 shiftLLong(left, result, MSB16);
9390 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9391 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9393 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9398 /* 1 <= shCount <= 7 */
9399 else if(shCount <= 3)
9401 shiftLLong(left, result, LSB);
9402 while(--shCount >= 1)
9403 shiftLLong(result, result, LSB);
9405 /* 3 <= shCount <= 7, optimize */
9407 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9408 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9409 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShiftLiteral - left shifting by known count */
9415 /*-----------------------------------------------------------------*/
9416 void pic16_genLeftShiftLiteral (operand *left,
9421 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9425 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9426 pic16_freeAsmop(right,NULL,ic,TRUE);
9428 pic16_aopOp(left,ic,FALSE);
9429 pic16_aopOp(result,ic,TRUE);
9431 size = getSize(operandType(result));
9434 pic16_emitcode("; shift left ","result %d, left %d",size,
9438 /* I suppose that the left size >= result size */
9441 movLeft2Result(left, size, result, size);
9445 else if(shCount >= (size * 8))
9447 pic16_aopPut(AOP(result),zero,size);
9451 genlshOne (result,left,shCount);
9456 genlshTwo (result,left,shCount);
9460 genlshFour (result,left,shCount);
9464 pic16_freeAsmop(left,NULL,ic,TRUE);
9465 pic16_freeAsmop(result,NULL,ic,TRUE);
9468 /*-----------------------------------------------------------------*
9469 * genMultiAsm - repeat assembly instruction for size of register.
9470 * if endian == 1, then the high byte (i.e base address + size of
9471 * register) is used first else the low byte is used first;
9472 *-----------------------------------------------------------------*/
9473 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9491 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9497 #if !(USE_GENERIC_SIGNED_SHIFT)
9498 /*-----------------------------------------------------------------*/
9499 /* genLeftShift - generates code for left shifting */
9500 /*-----------------------------------------------------------------*/
9501 static void genLeftShift (iCode *ic)
9503 operand *left,*right, *result;
9506 symbol *tlbl , *tlbl1;
9509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9511 right = IC_RIGHT(ic);
9513 result = IC_RESULT(ic);
9515 pic16_aopOp(right,ic,FALSE);
9517 /* if the shift count is known then do it
9518 as efficiently as possible */
9519 if (AOP_TYPE(right) == AOP_LIT) {
9520 pic16_genLeftShiftLiteral (left,right,result,ic);
9524 /* shift count is unknown then we have to form
9525 * a loop. Get the loop count in WREG : Note: we take
9526 * only the lower order byte since shifting
9527 * more than 32 bits make no sense anyway, ( the
9528 * largest size of an object can be only 32 bits ) */
9530 pic16_aopOp(left,ic,FALSE);
9531 pic16_aopOp(result,ic,FALSE);
9533 /* now move the left to the result if they are not the
9534 * same, and if size > 1,
9535 * and if right is not same to result (!!!) -- VR */
9536 if (!pic16_sameRegs(AOP(left),AOP(result))
9537 && (AOP_SIZE(result) > 1)) {
9539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9541 size = AOP_SIZE(result);
9546 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9547 if (*l == '@' && (IS_AOP_PREG(result))) {
9549 pic16_emitcode("mov","a,%s",l);
9550 pic16_aopPut(AOP(result),"a",offset);
9554 /* we don't know if left is a literal or a register, take care -- VR */
9555 mov2f(AOP(result), AOP(left), offset);
9561 size = AOP_SIZE(result);
9563 /* if it is only one byte then */
9565 if(optimized_for_speed) {
9566 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9567 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9568 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9569 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9571 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9572 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9573 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9574 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9575 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9576 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9577 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9582 tlbl = newiTempLabel(NULL);
9585 /* this is already done, why change it? */
9586 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9587 mov2f(AOP(result), AOP(left), 0);
9591 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9592 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9593 pic16_emitpLabel(tlbl->key);
9594 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602 if (pic16_sameRegs(AOP(left),AOP(result))) {
9604 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9606 tlbl = newiTempLabel(NULL);
9607 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9608 genMultiAsm(POC_RRCF, result, size,1);
9609 pic16_emitpLabel(tlbl->key);
9610 genMultiAsm(POC_RLCF, result, size,0);
9611 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9613 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9617 //tlbl = newiTempLabel(NULL);
9619 //tlbl1 = newiTempLabel(NULL);
9621 //reAdjustPreg(AOP(result));
9623 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9624 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9625 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9627 //pic16_emitcode("add","a,acc");
9628 //pic16_aopPut(AOP(result),"a",offset++);
9630 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9632 // pic16_emitcode("rlc","a");
9633 // pic16_aopPut(AOP(result),"a",offset++);
9635 //reAdjustPreg(AOP(result));
9637 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9638 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9641 tlbl = newiTempLabel(NULL);
9642 tlbl1= newiTempLabel(NULL);
9644 size = AOP_SIZE(result);
9647 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9651 /* offset should be 0, 1 or 3 */
9653 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9655 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9657 pic16_emitpcode(POC_MOVWF, pctemp);
9660 pic16_emitpLabel(tlbl->key);
9663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9665 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9667 pic16_emitpcode(POC_DECFSZ, pctemp);
9668 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9669 pic16_emitpLabel(tlbl1->key);
9671 pic16_popReleaseTempReg(pctemp,1);
9675 pic16_freeAsmop (right,NULL,ic,TRUE);
9676 pic16_freeAsmop(left,NULL,ic,TRUE);
9677 pic16_freeAsmop(result,NULL,ic,TRUE);
9683 #error old code (left here for reference)
9684 /*-----------------------------------------------------------------*/
9685 /* genLeftShift - generates code for left shifting */
9686 /*-----------------------------------------------------------------*/
9687 static void genLeftShift (iCode *ic)
9689 operand *left,*right, *result;
9692 symbol *tlbl , *tlbl1;
9695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9697 right = IC_RIGHT(ic);
9699 result = IC_RESULT(ic);
9701 pic16_aopOp(right,ic,FALSE);
9703 /* if the shift count is known then do it
9704 as efficiently as possible */
9705 if (AOP_TYPE(right) == AOP_LIT) {
9706 pic16_genLeftShiftLiteral (left,right,result,ic);
9710 /* shift count is unknown then we have to form
9711 a loop get the loop count in B : Note: we take
9712 only the lower order byte since shifting
9713 more that 32 bits make no sense anyway, ( the
9714 largest size of an object can be only 32 bits ) */
9717 pic16_aopOp(left,ic,FALSE);
9718 pic16_aopOp(result,ic,FALSE);
9720 /* now move the left to the result if they are not the
9722 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9723 AOP_SIZE(result) > 1) {
9725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9727 size = AOP_SIZE(result);
9730 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9731 if (*l == '@' && (IS_AOP_PREG(result))) {
9733 pic16_emitcode("mov","a,%s",l);
9734 pic16_aopPut(AOP(result),"a",offset);
9737 /* we don't know if left is a literal or a register, take care -- VR */
9738 mov2f(AOP(result), AOP(left), offset);
9744 size = AOP_SIZE(result);
9746 /* if it is only one byte then */
9748 if(optimized_for_speed) {
9749 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9750 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9751 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9754 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9755 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9756 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9757 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9758 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9759 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9760 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9765 tlbl = newiTempLabel(NULL);
9766 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9767 mov2f(AOP(result), AOP(left), 0);
9769 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9770 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9773 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9774 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9775 pic16_emitpLabel(tlbl->key);
9776 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9777 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784 if (pic16_sameRegs(AOP(left),AOP(result))) {
9786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9788 tlbl = newiTempLabel(NULL);
9789 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9790 genMultiAsm(POC_RRCF, result, size,1);
9791 pic16_emitpLabel(tlbl->key);
9792 genMultiAsm(POC_RLCF, result, size,0);
9793 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9795 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9799 //tlbl = newiTempLabel(NULL);
9801 //tlbl1 = newiTempLabel(NULL);
9803 //reAdjustPreg(AOP(result));
9805 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9806 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9807 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9809 //pic16_emitcode("add","a,acc");
9810 //pic16_aopPut(AOP(result),"a",offset++);
9812 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9814 // pic16_emitcode("rlc","a");
9815 // pic16_aopPut(AOP(result),"a",offset++);
9817 //reAdjustPreg(AOP(result));
9819 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9820 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9823 tlbl = newiTempLabel(NULL);
9824 tlbl1= newiTempLabel(NULL);
9826 size = AOP_SIZE(result);
9829 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9831 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9833 /* offset should be 0, 1 or 3 */
9835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9837 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9839 pic16_emitpcode(POC_MOVWF, pctemp);
9842 pic16_emitpLabel(tlbl->key);
9845 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9847 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9849 pic16_emitpcode(POC_DECFSZ, pctemp);
9850 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851 pic16_emitpLabel(tlbl1->key);
9853 pic16_popReleaseTempReg(pctemp,1);
9857 pic16_freeAsmop (right,NULL,ic,TRUE);
9858 pic16_freeAsmop(left,NULL,ic,TRUE);
9859 pic16_freeAsmop(result,NULL,ic,TRUE);
9863 /*-----------------------------------------------------------------*/
9864 /* genrshOne - right shift a one byte quantity by known count */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshOne (operand *result, operand *left,
9867 int shCount, int sign)
9869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9870 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9873 /*-----------------------------------------------------------------*/
9874 /* genrshTwo - right shift two bytes by known amount != 0 */
9875 /*-----------------------------------------------------------------*/
9876 static void genrshTwo (operand *result,operand *left,
9877 int shCount, int sign)
9879 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9880 /* if shCount >= 8 */
9884 shiftR1Left2Result(left, MSB16, result, LSB,
9887 movLeft2Result(left, MSB16, result, LSB);
9889 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9892 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9893 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9897 /* 1 <= shCount <= 7 */
9899 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9902 /*-----------------------------------------------------------------*/
9903 /* shiftRLong - shift right one long from left to result */
9904 /* offl = LSB or MSB16 */
9905 /*-----------------------------------------------------------------*/
9906 static void shiftRLong (operand *left, int offl,
9907 operand *result, int sign)
9909 int size = AOP_SIZE(result);
9910 int same = pic16_sameRegs(AOP(left),AOP(result));
9912 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9914 if (same && (offl == MSB16)) { //shift one byte right
9915 for(i=MSB16;i<size;i++) {
9916 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9917 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9922 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9928 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9930 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9935 /* add sign of "a" */
9936 pic16_addSign(result, MSB32, sign);
9940 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9942 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9947 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9954 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9963 /*-----------------------------------------------------------------*/
9964 /* genrshFour - shift four byte by a known amount != 0 */
9965 /*-----------------------------------------------------------------*/
9966 static void genrshFour (operand *result, operand *left,
9967 int shCount, int sign)
9969 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9970 /* if shifting more that 3 bytes */
9971 if(shCount >= 24 ) {
9974 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9976 movLeft2Result(left, MSB32, result, LSB);
9978 pic16_addSign(result, MSB16, sign);
9980 else if(shCount >= 16){
9983 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9985 movLeft2Result(left, MSB24, result, LSB);
9986 movLeft2Result(left, MSB32, result, MSB16);
9988 pic16_addSign(result, MSB24, sign);
9990 else if(shCount >= 8){
9993 shiftRLong(left, MSB16, result, sign);
9994 else if(shCount == 0){
9995 movLeft2Result(left, MSB16, result, LSB);
9996 movLeft2Result(left, MSB24, result, MSB16);
9997 movLeft2Result(left, MSB32, result, MSB24);
9998 pic16_addSign(result, MSB32, sign);
10000 else{ //shcount >= 2
10001 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10002 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10003 /* the last shift is signed */
10004 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10005 pic16_addSign(result, MSB32, sign);
10008 else{ /* 1 <= shCount <= 7 */
10010 shiftRLong(left, LSB, result, sign);
10012 shiftRLong(result, LSB, result, sign);
10015 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10016 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10017 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10022 /*-----------------------------------------------------------------*/
10023 /* genRightShiftLiteral - right shifting by known count */
10024 /*-----------------------------------------------------------------*/
10025 static void genRightShiftLiteral (operand *left,
10031 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10032 int lsize,res_size;
10034 pic16_freeAsmop(right,NULL,ic,TRUE);
10036 pic16_aopOp(left,ic,FALSE);
10037 pic16_aopOp(result,ic,TRUE);
10039 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10042 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10046 lsize = pic16_getDataSize(left);
10047 res_size = pic16_getDataSize(result);
10048 /* test the LEFT size !!! */
10050 /* I suppose that the left size >= result size */
10052 assert (res_size <= lsize);
10053 while (res_size--) {
10054 mov2f (AOP(result), AOP(left), res_size);
10058 else if(shCount >= (lsize * 8)){
10060 if(res_size == 1) {
10061 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10063 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10064 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10070 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10071 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10078 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10083 switch (res_size) {
10085 genrshOne (result,left,shCount,sign);
10089 genrshTwo (result,left,shCount,sign);
10093 genrshFour (result,left,shCount,sign);
10101 pic16_freeAsmop(left,NULL,ic,TRUE);
10102 pic16_freeAsmop(result,NULL,ic,TRUE);
10105 #if !(USE_GENERIC_SIGNED_SHIFT)
10106 /*-----------------------------------------------------------------*/
10107 /* genSignedRightShift - right shift of signed number */
10108 /*-----------------------------------------------------------------*/
10109 static void genSignedRightShift (iCode *ic)
10111 operand *right, *left, *result;
10114 symbol *tlbl, *tlbl1 ;
10117 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10119 /* we do it the hard way put the shift count in b
10120 and loop thru preserving the sign */
10121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10123 right = IC_RIGHT(ic);
10124 left = IC_LEFT(ic);
10125 result = IC_RESULT(ic);
10127 pic16_aopOp(right,ic,FALSE);
10128 pic16_aopOp(left,ic,FALSE);
10129 pic16_aopOp(result,ic,FALSE);
10132 if ( AOP_TYPE(right) == AOP_LIT) {
10133 genRightShiftLiteral (left,right,result,ic,1);
10136 /* shift count is unknown then we have to form
10137 a loop get the loop count in B : Note: we take
10138 only the lower order byte since shifting
10139 more that 32 bits make no sense anyway, ( the
10140 largest size of an object can be only 32 bits ) */
10142 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10143 //pic16_emitcode("inc","b");
10144 //pic16_freeAsmop (right,NULL,ic,TRUE);
10145 //pic16_aopOp(left,ic,FALSE);
10146 //pic16_aopOp(result,ic,FALSE);
10148 /* now move the left to the result if they are not the
10150 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10151 AOP_SIZE(result) > 1) {
10153 size = AOP_SIZE(result);
10157 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10158 if (*l == '@' && IS_AOP_PREG(result)) {
10160 pic16_emitcode("mov","a,%s",l);
10161 pic16_aopPut(AOP(result),"a",offset);
10163 pic16_aopPut(AOP(result),l,offset);
10165 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10166 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10172 /* mov the highest order bit to OVR */
10173 tlbl = newiTempLabel(NULL);
10174 tlbl1= newiTempLabel(NULL);
10176 size = AOP_SIZE(result);
10179 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10181 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10183 /* offset should be 0, 1 or 3 */
10184 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10186 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10188 pic16_emitpcode(POC_MOVWF, pctemp);
10191 pic16_emitpLabel(tlbl->key);
10193 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10194 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10197 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10200 pic16_emitpcode(POC_DECFSZ, pctemp);
10201 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10202 pic16_emitpLabel(tlbl1->key);
10204 pic16_popReleaseTempReg(pctemp,1);
10206 size = AOP_SIZE(result);
10208 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10209 pic16_emitcode("rlc","a");
10210 pic16_emitcode("mov","ov,c");
10211 /* if it is only one byte then */
10213 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10215 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10216 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10217 pic16_emitcode("mov","c,ov");
10218 pic16_emitcode("rrc","a");
10219 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10220 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10221 pic16_aopPut(AOP(result),"a",0);
10225 reAdjustPreg(AOP(result));
10226 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10227 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10228 pic16_emitcode("mov","c,ov");
10230 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10232 pic16_emitcode("rrc","a");
10233 pic16_aopPut(AOP(result),"a",offset--);
10235 reAdjustPreg(AOP(result));
10236 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10237 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10242 pic16_freeAsmop(left,NULL,ic,TRUE);
10243 pic16_freeAsmop(result,NULL,ic,TRUE);
10244 pic16_freeAsmop(right,NULL,ic,TRUE);
10248 #if !(USE_GENERIC_SIGNED_SHIFT)
10249 #warning This implementation of genRightShift() is incomplete!
10250 /*-----------------------------------------------------------------*/
10251 /* genRightShift - generate code for right shifting */
10252 /*-----------------------------------------------------------------*/
10253 static void genRightShift (iCode *ic)
10255 operand *right, *left, *result;
10259 symbol *tlbl, *tlbl1 ;
10261 /* if signed then we do it the hard way preserve the
10262 sign bit moving it inwards */
10263 letype = getSpec(operandType(IC_LEFT(ic)));
10264 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10266 if (!SPEC_USIGN(letype)) {
10267 genSignedRightShift (ic);
10271 /* signed & unsigned types are treated the same : i.e. the
10272 signed is NOT propagated inwards : quoting from the
10273 ANSI - standard : "for E1 >> E2, is equivalent to division
10274 by 2**E2 if unsigned or if it has a non-negative value,
10275 otherwise the result is implementation defined ", MY definition
10276 is that the sign does not get propagated */
10278 right = IC_RIGHT(ic);
10279 left = IC_LEFT(ic);
10280 result = IC_RESULT(ic);
10282 pic16_aopOp(right,ic,FALSE);
10284 /* if the shift count is known then do it
10285 as efficiently as possible */
10286 if (AOP_TYPE(right) == AOP_LIT) {
10287 genRightShiftLiteral (left,right,result,ic, 0);
10291 /* shift count is unknown then we have to form
10292 a loop get the loop count in B : Note: we take
10293 only the lower order byte since shifting
10294 more that 32 bits make no sense anyway, ( the
10295 largest size of an object can be only 32 bits ) */
10297 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10298 pic16_emitcode("inc","b");
10299 pic16_aopOp(left,ic,FALSE);
10300 pic16_aopOp(result,ic,FALSE);
10302 /* now move the left to the result if they are not the
10304 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10305 AOP_SIZE(result) > 1) {
10307 size = AOP_SIZE(result);
10310 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10311 if (*l == '@' && IS_AOP_PREG(result)) {
10313 pic16_emitcode("mov","a,%s",l);
10314 pic16_aopPut(AOP(result),"a",offset);
10316 pic16_aopPut(AOP(result),l,offset);
10321 tlbl = newiTempLabel(NULL);
10322 tlbl1= newiTempLabel(NULL);
10323 size = AOP_SIZE(result);
10326 /* if it is only one byte then */
10329 tlbl = newiTempLabel(NULL);
10330 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10331 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10332 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10335 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10336 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10337 pic16_emitpLabel(tlbl->key);
10338 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10339 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10341 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10346 reAdjustPreg(AOP(result));
10347 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10348 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10351 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10353 pic16_emitcode("rrc","a");
10354 pic16_aopPut(AOP(result),"a",offset--);
10356 reAdjustPreg(AOP(result));
10358 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10359 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10362 pic16_freeAsmop(left,NULL,ic,TRUE);
10363 pic16_freeAsmop (right,NULL,ic,TRUE);
10364 pic16_freeAsmop(result,NULL,ic,TRUE);
10368 #if (USE_GENERIC_SIGNED_SHIFT)
10369 /*-----------------------------------------------------------------*/
10370 /* genGenericShift - generates code for left or right shifting */
10371 /*-----------------------------------------------------------------*/
10372 static void genGenericShift (iCode *ic, int isShiftLeft) {
10373 operand *left,*right, *result;
10375 int sign, signedCount;
10376 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10377 PIC_OPCODE pos_shift, neg_shift;
10381 right = IC_RIGHT(ic);
10382 left = IC_LEFT(ic);
10383 result = IC_RESULT(ic);
10385 pic16_aopOp(right,ic,FALSE);
10386 pic16_aopOp(left,ic,FALSE);
10387 pic16_aopOp(result,ic,TRUE);
10389 sign = !SPEC_USIGN(operandType (left));
10390 signedCount = !SPEC_USIGN(operandType (right));
10392 /* if the shift count is known then do it
10393 as efficiently as possible */
10394 if (AOP_TYPE(right) == AOP_LIT) {
10395 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10396 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10397 // we should modify right->aopu.aop_lit here!
10398 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10399 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10401 pic16_genLeftShiftLiteral (left,right,result,ic);
10403 genRightShiftLiteral (left,right,result,ic, sign);
10406 } // if (right is literal)
10408 /* shift count is unknown then we have to form a loop.
10409 * Note: we take only the lower order byte since shifting
10410 * more than 32 bits make no sense anyway, ( the
10411 * largest size of an object can be only 32 bits )
10412 * Note: we perform arithmetic shifts if the left operand is
10413 * signed and we do an (effective) right shift, i. e. we
10414 * shift in the sign bit from the left. */
10416 label_complete = newiTempLabel ( NULL );
10417 label_loop_pos = newiTempLabel ( NULL );
10418 label_loop_neg = NULL;
10419 label_negative = NULL;
10420 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10421 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10424 // additional labels needed
10425 label_loop_neg = newiTempLabel ( NULL );
10426 label_negative = newiTempLabel ( NULL );
10429 // copy source to result -- this will effectively truncate the left operand to the size of result!
10430 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10431 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10432 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10433 mov2f (AOP(result),AOP(left), offset);
10436 // if result is longer than left, fill with zeros (or sign)
10437 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10438 if (sign && AOP_SIZE(left) > 0) {
10439 // shift signed operand -- fill with sign
10440 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10441 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10442 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10443 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10444 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10447 // shift unsigned operand -- fill result with zeros
10448 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10449 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10452 } // if (size mismatch)
10454 pic16_mov2w (AOP(right), 0);
10455 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10456 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10459 // perform a shift by one (shift count is positive)
10460 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10461 // 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])
10462 pic16_emitpLabel (label_loop_pos->key);
10464 if (sign && (pos_shift == POC_RRCF)) {
10465 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10468 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10469 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10470 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10472 // perform a shift by one (shift count is positive)
10473 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10474 // 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])
10475 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10476 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10478 pic16_emitpLabel (label_loop_pos->key);
10479 if (sign && (pos_shift == POC_RRCF)) {
10480 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10483 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10484 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10485 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10486 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10490 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10492 pic16_emitpLabel (label_negative->key);
10493 // perform a shift by -1 (shift count is negative)
10494 // 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)
10496 pic16_emitpLabel (label_loop_neg->key);
10497 if (sign && (neg_shift == POC_RRCF)) {
10498 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10501 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10502 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10503 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10504 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10505 } // if (signedCount)
10507 pic16_emitpLabel (label_complete->key);
10510 pic16_freeAsmop (right,NULL,ic,TRUE);
10511 pic16_freeAsmop(left,NULL,ic,TRUE);
10512 pic16_freeAsmop(result,NULL,ic,TRUE);
10515 static void genLeftShift (iCode *ic) {
10516 genGenericShift (ic, 1);
10519 static void genRightShift (iCode *ic) {
10520 genGenericShift (ic, 0);
10525 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10526 void pic16_loadFSR0(operand *op, int lit)
10528 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10529 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10531 assert (!OP_SYMBOL(op)->remat);
10532 // set up FSR0 with address of result
10533 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10534 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10538 /*-----------------------------------------------------------------*/
10539 /* genUnpackBits - generates code for unpacking bits */
10540 /*-----------------------------------------------------------------*/
10541 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10545 sym_link *etype, *letype;
10546 int blen=0, bstr=0;
10550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10551 etype = getSpec(operandType(result));
10552 letype = getSpec(operandType(left));
10554 // if(IS_BITFIELD(etype)) {
10555 blen = SPEC_BLEN(etype);
10556 bstr = SPEC_BSTR(etype);
10559 lbstr = SPEC_BSTR( letype );
10562 if((blen == 1) && (bstr < 8)) {
10563 /* it is a single bit, so use the appropriate bit instructions */
10564 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10566 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10568 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10569 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10570 /* workaround to reduce the extra lfsr instruction */
10571 pic16_emitpcode(POC_BTFSC,
10572 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10574 pic16_loadFSR0 (left, 0);
10575 pic16_emitpcode(POC_BTFSC,
10576 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10579 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10581 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10587 /* the following call to pic16_loadFSR0 is temporary until
10588 * optimization to handle single bit assignments is added
10589 * to the function. Until then use the old safe way! -- VR */
10591 if (OP_SYMBOL(left)->remat) {
10592 // access symbol directly
10593 pic16_mov2w (AOP(left), 0);
10595 pic16_loadFSR0( left, 0 );
10597 /* read the first byte */
10604 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10607 pic16_emitcode("clr","a");
10608 pic16_emitcode("movc","a","@a+dptr");
10614 /* if we have bitdisplacement then it fits */
10615 /* into this byte completely or if length is */
10616 /* less than a byte */
10617 if ((shCnt = SPEC_BSTR(etype)) ||
10618 (SPEC_BLEN(etype) <= 8)) {
10620 /* shift right acc */
10623 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10624 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10626 /* VR -- normally I would use the following, but since we use the hack,
10627 * to avoid the masking from AccRsh, why not mask it right now? */
10630 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10639 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10640 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10643 /* bit field did not fit in a byte */
10644 rlen = SPEC_BLEN(etype) - 8;
10645 pic16_aopPut(AOP(result),"a",offset++);
10652 pic16_emitcode("inc","%s",rname);
10653 pic16_emitcode("mov","a,@%s",rname);
10657 pic16_emitcode("inc","%s",rname);
10658 pic16_emitcode("movx","a,@%s",rname);
10662 pic16_emitcode("inc","dptr");
10663 pic16_emitcode("movx","a,@dptr");
10667 pic16_emitcode("clr","a");
10668 pic16_emitcode("inc","dptr");
10669 pic16_emitcode("movc","a","@a+dptr");
10673 pic16_emitcode("inc","dptr");
10674 pic16_emitcode("lcall","__gptrget");
10679 /* if we are done */
10683 pic16_aopPut(AOP(result),"a",offset++);
10688 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10689 pic16_aopPut(AOP(result),"a",offset);
10696 static void genDataPointerGet(operand *left,
10700 int size, offset = 0, leoffset=0 ;
10702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10703 pic16_aopOp(result, ic, TRUE);
10707 size = AOP_SIZE(result);
10708 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10712 /* The following tests may save a redudant movff instruction when
10713 * accessing unions */
10715 /* if they are the same */
10716 if (operandsEqu (left, result)) {
10717 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10723 /* if they are the same registers */
10724 if (pic16_sameRegs(AOP(left),AOP(result))) {
10725 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10731 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10732 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10733 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10740 if ( AOP_TYPE(left) == AOP_PCODE) {
10741 fprintf(stderr,"genDataPointerGet %s, %d\n",
10742 AOP(left)->aopu.pcop->name,
10743 (AOP(left)->aopu.pcop->type == PO_DIR)?
10744 PCOR(AOP(left)->aopu.pcop)->instance:
10745 PCOI(AOP(left)->aopu.pcop)->offset);
10749 if(AOP(left)->aopu.pcop->type == PO_DIR)
10750 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10752 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10755 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10757 // pic16_DumpOp("(result)",result);
10758 if(is_LitAOp(AOP(result))) {
10759 pic16_mov2w(AOP(left), offset); // patch 8
10760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10762 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10763 pic16_popGet(AOP(left), offset), //patch 8
10764 pic16_popGet(AOP(result), offset)));
10772 pic16_freeAsmop(result,NULL,ic,TRUE);
10777 /*-----------------------------------------------------------------*/
10778 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10779 /*-----------------------------------------------------------------*/
10780 static void genNearPointerGet (operand *left,
10784 // asmop *aop = NULL;
10785 //regs *preg = NULL ;
10786 sym_link *rtype, *retype;
10787 sym_link *ltype = operandType(left);
10791 rtype = operandType(result);
10792 retype= getSpec(rtype);
10794 pic16_aopOp(left,ic,FALSE);
10796 // pic16_DumpOp("(left)",left);
10797 // pic16_DumpOp("(result)",result);
10799 /* if left is rematerialisable and
10800 * result is not bit variable type and
10801 * the left is pointer to data space i.e
10802 * lower 128 bytes of space */
10804 if (AOP_TYPE(left) == AOP_PCODE
10805 && !IS_BITFIELD(retype)
10806 && DCL_TYPE(ltype) == POINTER) {
10808 genDataPointerGet (left,result,ic);
10809 pic16_freeAsmop(left, NULL, ic, TRUE);
10813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10814 pic16_aopOp (result,ic,TRUE);
10816 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10819 if(IS_BITFIELD( retype )
10820 && (SPEC_BLEN(operandType(result))==1)
10824 int bitstrt, bytestrt;
10826 /* if this is bitfield of size 1, see if we are checking the value
10827 * of a single bit in an if-statement,
10828 * if yes, then don't generate usual code, but execute the
10829 * genIfx directly -- VR */
10833 /* CHECK: if next iCode is IFX
10834 * and current result operand is nextic's conditional operand
10835 * and current result operand live ranges ends at nextic's key number
10837 if((nextic->op == IFX)
10838 && (result == IC_COND(nextic))
10839 && (OP_LIVETO(result) == nextic->seq)
10840 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10842 /* everything is ok then */
10843 /* find a way to optimize the genIfx iCode */
10845 bytestrt = SPEC_BSTR(operandType(result))/8;
10846 bitstrt = SPEC_BSTR(operandType(result))%8;
10848 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10850 genIfxpCOpJump(nextic, jop);
10852 pic16_freeAsmop(left, NULL, ic, TRUE);
10853 pic16_freeAsmop(result, NULL, ic, TRUE);
10860 /* if the value is already in a pointer register
10861 * then don't need anything more */
10862 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10863 /* otherwise get a free pointer register */
10864 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10869 /* if bitfield then unpack the bits */
10870 if (IS_BITFIELD(retype))
10871 genUnpackBits (result, left, NULL, POINTER);
10873 /* we have can just get the values */
10874 int size = AOP_SIZE(result);
10877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10879 pic16_loadFSR0( left, 0 );
10883 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10884 pic16_popGet(AOP(result), offset++)));
10886 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10887 pic16_popGet(AOP(result), offset++)));
10893 /* now some housekeeping stuff */
10895 /* we had to allocate for this iCode */
10896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10897 pic16_freeAsmop(NULL,aop,ic,TRUE);
10899 /* we did not allocate which means left
10900 * already in a pointer register, then
10901 * if size > 0 && this could be used again
10902 * we have to point it back to where it
10904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10905 if (AOP_SIZE(result) > 1
10906 && !OP_SYMBOL(left)->remat
10907 && ( OP_SYMBOL(left)->liveTo > ic->seq
10909 // int size = AOP_SIZE(result) - 1;
10911 // pic16_emitcode("dec","%s",rname);
10917 pic16_freeAsmop(left,NULL,ic,TRUE);
10918 pic16_freeAsmop(result,NULL,ic,TRUE);
10921 /*-----------------------------------------------------------------*/
10922 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10923 /*-----------------------------------------------------------------*/
10924 static void genPagedPointerGet (operand *left,
10929 regs *preg = NULL ;
10931 sym_link *rtype, *retype;
10933 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10935 rtype = operandType(result);
10936 retype= getSpec(rtype);
10938 pic16_aopOp(left,ic,FALSE);
10940 /* if the value is already in a pointer register
10941 then don't need anything more */
10942 if (!AOP_INPREG(AOP(left))) {
10943 /* otherwise get a free pointer register */
10945 preg = getFreePtr(ic,&aop,FALSE);
10946 pic16_emitcode("mov","%s,%s",
10948 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10949 rname = preg->name ;
10951 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10953 pic16_freeAsmop(left,NULL,ic,TRUE);
10954 pic16_aopOp (result,ic,TRUE);
10956 /* if bitfield then unpack the bits */
10957 if (IS_BITFIELD(retype))
10958 genUnpackBits (result,left,rname,PPOINTER);
10960 /* we have can just get the values */
10961 int size = AOP_SIZE(result);
10966 pic16_emitcode("movx","a,@%s",rname);
10967 pic16_aopPut(AOP(result),"a",offset);
10972 pic16_emitcode("inc","%s",rname);
10976 /* now some housekeeping stuff */
10978 /* we had to allocate for this iCode */
10979 pic16_freeAsmop(NULL,aop,ic,TRUE);
10981 /* we did not allocate which means left
10982 already in a pointer register, then
10983 if size > 0 && this could be used again
10984 we have to point it back to where it
10986 if (AOP_SIZE(result) > 1 &&
10987 !OP_SYMBOL(left)->remat &&
10988 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10990 int size = AOP_SIZE(result) - 1;
10992 pic16_emitcode("dec","%s",rname);
10997 pic16_freeAsmop(result,NULL,ic,TRUE);
11002 /*-----------------------------------------------------------------*/
11003 /* genFarPointerGet - gget value from far space */
11004 /*-----------------------------------------------------------------*/
11005 static void genFarPointerGet (operand *left,
11006 operand *result, iCode *ic)
11009 sym_link *retype = getSpec(operandType(result));
11011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11013 pic16_aopOp(left,ic,FALSE);
11015 /* if the operand is already in dptr
11016 then we do nothing else we move the value to dptr */
11017 if (AOP_TYPE(left) != AOP_STR) {
11018 /* if this is remateriazable */
11019 if (AOP_TYPE(left) == AOP_IMMD)
11020 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11021 else { /* we need to get it byte by byte */
11022 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11023 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11024 if (options.model == MODEL_FLAT24)
11026 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11030 /* so dptr know contains the address */
11031 pic16_freeAsmop(left,NULL,ic,TRUE);
11032 pic16_aopOp(result,ic,TRUE);
11034 /* if bit then unpack */
11035 if (IS_BITFIELD(retype))
11036 genUnpackBits(result,left,"dptr",FPOINTER);
11038 size = AOP_SIZE(result);
11042 pic16_emitcode("movx","a,@dptr");
11043 pic16_aopPut(AOP(result),"a",offset++);
11045 pic16_emitcode("inc","dptr");
11049 pic16_freeAsmop(result,NULL,ic,TRUE);
11053 /*-----------------------------------------------------------------*/
11054 /* genCodePointerGet - get value from code space */
11055 /*-----------------------------------------------------------------*/
11056 static void genCodePointerGet (operand *left,
11057 operand *result, iCode *ic)
11060 sym_link *retype = getSpec(operandType(result));
11062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11064 pic16_aopOp(left,ic,FALSE);
11066 /* if the operand is already in dptr
11067 then we do nothing else we move the value to dptr */
11068 if (AOP_TYPE(left) != AOP_STR) {
11069 /* if this is remateriazable */
11070 if (AOP_TYPE(left) == AOP_IMMD)
11071 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11072 else { /* we need to get it byte by byte */
11073 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11074 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11075 if (options.model == MODEL_FLAT24)
11077 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11081 /* so dptr know contains the address */
11082 pic16_freeAsmop(left,NULL,ic,TRUE);
11083 pic16_aopOp(result,ic,FALSE);
11085 /* if bit then unpack */
11086 if (IS_BITFIELD(retype))
11087 genUnpackBits(result,left,"dptr",CPOINTER);
11089 size = AOP_SIZE(result);
11093 pic16_emitcode("clr","a");
11094 pic16_emitcode("movc","a,@a+dptr");
11095 pic16_aopPut(AOP(result),"a",offset++);
11097 pic16_emitcode("inc","dptr");
11101 pic16_freeAsmop(result,NULL,ic,TRUE);
11106 /*-----------------------------------------------------------------*/
11107 /* genGenPointerGet - gget value from generic pointer space */
11108 /*-----------------------------------------------------------------*/
11109 static void genGenPointerGet (operand *left,
11110 operand *result, iCode *ic)
11112 int size, offset, lit;
11113 sym_link *retype = getSpec(operandType(result));
11115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11116 pic16_aopOp(left,ic,FALSE);
11117 pic16_aopOp(result,ic,FALSE);
11118 size = AOP_SIZE(result);
11120 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11122 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11124 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11125 // load FSR0 from immediate
11126 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11128 // pic16_loadFSR0( left );
11133 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11135 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11142 else { /* we need to get it byte by byte */
11143 // set up FSR0 with address from left
11144 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11151 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11153 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11160 /* if bit then unpack */
11161 if (IS_BITFIELD(retype))
11162 genUnpackBits(result,left,"BAD",GPOINTER);
11165 pic16_freeAsmop(left,NULL,ic,TRUE);
11166 pic16_freeAsmop(result,NULL,ic,TRUE);
11172 /*-----------------------------------------------------------------*/
11173 /* genGenPointerGet - gget value from generic pointer space */
11174 /*-----------------------------------------------------------------*/
11175 static void genGenPointerGet (operand *left,
11176 operand *result, iCode *ic)
11178 int size, offset, lit;
11179 sym_link *retype = getSpec(operandType(result));
11182 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11183 pic16_aopOp(left,ic,FALSE);
11184 pic16_aopOp(result,ic,TRUE);
11185 size = AOP_SIZE(result);
11187 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11189 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11191 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11192 // load FSR0 from immediate
11193 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11195 werror(W_POSSBUG2, __FILE__, __LINE__);
11200 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11202 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11209 } else { /* we need to get it byte by byte */
11211 /* set up WREG:PRODL:FSR0L with address from left */
11212 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11213 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11217 case 1: strcpy(fgptrget, "__gptrget1"); break;
11218 case 2: strcpy(fgptrget, "__gptrget2"); break;
11219 case 3: strcpy(fgptrget, "__gptrget3"); break;
11220 case 4: strcpy(fgptrget, "__gptrget4"); break;
11222 werror(W_POSSBUG2, __FILE__, __LINE__);
11226 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11228 assignResultValue(result, 1);
11233 sym = newSymbol( fgptrget, 0 );
11235 strcpy(sym->rname, fgptrget);
11236 checkAddSym(&externs, sym);
11238 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11244 /* if bit then unpack */
11245 if (IS_BITFIELD(retype))
11246 genUnpackBits(result,left,"BAD",GPOINTER);
11249 pic16_freeAsmop(left,NULL,ic,TRUE);
11250 pic16_freeAsmop(result,NULL,ic,TRUE);
11253 /*-----------------------------------------------------------------*/
11254 /* genConstPointerGet - get value from const generic pointer space */
11255 /*-----------------------------------------------------------------*/
11256 static void genConstPointerGet (operand *left,
11257 operand *result, iCode *ic)
11259 //sym_link *retype = getSpec(operandType(result));
11260 // symbol *albl = newiTempLabel(NULL); // patch 15
11261 // symbol *blbl = newiTempLabel(NULL); //
11262 // PIC_OPCODE poc; // patch 15
11266 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11267 pic16_aopOp(left,ic,FALSE);
11268 pic16_aopOp(result,ic,TRUE);
11269 size = AOP_SIZE(result);
11271 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11273 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11275 // set up table pointer
11276 if( (AOP_TYPE(left) == AOP_PCODE)
11277 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11278 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11280 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11281 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11282 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11283 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11284 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11285 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11287 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11288 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11289 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11293 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11294 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11298 pic16_freeAsmop(left,NULL,ic,TRUE);
11299 pic16_freeAsmop(result,NULL,ic,TRUE);
11303 /*-----------------------------------------------------------------*/
11304 /* genPointerGet - generate code for pointer get */
11305 /*-----------------------------------------------------------------*/
11306 static void genPointerGet (iCode *ic)
11308 operand *left, *result ;
11309 sym_link *type, *etype;
11314 left = IC_LEFT(ic);
11315 result = IC_RESULT(ic) ;
11317 /* depending on the type of pointer we need to
11318 move it to the correct pointer register */
11319 type = operandType(left);
11320 etype = getSpec(type);
11323 if (IS_PTR_CONST(type))
11325 if (IS_CODEPTR(type))
11327 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11329 /* if left is of type of pointer then it is simple */
11330 if (IS_PTR(type) && !IS_FUNC(type->next))
11331 p_type = DCL_TYPE(type);
11333 /* we have to go by the storage class */
11334 p_type = PTR_TYPE(SPEC_OCLS(etype));
11336 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11338 if (SPEC_OCLS(etype)->codesp ) {
11339 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11340 //p_type = CPOINTER ;
11342 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11343 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11344 /*p_type = FPOINTER ;*/
11346 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11347 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11348 /* p_type = PPOINTER; */
11350 if (SPEC_OCLS(etype) == idata ) {
11351 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11352 /* p_type = IPOINTER; */
11354 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11355 /* p_type = POINTER ; */
11359 /* now that we have the pointer type we assign
11360 the pointer values */
11364 genNearPointerGet (left,result,ic);
11368 genPagedPointerGet(left,result,ic);
11372 genFarPointerGet (left,result,ic);
11376 genConstPointerGet (left,result,ic);
11377 //pic16_emitcodePointerGet (left,result,ic);
11382 if (IS_PTR_CONST(type))
11383 genConstPointerGet (left,result,ic);
11386 genGenPointerGet (left,result,ic);
11390 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11391 "genPointerGet: illegal pointer type");
11396 /*-----------------------------------------------------------------*/
11397 /* genPackBits - generates code for packed bit storage */
11398 /*-----------------------------------------------------------------*/
11399 static void genPackBits (sym_link *etype , operand *result,
11401 char *rname, int p_type)
11409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11410 blen = SPEC_BLEN(etype);
11411 bstr = SPEC_BSTR(etype);
11413 retype = getSpec(operandType(right));
11415 if(AOP_TYPE(right) == AOP_LIT) {
11416 if((blen == 1) && (bstr < 8)) {
11418 /* it is a single bit, so use the appropriate bit instructions */
11420 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11422 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11423 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11424 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11425 /* workaround to reduce the extra lfsr instruction */
11427 pic16_emitpcode(POC_BSF,
11428 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11430 pic16_emitpcode(POC_BCF,
11431 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11434 pic16_loadFSR0(result, 0);
11436 pic16_emitpcode(POC_BSF,
11437 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11439 pic16_emitpcode(POC_BCF,
11440 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11446 /* move literal to W */
11447 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11450 if(IS_BITFIELD(retype)
11451 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11455 rblen = SPEC_BLEN( retype );
11456 rbstr = SPEC_BSTR( retype );
11459 if(IS_BITFIELD(etype)) {
11460 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11461 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11463 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11466 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11468 if(IS_BITFIELD(etype)) {
11469 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11471 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11474 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11478 /* move right to W */
11479 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11482 /* if the bit length is less than or */
11483 /* it exactly fits a byte then */
11484 if((shCnt=SPEC_BSTR(etype))
11485 || SPEC_BLEN(etype) <= 8 ) {
11486 int fsr0_setup = 0;
11488 if (blen != 8 || bstr != 0) {
11489 // we need to combine the value with the old value
11490 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11492 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11493 SPEC_BSTR(etype), SPEC_BLEN(etype));
11495 /* shift left acc */
11498 /* using PRODH as a temporary register here */
11499 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11501 if (OP_SYMBOL(result)->remat) {
11502 // access symbol directly
11503 pic16_mov2w (AOP(result), 0);
11505 /* get old value */
11509 pic16_loadFSR0( result, 0 );
11511 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11512 // pic16_emitcode ("mov","b,a");
11513 // pic16_emitcode("mov","a,@%s",rname);
11517 if (AOP(result)->aopu.aop_reg[2]) {
11518 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11519 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11520 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11521 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11522 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11525 sym = newSymbol( "__gptrget1", 0 );
11526 strcpy(sym->rname, "__gptrget1");
11527 checkAddSym(&externs, sym);
11530 // data pointer (just 2 byte given)
11531 pic16_loadFSR0( result, 0 );
11533 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11536 // warnings will be emitted below
11537 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11538 //werror(W_POSSBUG2, __FILE__, __LINE__);
11542 assert (0 && "invalid pointer type specified");
11547 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11548 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11549 (unsigned char)(0xff >> (8-bstr))) ));
11550 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11551 } // if (blen != 8 || bstr != 0)
11553 /* write new value back */
11554 if (OP_SYMBOL(result)->remat) {
11555 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11560 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11561 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11565 if (AOP(result)->aopu.aop_reg[2]) {
11566 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11567 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11568 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11569 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11570 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11571 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11574 sym = newSymbol( "__gptrput1", 0 );
11575 strcpy(sym->rname, "__gptrput1");
11576 checkAddSym(&externs, sym);
11579 // data pointer (just 2 byte given)
11580 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11581 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11584 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11585 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11586 werror(W_POSSBUG2, __FILE__, __LINE__);
11590 assert (0 && "invalid pointer type specified");
11601 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11602 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11607 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11608 rLen = SPEC_BLEN(etype)-8;
11610 /* now generate for lengths greater than one byte */
11614 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11620 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11626 pic16_emitcode("movx","@dptr,a");
11631 DEBUGpic16_emitcode(";lcall","__gptrput");
11639 pic16_mov2w(AOP(right), offset++);
11642 /* last last was not complete */
11644 /* save the byte & read byte */
11647 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11648 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11653 pic16_emitcode ("mov","b,a");
11654 pic16_emitcode("movx","a,@dptr");
11658 pic16_emitcode ("push","b");
11659 pic16_emitcode ("push","acc");
11660 pic16_emitcode ("lcall","__gptrget");
11661 pic16_emitcode ("pop","b");
11667 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11668 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11669 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11670 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11671 // pic16_emitcode ("orl","a,b");
11674 // if (p_type == GPOINTER)
11675 // pic16_emitcode("pop","b");
11680 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11681 // pic16_emitcode("mov","@%s,a",rname);
11685 pic16_emitcode("movx","@dptr,a");
11689 DEBUGpic16_emitcode(";lcall","__gptrput");
11696 // pic16_freeAsmop(right, NULL, ic, TRUE);
11698 /*-----------------------------------------------------------------*/
11699 /* genDataPointerSet - remat pointer to data space */
11700 /*-----------------------------------------------------------------*/
11701 static void genDataPointerSet(operand *right,
11705 int size, offset = 0, resoffset=0 ;
11707 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11708 pic16_aopOp(right,ic,FALSE);
11710 size = AOP_SIZE(right);
11712 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11715 if ( AOP_TYPE(result) == AOP_PCODE) {
11716 fprintf(stderr,"genDataPointerSet %s, %d\n",
11717 AOP(result)->aopu.pcop->name,
11718 (AOP(result)->aopu.pcop->type == PO_DIR)?
11719 PCOR(AOP(result)->aopu.pcop)->instance:
11720 PCOI(AOP(result)->aopu.pcop)->offset);
11724 if(AOP(result)->aopu.pcop->type == PO_DIR)
11725 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11728 if (AOP_TYPE(right) == AOP_LIT) {
11731 if(!IS_FLOAT(operandType( right )))
11732 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11735 unsigned long lit_int;
11739 /* take care if literal is a float */
11740 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11741 lit = info.lit_int;
11744 lit = lit >> (8*offset);
11746 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11749 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11752 pic16_mov2w(AOP(right), offset);
11753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11759 pic16_freeAsmop(right,NULL,ic,TRUE);
11764 /*-----------------------------------------------------------------*/
11765 /* genNearPointerSet - pic16_emitcode for near pointer put */
11766 /*-----------------------------------------------------------------*/
11767 static void genNearPointerSet (operand *right,
11773 sym_link *ptype = operandType(result);
11774 sym_link *resetype;
11776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11777 retype= getSpec(operandType(right));
11778 resetype = getSpec(operandType(result));
11780 pic16_aopOp(result,ic,FALSE);
11782 /* if the result is rematerializable &
11783 * in data space & not a bit variable */
11785 /* and result is not a bit variable */
11786 if (AOP_TYPE(result) == AOP_PCODE
11787 // && AOP_TYPE(result) == AOP_IMMD
11788 && DCL_TYPE(ptype) == POINTER
11789 && !IS_BITFIELD(retype)
11790 && !IS_BITFIELD(resetype)) {
11792 genDataPointerSet (right,result,ic);
11793 pic16_freeAsmop(result,NULL,ic,TRUE);
11797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11798 pic16_aopOp(right,ic,FALSE);
11799 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11801 /* if the value is already in a pointer register
11802 * then don't need anything more */
11803 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11804 /* otherwise get a free pointer register */
11805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11812 /* if bitfield then unpack the bits */
11813 if (IS_BITFIELD(resetype)) {
11814 genPackBits (resetype, result, right, NULL, POINTER);
11816 /* we have can just get the values */
11817 int size = AOP_SIZE(right);
11820 pic16_loadFSR0(result, 0);
11822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11824 if (AOP_TYPE(right) == AOP_LIT) {
11825 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11827 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11829 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11831 } else { // no literal
11833 pic16_emitpcode(POC_MOVFF,
11834 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11835 pic16_popCopyReg(&pic16_pc_postinc0)));
11837 pic16_emitpcode(POC_MOVFF,
11838 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11839 pic16_popCopyReg(&pic16_pc_indf0)));
11846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11847 /* now some housekeeping stuff */
11849 /* we had to allocate for this iCode */
11850 pic16_freeAsmop(NULL,aop,ic,TRUE);
11852 /* we did not allocate which means left
11853 * already in a pointer register, then
11854 * if size > 0 && this could be used again
11855 * we have to point it back to where it
11857 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11858 if (AOP_SIZE(right) > 1
11859 && !OP_SYMBOL(result)->remat
11860 && ( OP_SYMBOL(result)->liveTo > ic->seq
11863 int size = AOP_SIZE(right) - 1;
11866 pic16_emitcode("decf","fsr0,f");
11867 //pic16_emitcode("dec","%s",rname);
11871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11874 pic16_freeAsmop(right,NULL,ic,TRUE);
11875 pic16_freeAsmop(result,NULL,ic,TRUE);
11878 /*-----------------------------------------------------------------*/
11879 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11880 /*-----------------------------------------------------------------*/
11881 static void genPagedPointerSet (operand *right,
11886 regs *preg = NULL ;
11890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11892 retype= getSpec(operandType(right));
11894 pic16_aopOp(result,ic,FALSE);
11896 /* if the value is already in a pointer register
11897 then don't need anything more */
11898 if (!AOP_INPREG(AOP(result))) {
11899 /* otherwise get a free pointer register */
11901 preg = getFreePtr(ic,&aop,FALSE);
11902 pic16_emitcode("mov","%s,%s",
11904 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11905 rname = preg->name ;
11907 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11909 pic16_freeAsmop(result,NULL,ic,TRUE);
11910 pic16_aopOp (right,ic,FALSE);
11912 /* if bitfield then unpack the bits */
11913 if (IS_BITFIELD(retype))
11914 genPackBits (retype,result,right,rname,PPOINTER);
11916 /* we have can just get the values */
11917 int size = AOP_SIZE(right);
11921 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11924 pic16_emitcode("movx","@%s,a",rname);
11927 pic16_emitcode("inc","%s",rname);
11933 /* now some housekeeping stuff */
11935 /* we had to allocate for this iCode */
11936 pic16_freeAsmop(NULL,aop,ic,TRUE);
11938 /* we did not allocate which means left
11939 already in a pointer register, then
11940 if size > 0 && this could be used again
11941 we have to point it back to where it
11943 if (AOP_SIZE(right) > 1 &&
11944 !OP_SYMBOL(result)->remat &&
11945 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11947 int size = AOP_SIZE(right) - 1;
11949 pic16_emitcode("dec","%s",rname);
11954 pic16_freeAsmop(right,NULL,ic,TRUE);
11959 /*-----------------------------------------------------------------*/
11960 /* genFarPointerSet - set value from far space */
11961 /*-----------------------------------------------------------------*/
11962 static void genFarPointerSet (operand *right,
11963 operand *result, iCode *ic)
11966 sym_link *retype = getSpec(operandType(right));
11968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11969 pic16_aopOp(result,ic,FALSE);
11971 /* if the operand is already in dptr
11972 then we do nothing else we move the value to dptr */
11973 if (AOP_TYPE(result) != AOP_STR) {
11974 /* if this is remateriazable */
11975 if (AOP_TYPE(result) == AOP_IMMD)
11976 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11977 else { /* we need to get it byte by byte */
11978 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11979 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11980 if (options.model == MODEL_FLAT24)
11982 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11986 /* so dptr know contains the address */
11987 pic16_freeAsmop(result,NULL,ic,TRUE);
11988 pic16_aopOp(right,ic,FALSE);
11990 /* if bit then unpack */
11991 if (IS_BITFIELD(retype))
11992 genPackBits(retype,result,right,"dptr",FPOINTER);
11994 size = AOP_SIZE(right);
11998 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12000 pic16_emitcode("movx","@dptr,a");
12002 pic16_emitcode("inc","dptr");
12006 pic16_freeAsmop(right,NULL,ic,TRUE);
12009 /*-----------------------------------------------------------------*/
12010 /* genGenPointerSet - set value from generic pointer space */
12011 /*-----------------------------------------------------------------*/
12013 static void genGenPointerSet (operand *right,
12014 operand *result, iCode *ic)
12016 int i, size, offset, lit;
12017 sym_link *retype = getSpec(operandType(right));
12019 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12021 pic16_aopOp(result,ic,FALSE);
12022 pic16_aopOp(right,ic,FALSE);
12023 size = AOP_SIZE(right);
12026 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12028 /* if the operand is already in dptr
12029 then we do nothing else we move the value to dptr */
12030 if (AOP_TYPE(result) != AOP_STR) {
12031 /* if this is remateriazable */
12032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12033 // WARNING: anythig until "else" is untested!
12034 if (AOP_TYPE(result) == AOP_IMMD) {
12035 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12036 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12037 // load FSR0 from immediate
12038 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12042 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12050 else { /* we need to get it byte by byte */
12051 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12052 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12054 // set up FSR0 with address of result
12055 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12056 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12058 /* hack hack! see if this the FSR. If so don't load W */
12059 if(AOP_TYPE(right) != AOP_ACC) {
12061 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12063 if(AOP_TYPE(right) == AOP_LIT)
12066 // note: pic16_popGet handles sign extension
12067 for(i=0;i<size;i++) {
12068 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12070 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12072 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12077 for(i=0;i<size;i++) {
12079 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12080 pic16_popCopyReg(&pic16_pc_postinc0)));
12082 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12083 pic16_popCopyReg(&pic16_pc_indf0)));
12089 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12090 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12092 } // if (AOP_TYPE(result) != AOP_IMMD)
12094 } // if (AOP_TYPE(result) != AOP_STR)
12095 /* so dptr know contains the address */
12098 /* if bit then unpack */
12099 if (IS_BITFIELD(retype))
12100 genPackBits(retype,result,right,"dptr",GPOINTER);
12102 size = AOP_SIZE(right);
12105 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12107 // set up FSR0 with address of result
12108 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12109 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12112 if (AOP_TYPE(right) == AOP_LIT) {
12113 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12115 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12117 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12119 } else { // no literal
12121 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12131 pic16_freeAsmop(right,NULL,ic,TRUE);
12132 pic16_freeAsmop(result,NULL,ic,TRUE);
12136 static void genGenPointerSet (operand *right,
12137 operand *result, iCode *ic)
12140 sym_link *retype = getSpec(operandType(right));
12143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12145 pic16_aopOp(result,ic,FALSE);
12146 pic16_aopOp(right,ic,FALSE);
12147 size = AOP_SIZE(right);
12149 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12152 /* if bit then unpack */
12153 if (IS_BITFIELD(retype)) {
12154 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12155 genPackBits(retype,result,right,"dptr",GPOINTER);
12159 size = AOP_SIZE(right);
12161 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12165 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12167 /* value of right+0 is placed on stack, which will be retrieved
12168 * by the support function this restoring the stack. The important
12169 * thing is that there is no need to manually restore stack pointer
12171 pushaop(AOP(right), 0);
12172 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12173 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12174 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12175 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12177 /* load address to write to in WREG:FSR0H:FSR0L */
12178 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12179 pic16_popCopyReg(&pic16_pc_fsr0l)));
12180 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12181 pic16_popCopyReg(&pic16_pc_prodl)));
12182 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12185 /* put code here */
12187 case 1: strcpy(fgptrput, "__gptrput1"); break;
12188 case 2: strcpy(fgptrput, "__gptrput2"); break;
12189 case 3: strcpy(fgptrput, "__gptrput3"); break;
12190 case 4: strcpy(fgptrput, "__gptrput4"); break;
12192 werror(W_POSSBUG2, __FILE__, __LINE__);
12196 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12201 sym = newSymbol( fgptrput, 0 );
12203 strcpy(sym->rname, fgptrput);
12204 checkAddSym(&externs, sym);
12208 pic16_freeAsmop(right,NULL,ic,TRUE);
12209 pic16_freeAsmop(result,NULL,ic,TRUE);
12212 /*-----------------------------------------------------------------*/
12213 /* genPointerSet - stores the value into a pointer location */
12214 /*-----------------------------------------------------------------*/
12215 static void genPointerSet (iCode *ic)
12217 operand *right, *result ;
12218 sym_link *type, *etype;
12223 right = IC_RIGHT(ic);
12224 result = IC_RESULT(ic) ;
12226 /* depending on the type of pointer we need to
12227 move it to the correct pointer register */
12228 type = operandType(result);
12229 etype = getSpec(type);
12230 /* if left is of type of pointer then it is simple */
12231 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12232 p_type = DCL_TYPE(type);
12235 /* we have to go by the storage class */
12236 p_type = PTR_TYPE(SPEC_OCLS(etype));
12238 /* if (SPEC_OCLS(etype)->codesp ) { */
12239 /* p_type = CPOINTER ; */
12242 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12243 /* p_type = FPOINTER ; */
12245 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12246 /* p_type = PPOINTER ; */
12248 /* if (SPEC_OCLS(etype) == idata ) */
12249 /* p_type = IPOINTER ; */
12251 /* p_type = POINTER ; */
12254 /* now that we have the pointer type we assign
12255 the pointer values */
12259 genNearPointerSet (right,result,ic);
12263 genPagedPointerSet (right,result,ic);
12267 genFarPointerSet (right,result,ic);
12271 genGenPointerSet (right,result,ic);
12275 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12276 "genPointerSet: illegal pointer type");
12280 /*-----------------------------------------------------------------*/
12281 /* genIfx - generate code for Ifx statement */
12282 /*-----------------------------------------------------------------*/
12283 static void genIfx (iCode *ic, iCode *popIc)
12285 operand *cond = IC_COND(ic);
12290 pic16_aopOp(cond,ic,FALSE);
12292 /* get the value into acc */
12293 if (AOP_TYPE(cond) != AOP_CRY)
12294 pic16_toBoolean(cond);
12297 /* the result is now in the accumulator */
12298 pic16_freeAsmop(cond,NULL,ic,TRUE);
12300 /* if there was something to be popped then do it */
12304 /* if the condition is a bit variable */
12305 if (isbit && IS_ITEMP(cond) &&
12307 genIfxJump(ic,"c");
12308 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12310 if (isbit && !IS_ITEMP(cond))
12311 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12313 genIfxJump(ic,"a");
12318 /*-----------------------------------------------------------------*/
12319 /* genAddrOf - generates code for address of */
12320 /*-----------------------------------------------------------------*/
12321 static void genAddrOf (iCode *ic)
12323 operand *result, *left;
12325 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12326 pCodeOp *pcop0, *pcop1, *pcop2;
12330 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12332 sym = OP_SYMBOL( IC_LEFT(ic) );
12335 /* get address of symbol on stack */
12336 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12338 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12339 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12342 // operands on stack are accessible via "FSR2 + index" with index
12343 // starting at 2 for arguments and growing from 0 downwards for
12344 // local variables (index == 0 is not assigned so we add one here)
12346 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12348 assert (soffs < 0);
12351 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12352 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12353 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12354 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12355 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12356 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12357 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12363 // if(pic16_debug_verbose) {
12364 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12365 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12368 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12369 size = AOP_SIZE(IC_RESULT(ic));
12371 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12372 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12373 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12376 pic16_emitpcode(POC_MOVLW, pcop0);
12377 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12378 pic16_emitpcode(POC_MOVLW, pcop1);
12379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12380 pic16_emitpcode(POC_MOVLW, pcop2);
12381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12384 pic16_emitpcode(POC_MOVLW, pcop0);
12385 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12386 pic16_emitpcode(POC_MOVLW, pcop1);
12387 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12389 pic16_emitpcode(POC_MOVLW, pcop0);
12390 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12393 pic16_freeAsmop(left, NULL, ic, FALSE);
12395 pic16_freeAsmop(result,NULL,ic,TRUE);
12400 /*-----------------------------------------------------------------*/
12401 /* genFarFarAssign - assignment when both are in far space */
12402 /*-----------------------------------------------------------------*/
12403 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12405 int size = AOP_SIZE(right);
12408 /* first push the right side on to the stack */
12410 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12412 pic16_emitcode ("push","acc");
12415 pic16_freeAsmop(right,NULL,ic,FALSE);
12416 /* now assign DPTR to result */
12417 pic16_aopOp(result,ic,FALSE);
12418 size = AOP_SIZE(result);
12420 pic16_emitcode ("pop","acc");
12421 pic16_aopPut(AOP(result),"a",--offset);
12423 pic16_freeAsmop(result,NULL,ic,FALSE);
12428 /*-----------------------------------------------------------------*/
12429 /* genAssign - generate code for assignment */
12430 /*-----------------------------------------------------------------*/
12431 static void genAssign (iCode *ic)
12433 operand *result, *right;
12434 int size, offset,know_W;
12435 unsigned long lit = 0L;
12437 result = IC_RESULT(ic);
12438 right = IC_RIGHT(ic) ;
12442 /* if they are the same */
12443 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12446 /* reversed order operands are aopOp'ed so that result operand
12447 * is effective in case right is a stack symbol. This maneauver
12448 * allows to use the _G.resDirect flag later */
12449 pic16_aopOp(result,ic,TRUE);
12450 pic16_aopOp(right,ic,FALSE);
12452 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12454 /* if they are the same registers */
12455 if (pic16_sameRegs(AOP(right),AOP(result)))
12458 /* if the result is a bit */
12459 if (AOP_TYPE(result) == AOP_CRY) {
12460 /* if the right size is a literal then
12461 we know what the value is */
12462 if (AOP_TYPE(right) == AOP_LIT) {
12464 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12465 pic16_popGet(AOP(result),0));
12467 if (((int) operandLitValue(right)))
12468 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12469 AOP(result)->aopu.aop_dir,
12470 AOP(result)->aopu.aop_dir);
12472 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12473 AOP(result)->aopu.aop_dir,
12474 AOP(result)->aopu.aop_dir);
12478 /* the right is also a bit variable */
12479 if (AOP_TYPE(right) == AOP_CRY) {
12480 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12481 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12482 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12484 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12485 AOP(result)->aopu.aop_dir,
12486 AOP(result)->aopu.aop_dir);
12487 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12488 AOP(right)->aopu.aop_dir,
12489 AOP(right)->aopu.aop_dir);
12490 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12491 AOP(result)->aopu.aop_dir,
12492 AOP(result)->aopu.aop_dir);
12496 /* we need to or */
12497 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12498 pic16_toBoolean(right);
12500 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12501 //pic16_aopPut(AOP(result),"a",0);
12505 /* bit variables done */
12507 size = AOP_SIZE(result);
12510 if(AOP_TYPE(right) == AOP_LIT) {
12511 if(!IS_FLOAT(operandType( right )))
12512 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12515 unsigned long lit_int;
12519 /* take care if literal is a float */
12520 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12521 lit = info.lit_int;
12525 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12526 // sizeof(unsigned long int), sizeof(float));
12529 if (AOP_TYPE(right) == AOP_REG) {
12530 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12533 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12538 if(AOP_TYPE(right) != AOP_LIT
12539 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12540 && !IS_FUNC(OP_SYM_TYPE(right))
12542 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12543 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12545 // set up table pointer
12546 if(is_LitOp(right)) {
12547 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12548 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12549 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12550 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12551 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12552 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12553 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12555 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12556 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12557 pic16_popCopyReg(&pic16_pc_tblptrl)));
12558 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12559 pic16_popCopyReg(&pic16_pc_tblptrh)));
12560 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12561 pic16_popCopyReg(&pic16_pc_tblptru)));
12564 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12566 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12567 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12568 pic16_popGet(AOP(result),offset)));
12572 size = getSize(OP_SYM_ETYPE(right));
12573 if(AOP_SIZE(result) > size) {
12574 size = AOP_SIZE(result) - size;
12576 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12586 /* VR - What is this?! */
12587 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12589 if(aopIdx(AOP(result),0) == 4) {
12591 /* this is a workaround to save value of right into wreg too,
12592 * value of wreg is going to be used later */
12593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12594 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12595 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12599 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12605 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12606 if(AOP_TYPE(right) == AOP_LIT) {
12608 if(know_W != (lit&0xff))
12609 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12611 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12613 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12617 } else if (AOP_TYPE(right) == AOP_CRY) {
12618 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12620 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12621 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12622 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12624 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12625 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12626 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12628 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12630 if(!_G.resDirect) /* use this aopForSym feature */
12631 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12638 pic16_freeAsmop (right,NULL,ic,FALSE);
12639 pic16_freeAsmop (result,NULL,ic,TRUE);
12642 /*-----------------------------------------------------------------*/
12643 /* genJumpTab - generates code for jump table */
12644 /*-----------------------------------------------------------------*/
12645 static void genJumpTab (iCode *ic)
12650 pCodeOp *jt_offs_hi;
12655 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12656 /* get the condition into accumulator */
12657 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12659 /* multiply by three */
12660 pic16_emitcode("add","a,acc");
12661 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12663 jtab = newiTempLabel(NULL);
12664 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12665 pic16_emitcode("jmp","@a+dptr");
12666 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12669 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12670 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12672 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12673 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12674 pic16_emitpLabel(jtab->key);
12678 jt_offs = pic16_popGetTempReg(0);
12679 jt_offs_hi = pic16_popGetTempReg(1);
12680 jt_label = pic16_popGetLabel (jtab->key);
12681 //fprintf (stderr, "Creating jump table...\n");
12683 // calculate offset into jump table (idx * sizeof (GOTO))
12684 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12685 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12686 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12687 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12688 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12689 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12690 pic16_emitpcode(POC_MOVWF , jt_offs);
12692 // prepare PCLATx (set to first entry in jump table)
12693 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12694 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12695 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12696 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12697 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12699 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12700 pic16_emitpcode(POC_ADDWF , jt_offs);
12701 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12702 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12704 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12706 // release temporaries and prepare jump into table (new PCL --> WREG)
12707 pic16_emitpcode(POC_MOVFW , jt_offs);
12708 pic16_popReleaseTempReg (jt_offs_hi, 1);
12709 pic16_popReleaseTempReg (jt_offs, 0);
12711 // jump into the table
12712 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12714 pic16_emitpLabelFORCE(jtab->key);
12717 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12718 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12720 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12721 /* now generate the jump labels */
12722 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12723 jtab = setNextItem(IC_JTLABELS(ic))) {
12724 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12725 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12728 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12732 /*-----------------------------------------------------------------*/
12733 /* genMixedOperation - gen code for operators between mixed types */
12734 /*-----------------------------------------------------------------*/
12736 TSD - Written for the PIC port - but this unfortunately is buggy.
12737 This routine is good in that it is able to efficiently promote
12738 types to different (larger) sizes. Unfortunately, the temporary
12739 variables that are optimized out by this routine are sometimes
12740 used in other places. So until I know how to really parse the
12741 iCode tree, I'm going to not be using this routine :(.
12743 static int genMixedOperation (iCode *ic)
12746 operand *result = IC_RESULT(ic);
12747 sym_link *ctype = operandType(IC_LEFT(ic));
12748 operand *right = IC_RIGHT(ic);
12754 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12756 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12762 nextright = IC_RIGHT(nextic);
12763 nextleft = IC_LEFT(nextic);
12764 nextresult = IC_RESULT(nextic);
12766 pic16_aopOp(right,ic,FALSE);
12767 pic16_aopOp(result,ic,FALSE);
12768 pic16_aopOp(nextright, nextic, FALSE);
12769 pic16_aopOp(nextleft, nextic, FALSE);
12770 pic16_aopOp(nextresult, nextic, FALSE);
12772 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12774 operand *t = right;
12778 pic16_emitcode(";remove right +","");
12780 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12782 operand *t = right;
12786 pic16_emitcode(";remove left +","");
12790 big = AOP_SIZE(nextleft);
12791 small = AOP_SIZE(nextright);
12793 switch(nextic->op) {
12796 pic16_emitcode(";optimize a +","");
12797 /* if unsigned or not an integral type */
12798 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12799 pic16_emitcode(";add a bit to something","");
12802 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12804 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12805 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12806 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12808 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12816 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12817 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12818 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12821 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12823 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12824 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12825 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12826 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12827 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12830 pic16_emitcode("rlf","known_zero,w");
12837 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12838 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12839 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12841 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12851 pic16_freeAsmop(right,NULL,ic,TRUE);
12852 pic16_freeAsmop(result,NULL,ic,TRUE);
12853 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12854 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12856 nextic->generated = 1;
12863 /*-----------------------------------------------------------------*/
12864 /* genCast - gen code for casting */
12865 /*-----------------------------------------------------------------*/
12866 static void genCast (iCode *ic)
12868 operand *result = IC_RESULT(ic);
12869 sym_link *ctype = operandType(IC_LEFT(ic));
12870 sym_link *rtype = operandType(IC_RIGHT(ic));
12871 sym_link *restype = operandType(IC_RESULT(ic));
12872 operand *right = IC_RIGHT(ic);
12878 /* if they are equivalent then do nothing */
12879 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12882 pic16_aopOp(result,ic,FALSE);
12883 pic16_aopOp(right,ic,FALSE) ;
12885 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12888 /* if the result is a bit */
12889 if (AOP_TYPE(result) == AOP_CRY) {
12891 /* if the right size is a literal then
12892 * we know what the value is */
12893 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12895 if (AOP_TYPE(right) == AOP_LIT) {
12896 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12897 pic16_popGet(AOP(result),0));
12899 if (((int) operandLitValue(right)))
12900 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12901 AOP(result)->aopu.aop_dir,
12902 AOP(result)->aopu.aop_dir);
12904 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12905 AOP(result)->aopu.aop_dir,
12906 AOP(result)->aopu.aop_dir);
12910 /* the right is also a bit variable */
12911 if (AOP_TYPE(right) == AOP_CRY) {
12913 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12915 pic16_emitcode("clrc","");
12916 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12917 AOP(right)->aopu.aop_dir,
12918 AOP(right)->aopu.aop_dir);
12919 pic16_aopPut(AOP(result),"c",0);
12923 /* we need to or */
12924 if (AOP_TYPE(right) == AOP_REG) {
12925 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12926 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12927 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12929 pic16_toBoolean(right);
12930 pic16_aopPut(AOP(result),"a",0);
12934 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12937 size = AOP_SIZE(result);
12939 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12941 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12942 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12943 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12946 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12951 if(IS_BITFIELD(getSpec(restype))
12952 && IS_BITFIELD(getSpec(rtype))) {
12953 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12956 /* if they are the same size : or less */
12957 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12959 /* if they are in the same place */
12960 if (pic16_sameRegs(AOP(right),AOP(result)))
12963 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12965 if (IS_PTR_CONST(rtype))
12967 if (IS_CODEPTR(rtype))
12969 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12972 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12974 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12976 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12979 if(AOP_TYPE(right) == AOP_IMMD) {
12980 pCodeOp *pcop0, *pcop1, *pcop2;
12981 symbol *sym = OP_SYMBOL( right );
12983 size = AOP_SIZE(result);
12985 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12987 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12989 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12992 pic16_emitpcode(POC_MOVLW, pcop0);
12993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12994 pic16_emitpcode(POC_MOVLW, pcop1);
12995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12996 pic16_emitpcode(POC_MOVLW, pcop2);
12997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13000 pic16_emitpcode(POC_MOVLW, pcop0);
13001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13002 pic16_emitpcode(POC_MOVLW, pcop1);
13003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13005 pic16_emitpcode(POC_MOVLW, pcop0);
13006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13010 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13011 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13012 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13013 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13015 if(AOP_SIZE(result) <2)
13016 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13018 /* if they in different places then copy */
13019 size = AOP_SIZE(result);
13022 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13030 /* if the result is of type pointer */
13031 if (IS_PTR(ctype)) {
13033 sym_link *type = operandType(right);
13034 sym_link *etype = getSpec(type);
13036 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13038 /* pointer to generic pointer */
13039 if (IS_GENPTR(ctype)) {
13043 p_type = DCL_TYPE(type);
13045 /* we have to go by the storage class */
13046 p_type = PTR_TYPE(SPEC_OCLS(etype));
13048 /* if (SPEC_OCLS(etype)->codesp ) */
13049 /* p_type = CPOINTER ; */
13051 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13052 /* p_type = FPOINTER ; */
13054 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13055 /* p_type = PPOINTER; */
13057 /* if (SPEC_OCLS(etype) == idata ) */
13058 /* p_type = IPOINTER ; */
13060 /* p_type = POINTER ; */
13063 /* the first two bytes are known */
13064 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13065 size = GPTRSIZE - 1;
13068 if(offset < AOP_SIZE(right)) {
13069 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13070 mov2f(AOP(result), AOP(right), offset);
13072 if ((AOP_TYPE(right) == AOP_PCODE) &&
13073 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13074 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13078 pic16_aopPut(AOP(result),
13079 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13084 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13087 /* the last byte depending on type */
13091 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13092 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13093 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13097 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13101 pic16_emitcode(";BUG!? ","%d",__LINE__);
13105 pic16_emitcode(";BUG!? ","%d",__LINE__);
13110 if (GPTRSIZE > AOP_SIZE(right)) {
13111 // assume data pointer... THIS MIGHT BE WRONG!
13112 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13113 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13115 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13120 /* this should never happen */
13121 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13122 "got unknown pointer type");
13125 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13131 /* just copy the pointers */
13132 size = AOP_SIZE(result);
13135 pic16_aopPut(AOP(result),
13136 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13145 /* so we now know that the size of destination is greater
13146 than the size of the source.
13147 Now, if the next iCode is an operator then we might be
13148 able to optimize the operation without performing a cast.
13150 if(genMixedOperation(ic))
13153 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13155 /* we move to result for the size of source */
13156 size = AOP_SIZE(right);
13161 mov2f(AOP(result), AOP(right), offset);
13165 /* now depending on the sign of the destination */
13166 size = AOP_SIZE(result) - AOP_SIZE(right);
13167 /* if unsigned or not an integral type */
13168 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13170 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13172 /* we need to extend the sign :( */
13175 /* Save one instruction of casting char to int */
13176 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13177 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13178 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13180 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13183 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13185 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13187 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13190 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13195 pic16_freeAsmop(right,NULL,ic,TRUE);
13196 pic16_freeAsmop(result,NULL,ic,TRUE);
13200 /*-----------------------------------------------------------------*/
13201 /* genDjnz - generate decrement & jump if not zero instrucion */
13202 /*-----------------------------------------------------------------*/
13203 static int genDjnz (iCode *ic, iCode *ifx)
13205 symbol *lbl, *lbl1;
13206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13211 /* if the if condition has a false label
13212 then we cannot save */
13216 /* if the minus is not of the form
13218 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13219 !IS_OP_LITERAL(IC_RIGHT(ic)))
13222 if (operandLitValue(IC_RIGHT(ic)) != 1)
13225 /* if the size of this greater than one then no
13227 if (getSize(operandType(IC_RESULT(ic))) > 1)
13230 /* otherwise we can save BIG */
13231 lbl = newiTempLabel(NULL);
13232 lbl1= newiTempLabel(NULL);
13234 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13236 if (IS_AOP_PREG(IC_RESULT(ic))) {
13237 pic16_emitcode("dec","%s",
13238 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13239 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13240 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13244 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13245 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13247 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13248 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13252 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13253 ifx->generated = 1;
13257 /*-----------------------------------------------------------------*/
13258 /* genReceive - generate code for a receive iCode */
13259 /*-----------------------------------------------------------------*/
13260 static void genReceive (iCode *ic)
13266 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13267 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13269 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13271 if (isOperandInFarSpace(IC_RESULT(ic))
13272 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13273 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13275 int size = getSize(operandType(IC_RESULT(ic)));
13276 int offset = pic16_fReturnSizePic - size;
13280 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13281 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13285 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13287 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13288 size = AOP_SIZE(IC_RESULT(ic));
13291 pic16_emitcode ("pop","acc");
13292 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13295 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13297 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13300 /* set pseudo stack pointer to where it should be - dw*/
13301 GpsuedoStkPtr = ic->parmBytes;
13303 /* setting GpsuedoStkPtr has side effects here: */
13304 assignResultValue(IC_RESULT(ic), 0);
13307 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13310 /*-----------------------------------------------------------------*/
13311 /* genDummyRead - generate code for dummy read of volatiles */
13312 /*-----------------------------------------------------------------*/
13314 genDummyRead (iCode * ic)
13320 if (op && IS_SYMOP(op)) {
13321 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13322 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13325 pic16_aopOp (op, ic, FALSE);
13326 for (i=0; i < AOP_SIZE(op); i++) {
13327 // may need to protect this from the peepholer -- this is not nice but works...
13328 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13329 pic16_mov2w (AOP(op),i);
13330 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13332 pic16_freeAsmop (op, NULL, ic, TRUE);
13334 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13338 /*-----------------------------------------------------------------*/
13339 /* genpic16Code - generate code for pic16 based controllers */
13340 /*-----------------------------------------------------------------*/
13342 * At this point, ralloc.c has gone through the iCode and attempted
13343 * to optimize in a way suitable for a PIC. Now we've got to generate
13344 * PIC instructions that correspond to the iCode.
13346 * Once the instructions are generated, we'll pass through both the
13347 * peep hole optimizer and the pCode optimizer.
13348 *-----------------------------------------------------------------*/
13350 void genpic16Code (iCode *lic)
13355 lineHead = lineCurr = NULL;
13357 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13358 pic16_addpBlock(pb);
13361 /* if debug information required */
13362 if (options.debug && currFunc) {
13364 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13369 for (ic = lic ; ic ; ic = ic->next ) {
13371 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13372 if ( cln != ic->lineno ) {
13373 if ( options.debug ) {
13374 debugFile->writeCLine (ic);
13377 if(!options.noCcodeInAsm) {
13378 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13379 printCLine(ic->filename, ic->lineno)));
13385 if(options.iCodeInAsm) {
13388 /* insert here code to print iCode as comment */
13389 l = Safe_strdup(printILine(ic));
13390 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13393 /* if the result is marked as
13394 * spilt and rematerializable or code for
13395 * this has already been generated then
13397 if (resultRemat(ic) || ic->generated )
13400 /* depending on the operation */
13419 /* IPOP happens only when trying to restore a
13420 * spilt live range, if there is an ifx statement
13421 * following this pop then the if statement might
13422 * be using some of the registers being popped which
13423 * would destroy the contents of the register so
13424 * we need to check for this condition and handle it */
13426 && ic->next->op == IFX
13427 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13428 genIfx (ic->next,ic);
13446 genEndFunction (ic);
13462 pic16_genPlus (ic) ;
13466 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13467 pic16_genMinus (ic);
13483 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13487 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13493 /* note these two are xlated by algebraic equivalence
13494 * during parsing SDCC.y */
13495 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13496 "got '>=' or '<=' shouldn't have come here");
13500 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13512 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13516 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13520 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13544 genRightShift (ic);
13547 case GET_VALUE_AT_ADDRESS:
13552 if (POINTER_SET(ic))
13579 addSet(&_G.sendSet,ic);
13582 case DUMMY_READ_VOLATILE:
13592 /* now we are ready to call the
13593 peep hole optimizer */
13594 if (!options.nopeep)
13595 peepHole (&lineHead);
13597 /* now do the actual printing */
13598 printLine (lineHead, codeOutFile);
13601 DFPRINTF((stderr,"printing pBlock\n\n"));
13602 pic16_printpBlock(stdout,pb);