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)
10 Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
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);
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 memcpy (pcor, pc, sizeof (pCodeOpReg));
1795 pcor->r->wasUsed = 1;
1797 //pcor->pcop.type = pc->pcop.type;
1799 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1800 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1802 pcor->pcop.name = NULL;
1805 //pcor->rIdx = pc->rIdx;
1806 //pcor->r->wasUsed=1;
1807 //pcor->instance = pc->instance;
1809 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1814 /*-----------------------------------------------------------------*/
1815 /* pic16_popGetLit - asm operator to pcode operator conversion */
1816 /*-----------------------------------------------------------------*/
1817 pCodeOp *pic16_popGetLit(int lit)
1819 return pic16_newpCodeOpLit(lit);
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1827 return pic16_newpCodeOpLit2(lit, arg2);
1831 /*-----------------------------------------------------------------*/
1832 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1833 /*-----------------------------------------------------------------*/
1834 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1836 return pic16_newpCodeOpImmd(name, offset,index, 0);
1840 /*-----------------------------------------------------------------*/
1841 /* pic16_popGet - asm operator to pcode operator conversion */
1842 /*-----------------------------------------------------------------*/
1843 pCodeOp *pic16_popGetWithString(char *str)
1849 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1853 pcop = pic16_newpCodeOp(str,PO_STR);
1858 /*-----------------------------------------------------------------*/
1859 /* pic16_popRegFromString - */
1860 /*-----------------------------------------------------------------*/
1861 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1864 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1865 pcop->type = PO_DIR;
1867 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1868 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1873 pcop->name = Safe_calloc(1,strlen(str)+1);
1874 strcpy(pcop->name,str);
1876 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1878 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1880 /* make sure that register doesn't exist,
1881 * and operand isn't NULL
1882 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1883 if((PCOR(pcop)->r == NULL)
1885 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1886 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1887 // __FUNCTION__, __LINE__, str, size, offset);
1889 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1890 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1893 PCOR(pcop)->instance = offset;
1898 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1902 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1904 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1905 PCOR(pcop)->rIdx = rIdx;
1906 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1908 PCOR(pcop)->r->isFree = 0;
1909 PCOR(pcop)->r->wasUsed = 1;
1911 pcop->type = PCOR(pcop)->r->pc_type;
1916 /*---------------------------------------------------------------------------------*/
1917 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1919 /*---------------------------------------------------------------------------------*/
1920 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1925 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1927 /* comment the following check, so errors to throw up */
1928 // if(!pcop2)return NULL;
1930 temp = pic16_popGet(aop_dst, offset);
1931 pcop2->pcop2 = temp;
1938 /*--------------------------------------------------------------------------------.-*/
1939 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1940 /* VR 030601 , adapted by Hans Dorn */
1941 /*--------------------------------------------------------------------------------.-*/
1942 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1946 pcop2 = (pCodeOpReg2 *)src;
1954 /*---------------------------------------------------------------------------------*/
1955 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1956 /* movff instruction */
1957 /*---------------------------------------------------------------------------------*/
1958 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1963 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1964 pcop2->pcop2 = pic16_popCopyReg(dst);
1966 /* the pCodeOp may be already allocated */
1967 pcop2 = (pCodeOpReg2 *)(src);
1968 pcop2->pcop2 = (pCodeOp *)(dst);
1975 /*-----------------------------------------------------------------*/
1976 /* pic16_popGet - asm operator to pcode operator conversion */
1977 /*-----------------------------------------------------------------*/
1978 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1980 //char *s = buffer ;
1985 /* offset is greater than
1988 // if (offset > (aop->size - 1) &&
1989 // aop->type != AOP_LIT)
1990 // return NULL; //zero;
1992 /* depending on type */
1993 switch (aop->type) {
1999 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2000 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2007 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2008 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2009 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2010 PCOR(pcop)->r->wasUsed = 1;
2011 PCOR(pcop)->r->isFree = 0;
2013 PCOR(pcop)->instance = offset;
2014 pcop->type = PCOR(pcop)->r->pc_type;
2018 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2019 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2022 /* pCodeOp is already allocated from aopForSym */
2023 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2024 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2030 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2032 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2034 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2036 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2037 PCOR(pcop)->rIdx = rIdx;
2038 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2039 PCOR(pcop)->r->wasUsed=1;
2040 PCOR(pcop)->r->isFree=0;
2042 PCOR(pcop)->instance = offset;
2043 pcop->type = PCOR(pcop)->r->pc_type;
2044 // rs = aop->aopu.aop_reg[offset]->name;
2045 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2049 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2050 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2056 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2057 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2061 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2062 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2068 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2069 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2071 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2073 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2074 // pcop->type = PO_GPR_REGISTER;
2075 PCOR(pcop)->rIdx = rIdx;
2076 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2077 PCOR(pcop)->r->wasUsed=1;
2078 PCOR(pcop)->r->isFree=0;
2080 PCOR(pcop)->instance = offset;
2081 pcop->type = PCOR(pcop)->r->pc_type;
2083 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2084 rs = aop->aopu.aop_reg[offset]->name;
2085 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2090 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2092 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2093 PCOR(pcop)->instance = offset;
2094 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2095 //if(PCOR(pcop)->r == NULL)
2096 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2100 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2101 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2104 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2105 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2108 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2109 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2110 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2111 pcop->type = PCOR(pcop)->r->pc_type;
2112 pcop->name = PCOR(pcop)->r->name;
2118 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2120 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2121 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2122 switch( aop->aopu.pcop->type ) {
2123 case PO_DIR: PCOR(pcop)->instance += offset; break;
2124 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2129 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2130 assert( 0 ); /* should never reach here */;
2135 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2136 "pic16_popGet got unsupported aop->type");
2139 /*-----------------------------------------------------------------*/
2140 /* pic16_aopPut - puts a string for a aop */
2141 /*-----------------------------------------------------------------*/
2142 void pic16_aopPut (asmop *aop, char *s, int offset)
2149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2151 if (aop->size && offset > ( aop->size - 1)) {
2152 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2153 "pic16_aopPut got offset > aop->size");
2157 /* will assign value to value */
2158 /* depending on where it is ofcourse */
2159 switch (aop->type) {
2162 sprintf(d,"(%s + %d)",
2163 aop->aopu.aop_dir,offset);
2164 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2167 sprintf(d,"%s",aop->aopu.aop_dir);
2170 DEBUGpic16_emitcode(";","%d",__LINE__);
2172 pic16_emitcode("movf","%s,w",s);
2173 pic16_emitcode("movwf","%s",d);
2176 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2177 if(offset >= aop->size) {
2178 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2181 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2184 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2191 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2192 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2195 strcmp(s,"r0") == 0 ||
2196 strcmp(s,"r1") == 0 ||
2197 strcmp(s,"r2") == 0 ||
2198 strcmp(s,"r3") == 0 ||
2199 strcmp(s,"r4") == 0 ||
2200 strcmp(s,"r5") == 0 ||
2201 strcmp(s,"r6") == 0 ||
2202 strcmp(s,"r7") == 0 )
2203 pic16_emitcode("mov","%s,%s ; %d",
2204 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2208 if(strcmp(s,"W")==0 )
2209 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2211 pic16_emitcode("movwf","%s",
2212 aop->aopu.aop_reg[offset]->name);
2214 if(strcmp(s,zero)==0) {
2215 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2217 } else if(strcmp(s,"W")==0) {
2218 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2219 pcop->type = PO_GPR_REGISTER;
2221 PCOR(pcop)->rIdx = -1;
2222 PCOR(pcop)->r = NULL;
2224 DEBUGpic16_emitcode(";","%d",__LINE__);
2225 pcop->name = Safe_strdup(s);
2226 pic16_emitpcode(POC_MOVFW,pcop);
2227 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2228 } else if(strcmp(s,one)==0) {
2229 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2230 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2232 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2240 if (aop->type == AOP_DPTR2)
2246 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2247 "pic16_aopPut writting to code space");
2251 while (offset > aop->coff) {
2253 pic16_emitcode ("inc","dptr");
2256 while (offset < aop->coff) {
2258 pic16_emitcode("lcall","__decdptr");
2263 /* if not in accumulater */
2266 pic16_emitcode ("movx","@dptr,a");
2268 if (aop->type == AOP_DPTR2)
2276 while (offset > aop->coff) {
2278 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2280 while (offset < aop->coff) {
2282 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2288 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2293 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2295 if (strcmp(s,"r0") == 0 ||
2296 strcmp(s,"r1") == 0 ||
2297 strcmp(s,"r2") == 0 ||
2298 strcmp(s,"r3") == 0 ||
2299 strcmp(s,"r4") == 0 ||
2300 strcmp(s,"r5") == 0 ||
2301 strcmp(s,"r6") == 0 ||
2302 strcmp(s,"r7") == 0 ) {
2304 sprintf(buffer,"a%s",s);
2305 pic16_emitcode("mov","@%s,%s",
2306 aop->aopu.aop_ptr->name,buffer);
2308 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2313 if (strcmp(s,"a") == 0)
2314 pic16_emitcode("push","acc");
2316 pic16_emitcode("push","%s",s);
2321 /* if bit variable */
2322 if (!aop->aopu.aop_dir) {
2323 pic16_emitcode("clr","a");
2324 pic16_emitcode("rlc","a");
2327 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2330 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2333 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2335 lbl = newiTempLabel(NULL);
2337 if (strcmp(s,"a")) {
2340 pic16_emitcode("clr","c");
2341 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2342 pic16_emitcode("cpl","c");
2343 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2344 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2351 if (strcmp(aop->aopu.aop_str[offset],s))
2352 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2357 if (!offset && (strcmp(s,"acc") == 0))
2360 if (strcmp(aop->aopu.aop_str[offset],s))
2361 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2365 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2366 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2367 // "pic16_aopPut got unsupported aop->type");
2373 /*-----------------------------------------------------------------*/
2374 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2375 /*-----------------------------------------------------------------*/
2376 void pic16_mov2w (asmop *aop, int offset)
2378 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2381 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2383 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2386 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2388 if(is_LitAOp(src)) {
2389 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2390 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2392 if(pic16_sameRegsOfs(src, dst, offset))return;
2393 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2394 pic16_popGet(dst, offset)));
2398 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2400 if(is_LitAOp(src)) {
2401 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2402 pic16_emitpcode(POC_MOVWF, dst);
2404 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2408 void pic16_testStackOverflow(void)
2410 #define GSTACK_TEST_NAME "_gstack_test"
2412 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2417 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2418 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2419 // strcpy(sym->rname, GSTACK_TEST_NAME);
2420 checkAddSym(&externs, sym);
2425 /* push pcop into stack */
2426 void pic16_pushpCodeOp(pCodeOp *pcop)
2428 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2429 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2430 if(pic16_options.gstack)
2431 pic16_testStackOverflow();
2435 /* pop pcop from stack */
2436 void pic16_poppCodeOp(pCodeOp *pcop)
2438 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2439 if(pic16_options.gstack)
2440 pic16_testStackOverflow();
2444 /*-----------------------------------------------------------------*/
2445 /* pushw - pushes wreg to stack */
2446 /*-----------------------------------------------------------------*/
2449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2450 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2451 if(pic16_options.gstack)
2452 pic16_testStackOverflow();
2456 /*-----------------------------------------------------------------*/
2457 /* pushaop - pushes aop to stack */
2458 /*-----------------------------------------------------------------*/
2459 void pushaop(asmop *aop, int offset)
2461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2463 if(is_LitAOp(aop)) {
2464 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2465 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2467 pic16_emitpcode(POC_MOVFF,
2468 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2471 if(pic16_options.gstack)
2472 pic16_testStackOverflow();
2475 /*-----------------------------------------------------------------*/
2476 /* popaop - pops aop from stack */
2477 /*-----------------------------------------------------------------*/
2478 void popaop(asmop *aop, int offset)
2480 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2481 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2482 if(pic16_options.gstack)
2483 pic16_testStackOverflow();
2486 void popaopidx(asmop *aop, int offset, int index)
2490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2492 if(STACK_MODEL_LARGE)ofs++;
2494 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2495 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2496 if(pic16_options.gstack)
2497 pic16_testStackOverflow();
2500 #if !(USE_GENERIC_SIGNED_SHIFT)
2501 /*-----------------------------------------------------------------*/
2502 /* reAdjustPreg - points a register back to where it should */
2503 /*-----------------------------------------------------------------*/
2504 static void reAdjustPreg (asmop *aop)
2508 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2510 if ((size = aop->size) <= 1)
2513 switch (aop->type) {
2517 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2521 if (aop->type == AOP_DPTR2)
2527 pic16_emitcode("lcall","__decdptr");
2530 if (aop->type == AOP_DPTR2)
2542 /*-----------------------------------------------------------------*/
2543 /* opIsGptr: returns non-zero if the passed operand is */
2544 /* a generic pointer type. */
2545 /*-----------------------------------------------------------------*/
2546 static int opIsGptr(operand *op)
2548 sym_link *type = operandType(op);
2550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2551 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2559 /*-----------------------------------------------------------------*/
2560 /* pic16_getDataSize - get the operand data size */
2561 /*-----------------------------------------------------------------*/
2562 int pic16_getDataSize(operand *op)
2564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2567 return AOP_SIZE(op);
2569 // tsd- in the pic port, the genptr size is 1, so this code here
2570 // fails. ( in the 8051 port, the size was 4).
2573 size = AOP_SIZE(op);
2574 if (size == GPTRSIZE)
2576 sym_link *type = operandType(op);
2577 if (IS_GENPTR(type))
2579 /* generic pointer; arithmetic operations
2580 * should ignore the high byte (pointer type).
2583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2590 /*-----------------------------------------------------------------*/
2591 /* pic16_outAcc - output Acc */
2592 /*-----------------------------------------------------------------*/
2593 void pic16_outAcc(operand *result)
2596 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2597 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2600 size = pic16_getDataSize(result);
2602 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2605 /* unsigned or positive */
2607 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2612 /*-----------------------------------------------------------------*/
2613 /* pic16_outBitC - output a bit C */
2614 /* Move to result the value of Carry flag -- VR */
2615 /*-----------------------------------------------------------------*/
2616 void pic16_outBitC(operand *result)
2620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2622 /* if the result is bit */
2623 if (AOP_TYPE(result) == AOP_CRY) {
2624 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2625 pic16_aopPut(AOP(result),"c",0);
2628 i = AOP_SIZE(result);
2630 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2632 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2636 /*-----------------------------------------------------------------*/
2637 /* pic16_outBitOp - output a bit from Op */
2638 /* Move to result the value of set/clr op -- VR */
2639 /*-----------------------------------------------------------------*/
2640 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2646 /* if the result is bit */
2647 if (AOP_TYPE(result) == AOP_CRY) {
2648 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2649 pic16_aopPut(AOP(result),"c",0);
2652 i = AOP_SIZE(result);
2654 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2656 pic16_emitpcode(POC_RRCF, pcop);
2657 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2661 /*-----------------------------------------------------------------*/
2662 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2663 /*-----------------------------------------------------------------*/
2664 void pic16_toBoolean(operand *oper)
2666 int size = AOP_SIZE(oper) - 1;
2669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2671 if ( AOP_TYPE(oper) != AOP_ACC) {
2672 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2675 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2680 #if !defined(GEN_Not)
2681 /*-----------------------------------------------------------------*/
2682 /* genNot - generate code for ! operation */
2683 /*-----------------------------------------------------------------*/
2684 static void pic16_genNot (iCode *ic)
2690 /* assign asmOps to operand & result */
2691 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2692 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2694 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2695 /* if in bit space then a special case */
2696 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2697 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2698 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2699 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2701 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2702 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2703 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2708 size = AOP_SIZE(IC_LEFT(ic));
2710 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2711 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2712 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2715 pic16_toBoolean(IC_LEFT(ic));
2717 tlbl = newiTempLabel(NULL);
2718 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2719 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2720 pic16_outBitC(IC_RESULT(ic));
2723 /* release the aops */
2724 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2725 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2730 #if !defined(GEN_Cpl)
2731 /*-----------------------------------------------------------------*/
2732 /* genCpl - generate code for complement */
2733 /*-----------------------------------------------------------------*/
2734 static void pic16_genCpl (iCode *ic)
2740 /* assign asmOps to operand & result */
2741 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2742 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2744 /* if both are in bit space then
2746 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2747 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2749 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2750 pic16_emitcode("cpl","c");
2751 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2755 size = AOP_SIZE(IC_RESULT(ic));
2758 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2760 pic16_emitcode("cpl","a");
2761 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2763 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2764 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2766 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2767 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2775 /* release the aops */
2776 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2777 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2781 /*-----------------------------------------------------------------*/
2782 /* genUminusFloat - unary minus for floating points */
2783 /*-----------------------------------------------------------------*/
2784 static void genUminusFloat(operand *op,operand *result)
2786 int size ,offset =0 ;
2789 /* for this we just need to flip the
2790 first it then copy the rest in place */
2791 size = AOP_SIZE(op);
2794 pic16_mov2f(AOP(result), AOP(op), offset);
2798 /* toggle the MSB's highest bit */
2799 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2802 /*-----------------------------------------------------------------*/
2803 /* genUminus - unary minus code generation */
2804 /*-----------------------------------------------------------------*/
2805 static void genUminus (iCode *ic)
2808 sym_link *optype, *rtype;
2815 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2816 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2818 /* if both in bit space then special case */
2819 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2820 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2822 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2823 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2824 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2828 optype = operandType(IC_LEFT(ic));
2829 rtype = operandType(IC_RESULT(ic));
2831 /* if float then do float stuff */
2832 if (IS_FLOAT(optype)) {
2833 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2837 /* otherwise subtract from zero by taking the 2's complement */
2838 size = AOP_SIZE(IC_LEFT(ic));
2839 label = newiTempLabel ( NULL );
2841 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2842 for (i=size-1; i > 0; i--) {
2843 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2846 for (i=1; i < size; i++) {
2847 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2848 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2851 for (i=size-1; i >= 0; i--) {
2852 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2853 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2856 for (i=0; i < size-2; i++) {
2857 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2858 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2860 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2862 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2865 pic16_emitpLabel (label->key);
2868 /* release the aops */
2869 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2870 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2874 /*-----------------------------------------------------------------*/
2875 /* saveRegisters - will look for a call and save the registers */
2876 /*-----------------------------------------------------------------*/
2877 static void saveRegisters(iCode *lic)
2884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2886 for (ic = lic ; ic ; ic = ic->next)
2887 if (ic->op == CALL || ic->op == PCALL)
2891 fprintf(stderr,"found parameter push with no function call\n");
2895 /* if the registers have been saved already then
2897 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2900 /* find the registers in use at this time
2901 and push them away to safety */
2902 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2906 if (options.useXstack) {
2907 if (bitVectBitValue(rsave,R0_IDX))
2908 pic16_emitcode("mov","b,r0");
2909 pic16_emitcode("mov","r0,%s",spname);
2910 for (i = 0 ; i < pic16_nRegs ; i++) {
2911 if (bitVectBitValue(rsave,i)) {
2913 pic16_emitcode("mov","a,b");
2915 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2916 pic16_emitcode("movx","@r0,a");
2917 pic16_emitcode("inc","r0");
2920 pic16_emitcode("mov","%s,r0",spname);
2921 if (bitVectBitValue(rsave,R0_IDX))
2922 pic16_emitcode("mov","r0,b");
2924 //for (i = 0 ; i < pic16_nRegs ; i++) {
2925 // if (bitVectBitValue(rsave,i))
2926 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2929 dtype = operandType(IC_LEFT(ic));
2930 if (currFunc && dtype &&
2931 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2932 IFFUNC_ISISR(currFunc->type) &&
2935 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2938 /*-----------------------------------------------------------------*/
2939 /* unsaveRegisters - pop the pushed registers */
2940 /*-----------------------------------------------------------------*/
2941 static void unsaveRegisters (iCode *ic)
2946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2947 /* find the registers in use at this time
2948 and push them away to safety */
2949 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2952 if (options.useXstack) {
2953 pic16_emitcode("mov","r0,%s",spname);
2954 for (i = pic16_nRegs ; i >= 0 ; i--) {
2955 if (bitVectBitValue(rsave,i)) {
2956 pic16_emitcode("dec","r0");
2957 pic16_emitcode("movx","a,@r0");
2959 pic16_emitcode("mov","b,a");
2961 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2965 pic16_emitcode("mov","%s,r0",spname);
2966 if (bitVectBitValue(rsave,R0_IDX))
2967 pic16_emitcode("mov","r0,b");
2969 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2970 // if (bitVectBitValue(rsave,i))
2971 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2978 /*-----------------------------------------------------------------*/
2980 /*-----------------------------------------------------------------*/
2981 static void pushSide(operand * oper, int size)
2984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2986 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2987 if (AOP_TYPE(oper) != AOP_REG &&
2988 AOP_TYPE(oper) != AOP_DIR &&
2990 pic16_emitcode("mov","a,%s",l);
2991 pic16_emitcode("push","acc");
2993 pic16_emitcode("push","%s",l);
2998 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3000 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3001 pic16_emitpcode(POC_MOVFW, src);
3002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3004 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3005 src, pic16_popGet(AOP(op), offset)));
3010 /*-----------------------------------------------------------------*/
3011 /* assignResultValue - assign results to oper, rescall==1 is */
3012 /* called from genCall() or genPcall() */
3013 /*-----------------------------------------------------------------*/
3014 static void assignResultValue(operand * oper, int rescall)
3016 int size = AOP_SIZE(oper);
3020 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3021 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3024 /* assign result from a call/pcall function() */
3026 /* function results are stored in a special order,
3027 * see top of file with Function return policy, or manual */
3030 /* 8-bits, result in WREG */
3031 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3034 /* 16-bits, result in PRODL:WREG */
3035 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3039 /* 24-bits, result in PRODH:PRODL:WREG */
3040 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3044 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3045 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3049 /* >32-bits, result on stack, and FSR0 points to beginning.
3050 * Fix stack when done */
3052 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3054 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3055 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3057 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3062 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3063 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3064 if(STACK_MODEL_LARGE) {
3066 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3070 int areg = 0; /* matching argument register */
3072 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3073 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3076 /* its called from genReceive (probably) -- VR */
3077 /* I hope this code will not be called from somewhere else in the future!
3078 * We manually set the pseudo stack pointer in genReceive. - dw
3080 if(!GpsuedoStkPtr && _G.useWreg) {
3081 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3083 /* The last byte in the assignment is in W */
3084 if(areg <= GpsuedoStkPtr) {
3086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3088 // debugf("receive from WREG\n", 0);
3090 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3093 _G.stack_lat = AOP_SIZE(oper)-1;
3098 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3099 // debugf("receive from STACK\n", 0);
3106 /*-----------------------------------------------------------------*/
3107 /* genIpush - generate code for pushing this gets a little complex */
3108 /*-----------------------------------------------------------------*/
3109 static void genIpush (iCode *ic)
3111 // int size, offset=0;
3114 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3117 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3119 /* send to stack as normal */
3120 addSet(&_G.sendSet,ic);
3121 // addSetHead(&_G.sendSet,ic);
3122 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3127 int size, offset = 0 ;
3131 /* if this is not a parm push : ie. it is spill push
3132 and spill push is always done on the local stack */
3133 if (!ic->parmPush) {
3135 /* and the item is spilt then do nothing */
3136 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3139 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3140 size = AOP_SIZE(IC_LEFT(ic));
3141 /* push it on the stack */
3143 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3148 pic16_emitcode("push","%s",l);
3153 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3157 /*-----------------------------------------------------------------*/
3158 /* genIpop - recover the registers: can happen only for spilling */
3159 /*-----------------------------------------------------------------*/
3160 static void genIpop (iCode *ic)
3163 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3168 /* if the temp was not pushed then */
3169 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3172 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3173 size = AOP_SIZE(IC_LEFT(ic));
3176 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3179 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3184 /*-----------------------------------------------------------------*/
3185 /* unsaverbank - restores the resgister bank from stack */
3186 /*-----------------------------------------------------------------*/
3187 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3189 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3197 if (options.useXstack) {
3199 r = getFreePtr(ic,&aop,FALSE);
3202 pic16_emitcode("mov","%s,_spx",r->name);
3203 pic16_emitcode("movx","a,@%s",r->name);
3204 pic16_emitcode("mov","psw,a");
3205 pic16_emitcode("dec","%s",r->name);
3208 pic16_emitcode ("pop","psw");
3211 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3212 if (options.useXstack) {
3213 pic16_emitcode("movx","a,@%s",r->name);
3214 //pic16_emitcode("mov","(%s+%d),a",
3215 // regspic16[i].base,8*bank+regspic16[i].offset);
3216 pic16_emitcode("dec","%s",r->name);
3219 pic16_emitcode("pop",""); //"(%s+%d)",
3220 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3223 if (options.useXstack) {
3225 pic16_emitcode("mov","_spx,%s",r->name);
3226 pic16_freeAsmop(NULL,aop,ic,TRUE);
3232 /*-----------------------------------------------------------------*/
3233 /* saverbank - saves an entire register bank on the stack */
3234 /*-----------------------------------------------------------------*/
3235 static void saverbank (int bank, iCode *ic, bool pushPsw)
3237 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3244 if (options.useXstack) {
3247 r = getFreePtr(ic,&aop,FALSE);
3248 pic16_emitcode("mov","%s,_spx",r->name);
3252 for (i = 0 ; i < pic16_nRegs ;i++) {
3253 if (options.useXstack) {
3254 pic16_emitcode("inc","%s",r->name);
3255 //pic16_emitcode("mov","a,(%s+%d)",
3256 // regspic16[i].base,8*bank+regspic16[i].offset);
3257 pic16_emitcode("movx","@%s,a",r->name);
3259 pic16_emitcode("push","");// "(%s+%d)",
3260 //regspic16[i].base,8*bank+regspic16[i].offset);
3264 if (options.useXstack) {
3265 pic16_emitcode("mov","a,psw");
3266 pic16_emitcode("movx","@%s,a",r->name);
3267 pic16_emitcode("inc","%s",r->name);
3268 pic16_emitcode("mov","_spx,%s",r->name);
3269 pic16_freeAsmop (NULL,aop,ic,TRUE);
3272 pic16_emitcode("push","psw");
3274 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3282 static int wparamCmp(void *p1, void *p2)
3284 return (!strcmp((char *)p1, (char *)p2));
3287 int inWparamList(char *s)
3289 return isinSetWith(wparamList, s, wparamCmp);
3293 /*-----------------------------------------------------------------*/
3294 /* genCall - generates a call statement */
3295 /*-----------------------------------------------------------------*/
3296 static void genCall (iCode *ic)
3306 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3307 /* if caller saves & we have not saved then */
3308 // if (!ic->regsSaved)
3309 // saveRegisters(ic);
3311 /* initialise stackParms for IPUSH pushes */
3312 // stackParms = psuedoStkPtr;
3313 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3314 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3315 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3318 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3321 /* if send set is not empty the assign */
3324 int psuedoStkPtr=-1;
3325 int firstTimeThruLoop = 1;
3328 /* reverse sendSet if function is not reentrant */
3329 if(!IFFUNC_ISREENT(ftype))
3330 _G.sendSet = reverseSet(_G.sendSet);
3332 /* First figure how many parameters are getting passed */
3336 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3340 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3341 size = AOP_SIZE(IC_LEFT(sic));
3345 /* pass the last byte through WREG */
3349 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3350 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3351 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3353 if(!firstTimeThruLoop) {
3354 /* If this is not the first time we've been through the loop
3355 * then we need to save the parameter in a temporary
3356 * register. The last byte of the last parameter is
3360 // --psuedoStkPtr; // sanity check
3364 firstTimeThruLoop=0;
3366 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3371 /* all arguments are passed via stack */
3375 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3376 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3377 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3379 // pushaop(AOP(IC_LEFT(sic)), size);
3380 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3387 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3391 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3392 pushw(); /* save last parameter to stack if functions has varargs */
3396 } else use_wreg = 0;
3398 _G.stackRegSet = _G.sendSet;
3403 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3407 /* if we need to assign a result value */
3408 if ((IS_ITEMP(IC_RESULT(ic))
3409 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3410 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3411 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3414 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3417 assignResultValue(IC_RESULT(ic), 1);
3419 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3422 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3425 if(!stackParms && ic->parmBytes) {
3426 stackParms = ic->parmBytes;
3429 stackParms -= use_wreg;
3432 if(stackParms == 1) {
3433 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3435 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3436 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3438 if(STACK_MODEL_LARGE) {
3440 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3445 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3448 /* adjust the stack for parameters if required */
3449 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3452 /* if register bank was saved then pop them */
3454 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3456 /* if we hade saved some registers then unsave them */
3457 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3458 unsaveRegisters (ic);
3464 /*-----------------------------------------------------------------*/
3465 /* genPcall - generates a call by pointer statement */
3466 /* new version, created from genCall - HJD */
3467 /*-----------------------------------------------------------------*/
3468 static void genPcall (iCode *ic)
3470 sym_link *ftype, *fntype;
3472 symbol *retlbl = newiTempLabel(NULL);
3473 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3477 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3478 fntype = operandType( IC_LEFT(ic) )->next;
3480 /* if send set is not empty the assign */
3483 int psuedoStkPtr=-1;
3485 /* reverse sendSet if function is not reentrant */
3486 if(!IFFUNC_ISREENT(fntype))
3487 _G.sendSet = reverseSet(_G.sendSet);
3491 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3494 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3495 size = AOP_SIZE(IC_LEFT(sic));
3498 /* all parameters are passed via stack, since WREG is clobbered
3499 * by the calling sequence */
3501 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3502 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3503 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3505 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3509 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3512 _G.stackRegSet = _G.sendSet;
3516 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3518 // push return address
3519 // push $ on return stack, then replace with retlbl
3521 /* Thanks to Thorsten Klose for pointing out that the following
3522 * snippet should be interrupt safe */
3523 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3524 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3526 pic16_emitpcodeNULLop(POC_PUSH);
3528 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3529 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3530 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3531 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3532 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3533 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3536 /* restore interrupt control register */
3537 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3538 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3540 /* make the call by writing the pointer into pc */
3541 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3542 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3544 // note: MOVFF to PCL not allowed
3545 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3546 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3549 /* return address is here: (X) */
3550 pic16_emitpLabelFORCE(retlbl->key);
3552 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3555 /* if we need assign a result value */
3556 if ((IS_ITEMP(IC_RESULT(ic))
3557 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3558 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3559 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3562 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3565 assignResultValue(IC_RESULT(ic), 1);
3567 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3568 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3570 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3573 // stackParms -= use_wreg;
3576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3577 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3578 if(STACK_MODEL_LARGE) {
3580 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3585 /*-----------------------------------------------------------------*/
3586 /* resultRemat - result is rematerializable */
3587 /*-----------------------------------------------------------------*/
3588 static int resultRemat (iCode *ic)
3590 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3591 if (SKIP_IC(ic) || ic->op == IFX)
3594 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3595 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3596 if (sym->remat && !POINTER_SET(ic))
3603 #if defined(__BORLANDC__) || defined(_MSC_VER)
3604 #define STRCASECMP stricmp
3606 #define STRCASECMP strcasecmp
3610 /*-----------------------------------------------------------------*/
3611 /* inExcludeList - return 1 if the string is in exclude Reg list */
3612 /*-----------------------------------------------------------------*/
3613 static bool inExcludeList(char *s)
3615 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3619 if (options.excludeRegs[i] &&
3620 STRCASECMP(options.excludeRegs[i],"none") == 0)
3623 for ( i = 0 ; options.excludeRegs[i]; i++) {
3624 if (options.excludeRegs[i] &&
3625 STRCASECMP(s,options.excludeRegs[i]) == 0)
3632 /*-----------------------------------------------------------------*/
3633 /* genFunction - generated code for function entry */
3634 /*-----------------------------------------------------------------*/
3635 static void genFunction (iCode *ic)
3641 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3643 pic16_labelOffset += (max_key+4);
3648 ftype = operandType(IC_LEFT(ic));
3649 sym = OP_SYMBOL(IC_LEFT(ic));
3651 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3652 /* create an absolute section at the interrupt vector:
3653 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3658 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3660 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3661 sprintf(asymname, "ivec_%s", sym->name);
3663 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3665 /* when an interrupt is declared as naked, do not emit the special
3666 * wrapper segment at vector address. The user should take care for
3667 * this instead. -- VR */
3669 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3670 asym = newSymbol(asymname, 0);
3671 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3672 pic16_addpBlock( apb );
3674 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3675 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3676 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3677 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3678 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3680 /* mark the end of this tiny function */
3681 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3683 sprintf(asymname, "%s", sym->rname);
3689 abSym = Safe_calloc(1, sizeof(absSym));
3690 strcpy(abSym->name, asymname);
3692 switch( FUNC_INTNO(sym->type) ) {
3693 case 0: abSym->address = 0x000000; break;
3694 case 1: abSym->address = 0x000008; break;
3695 case 2: abSym->address = 0x000018; break;
3698 // fprintf(stderr, "no interrupt number is given\n");
3699 abSym->address = -1; break;
3702 /* relocate interrupt vectors if needed */
3703 if(abSym->address != -1)
3704 abSym->address += pic16_options.ivt_loc;
3706 addSet(&absSymSet, abSym);
3710 /* create the function header */
3711 pic16_emitcode(";","-----------------------------------------");
3712 pic16_emitcode(";"," function %s",sym->name);
3713 pic16_emitcode(";","-----------------------------------------");
3715 pic16_emitcode("","%s:",sym->rname);
3716 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3721 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3722 if(!strcmp(ab->name, sym->rname)) {
3723 pic16_pBlockConvert2Absolute(pb);
3729 if(IFFUNC_ISNAKED(ftype)) {
3730 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3734 /* if critical function then turn interrupts off */
3735 if (IFFUNC_ISCRITICAL(ftype)) {
3736 //pic16_emitcode("clr","ea");
3739 currFunc = sym; /* update the currFunc symbol */
3740 _G.fregsUsed = sym->regsUsed;
3741 _G.sregsAlloc = newBitVect(128);
3744 /* if this is an interrupt service routine then
3745 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3746 if (IFFUNC_ISISR(sym->type)) {
3747 _G.usefastretfie = 1; /* use shadow registers by default */
3749 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3750 if(!FUNC_ISSHADOWREGS(sym->type)) {
3751 /* do not save WREG,STATUS,BSR for high priority interrupts
3752 * because they are stored in the hardware shadow registers already */
3753 _G.usefastretfie = 0;
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3759 /* these should really be optimized somehow, because not all
3760 * interrupt handlers modify them */
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3764 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3766 // pic16_pBlockConvert2ISR(pb);
3769 /* emit code to setup stack frame if user enabled,
3770 * and function is not main() */
3772 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3773 if(strcmp(sym->name, "main")) {
3775 || !options.ommitFramePtr
3777 || IFFUNC_ARGS(sym->type)
3778 || FUNC_HASSTACKPARM(sym->etype)
3780 /* setup the stack frame */
3781 if(STACK_MODEL_LARGE)
3782 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3783 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3785 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3786 if(STACK_MODEL_LARGE)
3787 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3791 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3794 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3796 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3797 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3799 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3802 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3803 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3810 /* if callee-save to be used for this function
3811 * then save the registers being used in this function */
3812 // if (IFFUNC_CALLEESAVES(sym->type))
3816 /* if any registers used */
3817 if (sym->regsUsed) {
3818 /* save the registers used */
3819 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3820 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3821 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3822 if (bitVectBitValue(sym->regsUsed,i)) {
3823 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3826 if(!pic16_regWithIdx(i)->wasUsed) {
3827 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3828 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3829 pic16_regWithIdx(i)->wasUsed = 1;
3833 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3837 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3838 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3841 /*-----------------------------------------------------------------*/
3842 /* genEndFunction - generates epilogue for functions */
3843 /*-----------------------------------------------------------------*/
3844 static void genEndFunction (iCode *ic)
3846 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3850 if(IFFUNC_ISNAKED(sym->type)) {
3851 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3857 /* add code for ISCRITICAL */
3858 if(IFFUNC_ISCRITICAL(sym->type)) {
3859 /* if critical function, turn on interrupts */
3861 /* TODO: add code here -- VR */
3864 // sym->regsUsed = _G.fregsUsed;
3866 /* now we need to restore the registers */
3867 /* if any registers used */
3869 /* first restore registers that might be used for stack access */
3870 if(_G.sregsAllocSet) {
3873 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3874 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3875 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3879 if (sym->regsUsed) {
3882 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3883 /* restore registers used */
3884 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3885 for ( i = sym->regsUsed->size; i >= 0; i--) {
3886 if (bitVectBitValue(sym->regsUsed,i)) {
3887 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3891 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3896 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3898 if (sym->stack == 1) {
3899 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3900 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3902 // we have to add more than one...
3903 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3904 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3905 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3907 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3908 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3909 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3913 if(strcmp(sym->name, "main")) {
3915 || !options.ommitFramePtr
3917 || IFFUNC_ARGS(sym->type)
3918 || FUNC_HASSTACKPARM(sym->etype)
3920 /* restore stack frame */
3921 if(STACK_MODEL_LARGE)
3922 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3923 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3929 if (IFFUNC_ISISR(sym->type)) {
3930 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3931 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3933 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3935 if(!FUNC_ISSHADOWREGS(sym->type)) {
3936 /* do not restore interrupt vector for WREG,STATUS,BSR
3937 * for high priority interrupt, see genFunction */
3938 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3939 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3940 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3942 // _G.interruptvector = 0; /* sanity check */
3945 /* if debug then send end of function */
3946 /* if (options.debug && currFunc) */
3948 debugFile->writeEndFunction (currFunc, ic, 1);
3951 if(_G.usefastretfie)
3952 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3954 pic16_emitpcodeNULLop(POC_RETFIE);
3956 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3958 _G.usefastretfie = 0;
3962 if (IFFUNC_ISCRITICAL(sym->type)) {
3963 pic16_emitcode("setb","ea");
3966 /* if debug then send end of function */
3968 debugFile->writeEndFunction (currFunc, ic, 1);
3971 /* insert code to restore stack frame, if user enabled it
3972 * and function is not main() */
3975 pic16_emitpcodeNULLop(POC_RETURN);
3977 /* Mark the end of a function */
3978 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3982 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3984 unsigned long lit=1;
3989 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3990 if(AOP_TYPE(op) == AOP_LIT) {
3991 if(!IS_FLOAT(operandType( op ))) {
3992 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3995 unsigned long lit_int;
3999 /* take care if literal is a float */
4000 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4006 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4007 pic16_emitpcode(POC_CLRF, dest);
4009 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4010 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4013 if(dest->type == PO_WREG && (offset == 0)) {
4014 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4017 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4021 /*-----------------------------------------------------------------*/
4022 /* genRet - generate code for return statement */
4023 /*-----------------------------------------------------------------*/
4024 static void genRet (iCode *ic)
4030 /* if we have no return value then
4031 * just generate the "ret" */
4036 /* we have something to return then
4037 * move the return value into place */
4038 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4039 size = AOP_SIZE(IC_LEFT(ic));
4043 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4046 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4049 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4051 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4054 /* >32-bits, setup stack and FSR0 */
4056 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4057 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4059 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4061 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4066 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4067 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4069 if(STACK_MODEL_LARGE) {
4070 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4071 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4073 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4078 /* old code, left here for reference -- VR */
4082 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4084 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4085 pic16_emitpcomment("push %s",l);
4088 DEBUGpic16_emitcode(";", "%d", __LINE__);
4089 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4090 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4092 if (strcmp(fReturn[offset],l)) {
4093 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4094 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4095 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4097 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4101 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4111 if (strcmp(fReturn[pushed],"a"))
4112 pic16_emitcode("pop",fReturn[pushed]);
4114 pic16_emitcode("pop","acc");
4120 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4123 /* generate a jump to the return label
4124 * if the next is not the return statement */
4125 if (!(ic->next && ic->next->op == LABEL
4126 && IC_LABEL(ic->next) == returnLabel)) {
4128 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4129 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4133 /*-----------------------------------------------------------------*/
4134 /* genLabel - generates a label */
4135 /*-----------------------------------------------------------------*/
4136 static void genLabel (iCode *ic)
4140 /* special case never generate */
4141 if (IC_LABEL(ic) == entryLabel)
4144 pic16_emitpLabel(IC_LABEL(ic)->key);
4145 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4148 /*-----------------------------------------------------------------*/
4149 /* genGoto - generates a goto */
4150 /*-----------------------------------------------------------------*/
4152 static void genGoto (iCode *ic)
4155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4156 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4160 /*-----------------------------------------------------------------*/
4161 /* genMultbits :- multiplication of bits */
4162 /*-----------------------------------------------------------------*/
4163 static void genMultbits (operand *left,
4169 if(!pic16_sameRegs(AOP(result),AOP(right)))
4170 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4172 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4173 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4174 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4179 /*-----------------------------------------------------------------*/
4180 /* genMultOneByte : 8 bit multiplication & division */
4181 /*-----------------------------------------------------------------*/
4182 static void genMultOneByte (operand *left,
4188 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4189 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4191 /* (if two literals, the value is computed before) */
4192 /* if one literal, literal on the right */
4193 if (AOP_TYPE(left) == AOP_LIT){
4199 /* size is already checked in genMult == 1 */
4200 // size = AOP_SIZE(result);
4202 if (AOP_TYPE(right) == AOP_LIT){
4203 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4204 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4206 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4208 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4209 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4211 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214 pic16_genMult8X8_8 (left, right,result);
4217 /*-----------------------------------------------------------------*/
4218 /* genMultOneWord : 16 bit multiplication */
4219 /*-----------------------------------------------------------------*/
4220 static void genMultOneWord (operand *left,
4225 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4226 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4228 /* (if two literals, the value is computed before)
4229 * if one literal, literal on the right */
4230 if (AOP_TYPE(left) == AOP_LIT){
4236 /* size is checked already == 2 */
4237 // size = AOP_SIZE(result);
4239 if (AOP_TYPE(right) == AOP_LIT) {
4240 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4241 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4242 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4243 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4245 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4246 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4247 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4248 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4251 pic16_genMult16X16_16(left, right,result);
4254 /*-----------------------------------------------------------------*/
4255 /* genMultOneLong : 32 bit multiplication */
4256 /*-----------------------------------------------------------------*/
4257 static void genMultOneLong (operand *left,
4262 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4263 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4265 /* (if two literals, the value is computed before)
4266 * if one literal, literal on the right */
4267 if (AOP_TYPE(left) == AOP_LIT){
4273 /* size is checked already == 4 */
4274 // size = AOP_SIZE(result);
4276 if (AOP_TYPE(right) == AOP_LIT) {
4277 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4278 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4279 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4280 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4282 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4283 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4284 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4285 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4288 pic16_genMult32X32_32(left, right,result);
4293 /*-----------------------------------------------------------------*/
4294 /* genMult - generates code for multiplication */
4295 /*-----------------------------------------------------------------*/
4296 static void genMult (iCode *ic)
4298 operand *left = IC_LEFT(ic);
4299 operand *right = IC_RIGHT(ic);
4300 operand *result= IC_RESULT(ic);
4303 /* assign the amsops */
4304 pic16_aopOp (left,ic,FALSE);
4305 pic16_aopOp (right,ic,FALSE);
4306 pic16_aopOp (result,ic,TRUE);
4308 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4310 /* special cases first *
4312 if (AOP_TYPE(left) == AOP_CRY
4313 && AOP_TYPE(right)== AOP_CRY) {
4314 genMultbits(left,right,result);
4318 /* if both are of size == 1 */
4319 if(AOP_SIZE(left) == 1
4320 && AOP_SIZE(right) == 1) {
4321 genMultOneByte(left,right,result);
4325 /* if both are of size == 2 */
4326 if(AOP_SIZE(left) == 2
4327 && AOP_SIZE(right) == 2) {
4328 genMultOneWord(left, right, result);
4332 /* if both are of size == 4 */
4333 if(AOP_SIZE(left) == 4
4334 && AOP_SIZE(right) == 4) {
4335 genMultOneLong(left, right, result);
4339 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4342 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4343 /* should have been converted to function call */
4347 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349 pic16_freeAsmop(result,NULL,ic,TRUE);
4352 /*-----------------------------------------------------------------*/
4353 /* genDivbits :- division of bits */
4354 /*-----------------------------------------------------------------*/
4355 static void genDivbits (operand *left,
4362 /* the result must be bit */
4363 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4364 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4368 pic16_emitcode("div","ab");
4369 pic16_emitcode("rrc","a");
4370 pic16_aopPut(AOP(result),"c",0);
4373 /*-----------------------------------------------------------------*/
4374 /* genDivOneByte : 8 bit division */
4375 /*-----------------------------------------------------------------*/
4376 static void genDivOneByte (operand *left,
4380 sym_link *opetype = operandType(result);
4385 /* result = divident / divisor
4386 * - divident may be a register or a literal,
4387 * - divisor may be a register or a literal,
4388 * so there are 3 cases (literal / literal is optimized
4389 * by the front-end) to handle.
4390 * In addition we must handle signed and unsigned, which
4391 * result in 6 final different cases -- VR */
4395 size = AOP_SIZE(result) - 1;
4397 /* signed or unsigned */
4398 if (SPEC_USIGN(opetype)) {
4399 pCodeOp *pct1, /* count */
4402 symbol *label1, *label2, *label3;;
4405 /* unsigned is easy */
4407 pct1 = pic16_popGetTempReg(1);
4408 pct2 = pic16_popGetTempReg(1);
4409 pct3 = pic16_popGetTempReg(1);
4411 label1 = newiTempLabel(NULL);
4412 label2 = newiTempLabel(NULL);
4413 label3 = newiTempLabel(NULL);
4415 /* the following algorithm is extracted from divuint.c */
4417 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4418 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4420 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4422 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4424 pic16_emitpLabel(label1->key);
4427 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4431 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4435 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4437 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4438 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4440 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4441 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4442 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4444 pic16_emitpLabel( label3->key );
4445 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4446 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4450 pic16_emitpLabel(label2->key);
4451 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4452 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4453 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4455 /* result is in wreg */
4456 if(AOP_TYPE(result) != AOP_ACC)
4457 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4459 pic16_popReleaseTempReg( pct3, 1);
4460 pic16_popReleaseTempReg( pct2, 1);
4461 pic16_popReleaseTempReg( pct1, 1);
4466 /* signed is a little bit more difficult */
4468 /* save the signs of the operands */
4469 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4471 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4472 pic16_emitcode("push","acc"); /* save it on the stack */
4474 /* now sign adjust for both left & right */
4475 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4477 lbl = newiTempLabel(NULL);
4478 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4479 pic16_emitcode("cpl","a");
4480 pic16_emitcode("inc","a");
4481 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4482 pic16_emitcode("mov","b,a");
4484 /* sign adjust left side */
4485 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4488 lbl = newiTempLabel(NULL);
4489 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4490 pic16_emitcode("cpl","a");
4491 pic16_emitcode("inc","a");
4492 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4494 /* now the division */
4495 pic16_emitcode("div","ab");
4496 /* we are interested in the lower order
4498 pic16_emitcode("mov","b,a");
4499 lbl = newiTempLabel(NULL);
4500 pic16_emitcode("pop","acc");
4501 /* if there was an over flow we don't
4502 adjust the sign of the result */
4503 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4504 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4506 pic16_emitcode("clr","a");
4507 pic16_emitcode("subb","a,b");
4508 pic16_emitcode("mov","b,a");
4509 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4511 /* now we are done */
4512 pic16_aopPut(AOP(result),"b",0);
4514 pic16_emitcode("mov","c,b.7");
4515 pic16_emitcode("subb","a,acc");
4518 pic16_aopPut(AOP(result),"a",offset++);
4522 /*-----------------------------------------------------------------*/
4523 /* genDiv - generates code for division */
4524 /*-----------------------------------------------------------------*/
4525 static void genDiv (iCode *ic)
4527 operand *left = IC_LEFT(ic);
4528 operand *right = IC_RIGHT(ic);
4529 operand *result= IC_RESULT(ic);
4532 /* Division is a very lengthy algorithm, so it is better
4533 * to call support routines than inlining algorithm.
4534 * Division functions written here just in case someone
4535 * wants to inline and not use the support libraries -- VR */
4539 /* assign the amsops */
4540 pic16_aopOp (left,ic,FALSE);
4541 pic16_aopOp (right,ic,FALSE);
4542 pic16_aopOp (result,ic,TRUE);
4544 /* special cases first */
4546 if (AOP_TYPE(left) == AOP_CRY &&
4547 AOP_TYPE(right)== AOP_CRY) {
4548 genDivbits(left,right,result);
4552 /* if both are of size == 1 */
4553 if (AOP_SIZE(left) == 1 &&
4554 AOP_SIZE(right) == 1 ) {
4555 genDivOneByte(left,right,result);
4559 /* should have been converted to function call */
4562 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4563 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4564 pic16_freeAsmop(result,NULL,ic,TRUE);
4567 /*-----------------------------------------------------------------*/
4568 /* genModbits :- modulus of bits */
4569 /*-----------------------------------------------------------------*/
4570 static void genModbits (operand *left,
4578 werror(W_POSSBUG2, __FILE__, __LINE__);
4579 /* the result must be bit */
4580 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4581 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4585 pic16_emitcode("div","ab");
4586 pic16_emitcode("mov","a,b");
4587 pic16_emitcode("rrc","a");
4588 pic16_aopPut(AOP(result),"c",0);
4591 /*-----------------------------------------------------------------*/
4592 /* genModOneByte : 8 bit modulus */
4593 /*-----------------------------------------------------------------*/
4594 static void genModOneByte (operand *left,
4598 sym_link *opetype = operandType(result);
4603 werror(W_POSSBUG2, __FILE__, __LINE__);
4605 /* signed or unsigned */
4606 if (SPEC_USIGN(opetype)) {
4607 /* unsigned is easy */
4608 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4609 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4611 pic16_emitcode("div","ab");
4612 pic16_aopPut(AOP(result),"b",0);
4616 /* signed is a little bit more difficult */
4618 /* save the signs of the operands */
4619 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4622 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4623 pic16_emitcode("push","acc"); /* save it on the stack */
4625 /* now sign adjust for both left & right */
4626 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4629 lbl = newiTempLabel(NULL);
4630 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4631 pic16_emitcode("cpl","a");
4632 pic16_emitcode("inc","a");
4633 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4634 pic16_emitcode("mov","b,a");
4636 /* sign adjust left side */
4637 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4640 lbl = newiTempLabel(NULL);
4641 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4642 pic16_emitcode("cpl","a");
4643 pic16_emitcode("inc","a");
4644 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4646 /* now the multiplication */
4647 pic16_emitcode("div","ab");
4648 /* we are interested in the lower order
4650 lbl = newiTempLabel(NULL);
4651 pic16_emitcode("pop","acc");
4652 /* if there was an over flow we don't
4653 adjust the sign of the result */
4654 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4655 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4657 pic16_emitcode("clr","a");
4658 pic16_emitcode("subb","a,b");
4659 pic16_emitcode("mov","b,a");
4660 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4662 /* now we are done */
4663 pic16_aopPut(AOP(result),"b",0);
4667 /*-----------------------------------------------------------------*/
4668 /* genMod - generates code for division */
4669 /*-----------------------------------------------------------------*/
4670 static void genMod (iCode *ic)
4672 operand *left = IC_LEFT(ic);
4673 operand *right = IC_RIGHT(ic);
4674 operand *result= IC_RESULT(ic);
4678 /* assign the amsops */
4679 pic16_aopOp (left,ic,FALSE);
4680 pic16_aopOp (right,ic,FALSE);
4681 pic16_aopOp (result,ic,TRUE);
4683 /* special cases first */
4685 if (AOP_TYPE(left) == AOP_CRY &&
4686 AOP_TYPE(right)== AOP_CRY) {
4687 genModbits(left,right,result);
4691 /* if both are of size == 1 */
4692 if (AOP_SIZE(left) == 1 &&
4693 AOP_SIZE(right) == 1 ) {
4694 genModOneByte(left,right,result);
4698 /* should have been converted to function call */
4702 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4703 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4704 pic16_freeAsmop(result,NULL,ic,TRUE);
4707 /*-----------------------------------------------------------------*/
4708 /* genIfxJump :- will create a jump depending on the ifx */
4709 /*-----------------------------------------------------------------*/
4711 note: May need to add parameter to indicate when a variable is in bit space.
4713 static void genIfxJump (iCode *ic, char *jval)
4717 /* if true label then we jump if condition
4719 if ( IC_TRUE(ic) ) {
4721 if(strcmp(jval,"a") == 0)
4723 else if (strcmp(jval,"c") == 0)
4726 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4727 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4730 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4731 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4735 /* false label is present */
4736 if(strcmp(jval,"a") == 0)
4738 else if (strcmp(jval,"c") == 0)
4741 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4742 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4745 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4746 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4751 /* mark the icode as generated */
4755 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4759 /* if true label then we jump if condition
4761 if ( IC_TRUE(ic) ) {
4762 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4763 pic16_emitpcode(POC_BTFSC, jop);
4765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4766 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4769 /* false label is present */
4770 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4771 pic16_emitpcode(POC_BTFSS, jop);
4773 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4774 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4778 /* mark the icode as generated */
4785 /*-----------------------------------------------------------------*/
4787 /*-----------------------------------------------------------------*/
4788 static void genSkip(iCode *ifx,int status_bit)
4790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4794 if ( IC_TRUE(ifx) ) {
4795 switch(status_bit) {
4810 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4811 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4815 switch(status_bit) {
4829 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4830 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4837 /*-----------------------------------------------------------------*/
4839 /*-----------------------------------------------------------------*/
4840 static void genSkipc(resolvedIfx *rifx)
4842 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4852 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4853 rifx->generated = 1;
4856 #if !(USE_SIMPLE_GENCMP)
4857 /*-----------------------------------------------------------------*/
4859 /*-----------------------------------------------------------------*/
4860 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4862 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4867 if( (rifx->condition ^ invert_condition) & 1)
4872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4873 rifx->generated = 1;
4878 /*-----------------------------------------------------------------*/
4880 /*-----------------------------------------------------------------*/
4881 static void genSkipz(iCode *ifx, int condition)
4892 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4897 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4899 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4904 #if !(USE_SIMPLE_GENCMP)
4905 /*-----------------------------------------------------------------*/
4907 /*-----------------------------------------------------------------*/
4908 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4914 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4916 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4919 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4920 rifx->generated = 1;
4925 /*-----------------------------------------------------------------*/
4926 /* genChkZeroes :- greater or less than comparison */
4927 /* For each byte in a literal that is zero, inclusive or the */
4928 /* the corresponding byte in the operand with W */
4929 /* returns true if any of the bytes are zero */
4930 /*-----------------------------------------------------------------*/
4931 static int genChkZeroes(operand *op, int lit, int size)
4938 i = (lit >> (size*8)) & 0xff;
4942 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4944 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4954 /*-----------------------------------------------------------------*/
4955 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4956 /* aop (if it's NOT a literal) or from lit (if */
4957 /* aop is a literal) */
4958 /*-----------------------------------------------------------------*/
4959 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4960 if (aop->type == AOP_LIT) {
4961 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4963 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4967 /*-----------------------------------------------------------------*/
4968 /* genCmp :- greater or less than comparison */
4969 /*-----------------------------------------------------------------*/
4971 #if USE_SIMPLE_GENCMP /* { */
4973 /* genCmp performs a left < right comparison, stores
4974 * the outcome in result (if != NULL) and generates
4975 * control flow code for the ifx (if != NULL).
4977 * This version leaves in sequences like
4978 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4979 * which should be optmized by the peephole
4980 * optimizer - RN 2005-01-01 */
4981 static void genCmp (operand *left,operand *right,
4982 operand *result, iCode *ifx, int sign)
4995 assert (AOP_SIZE(left) == AOP_SIZE(right));
4996 assert (left && right);
4998 size = AOP_SIZE(right) - 1;
4999 mask = (0x100UL << (size*8)) - 1;
5000 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5005 resolveIfx (&rIfx, ifx);
5007 /* handle for special cases */
5008 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5011 /**********************************************************************
5012 * handle bits - bit compares are promoted to int compares seemingly! *
5013 **********************************************************************/
5015 // THIS IS COMPLETELY UNTESTED!
5016 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5017 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5018 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5019 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5022 // 1 < {0,1} is false --> clear C by skipping the next instruction
5023 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5024 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5025 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5026 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5027 emitCLRC; // only skipped for left=0 && right=1
5029 goto correct_result_in_carry;
5033 /*************************************************
5034 * make sure that left is register (or the like) *
5035 *************************************************/
5036 if (!isAOP_REGlike(left)) {
5037 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5038 assert (isAOP_LIT(left));
5039 assert (isAOP_REGlike(right));
5040 // swap left and right
5041 // left < right <==> right > left <==> (right >= left + 1)
5042 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5044 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5045 // MAXVALUE < right? always false
5046 if (performedLt) emitCLRC; else emitSETC;
5047 goto correct_result_in_carry;
5050 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5051 // that's why we handled it above.
5058 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5059 } else if (isAOP_LIT(right)) {
5060 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5063 assert (isAOP_REGlike(left)); // left must be register or the like
5064 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5066 /*************************************************
5067 * special cases go here *
5068 *************************************************/
5070 if (isAOP_LIT(right)) {
5072 // unsigned comparison to a literal
5073 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5075 // unsigned left < 0? always false
5076 if (performedLt) emitCLRC; else emitSETC;
5077 goto correct_result_in_carry;
5080 // signed comparison to a literal
5081 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5082 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5083 // signed left < 0x80000000? always false
5084 if (performedLt) emitCLRC; else emitSETC;
5085 goto correct_result_in_carry;
5086 } else if (lit == 0) {
5087 // compare left < 0; set CARRY if SIGNBIT(left) is set
5088 if (performedLt) emitSETC; else emitCLRC;
5089 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5090 if (performedLt) emitCLRC; else emitSETC;
5091 goto correct_result_in_carry;
5094 } // right is literal
5096 /*************************************************
5097 * perform a general case comparison *
5098 * make sure we get CARRY==1 <==> left >= right *
5099 *************************************************/
5100 // compare most significant bytes
5101 //DEBUGpc ("comparing bytes at offset %d", size);
5103 // unsigned comparison
5104 mov2w_regOrLit (AOP(right), lit, size);
5105 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5107 // signed comparison
5108 // (add 2^n to both operands then perform an unsigned comparison)
5109 if (isAOP_LIT(right)) {
5110 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5111 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5113 if (litbyte == 0x80) {
5114 // left >= 0x80 -- always true, but more bytes to come
5115 pic16_mov2w (AOP(left), size);
5116 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5119 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5120 pic16_mov2w (AOP(left), size);
5121 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5122 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5125 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5126 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5127 pic16_mov2w (AOP(left), size);
5128 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5129 pic16_emitpcode (POC_MOVWF, pctemp);
5130 pic16_mov2w (AOP(right), size);
5131 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5132 pic16_emitpcode (POC_SUBFW, pctemp);
5133 //pic16_popReleaseTempReg(pctemp, 1);
5137 // compare remaining bytes (treat as unsigned case from above)
5138 templbl = newiTempLabel ( NULL );
5141 //DEBUGpc ("comparing bytes at offset %d", offs);
5142 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5143 mov2w_regOrLit (AOP(right), lit, offs);
5144 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5146 pic16_emitpLabel (templbl->key);
5147 goto result_in_carry;
5151 /****************************************************
5152 * now CARRY contains the result of the comparison: *
5153 * SUBWF sets CARRY iff *
5154 * F-W >= 0 <==> F >= W <==> !(F < W) *
5155 * (F=left, W=right) *
5156 ****************************************************/
5159 if (result && AOP_TYPE(result) != AOP_CRY) {
5160 // value will be stored
5163 // value wil only be used in the following genSkipc()
5164 rIfx.condition ^= 1;
5168 correct_result_in_carry:
5170 // assign result to variable (if neccessary)
5171 if (result && AOP_TYPE(result) != AOP_CRY) {
5172 //DEBUGpc ("assign result");
5173 size = AOP_SIZE(result);
5175 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5177 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5180 // perform conditional jump
5182 //DEBUGpc ("generate control flow");
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_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);
6172 /* unsigned compare */
6173 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6175 compareAopfirstpass=1;
6178 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6179 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6182 if(ifx)ifx->generated = 1;
6184 if(AOP_SIZE(result)) {
6185 pic16_emitpLabel(falselbl->key);
6186 pic16_outBitC( result );
6191 /* compare registers */
6192 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6196 pCodeOp *pct, *pct2;
6198 /* signed compare */
6199 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6201 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6202 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6203 tlbl = newiTempLabel( NULL );
6205 compareAopfirstpass=1;
6208 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6209 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6210 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6211 pic16_emitpcode(POC_MOVWF, pct);
6213 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6214 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6215 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217 /* WREG already holds left + 0x80 */
6218 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6221 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6222 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6223 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6224 pic16_emitpcode(POC_MOVWF, pct);
6226 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6227 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6228 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230 /* WREG already holds left + 0x80 */
6231 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6232 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6235 if(ifx)ifx->generated = 1;
6237 if(AOP_SIZE(result)) {
6238 pic16_emitpLabel(tlbl->key);
6239 pic16_emitpLabel(falselbl->key);
6240 pic16_outBitOp( result, pct2 );
6242 pic16_emitpLabel(tlbl->key);
6246 /* unsigned compare */
6247 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6249 compareAopfirstpass=1;
6252 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6253 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6257 if(ifx)ifx->generated = 1;
6258 if(AOP_SIZE(result)) {
6260 pic16_emitpLabel(falselbl->key);
6261 pic16_outBitC( result );
6272 /*-----------------------------------------------------------------*/
6273 /* genCmpGt :- greater than comparison */
6274 /*-----------------------------------------------------------------*/
6275 static void genCmpGt (iCode *ic, iCode *ifx)
6277 operand *left, *right, *result;
6278 sym_link *letype , *retype;
6284 right= IC_RIGHT(ic);
6285 result = IC_RESULT(ic);
6287 letype = getSpec(operandType(left));
6288 retype =getSpec(operandType(right));
6289 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6290 /* assign the amsops */
6291 pic16_aopOp (left,ic,FALSE);
6292 pic16_aopOp (right,ic,FALSE);
6293 pic16_aopOp (result,ic,TRUE);
6295 genCmp(right, left, result, ifx, sign);
6297 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299 pic16_freeAsmop(result,NULL,ic,TRUE);
6302 /*-----------------------------------------------------------------*/
6303 /* genCmpLt - less than comparisons */
6304 /*-----------------------------------------------------------------*/
6305 static void genCmpLt (iCode *ic, iCode *ifx)
6307 operand *left, *right, *result;
6308 sym_link *letype , *retype;
6314 right= IC_RIGHT(ic);
6315 result = IC_RESULT(ic);
6317 letype = getSpec(operandType(left));
6318 retype =getSpec(operandType(right));
6319 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6321 /* assign the amsops */
6322 pic16_aopOp (left,ic,FALSE);
6323 pic16_aopOp (right,ic,FALSE);
6324 pic16_aopOp (result,ic,TRUE);
6326 genCmp(left, right, result, ifx, sign);
6328 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330 pic16_freeAsmop(result,NULL,ic,TRUE);
6335 // FIXME reenable literal optimisation when the pic16 port is stable
6337 /*-----------------------------------------------------------------*/
6338 /* genc16bit2lit - compare a 16 bit value to a literal */
6339 /*-----------------------------------------------------------------*/
6340 static void genc16bit2lit(operand *op, int lit, int offset)
6344 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6345 if( (lit&0xff) == 0)
6350 switch( BYTEofLONG(lit,i)) {
6352 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6355 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6358 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6362 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6367 switch( BYTEofLONG(lit,i)) {
6369 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6373 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6377 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6380 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6382 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6391 /*-----------------------------------------------------------------*/
6392 /* gencjneshort - compare and jump if not equal */
6393 /*-----------------------------------------------------------------*/
6394 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6396 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6398 int res_offset = 0; /* the result may be a different size then left or right */
6399 int res_size = AOP_SIZE(result);
6401 symbol *lbl, *lbl_done;
6403 unsigned long lit = 0L;
6404 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6406 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6407 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6409 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6410 resolveIfx(&rIfx,ifx);
6411 lbl = newiTempLabel(NULL);
6412 lbl_done = newiTempLabel(NULL);
6415 /* if the left side is a literal or
6416 if the right is in a pointer register and left
6418 if ((AOP_TYPE(left) == AOP_LIT) ||
6419 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6424 if(AOP_TYPE(right) == AOP_LIT)
6425 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6427 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6428 preserve_result = 1;
6430 if(result && !preserve_result)
6433 for(i = 0; i < AOP_SIZE(result); i++)
6434 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6438 /* if the right side is a literal then anything goes */
6439 if (AOP_TYPE(right) == AOP_LIT &&
6440 AOP_TYPE(left) != AOP_DIR ) {
6443 genc16bit2lit(left, lit, 0);
6445 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6448 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6451 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6452 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6454 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6458 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6460 if(res_offset < res_size-1)
6468 /* if the right side is in a register or in direct space or
6469 if the left is a pointer register & right is not */
6470 else if (AOP_TYPE(right) == AOP_REG ||
6471 AOP_TYPE(right) == AOP_DIR ||
6472 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6473 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6474 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6475 int lbl_key = lbl->key;
6478 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6479 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6481 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6482 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6483 __FUNCTION__,__LINE__);
6487 /* switch(size) { */
6489 /* genc16bit2lit(left, lit, 0); */
6491 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6496 if((AOP_TYPE(left) == AOP_DIR) &&
6497 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6499 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6500 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6502 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6504 switch (lit & 0xff) {
6506 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6509 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6510 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6511 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6515 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6516 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6518 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6522 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6523 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6528 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6531 if(AOP_TYPE(result) == AOP_CRY) {
6532 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6537 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6539 /* fix me. probably need to check result size too */
6540 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6545 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6546 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6553 if(res_offset < res_size-1)
6558 } else if(AOP_TYPE(right) == AOP_REG &&
6559 AOP_TYPE(left) != AOP_DIR){
6562 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6563 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6564 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6569 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6571 if(res_offset < res_size-1)
6576 /* right is a pointer reg need both a & b */
6578 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6580 pic16_emitcode("mov","b,%s",l);
6581 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6582 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6587 if(result && preserve_result)
6590 for(i = 0; i < AOP_SIZE(result); i++)
6591 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6594 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6596 if(result && preserve_result)
6597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6600 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6602 pic16_emitpLabel(lbl->key);
6604 if(result && preserve_result)
6607 for(i = 0; i < AOP_SIZE(result); i++)
6608 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6610 pic16_emitpLabel(lbl_done->key);
6613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6621 /*-----------------------------------------------------------------*/
6622 /* gencjne - compare and jump if not equal */
6623 /*-----------------------------------------------------------------*/
6624 static void gencjne(operand *left, operand *right, iCode *ifx)
6626 symbol *tlbl = newiTempLabel(NULL);
6628 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6629 gencjneshort(left, right, lbl);
6631 pic16_emitcode("mov","a,%s",one);
6632 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6633 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6634 pic16_emitcode("clr","a");
6635 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6637 pic16_emitpLabel(lbl->key);
6638 pic16_emitpLabel(tlbl->key);
6644 /*-----------------------------------------------------------------*/
6645 /* is_LitOp - check if operand has to be treated as literal */
6646 /*-----------------------------------------------------------------*/
6647 static bool is_LitOp(operand *op)
6649 return ((AOP_TYPE(op) == AOP_LIT)
6650 || ( (AOP_TYPE(op) == AOP_PCODE)
6651 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6652 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6655 /*-----------------------------------------------------------------*/
6656 /* is_LitAOp - check if operand has to be treated as literal */
6657 /*-----------------------------------------------------------------*/
6658 static bool is_LitAOp(asmop *aop)
6660 return ((aop->type == AOP_LIT)
6661 || ( (aop->type == AOP_PCODE)
6662 && ( (aop->aopu.pcop->type == PO_LITERAL)
6663 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6668 /*-----------------------------------------------------------------*/
6669 /* genCmpEq - generates code for equal to */
6670 /*-----------------------------------------------------------------*/
6671 static void genCmpEq (iCode *ic, iCode *ifx)
6673 operand *left, *right, *result;
6674 symbol *falselbl = newiTempLabel(NULL);
6675 symbol *donelbl = newiTempLabel(NULL);
6677 int preserve_result = 0;
6678 int generate_result = 0;
6680 unsigned long lit = -1;
6684 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6685 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6686 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6688 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6690 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6692 werror(W_POSSBUG2, __FILE__, __LINE__);
6693 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6694 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6698 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6700 operand *tmp = right ;
6705 if (AOP_TYPE(right) == AOP_LIT) {
6706 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6709 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6710 preserve_result = 1;
6712 if(result && AOP_SIZE(result))
6713 generate_result = 1;
6715 if(generate_result && !preserve_result)
6717 for(i = 0; i < AOP_SIZE(result); i++)
6718 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6721 for(i=0; i < AOP_SIZE(left); i++)
6723 if(AOP_TYPE(left) != AOP_ACC)
6726 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6728 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6730 if(is_LitOp(right)) {
6731 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6732 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6735 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6737 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6742 if(generate_result && preserve_result)
6744 for(i = 0; i < AOP_SIZE(result); i++)
6745 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6749 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6751 if(generate_result && preserve_result)
6752 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6754 if(ifx && IC_TRUE(ifx))
6755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6757 if(ifx && IC_FALSE(ifx))
6758 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6760 pic16_emitpLabel(falselbl->key);
6764 if(ifx && IC_FALSE(ifx))
6765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6767 if(generate_result && preserve_result)
6769 for(i = 0; i < AOP_SIZE(result); i++)
6770 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6773 pic16_emitpLabel(donelbl->key);
6779 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6780 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6781 pic16_freeAsmop(result,NULL,ic,TRUE);
6787 // old version kept for reference
6789 /*-----------------------------------------------------------------*/
6790 /* genCmpEq - generates code for equal to */
6791 /*-----------------------------------------------------------------*/
6792 static void genCmpEq (iCode *ic, iCode *ifx)
6794 operand *left, *right, *result;
6795 unsigned long lit = 0L;
6797 symbol *falselbl = newiTempLabel(NULL);
6800 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6803 DEBUGpic16_emitcode ("; ifx is non-null","");
6805 DEBUGpic16_emitcode ("; ifx is null","");
6807 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6808 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6809 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6811 size = max(AOP_SIZE(left),AOP_SIZE(right));
6813 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6815 /* if literal, literal on the right or
6816 if the right is in a pointer register and left
6818 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6819 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6820 operand *tmp = right ;
6826 if(ifx && !AOP_SIZE(result)){
6828 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6829 /* if they are both bit variables */
6830 if (AOP_TYPE(left) == AOP_CRY &&
6831 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6832 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6833 if(AOP_TYPE(right) == AOP_LIT){
6834 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6836 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6837 pic16_emitcode("cpl","c");
6838 } else if(lit == 1L) {
6839 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6841 pic16_emitcode("clr","c");
6843 /* AOP_TYPE(right) == AOP_CRY */
6845 symbol *lbl = newiTempLabel(NULL);
6846 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6847 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6848 pic16_emitcode("cpl","c");
6849 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6851 /* if true label then we jump if condition
6853 tlbl = newiTempLabel(NULL);
6854 if ( IC_TRUE(ifx) ) {
6855 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6856 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6858 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6859 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6861 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6864 /* left and right are both bit variables, result is carry */
6867 resolveIfx(&rIfx,ifx);
6869 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6870 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6871 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6872 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6877 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6879 /* They're not both bit variables. Is the right a literal? */
6880 if(AOP_TYPE(right) == AOP_LIT) {
6881 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6886 switch(lit & 0xff) {
6888 if ( IC_TRUE(ifx) ) {
6889 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6893 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6898 if ( IC_TRUE(ifx) ) {
6899 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6903 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6904 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6908 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6910 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6915 /* end of size == 1 */
6919 genc16bit2lit(left,lit,offset);
6922 /* end of size == 2 */
6927 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6928 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6929 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6930 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6933 /* search for patterns that can be optimized */
6935 genc16bit2lit(left,lit,0);
6939 emitSKPZ; // if hi word unequal
6941 emitSKPNZ; // if hi word equal
6943 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6944 genc16bit2lit(left,lit,2);
6947 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6948 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6952 pic16_emitpLabel(falselbl->key);
6961 } else if(AOP_TYPE(right) == AOP_CRY ) {
6962 /* we know the left is not a bit, but that the right is */
6963 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6964 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6965 pic16_popGet(AOP(right),offset));
6966 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6968 /* if the two are equal, then W will be 0 and the Z bit is set
6969 * we could test Z now, or go ahead and check the high order bytes if
6970 * the variable we're comparing is larger than a byte. */
6973 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6975 if ( IC_TRUE(ifx) ) {
6977 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6978 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6981 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6982 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6986 /* They're both variables that are larger than bits */
6989 tlbl = newiTempLabel(NULL);
6992 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6993 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6995 if ( IC_TRUE(ifx) ) {
6999 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7001 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7002 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7006 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7009 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7010 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7015 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7017 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7018 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7022 if(s>1 && IC_TRUE(ifx)) {
7023 pic16_emitpLabel(tlbl->key);
7024 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7028 /* mark the icode as generated */
7033 /* if they are both bit variables */
7034 if (AOP_TYPE(left) == AOP_CRY &&
7035 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7036 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7037 if(AOP_TYPE(right) == AOP_LIT){
7038 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7040 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7041 pic16_emitcode("cpl","c");
7042 } else if(lit == 1L) {
7043 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7045 pic16_emitcode("clr","c");
7047 /* AOP_TYPE(right) == AOP_CRY */
7049 symbol *lbl = newiTempLabel(NULL);
7050 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7051 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7052 pic16_emitcode("cpl","c");
7053 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7056 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7057 pic16_outBitC(result);
7061 genIfxJump (ifx,"c");
7064 /* if the result is used in an arithmetic operation
7065 then put the result in place */
7066 pic16_outBitC(result);
7069 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7070 gencjne(left,right,result,ifx);
7073 gencjne(left,right,newiTempLabel(NULL));
7075 if(IC_TRUE(ifx)->key)
7076 gencjne(left,right,IC_TRUE(ifx)->key);
7078 gencjne(left,right,IC_FALSE(ifx)->key);
7082 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7083 pic16_aopPut(AOP(result),"a",0);
7088 genIfxJump (ifx,"a");
7092 /* if the result is used in an arithmetic operation
7093 then put the result in place */
7095 if (AOP_TYPE(result) != AOP_CRY)
7096 pic16_outAcc(result);
7098 /* leave the result in acc */
7102 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7103 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7104 pic16_freeAsmop(result,NULL,ic,TRUE);
7108 /*-----------------------------------------------------------------*/
7109 /* ifxForOp - returns the icode containing the ifx for operand */
7110 /*-----------------------------------------------------------------*/
7111 static iCode *ifxForOp ( operand *op, iCode *ic )
7115 /* if true symbol then needs to be assigned */
7116 if (IS_TRUE_SYMOP(op))
7119 /* if this has register type condition and
7120 the next instruction is ifx with the same operand
7121 and live to of the operand is upto the ifx only then */
7123 && ic->next->op == IFX
7124 && IC_COND(ic->next)->key == op->key
7125 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7127 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7133 ic->next->op == IFX &&
7134 IC_COND(ic->next)->key == op->key) {
7135 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7140 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7142 ic->next->op == IFX)
7143 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7146 ic->next->op == IFX &&
7147 IC_COND(ic->next)->key == op->key) {
7148 DEBUGpic16_emitcode ("; "," key is okay");
7149 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7150 OP_SYMBOL(op)->liveTo,
7155 /* the code below is completely untested
7156 * it just allows ulong2fs.c compile -- VR */
7159 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7160 __FILE__, __FUNCTION__, __LINE__);
7162 /* if this has register type condition and
7163 the next instruction is ifx with the same operand
7164 and live to of the operand is upto the ifx only then */
7166 ic->next->op == IFX &&
7167 IC_COND(ic->next)->key == op->key &&
7168 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7172 ic->next->op == IFX &&
7173 IC_COND(ic->next)->key == op->key) {
7174 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7178 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7179 __FILE__, __FUNCTION__, __LINE__);
7181 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7186 /*-----------------------------------------------------------------*/
7187 /* genAndOp - for && operation */
7188 /*-----------------------------------------------------------------*/
7189 static void genAndOp (iCode *ic)
7191 operand *left,*right, *result;
7196 /* note here that && operations that are in an
7197 if statement are taken away by backPatchLabels
7198 only those used in arthmetic operations remain */
7199 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7200 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7201 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7203 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7206 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7207 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7209 /* if both are bit variables */
7210 /* if (AOP_TYPE(left) == AOP_CRY && */
7211 /* AOP_TYPE(right) == AOP_CRY ) { */
7212 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7213 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7214 /* pic16_outBitC(result); */
7216 /* tlbl = newiTempLabel(NULL); */
7217 /* pic16_toBoolean(left); */
7218 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7219 /* pic16_toBoolean(right); */
7220 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7221 /* pic16_outBitAcc(result); */
7224 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7225 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226 pic16_freeAsmop(result,NULL,ic,TRUE);
7230 /*-----------------------------------------------------------------*/
7231 /* genOrOp - for || operation */
7232 /*-----------------------------------------------------------------*/
7235 modified this code, but it doesn't appear to ever get called
7238 static void genOrOp (iCode *ic)
7240 operand *left,*right, *result;
7245 /* note here that || operations that are in an
7246 if statement are taken away by backPatchLabels
7247 only those used in arthmetic operations remain */
7248 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7249 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7250 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7252 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7254 /* if both are bit variables */
7255 if (AOP_TYPE(left) == AOP_CRY &&
7256 AOP_TYPE(right) == AOP_CRY ) {
7257 pic16_emitcode("clrc","");
7258 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7259 AOP(left)->aopu.aop_dir,
7260 AOP(left)->aopu.aop_dir);
7261 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7262 AOP(right)->aopu.aop_dir,
7263 AOP(right)->aopu.aop_dir);
7264 pic16_emitcode("setc","");
7267 tlbl = newiTempLabel(NULL);
7268 pic16_toBoolean(left);
7270 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7271 pic16_toBoolean(right);
7272 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7274 pic16_outBitAcc(result);
7277 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7278 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7279 pic16_freeAsmop(result,NULL,ic,TRUE);
7282 /*-----------------------------------------------------------------*/
7283 /* isLiteralBit - test if lit == 2^n */
7284 /*-----------------------------------------------------------------*/
7285 static int isLiteralBit(unsigned long lit)
7287 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7288 0x100L,0x200L,0x400L,0x800L,
7289 0x1000L,0x2000L,0x4000L,0x8000L,
7290 0x10000L,0x20000L,0x40000L,0x80000L,
7291 0x100000L,0x200000L,0x400000L,0x800000L,
7292 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7293 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7296 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7297 for(idx = 0; idx < 32; idx++)
7303 /*-----------------------------------------------------------------*/
7304 /* continueIfTrue - */
7305 /*-----------------------------------------------------------------*/
7306 static void continueIfTrue (iCode *ic)
7310 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7314 /*-----------------------------------------------------------------*/
7316 /*-----------------------------------------------------------------*/
7317 static void jumpIfTrue (iCode *ic)
7321 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7325 /*-----------------------------------------------------------------*/
7326 /* jmpTrueOrFalse - */
7327 /*-----------------------------------------------------------------*/
7328 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7330 // ugly but optimized by peephole
7333 symbol *nlbl = newiTempLabel(NULL);
7334 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7335 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7336 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7337 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7339 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7340 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7345 /*-----------------------------------------------------------------*/
7346 /* genAnd - code for and */
7347 /*-----------------------------------------------------------------*/
7348 static void genAnd (iCode *ic, iCode *ifx)
7350 operand *left, *right, *result;
7352 unsigned long lit = 0L;
7358 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7359 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7360 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7362 resolveIfx(&rIfx,ifx);
7364 /* if left is a literal & right is not then exchange them */
7365 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7366 AOP_NEEDSACC(left)) {
7367 operand *tmp = right ;
7372 /* if result = right then exchange them */
7373 if(pic16_sameRegs(AOP(result),AOP(right))){
7374 operand *tmp = right ;
7379 /* if right is bit then exchange them */
7380 if (AOP_TYPE(right) == AOP_CRY &&
7381 AOP_TYPE(left) != AOP_CRY){
7382 operand *tmp = right ;
7386 if(AOP_TYPE(right) == AOP_LIT)
7387 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7389 size = AOP_SIZE(result);
7391 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7394 // result = bit & yy;
7395 if (AOP_TYPE(left) == AOP_CRY){
7396 // c = bit & literal;
7397 if(AOP_TYPE(right) == AOP_LIT){
7399 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7402 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7405 if(size && (AOP_TYPE(result) == AOP_CRY)){
7406 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7409 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7413 pic16_emitcode("clr","c");
7416 if (AOP_TYPE(right) == AOP_CRY){
7418 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7419 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7422 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7424 pic16_emitcode("rrc","a");
7425 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7431 pic16_outBitC(result);
7433 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7434 genIfxJump(ifx, "c");
7438 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7439 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7440 if((AOP_TYPE(right) == AOP_LIT) &&
7441 (AOP_TYPE(result) == AOP_CRY) &&
7442 (AOP_TYPE(left) != AOP_CRY)){
7443 int posbit = isLiteralBit(lit);
7447 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7450 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7456 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7459 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7463 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7464 size = AOP_SIZE(left);
7467 int bp = posbit, ofs=0;
7474 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7475 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7479 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7480 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7482 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7489 symbol *tlbl = newiTempLabel(NULL);
7490 int sizel = AOP_SIZE(left);
7496 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7498 /* patch provided by Aaron Colwell */
7499 if((posbit = isLiteralBit(bytelit)) != 0) {
7500 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7501 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7502 (posbit-1),0, PO_GPR_REGISTER));
7504 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7505 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7507 if (bytelit == 0xff) {
7508 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7509 * a peephole could optimize it out -- VR */
7510 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7512 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7513 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7516 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7517 pic16_popGetLabel(tlbl->key));
7521 /* old code, left here for reference -- VR 09/2004 */
7522 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7524 if((posbit = isLiteralBit(bytelit)) != 0)
7525 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7527 if(bytelit != 0x0FFL)
7528 pic16_emitcode("anl","a,%s",
7529 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7530 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7536 // bit = left & literal
7539 pic16_emitpLabel(tlbl->key);
7541 // if(left & literal)
7544 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7547 pic16_emitpLabel(tlbl->key);
7552 pic16_outBitC(result);
7556 /* if left is same as result */
7557 if(pic16_sameRegs(AOP(result),AOP(left))){
7559 for(;size--; offset++,lit>>=8) {
7560 if(AOP_TYPE(right) == AOP_LIT){
7561 switch(lit & 0xff) {
7563 /* and'ing with 0 has clears the result */
7564 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7565 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7568 /* and'ing with 0xff is a nop when the result and left are the same */
7573 int p = pic16_my_powof2( (~lit) & 0xff );
7575 /* only one bit is set in the literal, so use a bcf instruction */
7576 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7577 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7580 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7581 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7582 if(know_W != (lit&0xff))
7583 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7585 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7590 if (AOP_TYPE(left) == AOP_ACC) {
7591 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7593 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7594 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7601 // left & result in different registers
7602 if(AOP_TYPE(result) == AOP_CRY){
7604 // if(size), result in bit
7605 // if(!size && ifx), conditional oper: if(left & right)
7606 symbol *tlbl = newiTempLabel(NULL);
7607 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7609 pic16_emitcode("setb","c");
7611 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7612 pic16_emitcode("anl","a,%s",
7613 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7614 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7619 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7620 pic16_outBitC(result);
7622 jmpTrueOrFalse(ifx, tlbl);
7624 for(;(size--);offset++) {
7626 // result = left & right
7627 if(AOP_TYPE(right) == AOP_LIT){
7628 int t = (lit >> (offset*8)) & 0x0FFL;
7631 pic16_emitcode("clrf","%s",
7632 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7633 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7636 pic16_emitcode("movf","%s,w",
7637 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7638 pic16_emitcode("movwf","%s",
7639 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7641 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7644 pic16_emitcode("movlw","0x%x",t);
7645 pic16_emitcode("andwf","%s,w",
7646 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7647 pic16_emitcode("movwf","%s",
7648 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7650 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7651 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7652 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7657 if (AOP_TYPE(left) == AOP_ACC) {
7658 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7659 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7661 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7662 pic16_emitcode("andwf","%s,w",
7663 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7664 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7665 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7667 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7668 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7674 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676 pic16_freeAsmop(result,NULL,ic,TRUE);
7679 /*-----------------------------------------------------------------*/
7680 /* genOr - code for or */
7681 /*-----------------------------------------------------------------*/
7682 static void genOr (iCode *ic, iCode *ifx)
7684 operand *left, *right, *result;
7686 unsigned long lit = 0L;
7688 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7690 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7691 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7692 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7694 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7696 /* if left is a literal & right is not then exchange them */
7697 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7698 AOP_NEEDSACC(left)) {
7699 operand *tmp = right ;
7704 /* if result = right then exchange them */
7705 if(pic16_sameRegs(AOP(result),AOP(right))){
7706 operand *tmp = right ;
7711 /* if right is bit then exchange them */
7712 if (AOP_TYPE(right) == AOP_CRY &&
7713 AOP_TYPE(left) != AOP_CRY){
7714 operand *tmp = right ;
7719 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7721 if(AOP_TYPE(right) == AOP_LIT)
7722 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7724 size = AOP_SIZE(result);
7728 if (AOP_TYPE(left) == AOP_CRY){
7729 if(AOP_TYPE(right) == AOP_LIT){
7730 // c = bit & literal;
7732 // lit != 0 => result = 1
7733 if(AOP_TYPE(result) == AOP_CRY){
7735 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7736 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7737 // AOP(result)->aopu.aop_dir,
7738 // AOP(result)->aopu.aop_dir);
7740 continueIfTrue(ifx);
7744 // lit == 0 => result = left
7745 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7747 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7750 if (AOP_TYPE(right) == AOP_CRY){
7751 if(pic16_sameRegs(AOP(result),AOP(left))){
7753 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7754 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7755 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7757 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7758 AOP(result)->aopu.aop_dir,
7759 AOP(result)->aopu.aop_dir);
7760 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7761 AOP(right)->aopu.aop_dir,
7762 AOP(right)->aopu.aop_dir);
7763 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7764 AOP(result)->aopu.aop_dir,
7765 AOP(result)->aopu.aop_dir);
7767 if( AOP_TYPE(result) == AOP_ACC) {
7768 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7769 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7770 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7771 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7775 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7776 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7780 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7781 AOP(result)->aopu.aop_dir,
7782 AOP(result)->aopu.aop_dir);
7783 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7784 AOP(right)->aopu.aop_dir,
7785 AOP(right)->aopu.aop_dir);
7786 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7787 AOP(left)->aopu.aop_dir,
7788 AOP(left)->aopu.aop_dir);
7789 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7790 AOP(result)->aopu.aop_dir,
7791 AOP(result)->aopu.aop_dir);
7796 symbol *tlbl = newiTempLabel(NULL);
7797 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7800 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7801 if( AOP_TYPE(right) == AOP_ACC) {
7802 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7804 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7805 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7810 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7811 pic16_emitcode(";XXX setb","c");
7812 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7813 AOP(left)->aopu.aop_dir,tlbl->key+100);
7814 pic16_toBoolean(right);
7815 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7816 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7817 jmpTrueOrFalse(ifx, tlbl);
7821 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7828 pic16_outBitC(result);
7830 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7831 genIfxJump(ifx, "c");
7835 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7836 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7837 if((AOP_TYPE(right) == AOP_LIT) &&
7838 (AOP_TYPE(result) == AOP_CRY) &&
7839 (AOP_TYPE(left) != AOP_CRY)){
7841 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7844 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7846 continueIfTrue(ifx);
7849 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7850 // lit = 0, result = boolean(left)
7852 pic16_emitcode(";XXX setb","c");
7853 pic16_toBoolean(right);
7855 symbol *tlbl = newiTempLabel(NULL);
7856 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7858 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7860 genIfxJump (ifx,"a");
7864 pic16_outBitC(result);
7868 /* if left is same as result */
7869 if(pic16_sameRegs(AOP(result),AOP(left))){
7871 for(;size--; offset++,lit>>=8) {
7872 if(AOP_TYPE(right) == AOP_LIT){
7873 if((lit & 0xff) == 0)
7874 /* or'ing with 0 has no effect */
7877 int p = pic16_my_powof2(lit & 0xff);
7879 /* only one bit is set in the literal, so use a bsf instruction */
7880 pic16_emitpcode(POC_BSF,
7881 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7883 if(know_W != (lit & 0xff))
7884 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7885 know_W = lit & 0xff;
7886 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7891 if (AOP_TYPE(left) == AOP_ACC) {
7892 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7893 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7895 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7896 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7898 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7899 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7905 // left & result in different registers
7906 if(AOP_TYPE(result) == AOP_CRY){
7908 // if(size), result in bit
7909 // if(!size && ifx), conditional oper: if(left | right)
7910 symbol *tlbl = newiTempLabel(NULL);
7911 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7912 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7916 pic16_emitcode(";XXX setb","c");
7918 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919 pic16_emitcode(";XXX orl","a,%s",
7920 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7926 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7927 pic16_outBitC(result);
7929 jmpTrueOrFalse(ifx, tlbl);
7930 } else for(;(size--);offset++){
7932 // result = left & right
7933 if(AOP_TYPE(right) == AOP_LIT){
7934 int t = (lit >> (offset*8)) & 0x0FFL;
7937 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7940 pic16_emitcode("movf","%s,w",
7941 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7942 pic16_emitcode("movwf","%s",
7943 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7946 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7947 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7950 pic16_emitcode("movlw","0x%x",t);
7951 pic16_emitcode("iorwf","%s,w",
7952 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7953 pic16_emitcode("movwf","%s",
7954 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7960 // faster than result <- left, anl result,right
7961 // and better if result is SFR
7962 if (AOP_TYPE(left) == AOP_ACC) {
7963 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7964 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7966 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7967 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7969 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7970 pic16_emitcode("iorwf","%s,w",
7971 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7973 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7974 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7979 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7980 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7981 pic16_freeAsmop(result,NULL,ic,TRUE);
7984 /*-----------------------------------------------------------------*/
7985 /* genXor - code for xclusive or */
7986 /*-----------------------------------------------------------------*/
7987 static void genXor (iCode *ic, iCode *ifx)
7989 operand *left, *right, *result;
7991 unsigned long lit = 0L;
7993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7995 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7996 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7997 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7999 /* if left is a literal & right is not ||
8000 if left needs acc & right does not */
8001 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8002 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8003 operand *tmp = right ;
8008 /* if result = right then exchange them */
8009 if(pic16_sameRegs(AOP(result),AOP(right))){
8010 operand *tmp = right ;
8015 /* if right is bit then exchange them */
8016 if (AOP_TYPE(right) == AOP_CRY &&
8017 AOP_TYPE(left) != AOP_CRY){
8018 operand *tmp = right ;
8022 if(AOP_TYPE(right) == AOP_LIT)
8023 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8025 size = AOP_SIZE(result);
8029 if (AOP_TYPE(left) == AOP_CRY){
8030 if(AOP_TYPE(right) == AOP_LIT){
8031 // c = bit & literal;
8033 // lit>>1 != 0 => result = 1
8034 if(AOP_TYPE(result) == AOP_CRY){
8036 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8037 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8039 continueIfTrue(ifx);
8042 pic16_emitcode("setb","c");
8046 // lit == 0, result = left
8047 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8049 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8051 // lit == 1, result = not(left)
8052 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8053 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8054 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8055 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8058 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8059 pic16_emitcode("cpl","c");
8066 symbol *tlbl = newiTempLabel(NULL);
8067 if (AOP_TYPE(right) == AOP_CRY){
8069 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8072 int sizer = AOP_SIZE(right);
8074 // if val>>1 != 0, result = 1
8075 pic16_emitcode("setb","c");
8077 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8079 // test the msb of the lsb
8080 pic16_emitcode("anl","a,#0xfe");
8081 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8085 pic16_emitcode("rrc","a");
8087 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8088 pic16_emitcode("cpl","c");
8089 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8094 pic16_outBitC(result);
8096 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8097 genIfxJump(ifx, "c");
8101 if(pic16_sameRegs(AOP(result),AOP(left))){
8102 /* if left is same as result */
8103 for(;size--; offset++) {
8104 if(AOP_TYPE(right) == AOP_LIT){
8105 int t = (lit >> (offset*8)) & 0x0FFL;
8109 if (IS_AOP_PREG(left)) {
8110 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8111 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8112 pic16_aopPut(AOP(result),"a",offset);
8114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8115 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8116 pic16_emitcode("xrl","%s,%s",
8117 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8118 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8121 if (AOP_TYPE(left) == AOP_ACC)
8122 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8125 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8127 if (IS_AOP_PREG(left)) {
8128 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8129 pic16_aopPut(AOP(result),"a",offset);
8131 pic16_emitcode("xrl","%s,a",
8132 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8138 // left & result in different registers
8139 if(AOP_TYPE(result) == AOP_CRY){
8141 // if(size), result in bit
8142 // if(!size && ifx), conditional oper: if(left ^ right)
8143 symbol *tlbl = newiTempLabel(NULL);
8144 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8146 pic16_emitcode("setb","c");
8148 if((AOP_TYPE(right) == AOP_LIT) &&
8149 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8150 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8152 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8153 pic16_emitcode("xrl","a,%s",
8154 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8161 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8162 pic16_outBitC(result);
8164 jmpTrueOrFalse(ifx, tlbl);
8165 } else for(;(size--);offset++){
8167 // result = left & right
8168 if(AOP_TYPE(right) == AOP_LIT){
8169 int t = (lit >> (offset*8)) & 0x0FFL;
8172 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8174 pic16_emitcode("movf","%s,w",
8175 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8176 pic16_emitcode("movwf","%s",
8177 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8180 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8181 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8182 pic16_emitcode("comf","%s,w",
8183 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8184 pic16_emitcode("movwf","%s",
8185 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8188 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8189 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8190 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8191 pic16_emitcode("movlw","0x%x",t);
8192 pic16_emitcode("xorwf","%s,w",
8193 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8194 pic16_emitcode("movwf","%s",
8195 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8201 // faster than result <- left, anl result,right
8202 // and better if result is SFR
8203 if (AOP_TYPE(left) == AOP_ACC) {
8204 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8205 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8207 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8208 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8209 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8210 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8212 if ( AOP_TYPE(result) != AOP_ACC){
8213 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8214 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8220 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8221 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8222 pic16_freeAsmop(result,NULL,ic,TRUE);
8225 /*-----------------------------------------------------------------*/
8226 /* genInline - write the inline code out */
8227 /*-----------------------------------------------------------------*/
8228 static void genInline (iCode *ic)
8230 char *buffer, *bp, *bp1;
8232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8234 _G.inLine += (!options.asmpeep);
8236 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8237 strcpy(buffer,IC_INLINE(ic));
8239 while((bp1=strstr(bp, "\\n"))) {
8247 /* This is an experimental code for #pragma inline
8248 and is temporarily disabled for 2.5.0 release */
8256 cbuf = Safe_strdup(buffer);
8257 cblen = strlen(buffer)+1;
8258 memset(cbuf, 0, cblen);
8263 if(*bp != '%')*bp1++ = *bp++;
8269 if(i>elementsInSet(asmInlineMap))break;
8272 s = indexSet(asmInlineMap, i);
8273 DEBUGpc("searching symbol s = `%s'", s);
8274 sym = findSym(SymbolTab, NULL, s);
8277 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8279 strcat(bp1, sym->rname);
8285 if(strlen(bp1) > cblen - 16) {
8286 int i = strlen(cbuf);
8288 cbuf = realloc(cbuf, cblen);
8289 memset(cbuf+i, 0, 50);
8295 buffer = Safe_strdup( cbuf );
8302 /* emit each line as a code */
8308 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8316 /* print label, use this special format with NULL directive
8317 * to denote that the argument should not be indented with tab */
8318 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8325 if ((bp1 != bp) && *bp1)
8326 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8331 _G.inLine -= (!options.asmpeep);
8334 /*-----------------------------------------------------------------*/
8335 /* genRRC - rotate right with carry */
8336 /*-----------------------------------------------------------------*/
8337 static void genRRC (iCode *ic)
8339 operand *left , *result ;
8340 int size, offset = 0, same;
8342 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8344 /* rotate right with carry */
8346 result=IC_RESULT(ic);
8347 pic16_aopOp (left,ic,FALSE);
8348 pic16_aopOp (result,ic,TRUE);
8350 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8352 same = pic16_sameRegs(AOP(result),AOP(left));
8354 size = AOP_SIZE(result);
8356 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8358 /* get the lsb and put it into the carry */
8359 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8366 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8368 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8369 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8375 pic16_freeAsmop(left,NULL,ic,TRUE);
8376 pic16_freeAsmop(result,NULL,ic,TRUE);
8379 /*-----------------------------------------------------------------*/
8380 /* genRLC - generate code for rotate left with carry */
8381 /*-----------------------------------------------------------------*/
8382 static void genRLC (iCode *ic)
8384 operand *left , *result ;
8385 int size, offset = 0;
8388 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8389 /* rotate right with carry */
8391 result=IC_RESULT(ic);
8392 pic16_aopOp (left,ic,FALSE);
8393 pic16_aopOp (result,ic,TRUE);
8395 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8397 same = pic16_sameRegs(AOP(result),AOP(left));
8399 /* move it to the result */
8400 size = AOP_SIZE(result);
8402 /* get the msb and put it into the carry */
8403 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8410 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8412 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8413 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8420 pic16_freeAsmop(left,NULL,ic,TRUE);
8421 pic16_freeAsmop(result,NULL,ic,TRUE);
8425 /* gpasm can get the highest order bit with HIGH/UPPER
8426 * so the following probably is not needed -- VR */
8428 /*-----------------------------------------------------------------*/
8429 /* genGetHbit - generates code get highest order bit */
8430 /*-----------------------------------------------------------------*/
8431 static void genGetHbit (iCode *ic)
8433 operand *left, *result;
8435 result=IC_RESULT(ic);
8436 pic16_aopOp (left,ic,FALSE);
8437 pic16_aopOp (result,ic,FALSE);
8439 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8440 /* get the highest order byte into a */
8441 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8442 if(AOP_TYPE(result) == AOP_CRY){
8443 pic16_emitcode("rlc","a");
8444 pic16_outBitC(result);
8447 pic16_emitcode("rl","a");
8448 pic16_emitcode("anl","a,#0x01");
8449 pic16_outAcc(result);
8453 pic16_freeAsmop(left,NULL,ic,TRUE);
8454 pic16_freeAsmop(result,NULL,ic,TRUE);
8458 /*-----------------------------------------------------------------*/
8459 /* AccRol - rotate left accumulator by known count */
8460 /*-----------------------------------------------------------------*/
8461 static void AccRol (int shCount)
8463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8464 shCount &= 0x0007; // shCount : 0..7
8469 pic16_emitcode("rl","a");
8472 pic16_emitcode("rl","a");
8473 pic16_emitcode("rl","a");
8476 pic16_emitcode("swap","a");
8477 pic16_emitcode("rr","a");
8480 pic16_emitcode("swap","a");
8483 pic16_emitcode("swap","a");
8484 pic16_emitcode("rl","a");
8487 pic16_emitcode("rr","a");
8488 pic16_emitcode("rr","a");
8491 pic16_emitcode("rr","a");
8497 /*-----------------------------------------------------------------*/
8498 /* AccLsh - left shift accumulator by known count */
8499 /*-----------------------------------------------------------------*/
8500 static void AccLsh (int shCount)
8502 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8508 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8511 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8515 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8522 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8526 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8530 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8534 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8537 /*-----------------------------------------------------------------*/
8538 /* AccRsh - right shift accumulator by known count */
8539 /*-----------------------------------------------------------------*/
8540 static void AccRsh (int shCount, int andmask)
8542 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8547 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8550 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8554 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8561 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8569 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8574 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8576 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8580 /*-----------------------------------------------------------------*/
8581 /* AccSRsh - signed right shift accumulator by known count */
8582 /*-----------------------------------------------------------------*/
8583 static void AccSRsh (int shCount)
8586 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8589 pic16_emitcode("mov","c,acc.7");
8590 pic16_emitcode("rrc","a");
8591 } else if(shCount == 2){
8592 pic16_emitcode("mov","c,acc.7");
8593 pic16_emitcode("rrc","a");
8594 pic16_emitcode("mov","c,acc.7");
8595 pic16_emitcode("rrc","a");
8597 tlbl = newiTempLabel(NULL);
8598 /* rotate right accumulator */
8599 AccRol(8 - shCount);
8600 /* and kill the higher order bits */
8601 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8602 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8603 pic16_emitcode("orl","a,#0x%02x",
8604 (unsigned char)~SRMask[shCount]);
8605 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8611 /*-----------------------------------------------------------------*/
8612 /* shiftR1Left2Result - shift right one byte from left to result */
8613 /*-----------------------------------------------------------------*/
8614 static void shiftR1Left2ResultSigned (operand *left, int offl,
8615 operand *result, int offr,
8620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8622 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8626 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8628 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8630 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8631 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8637 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8639 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8641 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8642 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8644 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8645 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8651 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8653 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8654 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8657 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8658 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8659 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8661 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8662 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8664 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8668 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8669 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8670 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8671 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8676 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8678 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8679 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8681 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8683 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8684 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8685 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8692 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8693 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8694 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8699 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8700 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8701 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8708 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8709 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8710 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8713 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8714 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8722 /*-----------------------------------------------------------------*/
8723 /* shiftR1Left2Result - shift right one byte from left to result */
8724 /*-----------------------------------------------------------------*/
8725 static void shiftR1Left2Result (operand *left, int offl,
8726 operand *result, int offr,
8727 int shCount, int sign)
8731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8733 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8735 /* Copy the msb into the carry if signed. */
8737 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8747 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8749 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8750 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8756 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8758 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8759 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8762 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8769 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8770 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8774 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8775 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8776 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8780 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8781 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8782 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8786 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8787 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8795 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8796 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8797 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8798 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8799 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8805 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8806 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8815 /*-----------------------------------------------------------------*/
8816 /* shiftL1Left2Result - shift left one byte from left to result */
8817 /*-----------------------------------------------------------------*/
8818 static void shiftL1Left2Result (operand *left, int offl,
8819 operand *result, int offr, int shCount)
8824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8826 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8827 DEBUGpic16_emitcode ("; ***","same = %d",same);
8828 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8830 /* shift left accumulator */
8831 //AccLsh(shCount); // don't comment out just yet...
8832 // pic16_aopPut(AOP(result),"a",offr);
8836 /* Shift left 1 bit position */
8837 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8839 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8841 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8842 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8846 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8847 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8848 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8849 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8854 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8855 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8859 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8860 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8861 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8865 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8866 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8871 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8872 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8878 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8883 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8888 /*-----------------------------------------------------------------*/
8889 /* movLeft2Result - move byte from left to result */
8890 /*-----------------------------------------------------------------*/
8891 static void movLeft2Result (operand *left, int offl,
8892 operand *result, int offr)
8895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8896 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8897 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8899 if (*l == '@' && (IS_AOP_PREG(result))) {
8900 pic16_emitcode("mov","a,%s",l);
8901 pic16_aopPut(AOP(result),"a",offr);
8903 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8909 /*-----------------------------------------------------------------*/
8910 /* shiftL2Left2Result - shift left two bytes from left to result */
8911 /*-----------------------------------------------------------------*/
8912 static void shiftL2Left2Result (operand *left, int offl,
8913 operand *result, int offr, int shCount)
8915 int same = pic16_sameRegs(AOP(result), AOP(left));
8918 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8920 if (same && (offl != offr)) { // shift bytes
8923 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8924 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8926 } else { // just treat as different later on
8939 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8945 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8952 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8953 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8954 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8971 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8977 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8980 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8991 /* note, use a mov/add for the shift since the mov has a
8992 chance of getting optimized out */
8993 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8994 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9001 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9008 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9009 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9010 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9011 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9012 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9014 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9015 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9019 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9025 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9026 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9027 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9030 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9033 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9039 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9041 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9042 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9048 /*-----------------------------------------------------------------*/
9049 /* shiftR2Left2Result - shift right two bytes from left to result */
9050 /*-----------------------------------------------------------------*/
9051 static void shiftR2Left2Result (operand *left, int offl,
9052 operand *result, int offr,
9053 int shCount, int sign)
9055 int same = pic16_sameRegs(AOP(result), AOP(left));
9057 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9059 if (same && (offl != offr)) { // shift right bytes
9062 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9063 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9065 } else { // just treat as different later on
9077 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9082 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9085 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9086 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9087 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9088 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9096 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9104 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9105 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9108 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9109 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9111 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9114 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9115 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9117 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9118 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9119 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9120 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9121 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9125 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9126 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9130 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9131 pic16_emitpcode(POC_BTFSC,
9132 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9133 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9141 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9144 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9145 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9146 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9147 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9149 pic16_emitpcode(POC_BTFSC,
9150 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9151 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9153 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9154 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9158 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9159 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9161 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9162 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9163 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9164 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9165 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9167 pic16_emitpcode(POC_BTFSC,
9168 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9169 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9171 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9172 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9179 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9180 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9181 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9182 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9185 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9187 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9192 /*-----------------------------------------------------------------*/
9193 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9194 /*-----------------------------------------------------------------*/
9195 static void shiftLLeftOrResult (operand *left, int offl,
9196 operand *result, int offr, int shCount)
9198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9200 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9201 /* shift left accumulator */
9203 /* or with result */
9204 /* back to result */
9205 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9208 /*-----------------------------------------------------------------*/
9209 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9210 /*-----------------------------------------------------------------*/
9211 static void shiftRLeftOrResult (operand *left, int offl,
9212 operand *result, int offr, int shCount)
9214 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9216 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9217 /* shift right accumulator */
9219 /* or with result */
9220 /* back to result */
9221 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9224 /*-----------------------------------------------------------------*/
9225 /* genlshOne - left shift a one byte quantity by known count */
9226 /*-----------------------------------------------------------------*/
9227 static void genlshOne (operand *result, operand *left, int shCount)
9229 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9230 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9233 /*-----------------------------------------------------------------*/
9234 /* genlshTwo - left shift two bytes by known amount != 0 */
9235 /*-----------------------------------------------------------------*/
9236 static void genlshTwo (operand *result,operand *left, int shCount)
9240 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9241 size = pic16_getDataSize(result);
9243 /* if shCount >= 8 */
9249 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9251 movLeft2Result(left, LSB, result, MSB16);
9253 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9256 /* 1 <= shCount <= 7 */
9259 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9261 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9265 /*-----------------------------------------------------------------*/
9266 /* shiftLLong - shift left one long from left to result */
9267 /* offr = LSB or MSB16 */
9268 /*-----------------------------------------------------------------*/
9269 static void shiftLLong (operand *left, operand *result, int offr )
9271 int size = AOP_SIZE(result);
9272 int same = pic16_sameRegs(AOP(left),AOP(result));
9275 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9277 if (same && (offr == MSB16)) { //shift one byte
9278 for(i=size-1;i>=MSB16;i--) {
9279 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9280 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9283 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9286 if (size > LSB+offr ){
9288 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9290 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9291 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9295 if(size > MSB16+offr){
9297 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9299 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9300 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9304 if(size > MSB24+offr){
9306 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9308 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9309 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9313 if(size > MSB32+offr){
9315 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9317 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9318 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9322 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9326 /*-----------------------------------------------------------------*/
9327 /* genlshFour - shift four byte by a known amount != 0 */
9328 /*-----------------------------------------------------------------*/
9329 static void genlshFour (operand *result, operand *left, int shCount)
9333 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9334 size = AOP_SIZE(result);
9336 /* if shifting more that 3 bytes */
9337 if (shCount >= 24 ) {
9340 /* lowest order of left goes to the highest
9341 order of the destination */
9342 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9344 movLeft2Result(left, LSB, result, MSB32);
9346 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9347 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9348 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9353 /* more than two bytes */
9354 else if ( shCount >= 16 ) {
9355 /* lower order two bytes goes to higher order two bytes */
9357 /* if some more remaining */
9359 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9361 movLeft2Result(left, MSB16, result, MSB32);
9362 movLeft2Result(left, LSB, result, MSB24);
9364 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9365 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9369 /* if more than 1 byte */
9370 else if ( shCount >= 8 ) {
9371 /* lower order three bytes goes to higher order three bytes */
9375 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9377 movLeft2Result(left, LSB, result, MSB16);
9379 else{ /* size = 4 */
9381 movLeft2Result(left, MSB24, result, MSB32);
9382 movLeft2Result(left, MSB16, result, MSB24);
9383 movLeft2Result(left, LSB, result, MSB16);
9384 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9386 else if(shCount == 1)
9387 shiftLLong(left, result, MSB16);
9389 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9390 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9391 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9392 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9397 /* 1 <= shCount <= 7 */
9398 else if(shCount <= 3)
9400 shiftLLong(left, result, LSB);
9401 while(--shCount >= 1)
9402 shiftLLong(result, result, LSB);
9404 /* 3 <= shCount <= 7, optimize */
9406 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9407 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9408 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9412 /*-----------------------------------------------------------------*/
9413 /* genLeftShiftLiteral - left shifting by known count */
9414 /*-----------------------------------------------------------------*/
9415 void pic16_genLeftShiftLiteral (operand *left,
9420 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9424 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9425 pic16_freeAsmop(right,NULL,ic,TRUE);
9427 pic16_aopOp(left,ic,FALSE);
9428 pic16_aopOp(result,ic,TRUE);
9430 size = getSize(operandType(result));
9433 pic16_emitcode("; shift left ","result %d, left %d",size,
9437 /* I suppose that the left size >= result size */
9440 movLeft2Result(left, size, result, size);
9444 else if(shCount >= (size * 8))
9446 pic16_aopPut(AOP(result),zero,size);
9450 genlshOne (result,left,shCount);
9455 genlshTwo (result,left,shCount);
9459 genlshFour (result,left,shCount);
9463 pic16_freeAsmop(left,NULL,ic,TRUE);
9464 pic16_freeAsmop(result,NULL,ic,TRUE);
9467 /*-----------------------------------------------------------------*
9468 * genMultiAsm - repeat assembly instruction for size of register.
9469 * if endian == 1, then the high byte (i.e base address + size of
9470 * register) is used first else the low byte is used first;
9471 *-----------------------------------------------------------------*/
9472 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9477 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9490 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9496 #if !(USE_GENERIC_SIGNED_SHIFT)
9497 /*-----------------------------------------------------------------*/
9498 /* genLeftShift - generates code for left shifting */
9499 /*-----------------------------------------------------------------*/
9500 static void genLeftShift (iCode *ic)
9502 operand *left,*right, *result;
9505 symbol *tlbl , *tlbl1;
9508 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9510 right = IC_RIGHT(ic);
9512 result = IC_RESULT(ic);
9514 pic16_aopOp(right,ic,FALSE);
9516 /* if the shift count is known then do it
9517 as efficiently as possible */
9518 if (AOP_TYPE(right) == AOP_LIT) {
9519 pic16_genLeftShiftLiteral (left,right,result,ic);
9523 /* shift count is unknown then we have to form
9524 * a loop. Get the loop count in WREG : Note: we take
9525 * only the lower order byte since shifting
9526 * more than 32 bits make no sense anyway, ( the
9527 * largest size of an object can be only 32 bits ) */
9529 pic16_aopOp(left,ic,FALSE);
9530 pic16_aopOp(result,ic,FALSE);
9532 /* now move the left to the result if they are not the
9533 * same, and if size > 1,
9534 * and if right is not same to result (!!!) -- VR */
9535 if (!pic16_sameRegs(AOP(left),AOP(result))
9536 && (AOP_SIZE(result) > 1)) {
9538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9540 size = AOP_SIZE(result);
9545 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9546 if (*l == '@' && (IS_AOP_PREG(result))) {
9548 pic16_emitcode("mov","a,%s",l);
9549 pic16_aopPut(AOP(result),"a",offset);
9553 /* we don't know if left is a literal or a register, take care -- VR */
9554 pic16_mov2f(AOP(result), AOP(left), offset);
9560 size = AOP_SIZE(result);
9562 /* if it is only one byte then */
9564 if(optimized_for_speed) {
9565 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9566 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9567 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9568 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9569 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9570 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9571 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9572 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9573 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9574 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9575 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9576 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9581 tlbl = newiTempLabel(NULL);
9584 /* this is already done, why change it? */
9585 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9586 pic16_mov2f(AOP(result), AOP(left), 0);
9590 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9591 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9592 pic16_emitpLabel(tlbl->key);
9593 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9594 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9596 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9601 if (pic16_sameRegs(AOP(left),AOP(result))) {
9603 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9605 tlbl = newiTempLabel(NULL);
9606 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9607 genMultiAsm(POC_RRCF, result, size,1);
9608 pic16_emitpLabel(tlbl->key);
9609 genMultiAsm(POC_RLCF, result, size,0);
9610 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9612 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9616 //tlbl = newiTempLabel(NULL);
9618 //tlbl1 = newiTempLabel(NULL);
9620 //reAdjustPreg(AOP(result));
9622 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9623 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9624 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9626 //pic16_emitcode("add","a,acc");
9627 //pic16_aopPut(AOP(result),"a",offset++);
9629 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9631 // pic16_emitcode("rlc","a");
9632 // pic16_aopPut(AOP(result),"a",offset++);
9634 //reAdjustPreg(AOP(result));
9636 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9637 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9640 tlbl = newiTempLabel(NULL);
9641 tlbl1= newiTempLabel(NULL);
9643 size = AOP_SIZE(result);
9646 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9648 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9650 /* offset should be 0, 1 or 3 */
9652 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9654 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9656 pic16_emitpcode(POC_MOVWF, pctemp);
9659 pic16_emitpLabel(tlbl->key);
9662 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9664 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9666 pic16_emitpcode(POC_DECFSZ, pctemp);
9667 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9668 pic16_emitpLabel(tlbl1->key);
9670 pic16_popReleaseTempReg(pctemp,1);
9674 pic16_freeAsmop (right,NULL,ic,TRUE);
9675 pic16_freeAsmop(left,NULL,ic,TRUE);
9676 pic16_freeAsmop(result,NULL,ic,TRUE);
9682 #error old code (left here for reference)
9683 /*-----------------------------------------------------------------*/
9684 /* genLeftShift - generates code for left shifting */
9685 /*-----------------------------------------------------------------*/
9686 static void genLeftShift (iCode *ic)
9688 operand *left,*right, *result;
9691 symbol *tlbl , *tlbl1;
9694 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9696 right = IC_RIGHT(ic);
9698 result = IC_RESULT(ic);
9700 pic16_aopOp(right,ic,FALSE);
9702 /* if the shift count is known then do it
9703 as efficiently as possible */
9704 if (AOP_TYPE(right) == AOP_LIT) {
9705 pic16_genLeftShiftLiteral (left,right,result,ic);
9709 /* shift count is unknown then we have to form
9710 a loop get the loop count in B : Note: we take
9711 only the lower order byte since shifting
9712 more that 32 bits make no sense anyway, ( the
9713 largest size of an object can be only 32 bits ) */
9716 pic16_aopOp(left,ic,FALSE);
9717 pic16_aopOp(result,ic,FALSE);
9719 /* now move the left to the result if they are not the
9721 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9722 AOP_SIZE(result) > 1) {
9724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9726 size = AOP_SIZE(result);
9729 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9730 if (*l == '@' && (IS_AOP_PREG(result))) {
9732 pic16_emitcode("mov","a,%s",l);
9733 pic16_aopPut(AOP(result),"a",offset);
9736 /* we don't know if left is a literal or a register, take care -- VR */
9737 pic16_mov2f(AOP(result), AOP(left), offset);
9743 size = AOP_SIZE(result);
9745 /* if it is only one byte then */
9747 if(optimized_for_speed) {
9748 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9749 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9750 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9751 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9753 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9754 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9755 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9756 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9757 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9758 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9759 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9762 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9764 tlbl = newiTempLabel(NULL);
9765 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9766 pic16_mov2f(AOP(result), AOP(left), 0);
9768 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9769 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9772 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9773 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9774 pic16_emitpLabel(tlbl->key);
9775 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9776 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9783 if (pic16_sameRegs(AOP(left),AOP(result))) {
9785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9787 tlbl = newiTempLabel(NULL);
9788 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9789 genMultiAsm(POC_RRCF, result, size,1);
9790 pic16_emitpLabel(tlbl->key);
9791 genMultiAsm(POC_RLCF, result, size,0);
9792 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9794 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9798 //tlbl = newiTempLabel(NULL);
9800 //tlbl1 = newiTempLabel(NULL);
9802 //reAdjustPreg(AOP(result));
9804 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9805 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9806 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9808 //pic16_emitcode("add","a,acc");
9809 //pic16_aopPut(AOP(result),"a",offset++);
9811 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9813 // pic16_emitcode("rlc","a");
9814 // pic16_aopPut(AOP(result),"a",offset++);
9816 //reAdjustPreg(AOP(result));
9818 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9819 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9822 tlbl = newiTempLabel(NULL);
9823 tlbl1= newiTempLabel(NULL);
9825 size = AOP_SIZE(result);
9828 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9830 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9832 /* offset should be 0, 1 or 3 */
9834 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9836 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9838 pic16_emitpcode(POC_MOVWF, pctemp);
9841 pic16_emitpLabel(tlbl->key);
9844 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9846 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9848 pic16_emitpcode(POC_DECFSZ, pctemp);
9849 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9850 pic16_emitpLabel(tlbl1->key);
9852 pic16_popReleaseTempReg(pctemp,1);
9856 pic16_freeAsmop (right,NULL,ic,TRUE);
9857 pic16_freeAsmop(left,NULL,ic,TRUE);
9858 pic16_freeAsmop(result,NULL,ic,TRUE);
9862 /*-----------------------------------------------------------------*/
9863 /* genrshOne - right shift a one byte quantity by known count */
9864 /*-----------------------------------------------------------------*/
9865 static void genrshOne (operand *result, operand *left,
9866 int shCount, int sign)
9868 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9869 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9872 /*-----------------------------------------------------------------*/
9873 /* genrshTwo - right shift two bytes by known amount != 0 */
9874 /*-----------------------------------------------------------------*/
9875 static void genrshTwo (operand *result,operand *left,
9876 int shCount, int sign)
9878 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9879 /* if shCount >= 8 */
9883 shiftR1Left2Result(left, MSB16, result, LSB,
9886 movLeft2Result(left, MSB16, result, LSB);
9888 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9891 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9892 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),MSB16));
9896 /* 1 <= shCount <= 7 */
9898 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9901 /*-----------------------------------------------------------------*/
9902 /* shiftRLong - shift right one long from left to result */
9903 /* offl = LSB or MSB16 */
9904 /*-----------------------------------------------------------------*/
9905 static void shiftRLong (operand *left, int offl,
9906 operand *result, int sign)
9908 int size = AOP_SIZE(result);
9909 int same = pic16_sameRegs(AOP(left),AOP(result));
9911 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9913 if (same && (offl == MSB16)) { //shift one byte right
9914 for(i=MSB16;i<size;i++) {
9915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9916 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9921 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9927 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9929 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9934 /* add sign of "a" */
9935 pic16_addSign(result, MSB32, sign);
9939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9953 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9956 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9957 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9962 /*-----------------------------------------------------------------*/
9963 /* genrshFour - shift four byte by a known amount != 0 */
9964 /*-----------------------------------------------------------------*/
9965 static void genrshFour (operand *result, operand *left,
9966 int shCount, int sign)
9968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9969 /* if shifting more that 3 bytes */
9970 if(shCount >= 24 ) {
9973 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9975 movLeft2Result(left, MSB32, result, LSB);
9977 pic16_addSign(result, MSB16, sign);
9979 else if(shCount >= 16){
9982 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9984 movLeft2Result(left, MSB24, result, LSB);
9985 movLeft2Result(left, MSB32, result, MSB16);
9987 pic16_addSign(result, MSB24, sign);
9989 else if(shCount >= 8){
9992 shiftRLong(left, MSB16, result, sign);
9993 else if(shCount == 0){
9994 movLeft2Result(left, MSB16, result, LSB);
9995 movLeft2Result(left, MSB24, result, MSB16);
9996 movLeft2Result(left, MSB32, result, MSB24);
9997 pic16_addSign(result, MSB32, sign);
9999 else{ //shcount >= 2
10000 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10001 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10002 /* the last shift is signed */
10003 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10004 pic16_addSign(result, MSB32, sign);
10007 else{ /* 1 <= shCount <= 7 */
10009 shiftRLong(left, LSB, result, sign);
10011 shiftRLong(result, LSB, result, sign);
10014 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10015 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10016 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10021 /*-----------------------------------------------------------------*/
10022 /* genRightShiftLiteral - right shifting by known count */
10023 /*-----------------------------------------------------------------*/
10024 static void genRightShiftLiteral (operand *left,
10030 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10031 int lsize,res_size;
10033 pic16_freeAsmop(right,NULL,ic,TRUE);
10035 pic16_aopOp(left,ic,FALSE);
10036 pic16_aopOp(result,ic,TRUE);
10038 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10041 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10045 lsize = pic16_getDataSize(left);
10046 res_size = pic16_getDataSize(result);
10047 /* test the LEFT size !!! */
10049 /* I suppose that the left size >= result size */
10051 assert (res_size <= lsize);
10052 while (res_size--) {
10053 pic16_mov2f (AOP(result), AOP(left), res_size);
10057 else if(shCount >= (lsize * 8)){
10059 if(res_size == 1) {
10060 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10062 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10068 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10069 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10077 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10082 switch (res_size) {
10084 genrshOne (result,left,shCount,sign);
10088 genrshTwo (result,left,shCount,sign);
10092 genrshFour (result,left,shCount,sign);
10100 pic16_freeAsmop(left,NULL,ic,TRUE);
10101 pic16_freeAsmop(result,NULL,ic,TRUE);
10104 #if !(USE_GENERIC_SIGNED_SHIFT)
10105 /*-----------------------------------------------------------------*/
10106 /* genSignedRightShift - right shift of signed number */
10107 /*-----------------------------------------------------------------*/
10108 static void genSignedRightShift (iCode *ic)
10110 operand *right, *left, *result;
10113 symbol *tlbl, *tlbl1 ;
10116 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10118 /* we do it the hard way put the shift count in b
10119 and loop thru preserving the sign */
10120 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10122 right = IC_RIGHT(ic);
10123 left = IC_LEFT(ic);
10124 result = IC_RESULT(ic);
10126 pic16_aopOp(right,ic,FALSE);
10127 pic16_aopOp(left,ic,FALSE);
10128 pic16_aopOp(result,ic,FALSE);
10131 if ( AOP_TYPE(right) == AOP_LIT) {
10132 genRightShiftLiteral (left,right,result,ic,1);
10135 /* shift count is unknown then we have to form
10136 a loop get the loop count in B : Note: we take
10137 only the lower order byte since shifting
10138 more that 32 bits make no sense anyway, ( the
10139 largest size of an object can be only 32 bits ) */
10141 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10142 //pic16_emitcode("inc","b");
10143 //pic16_freeAsmop (right,NULL,ic,TRUE);
10144 //pic16_aopOp(left,ic,FALSE);
10145 //pic16_aopOp(result,ic,FALSE);
10147 /* now move the left to the result if they are not the
10149 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10150 AOP_SIZE(result) > 1) {
10152 size = AOP_SIZE(result);
10156 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10157 if (*l == '@' && IS_AOP_PREG(result)) {
10159 pic16_emitcode("mov","a,%s",l);
10160 pic16_aopPut(AOP(result),"a",offset);
10162 pic16_aopPut(AOP(result),l,offset);
10164 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10165 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10171 /* mov the highest order bit to OVR */
10172 tlbl = newiTempLabel(NULL);
10173 tlbl1= newiTempLabel(NULL);
10175 size = AOP_SIZE(result);
10178 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10180 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10182 /* offset should be 0, 1 or 3 */
10183 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10185 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10187 pic16_emitpcode(POC_MOVWF, pctemp);
10190 pic16_emitpLabel(tlbl->key);
10192 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10193 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10196 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10199 pic16_emitpcode(POC_DECFSZ, pctemp);
10200 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10201 pic16_emitpLabel(tlbl1->key);
10203 pic16_popReleaseTempReg(pctemp,1);
10205 size = AOP_SIZE(result);
10207 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10208 pic16_emitcode("rlc","a");
10209 pic16_emitcode("mov","ov,c");
10210 /* if it is only one byte then */
10212 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10214 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10215 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10216 pic16_emitcode("mov","c,ov");
10217 pic16_emitcode("rrc","a");
10218 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10219 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10220 pic16_aopPut(AOP(result),"a",0);
10224 reAdjustPreg(AOP(result));
10225 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10227 pic16_emitcode("mov","c,ov");
10229 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10231 pic16_emitcode("rrc","a");
10232 pic16_aopPut(AOP(result),"a",offset--);
10234 reAdjustPreg(AOP(result));
10235 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10241 pic16_freeAsmop(left,NULL,ic,TRUE);
10242 pic16_freeAsmop(result,NULL,ic,TRUE);
10243 pic16_freeAsmop(right,NULL,ic,TRUE);
10247 #if !(USE_GENERIC_SIGNED_SHIFT)
10248 #warning This implementation of genRightShift() is incomplete!
10249 /*-----------------------------------------------------------------*/
10250 /* genRightShift - generate code for right shifting */
10251 /*-----------------------------------------------------------------*/
10252 static void genRightShift (iCode *ic)
10254 operand *right, *left, *result;
10258 symbol *tlbl, *tlbl1 ;
10260 /* if signed then we do it the hard way preserve the
10261 sign bit moving it inwards */
10262 letype = getSpec(operandType(IC_LEFT(ic)));
10263 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10265 if (!SPEC_USIGN(letype)) {
10266 genSignedRightShift (ic);
10270 /* signed & unsigned types are treated the same : i.e. the
10271 signed is NOT propagated inwards : quoting from the
10272 ANSI - standard : "for E1 >> E2, is equivalent to division
10273 by 2**E2 if unsigned or if it has a non-negative value,
10274 otherwise the result is implementation defined ", MY definition
10275 is that the sign does not get propagated */
10277 right = IC_RIGHT(ic);
10278 left = IC_LEFT(ic);
10279 result = IC_RESULT(ic);
10281 pic16_aopOp(right,ic,FALSE);
10283 /* if the shift count is known then do it
10284 as efficiently as possible */
10285 if (AOP_TYPE(right) == AOP_LIT) {
10286 genRightShiftLiteral (left,right,result,ic, 0);
10290 /* shift count is unknown then we have to form
10291 a loop get the loop count in B : Note: we take
10292 only the lower order byte since shifting
10293 more that 32 bits make no sense anyway, ( the
10294 largest size of an object can be only 32 bits ) */
10296 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10297 pic16_emitcode("inc","b");
10298 pic16_aopOp(left,ic,FALSE);
10299 pic16_aopOp(result,ic,FALSE);
10301 /* now move the left to the result if they are not the
10303 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10304 AOP_SIZE(result) > 1) {
10306 size = AOP_SIZE(result);
10309 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10310 if (*l == '@' && IS_AOP_PREG(result)) {
10312 pic16_emitcode("mov","a,%s",l);
10313 pic16_aopPut(AOP(result),"a",offset);
10315 pic16_aopPut(AOP(result),l,offset);
10320 tlbl = newiTempLabel(NULL);
10321 tlbl1= newiTempLabel(NULL);
10322 size = AOP_SIZE(result);
10325 /* if it is only one byte then */
10328 tlbl = newiTempLabel(NULL);
10329 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10330 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10334 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10335 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10336 pic16_emitpLabel(tlbl->key);
10337 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10338 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10340 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10345 reAdjustPreg(AOP(result));
10346 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10347 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10350 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10352 pic16_emitcode("rrc","a");
10353 pic16_aopPut(AOP(result),"a",offset--);
10355 reAdjustPreg(AOP(result));
10357 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10358 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10361 pic16_freeAsmop(left,NULL,ic,TRUE);
10362 pic16_freeAsmop (right,NULL,ic,TRUE);
10363 pic16_freeAsmop(result,NULL,ic,TRUE);
10367 #if (USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genGenericShift - generates code for left or right shifting */
10370 /*-----------------------------------------------------------------*/
10371 static void genGenericShift (iCode *ic, int isShiftLeft) {
10372 operand *left,*right, *result;
10374 int sign, signedCount;
10375 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10376 PIC_OPCODE pos_shift, neg_shift;
10380 right = IC_RIGHT(ic);
10381 left = IC_LEFT(ic);
10382 result = IC_RESULT(ic);
10384 pic16_aopOp(right,ic,FALSE);
10385 pic16_aopOp(left,ic,FALSE);
10386 pic16_aopOp(result,ic,TRUE);
10388 sign = !SPEC_USIGN(operandType (left));
10389 signedCount = !SPEC_USIGN(operandType (right));
10391 /* if the shift count is known then do it
10392 as efficiently as possible */
10393 if (AOP_TYPE(right) == AOP_LIT) {
10394 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10395 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10396 // we should modify right->aopu.aop_lit here!
10397 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10398 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10400 pic16_genLeftShiftLiteral (left,right,result,ic);
10402 genRightShiftLiteral (left,right,result,ic, sign);
10405 } // if (right is literal)
10407 /* shift count is unknown then we have to form a loop.
10408 * Note: we take only the lower order byte since shifting
10409 * more than 32 bits make no sense anyway, ( the
10410 * largest size of an object can be only 32 bits )
10411 * Note: we perform arithmetic shifts if the left operand is
10412 * signed and we do an (effective) right shift, i. e. we
10413 * shift in the sign bit from the left. */
10415 label_complete = newiTempLabel ( NULL );
10416 label_loop_pos = newiTempLabel ( NULL );
10417 label_loop_neg = NULL;
10418 label_negative = NULL;
10419 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10420 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10423 // additional labels needed
10424 label_loop_neg = newiTempLabel ( NULL );
10425 label_negative = newiTempLabel ( NULL );
10428 // copy source to result -- this will effectively truncate the left operand to the size of result!
10429 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10430 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10431 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10432 pic16_mov2f (AOP(result),AOP(left), offset);
10435 // if result is longer than left, fill with zeros (or sign)
10436 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10437 if (sign && AOP_SIZE(left) > 0) {
10438 // shift signed operand -- fill with sign
10439 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10440 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10441 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10442 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10446 // shift unsigned operand -- fill result with zeros
10447 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10451 } // if (size mismatch)
10453 pic16_mov2w (AOP(right), 0);
10454 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10455 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10458 // perform a shift by one (shift count is positive)
10459 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460 // 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])
10461 pic16_emitpLabel (label_loop_pos->key);
10463 if (sign && (pos_shift == POC_RRCF)) {
10464 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10467 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10468 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10469 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10471 // perform a shift by one (shift count is positive)
10472 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10473 // 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])
10474 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10475 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10477 pic16_emitpLabel (label_loop_pos->key);
10478 if (sign && (pos_shift == POC_RRCF)) {
10479 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10482 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10483 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10484 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10485 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10489 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10491 pic16_emitpLabel (label_negative->key);
10492 // perform a shift by -1 (shift count is negative)
10493 // 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)
10495 pic16_emitpLabel (label_loop_neg->key);
10496 if (sign && (neg_shift == POC_RRCF)) {
10497 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10500 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10501 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10502 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10503 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10504 } // if (signedCount)
10506 pic16_emitpLabel (label_complete->key);
10509 pic16_freeAsmop (right,NULL,ic,TRUE);
10510 pic16_freeAsmop(left,NULL,ic,TRUE);
10511 pic16_freeAsmop(result,NULL,ic,TRUE);
10514 static void genLeftShift (iCode *ic) {
10515 genGenericShift (ic, 1);
10518 static void genRightShift (iCode *ic) {
10519 genGenericShift (ic, 0);
10524 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10525 void pic16_loadFSR0(operand *op, int lit)
10527 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10528 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10530 assert (!OP_SYMBOL(op)->remat);
10531 // set up FSR0 with address of result
10532 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10533 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10537 /*-----------------------------------------------------------------*/
10538 /* genUnpackBits - generates code for unpacking bits */
10539 /*-----------------------------------------------------------------*/
10540 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10544 sym_link *etype, *letype;
10545 int blen=0, bstr=0;
10549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10550 etype = getSpec(operandType(result));
10551 letype = getSpec(operandType(left));
10553 // if(IS_BITFIELD(etype)) {
10554 blen = SPEC_BLEN(etype);
10555 bstr = SPEC_BSTR(etype);
10558 lbstr = SPEC_BSTR( letype );
10561 if((blen == 1) && (bstr < 8)) {
10562 /* it is a single bit, so use the appropriate bit instructions */
10563 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10565 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10567 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10568 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10569 /* workaround to reduce the extra lfsr instruction */
10570 pic16_emitpcode(POC_BTFSC,
10571 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10573 pic16_loadFSR0 (left, 0);
10574 pic16_emitpcode(POC_BTFSC,
10575 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10578 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10580 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10586 /* the following call to pic16_loadFSR0 is temporary until
10587 * optimization to handle single bit assignments is added
10588 * to the function. Until then use the old safe way! -- VR */
10590 if (OP_SYMBOL(left)->remat) {
10591 // access symbol directly
10592 pic16_mov2w (AOP(left), 0);
10594 pic16_loadFSR0( left, 0 );
10596 /* read the first byte */
10603 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10606 pic16_emitcode("clr","a");
10607 pic16_emitcode("movc","a","@a+dptr");
10613 /* if we have bitdisplacement then it fits */
10614 /* into this byte completely or if length is */
10615 /* less than a byte */
10616 if ((shCnt = SPEC_BSTR(etype)) ||
10617 (SPEC_BLEN(etype) <= 8)) {
10619 /* shift right acc */
10622 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10623 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10625 /* VR -- normally I would use the following, but since we use the hack,
10626 * to avoid the masking from AccRsh, why not mask it right now? */
10629 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10638 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10639 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10642 /* bit field did not fit in a byte */
10643 rlen = SPEC_BLEN(etype) - 8;
10644 pic16_aopPut(AOP(result),"a",offset++);
10651 pic16_emitcode("inc","%s",rname);
10652 pic16_emitcode("mov","a,@%s",rname);
10656 pic16_emitcode("inc","%s",rname);
10657 pic16_emitcode("movx","a,@%s",rname);
10661 pic16_emitcode("inc","dptr");
10662 pic16_emitcode("movx","a,@dptr");
10666 pic16_emitcode("clr","a");
10667 pic16_emitcode("inc","dptr");
10668 pic16_emitcode("movc","a","@a+dptr");
10672 pic16_emitcode("inc","dptr");
10673 pic16_emitcode("lcall","__gptrget");
10678 /* if we are done */
10682 pic16_aopPut(AOP(result),"a",offset++);
10687 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10688 pic16_aopPut(AOP(result),"a",offset);
10695 static void genDataPointerGet(operand *left,
10699 int size, offset = 0, leoffset=0 ;
10701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10702 pic16_aopOp(result, ic, TRUE);
10706 size = AOP_SIZE(result);
10707 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10711 /* The following tests may save a redudant movff instruction when
10712 * accessing unions */
10714 /* if they are the same */
10715 if (operandsEqu (left, result)) {
10716 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10722 /* if they are the same registers */
10723 if (pic16_sameRegs(AOP(left),AOP(result))) {
10724 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10730 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10731 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10732 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10739 if ( AOP_TYPE(left) == AOP_PCODE) {
10740 fprintf(stderr,"genDataPointerGet %s, %d\n",
10741 AOP(left)->aopu.pcop->name,
10742 (AOP(left)->aopu.pcop->type == PO_DIR)?
10743 PCOR(AOP(left)->aopu.pcop)->instance:
10744 PCOI(AOP(left)->aopu.pcop)->offset);
10748 if(AOP(left)->aopu.pcop->type == PO_DIR)
10749 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10751 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10754 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10756 // pic16_DumpOp("(result)",result);
10757 if(is_LitAOp(AOP(result))) {
10758 pic16_mov2w(AOP(left), offset); // patch 8
10759 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10761 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10762 pic16_popGet(AOP(left), offset), //patch 8
10763 pic16_popGet(AOP(result), offset)));
10771 pic16_freeAsmop(result,NULL,ic,TRUE);
10776 /*-----------------------------------------------------------------*/
10777 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10778 /*-----------------------------------------------------------------*/
10779 static void genNearPointerGet (operand *left,
10783 // asmop *aop = NULL;
10784 //regs *preg = NULL ;
10785 sym_link *rtype, *retype;
10786 sym_link *ltype = operandType(left);
10790 rtype = operandType(result);
10791 retype= getSpec(rtype);
10793 pic16_aopOp(left,ic,FALSE);
10795 // pic16_DumpOp("(left)",left);
10796 // pic16_DumpOp("(result)",result);
10798 /* if left is rematerialisable and
10799 * result is not bit variable type and
10800 * the left is pointer to data space i.e
10801 * lower 128 bytes of space */
10803 if (AOP_TYPE(left) == AOP_PCODE
10804 && !IS_BITFIELD(retype)
10805 && DCL_TYPE(ltype) == POINTER) {
10807 genDataPointerGet (left,result,ic);
10808 pic16_freeAsmop(left, NULL, ic, TRUE);
10812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10813 pic16_aopOp (result,ic,TRUE);
10815 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10818 if(IS_BITFIELD( retype )
10819 && (SPEC_BLEN(operandType(result))==1)
10823 int bitstrt, bytestrt;
10825 /* if this is bitfield of size 1, see if we are checking the value
10826 * of a single bit in an if-statement,
10827 * if yes, then don't generate usual code, but execute the
10828 * genIfx directly -- VR */
10832 /* CHECK: if next iCode is IFX
10833 * and current result operand is nextic's conditional operand
10834 * and current result operand live ranges ends at nextic's key number
10836 if((nextic->op == IFX)
10837 && (result == IC_COND(nextic))
10838 && (OP_LIVETO(result) == nextic->seq)
10839 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10841 /* everything is ok then */
10842 /* find a way to optimize the genIfx iCode */
10844 bytestrt = SPEC_BSTR(operandType(result))/8;
10845 bitstrt = SPEC_BSTR(operandType(result))%8;
10847 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10849 genIfxpCOpJump(nextic, jop);
10851 pic16_freeAsmop(left, NULL, ic, TRUE);
10852 pic16_freeAsmop(result, NULL, ic, TRUE);
10859 /* if the value is already in a pointer register
10860 * then don't need anything more */
10861 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10862 /* otherwise get a free pointer register */
10863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10868 /* if bitfield then unpack the bits */
10869 if (IS_BITFIELD(retype))
10870 genUnpackBits (result, left, NULL, POINTER);
10872 /* we have can just get the values */
10873 int size = AOP_SIZE(result);
10876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10878 pic16_loadFSR0( left, 0 );
10882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10883 pic16_popGet(AOP(result), offset++)));
10885 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10886 pic16_popGet(AOP(result), offset++)));
10892 /* now some housekeeping stuff */
10894 /* we had to allocate for this iCode */
10895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10896 pic16_freeAsmop(NULL,aop,ic,TRUE);
10898 /* we did not allocate which means left
10899 * already in a pointer register, then
10900 * if size > 0 && this could be used again
10901 * we have to point it back to where it
10903 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10904 if (AOP_SIZE(result) > 1
10905 && !OP_SYMBOL(left)->remat
10906 && ( OP_SYMBOL(left)->liveTo > ic->seq
10908 // int size = AOP_SIZE(result) - 1;
10910 // pic16_emitcode("dec","%s",rname);
10916 pic16_freeAsmop(left,NULL,ic,TRUE);
10917 pic16_freeAsmop(result,NULL,ic,TRUE);
10920 /*-----------------------------------------------------------------*/
10921 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10922 /*-----------------------------------------------------------------*/
10923 static void genPagedPointerGet (operand *left,
10928 regs *preg = NULL ;
10930 sym_link *rtype, *retype;
10932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10934 rtype = operandType(result);
10935 retype= getSpec(rtype);
10937 pic16_aopOp(left,ic,FALSE);
10939 /* if the value is already in a pointer register
10940 then don't need anything more */
10941 if (!AOP_INPREG(AOP(left))) {
10942 /* otherwise get a free pointer register */
10944 preg = getFreePtr(ic,&aop,FALSE);
10945 pic16_emitcode("mov","%s,%s",
10947 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10948 rname = preg->name ;
10950 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10952 pic16_freeAsmop(left,NULL,ic,TRUE);
10953 pic16_aopOp (result,ic,TRUE);
10955 /* if bitfield then unpack the bits */
10956 if (IS_BITFIELD(retype))
10957 genUnpackBits (result,left,rname,PPOINTER);
10959 /* we have can just get the values */
10960 int size = AOP_SIZE(result);
10965 pic16_emitcode("movx","a,@%s",rname);
10966 pic16_aopPut(AOP(result),"a",offset);
10971 pic16_emitcode("inc","%s",rname);
10975 /* now some housekeeping stuff */
10977 /* we had to allocate for this iCode */
10978 pic16_freeAsmop(NULL,aop,ic,TRUE);
10980 /* we did not allocate which means left
10981 already in a pointer register, then
10982 if size > 0 && this could be used again
10983 we have to point it back to where it
10985 if (AOP_SIZE(result) > 1 &&
10986 !OP_SYMBOL(left)->remat &&
10987 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10989 int size = AOP_SIZE(result) - 1;
10991 pic16_emitcode("dec","%s",rname);
10996 pic16_freeAsmop(result,NULL,ic,TRUE);
11001 /*-----------------------------------------------------------------*/
11002 /* genFarPointerGet - gget value from far space */
11003 /*-----------------------------------------------------------------*/
11004 static void genFarPointerGet (operand *left,
11005 operand *result, iCode *ic)
11008 sym_link *retype = getSpec(operandType(result));
11010 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11012 pic16_aopOp(left,ic,FALSE);
11014 /* if the operand is already in dptr
11015 then we do nothing else we move the value to dptr */
11016 if (AOP_TYPE(left) != AOP_STR) {
11017 /* if this is remateriazable */
11018 if (AOP_TYPE(left) == AOP_IMMD)
11019 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11020 else { /* we need to get it byte by byte */
11021 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11022 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11023 if (options.model == MODEL_FLAT24)
11025 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11029 /* so dptr know contains the address */
11030 pic16_freeAsmop(left,NULL,ic,TRUE);
11031 pic16_aopOp(result,ic,TRUE);
11033 /* if bit then unpack */
11034 if (IS_BITFIELD(retype))
11035 genUnpackBits(result,left,"dptr",FPOINTER);
11037 size = AOP_SIZE(result);
11041 pic16_emitcode("movx","a,@dptr");
11042 pic16_aopPut(AOP(result),"a",offset++);
11044 pic16_emitcode("inc","dptr");
11048 pic16_freeAsmop(result,NULL,ic,TRUE);
11052 /*-----------------------------------------------------------------*/
11053 /* genCodePointerGet - get value from code space */
11054 /*-----------------------------------------------------------------*/
11055 static void genCodePointerGet (operand *left,
11056 operand *result, iCode *ic)
11059 sym_link *retype = getSpec(operandType(result));
11061 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11063 pic16_aopOp(left,ic,FALSE);
11065 /* if the operand is already in dptr
11066 then we do nothing else we move the value to dptr */
11067 if (AOP_TYPE(left) != AOP_STR) {
11068 /* if this is remateriazable */
11069 if (AOP_TYPE(left) == AOP_IMMD)
11070 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11071 else { /* we need to get it byte by byte */
11072 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11073 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11074 if (options.model == MODEL_FLAT24)
11076 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11080 /* so dptr know contains the address */
11081 pic16_freeAsmop(left,NULL,ic,TRUE);
11082 pic16_aopOp(result,ic,FALSE);
11084 /* if bit then unpack */
11085 if (IS_BITFIELD(retype))
11086 genUnpackBits(result,left,"dptr",CPOINTER);
11088 size = AOP_SIZE(result);
11092 pic16_emitcode("clr","a");
11093 pic16_emitcode("movc","a,@a+dptr");
11094 pic16_aopPut(AOP(result),"a",offset++);
11096 pic16_emitcode("inc","dptr");
11100 pic16_freeAsmop(result,NULL,ic,TRUE);
11105 /*-----------------------------------------------------------------*/
11106 /* genGenPointerGet - gget value from generic pointer space */
11107 /*-----------------------------------------------------------------*/
11108 static void genGenPointerGet (operand *left,
11109 operand *result, iCode *ic)
11111 int size, offset, lit;
11112 sym_link *retype = getSpec(operandType(result));
11114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11115 pic16_aopOp(left,ic,FALSE);
11116 pic16_aopOp(result,ic,FALSE);
11117 size = AOP_SIZE(result);
11119 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11121 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11123 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11124 // load FSR0 from immediate
11125 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11127 // pic16_loadFSR0( left );
11132 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11134 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11141 else { /* we need to get it byte by byte */
11142 // set up FSR0 with address from left
11143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11144 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11150 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11152 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11159 /* if bit then unpack */
11160 if (IS_BITFIELD(retype))
11161 genUnpackBits(result,left,"BAD",GPOINTER);
11164 pic16_freeAsmop(left,NULL,ic,TRUE);
11165 pic16_freeAsmop(result,NULL,ic,TRUE);
11171 /*-----------------------------------------------------------------*/
11172 /* genGenPointerGet - gget value from generic pointer space */
11173 /*-----------------------------------------------------------------*/
11174 static void genGenPointerGet (operand *left,
11175 operand *result, iCode *ic)
11177 int size, offset, lit;
11178 sym_link *retype = getSpec(operandType(result));
11180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11181 pic16_aopOp(left,ic,FALSE);
11182 pic16_aopOp(result,ic,TRUE);
11183 size = AOP_SIZE(result);
11185 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11187 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11189 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11190 // load FSR0 from immediate
11191 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11193 werror(W_POSSBUG2, __FILE__, __LINE__);
11198 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11200 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11207 } else { /* we need to get it byte by byte */
11209 /* set up WREG:PRODL:FSR0L with address from left */
11210 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11211 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11212 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11214 pic16_callGenericPointerRW(0, size);
11216 assignResultValue(result, 1);
11221 /* if bit then unpack */
11222 if (IS_BITFIELD(retype))
11223 genUnpackBits(result,left,"BAD",GPOINTER);
11226 pic16_freeAsmop(left,NULL,ic,TRUE);
11227 pic16_freeAsmop(result,NULL,ic,TRUE);
11230 /*-----------------------------------------------------------------*/
11231 /* genConstPointerGet - get value from const generic pointer space */
11232 /*-----------------------------------------------------------------*/
11233 static void genConstPointerGet (operand *left,
11234 operand *result, iCode *ic)
11236 //sym_link *retype = getSpec(operandType(result));
11237 // symbol *albl = newiTempLabel(NULL); // patch 15
11238 // symbol *blbl = newiTempLabel(NULL); //
11239 // PIC_OPCODE poc; // patch 15
11243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11244 pic16_aopOp(left,ic,FALSE);
11245 pic16_aopOp(result,ic,TRUE);
11246 size = AOP_SIZE(result);
11248 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11250 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11252 // set up table pointer
11253 if( (AOP_TYPE(left) == AOP_PCODE)
11254 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11255 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11257 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11258 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11259 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11260 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11261 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11262 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11266 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11270 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11271 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11275 pic16_freeAsmop(left,NULL,ic,TRUE);
11276 pic16_freeAsmop(result,NULL,ic,TRUE);
11280 /*-----------------------------------------------------------------*/
11281 /* genPointerGet - generate code for pointer get */
11282 /*-----------------------------------------------------------------*/
11283 static void genPointerGet (iCode *ic)
11285 operand *left, *result ;
11286 sym_link *type, *etype;
11291 left = IC_LEFT(ic);
11292 result = IC_RESULT(ic) ;
11294 /* depending on the type of pointer we need to
11295 move it to the correct pointer register */
11296 type = operandType(left);
11297 etype = getSpec(type);
11300 if (IS_PTR_CONST(type))
11302 if (IS_CODEPTR(type))
11304 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11306 /* if left is of type of pointer then it is simple */
11307 if (IS_PTR(type) && !IS_FUNC(type->next))
11308 p_type = DCL_TYPE(type);
11310 /* we have to go by the storage class */
11311 p_type = PTR_TYPE(SPEC_OCLS(etype));
11313 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11315 if (SPEC_OCLS(etype)->codesp ) {
11316 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11317 //p_type = CPOINTER ;
11319 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11320 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11321 /*p_type = FPOINTER ;*/
11323 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11324 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11325 /* p_type = PPOINTER; */
11327 if (SPEC_OCLS(etype) == idata ) {
11328 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11329 /* p_type = IPOINTER; */
11331 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11332 /* p_type = POINTER ; */
11336 /* now that we have the pointer type we assign
11337 the pointer values */
11341 genNearPointerGet (left,result,ic);
11345 genPagedPointerGet(left,result,ic);
11349 genFarPointerGet (left,result,ic);
11353 genConstPointerGet (left,result,ic);
11354 //pic16_emitcodePointerGet (left,result,ic);
11359 if (IS_PTR_CONST(type))
11360 genConstPointerGet (left,result,ic);
11363 genGenPointerGet (left,result,ic);
11367 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11368 "genPointerGet: illegal pointer type");
11373 /*-----------------------------------------------------------------*/
11374 /* genPackBits - generates code for packed bit storage */
11375 /*-----------------------------------------------------------------*/
11376 static void genPackBits (sym_link *etype , operand *result,
11378 char *rname, int p_type)
11386 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11387 blen = SPEC_BLEN(etype);
11388 bstr = SPEC_BSTR(etype);
11390 retype = getSpec(operandType(right));
11392 if(AOP_TYPE(right) == AOP_LIT) {
11393 if((blen == 1) && (bstr < 8)) {
11395 /* it is a single bit, so use the appropriate bit instructions */
11397 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11399 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11400 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11401 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11402 /* workaround to reduce the extra lfsr instruction */
11404 pic16_emitpcode(POC_BSF,
11405 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11407 pic16_emitpcode(POC_BCF,
11408 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11411 pic16_loadFSR0(result, 0);
11413 pic16_emitpcode(POC_BSF,
11414 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11416 pic16_emitpcode(POC_BCF,
11417 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11423 /* move literal to W */
11424 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11427 if(IS_BITFIELD(retype)
11428 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11432 rblen = SPEC_BLEN( retype );
11433 rbstr = SPEC_BSTR( retype );
11436 if(IS_BITFIELD(etype)) {
11437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11438 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11440 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11443 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11445 if(IS_BITFIELD(etype)) {
11446 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11448 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11451 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11455 /* move right to W */
11456 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11459 /* if the bit length is less than or */
11460 /* it exactly fits a byte then */
11461 if((shCnt=SPEC_BSTR(etype))
11462 || SPEC_BLEN(etype) <= 8 ) {
11463 int fsr0_setup = 0;
11465 if (blen != 8 || bstr != 0) {
11466 // we need to combine the value with the old value
11467 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11469 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11470 SPEC_BSTR(etype), SPEC_BLEN(etype));
11472 /* shift left acc */
11475 /* using PRODH as a temporary register here */
11476 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11478 if (OP_SYMBOL(result)->remat) {
11479 // access symbol directly
11480 pic16_mov2w (AOP(result), 0);
11482 /* get old value */
11486 pic16_loadFSR0( result, 0 );
11488 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11489 // pic16_emitcode ("mov","b,a");
11490 // pic16_emitcode("mov","a,@%s",rname);
11494 if (AOP(result)->aopu.aop_reg[2]) {
11495 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11496 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11497 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11498 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11500 pic16_callGenericPointerRW(0, 1);
11502 // data pointer (just 2 byte given)
11503 pic16_loadFSR0( result, 0 );
11505 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11508 // warnings will be emitted below
11509 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11510 //werror(W_POSSBUG2, __FILE__, __LINE__);
11514 assert (0 && "invalid pointer type specified");
11519 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11520 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11521 (unsigned char)(0xff >> (8-bstr))) ));
11522 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11523 } // if (blen != 8 || bstr != 0)
11525 /* write new value back */
11526 if (OP_SYMBOL(result)->remat) {
11527 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11532 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11533 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11537 if (AOP(result)->aopu.aop_reg[2]) {
11538 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11539 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11540 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11541 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11542 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11544 pic16_callGenericPointerRW(1, 1);
11546 // data pointer (just 2 byte given)
11547 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11548 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11551 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11552 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11553 werror(W_POSSBUG2, __FILE__, __LINE__);
11557 assert (0 && "invalid pointer type specified");
11568 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11569 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11574 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11575 rLen = SPEC_BLEN(etype)-8;
11577 /* now generate for lengths greater than one byte */
11581 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11587 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11593 pic16_emitcode("movx","@dptr,a");
11598 DEBUGpic16_emitcode(";lcall","__gptrput");
11606 pic16_mov2w(AOP(right), offset++);
11609 /* last last was not complete */
11611 /* save the byte & read byte */
11614 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11615 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11620 pic16_emitcode ("mov","b,a");
11621 pic16_emitcode("movx","a,@dptr");
11625 pic16_emitcode ("push","b");
11626 pic16_emitcode ("push","acc");
11627 pic16_emitcode ("lcall","__gptrget");
11628 pic16_emitcode ("pop","b");
11634 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11635 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11636 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11637 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11638 // pic16_emitcode ("orl","a,b");
11641 // if (p_type == GPOINTER)
11642 // pic16_emitcode("pop","b");
11647 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11648 // pic16_emitcode("mov","@%s,a",rname);
11652 pic16_emitcode("movx","@dptr,a");
11656 DEBUGpic16_emitcode(";lcall","__gptrput");
11663 // pic16_freeAsmop(right, NULL, ic, TRUE);
11665 /*-----------------------------------------------------------------*/
11666 /* genDataPointerSet - remat pointer to data space */
11667 /*-----------------------------------------------------------------*/
11668 static void genDataPointerSet(operand *right,
11672 int size, offset = 0, resoffset=0 ;
11674 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11675 pic16_aopOp(right,ic,FALSE);
11677 size = AOP_SIZE(right);
11679 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11682 if ( AOP_TYPE(result) == AOP_PCODE) {
11683 fprintf(stderr,"genDataPointerSet %s, %d\n",
11684 AOP(result)->aopu.pcop->name,
11685 (AOP(result)->aopu.pcop->type == PO_DIR)?
11686 PCOR(AOP(result)->aopu.pcop)->instance:
11687 PCOI(AOP(result)->aopu.pcop)->offset);
11691 if(AOP(result)->aopu.pcop->type == PO_DIR)
11692 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11695 if (AOP_TYPE(right) == AOP_LIT) {
11698 if(!IS_FLOAT(operandType( right )))
11699 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11702 unsigned long lit_int;
11706 /* take care if literal is a float */
11707 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11708 lit = info.lit_int;
11711 lit = lit >> (8*offset);
11713 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11716 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11719 pic16_mov2w(AOP(right), offset);
11720 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11726 pic16_freeAsmop(right,NULL,ic,TRUE);
11731 /*-----------------------------------------------------------------*/
11732 /* genNearPointerSet - pic16_emitcode for near pointer put */
11733 /*-----------------------------------------------------------------*/
11734 static void genNearPointerSet (operand *right,
11740 sym_link *ptype = operandType(result);
11741 sym_link *resetype;
11743 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11744 retype= getSpec(operandType(right));
11745 resetype = getSpec(operandType(result));
11747 pic16_aopOp(result,ic,FALSE);
11749 /* if the result is rematerializable &
11750 * in data space & not a bit variable */
11752 /* and result is not a bit variable */
11753 if (AOP_TYPE(result) == AOP_PCODE
11754 // && AOP_TYPE(result) == AOP_IMMD
11755 && DCL_TYPE(ptype) == POINTER
11756 && !IS_BITFIELD(retype)
11757 && !IS_BITFIELD(resetype)) {
11759 genDataPointerSet (right,result,ic);
11760 pic16_freeAsmop(result,NULL,ic,TRUE);
11764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11765 pic16_aopOp(right,ic,FALSE);
11766 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11768 /* if the value is already in a pointer register
11769 * then don't need anything more */
11770 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11771 /* otherwise get a free pointer register */
11772 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11779 /* if bitfield then unpack the bits */
11780 if (IS_BITFIELD(resetype)) {
11781 genPackBits (resetype, result, right, NULL, POINTER);
11783 /* we have can just get the values */
11784 int size = AOP_SIZE(right);
11787 pic16_loadFSR0(result, 0);
11789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11791 if (AOP_TYPE(right) == AOP_LIT) {
11792 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11794 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11796 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11798 } else { // no literal
11800 pic16_emitpcode(POC_MOVFF,
11801 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11802 pic16_popCopyReg(&pic16_pc_postinc0)));
11804 pic16_emitpcode(POC_MOVFF,
11805 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11806 pic16_popCopyReg(&pic16_pc_indf0)));
11813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11814 /* now some housekeeping stuff */
11816 /* we had to allocate for this iCode */
11817 pic16_freeAsmop(NULL,aop,ic,TRUE);
11819 /* we did not allocate which means left
11820 * already in a pointer register, then
11821 * if size > 0 && this could be used again
11822 * we have to point it back to where it
11824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11825 if (AOP_SIZE(right) > 1
11826 && !OP_SYMBOL(result)->remat
11827 && ( OP_SYMBOL(result)->liveTo > ic->seq
11830 int size = AOP_SIZE(right) - 1;
11833 pic16_emitcode("decf","fsr0,f");
11834 //pic16_emitcode("dec","%s",rname);
11838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11841 pic16_freeAsmop(right,NULL,ic,TRUE);
11842 pic16_freeAsmop(result,NULL,ic,TRUE);
11845 /*-----------------------------------------------------------------*/
11846 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11847 /*-----------------------------------------------------------------*/
11848 static void genPagedPointerSet (operand *right,
11853 regs *preg = NULL ;
11857 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11859 retype= getSpec(operandType(right));
11861 pic16_aopOp(result,ic,FALSE);
11863 /* if the value is already in a pointer register
11864 then don't need anything more */
11865 if (!AOP_INPREG(AOP(result))) {
11866 /* otherwise get a free pointer register */
11868 preg = getFreePtr(ic,&aop,FALSE);
11869 pic16_emitcode("mov","%s,%s",
11871 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11872 rname = preg->name ;
11874 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11876 pic16_freeAsmop(result,NULL,ic,TRUE);
11877 pic16_aopOp (right,ic,FALSE);
11879 /* if bitfield then unpack the bits */
11880 if (IS_BITFIELD(retype))
11881 genPackBits (retype,result,right,rname,PPOINTER);
11883 /* we have can just get the values */
11884 int size = AOP_SIZE(right);
11888 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11891 pic16_emitcode("movx","@%s,a",rname);
11894 pic16_emitcode("inc","%s",rname);
11900 /* now some housekeeping stuff */
11902 /* we had to allocate for this iCode */
11903 pic16_freeAsmop(NULL,aop,ic,TRUE);
11905 /* we did not allocate which means left
11906 already in a pointer register, then
11907 if size > 0 && this could be used again
11908 we have to point it back to where it
11910 if (AOP_SIZE(right) > 1 &&
11911 !OP_SYMBOL(result)->remat &&
11912 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11914 int size = AOP_SIZE(right) - 1;
11916 pic16_emitcode("dec","%s",rname);
11921 pic16_freeAsmop(right,NULL,ic,TRUE);
11926 /*-----------------------------------------------------------------*/
11927 /* genFarPointerSet - set value from far space */
11928 /*-----------------------------------------------------------------*/
11929 static void genFarPointerSet (operand *right,
11930 operand *result, iCode *ic)
11933 sym_link *retype = getSpec(operandType(right));
11935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11936 pic16_aopOp(result,ic,FALSE);
11938 /* if the operand is already in dptr
11939 then we do nothing else we move the value to dptr */
11940 if (AOP_TYPE(result) != AOP_STR) {
11941 /* if this is remateriazable */
11942 if (AOP_TYPE(result) == AOP_IMMD)
11943 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11944 else { /* we need to get it byte by byte */
11945 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11946 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11947 if (options.model == MODEL_FLAT24)
11949 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11953 /* so dptr know contains the address */
11954 pic16_freeAsmop(result,NULL,ic,TRUE);
11955 pic16_aopOp(right,ic,FALSE);
11957 /* if bit then unpack */
11958 if (IS_BITFIELD(retype))
11959 genPackBits(retype,result,right,"dptr",FPOINTER);
11961 size = AOP_SIZE(right);
11965 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11967 pic16_emitcode("movx","@dptr,a");
11969 pic16_emitcode("inc","dptr");
11973 pic16_freeAsmop(right,NULL,ic,TRUE);
11976 /*-----------------------------------------------------------------*/
11977 /* genGenPointerSet - set value from generic pointer space */
11978 /*-----------------------------------------------------------------*/
11980 static void genGenPointerSet (operand *right,
11981 operand *result, iCode *ic)
11983 int i, size, offset, lit;
11984 sym_link *retype = getSpec(operandType(right));
11986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11988 pic16_aopOp(result,ic,FALSE);
11989 pic16_aopOp(right,ic,FALSE);
11990 size = AOP_SIZE(right);
11993 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11995 /* if the operand is already in dptr
11996 then we do nothing else we move the value to dptr */
11997 if (AOP_TYPE(result) != AOP_STR) {
11998 /* if this is remateriazable */
11999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12000 // WARNING: anythig until "else" is untested!
12001 if (AOP_TYPE(result) == AOP_IMMD) {
12002 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12003 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12004 // load FSR0 from immediate
12005 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12009 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12011 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12017 else { /* we need to get it byte by byte */
12018 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12019 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12021 // set up FSR0 with address of result
12022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12025 /* hack hack! see if this the FSR. If so don't load W */
12026 if(AOP_TYPE(right) != AOP_ACC) {
12028 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12030 if(AOP_TYPE(right) == AOP_LIT)
12033 // note: pic16_popGet handles sign extension
12034 for(i=0;i<size;i++) {
12035 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12037 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12039 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12044 for(i=0;i<size;i++) {
12046 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12047 pic16_popCopyReg(&pic16_pc_postinc0)));
12049 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12050 pic16_popCopyReg(&pic16_pc_indf0)));
12056 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12057 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12059 } // if (AOP_TYPE(result) != AOP_IMMD)
12061 } // if (AOP_TYPE(result) != AOP_STR)
12062 /* so dptr know contains the address */
12065 /* if bit then unpack */
12066 if (IS_BITFIELD(retype))
12067 genPackBits(retype,result,right,"dptr",GPOINTER);
12069 size = AOP_SIZE(right);
12072 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12074 // set up FSR0 with address of result
12075 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12076 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12079 if (AOP_TYPE(right) == AOP_LIT) {
12080 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12082 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12084 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12086 } else { // no literal
12088 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12098 pic16_freeAsmop(right,NULL,ic,TRUE);
12099 pic16_freeAsmop(result,NULL,ic,TRUE);
12103 static void genGenPointerSet (operand *right,
12104 operand *result, iCode *ic)
12107 sym_link *retype = getSpec(operandType(right));
12109 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12111 pic16_aopOp(result,ic,FALSE);
12112 pic16_aopOp(right,ic,FALSE);
12113 size = AOP_SIZE(right);
12115 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12118 /* if bit then unpack */
12119 if (IS_BITFIELD(retype)) {
12120 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12121 genPackBits(retype,result,right,"dptr",GPOINTER);
12125 size = AOP_SIZE(right);
12127 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12131 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12133 /* value of right+0 is placed on stack, which will be retrieved
12134 * by the support function this restoring the stack. The important
12135 * thing is that there is no need to manually restore stack pointer
12137 pushaop(AOP(right), 0);
12138 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12139 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12140 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12141 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12143 /* load address to write to in WREG:FSR0H:FSR0L */
12144 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12145 pic16_popCopyReg(&pic16_pc_fsr0l)));
12146 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12147 pic16_popCopyReg(&pic16_pc_prodl)));
12148 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12150 pic16_callGenericPointerRW(1, size);
12153 pic16_freeAsmop(right,NULL,ic,TRUE);
12154 pic16_freeAsmop(result,NULL,ic,TRUE);
12157 /*-----------------------------------------------------------------*/
12158 /* genPointerSet - stores the value into a pointer location */
12159 /*-----------------------------------------------------------------*/
12160 static void genPointerSet (iCode *ic)
12162 operand *right, *result ;
12163 sym_link *type, *etype;
12168 right = IC_RIGHT(ic);
12169 result = IC_RESULT(ic) ;
12171 /* depending on the type of pointer we need to
12172 move it to the correct pointer register */
12173 type = operandType(result);
12174 etype = getSpec(type);
12175 /* if left is of type of pointer then it is simple */
12176 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12177 p_type = DCL_TYPE(type);
12180 /* we have to go by the storage class */
12181 p_type = PTR_TYPE(SPEC_OCLS(etype));
12183 /* if (SPEC_OCLS(etype)->codesp ) { */
12184 /* p_type = CPOINTER ; */
12187 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12188 /* p_type = FPOINTER ; */
12190 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12191 /* p_type = PPOINTER ; */
12193 /* if (SPEC_OCLS(etype) == idata ) */
12194 /* p_type = IPOINTER ; */
12196 /* p_type = POINTER ; */
12199 /* now that we have the pointer type we assign
12200 the pointer values */
12204 genNearPointerSet (right,result,ic);
12208 genPagedPointerSet (right,result,ic);
12212 genFarPointerSet (right,result,ic);
12216 genGenPointerSet (right,result,ic);
12220 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12221 "genPointerSet: illegal pointer type");
12225 /*-----------------------------------------------------------------*/
12226 /* genIfx - generate code for Ifx statement */
12227 /*-----------------------------------------------------------------*/
12228 static void genIfx (iCode *ic, iCode *popIc)
12230 operand *cond = IC_COND(ic);
12235 pic16_aopOp(cond,ic,FALSE);
12237 /* get the value into acc */
12238 if (AOP_TYPE(cond) != AOP_CRY)
12239 pic16_toBoolean(cond);
12242 /* the result is now in the accumulator */
12243 pic16_freeAsmop(cond,NULL,ic,TRUE);
12245 /* if there was something to be popped then do it */
12249 /* if the condition is a bit variable */
12250 if (isbit && IS_ITEMP(cond) &&
12252 genIfxJump(ic,"c");
12253 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12255 if (isbit && !IS_ITEMP(cond))
12256 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12258 genIfxJump(ic,"a");
12263 /*-----------------------------------------------------------------*/
12264 /* genAddrOf - generates code for address of */
12265 /*-----------------------------------------------------------------*/
12266 static void genAddrOf (iCode *ic)
12268 operand *result, *left;
12270 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12271 pCodeOp *pcop0, *pcop1, *pcop2;
12275 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12277 sym = OP_SYMBOL( IC_LEFT(ic) );
12280 /* get address of symbol on stack */
12281 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12283 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12284 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12287 // operands on stack are accessible via "FSR2 + index" with index
12288 // starting at 2 for arguments and growing from 0 downwards for
12289 // local variables (index == 0 is not assigned so we add one here)
12291 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12293 assert (soffs < 0);
12296 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12297 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12298 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12299 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12300 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12301 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12302 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12308 // if(pic16_debug_verbose) {
12309 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12310 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12313 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12314 size = AOP_SIZE(IC_RESULT(ic));
12316 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12317 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12318 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12321 pic16_emitpcode(POC_MOVLW, pcop0);
12322 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12323 pic16_emitpcode(POC_MOVLW, pcop1);
12324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12325 pic16_emitpcode(POC_MOVLW, pcop2);
12326 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12329 pic16_emitpcode(POC_MOVLW, pcop0);
12330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12331 pic16_emitpcode(POC_MOVLW, pcop1);
12332 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12334 pic16_emitpcode(POC_MOVLW, pcop0);
12335 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12338 pic16_freeAsmop(left, NULL, ic, FALSE);
12340 pic16_freeAsmop(result,NULL,ic,TRUE);
12345 /*-----------------------------------------------------------------*/
12346 /* genFarFarAssign - assignment when both are in far space */
12347 /*-----------------------------------------------------------------*/
12348 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12350 int size = AOP_SIZE(right);
12353 /* first push the right side on to the stack */
12355 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12357 pic16_emitcode ("push","acc");
12360 pic16_freeAsmop(right,NULL,ic,FALSE);
12361 /* now assign DPTR to result */
12362 pic16_aopOp(result,ic,FALSE);
12363 size = AOP_SIZE(result);
12365 pic16_emitcode ("pop","acc");
12366 pic16_aopPut(AOP(result),"a",--offset);
12368 pic16_freeAsmop(result,NULL,ic,FALSE);
12373 /*-----------------------------------------------------------------*/
12374 /* genAssign - generate code for assignment */
12375 /*-----------------------------------------------------------------*/
12376 static void genAssign (iCode *ic)
12378 operand *result, *right;
12379 int size, offset,know_W;
12380 unsigned long lit = 0L;
12382 result = IC_RESULT(ic);
12383 right = IC_RIGHT(ic) ;
12387 /* if they are the same */
12388 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12391 /* reversed order operands are aopOp'ed so that result operand
12392 * is effective in case right is a stack symbol. This maneauver
12393 * allows to use the _G.resDirect flag later */
12394 pic16_aopOp(result,ic,TRUE);
12395 pic16_aopOp(right,ic,FALSE);
12397 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12399 /* if they are the same registers */
12400 if (pic16_sameRegs(AOP(right),AOP(result)))
12403 /* if the result is a bit */
12404 if (AOP_TYPE(result) == AOP_CRY) {
12405 /* if the right size is a literal then
12406 we know what the value is */
12407 if (AOP_TYPE(right) == AOP_LIT) {
12409 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12410 pic16_popGet(AOP(result),0));
12412 if (((int) operandLitValue(right)))
12413 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12414 AOP(result)->aopu.aop_dir,
12415 AOP(result)->aopu.aop_dir);
12417 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12418 AOP(result)->aopu.aop_dir,
12419 AOP(result)->aopu.aop_dir);
12423 /* the right is also a bit variable */
12424 if (AOP_TYPE(right) == AOP_CRY) {
12425 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12426 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12427 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12429 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12430 AOP(result)->aopu.aop_dir,
12431 AOP(result)->aopu.aop_dir);
12432 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12433 AOP(right)->aopu.aop_dir,
12434 AOP(right)->aopu.aop_dir);
12435 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12436 AOP(result)->aopu.aop_dir,
12437 AOP(result)->aopu.aop_dir);
12441 /* we need to or */
12442 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12443 pic16_toBoolean(right);
12445 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12446 //pic16_aopPut(AOP(result),"a",0);
12450 /* bit variables done */
12452 size = AOP_SIZE(result);
12455 if(AOP_TYPE(right) == AOP_LIT) {
12456 if(!IS_FLOAT(operandType( right )))
12457 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12460 unsigned long lit_int;
12464 /* take care if literal is a float */
12465 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12466 lit = info.lit_int;
12470 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12471 // sizeof(unsigned long int), sizeof(float));
12474 if (AOP_TYPE(right) == AOP_REG) {
12475 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12477 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12482 /* when do we have to read the program memory?
12483 * - if right itself is a symbol in code space
12484 * (we don't care what it points to if it's a pointer)
12485 * - AND right is not a function (we would want its address)
12487 if(AOP_TYPE(right) != AOP_LIT
12488 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12489 && !IS_FUNC(OP_SYM_TYPE(right))
12490 && !IS_ITEMP(right))
12492 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12493 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12495 // set up table pointer
12496 if(is_LitOp(right)) {
12497 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12498 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12499 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12500 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12501 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12502 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12503 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12505 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12506 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12507 pic16_popCopyReg(&pic16_pc_tblptrl)));
12508 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12509 pic16_popCopyReg(&pic16_pc_tblptrh)));
12510 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12511 pic16_popCopyReg(&pic16_pc_tblptru)));
12514 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12515 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12517 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12518 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12519 pic16_popGet(AOP(result),offset)));
12523 /* FIXME: for pointers we need to extend differently (according
12524 * to pointer type DATA/CODE/EEPROM/... :*/
12525 size = getSize(OP_SYM_TYPE(right));
12526 if(AOP_SIZE(result) > size) {
12527 size = AOP_SIZE(result) - size;
12529 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12539 /* VR - What is this?! */
12540 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12542 if(aopIdx(AOP(result),0) == 4) {
12544 /* this is a workaround to save value of right into wreg too,
12545 * value of wreg is going to be used later */
12546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12547 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12552 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12558 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12559 if(AOP_TYPE(right) == AOP_LIT) {
12561 if(know_W != (lit&0xff))
12562 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12564 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12566 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12570 } else if (AOP_TYPE(right) == AOP_CRY) {
12571 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12573 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12574 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12575 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12577 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12578 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12579 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12581 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12583 if(!_G.resDirect) /* use this aopForSym feature */
12584 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12591 pic16_freeAsmop (right,NULL,ic,FALSE);
12592 pic16_freeAsmop (result,NULL,ic,TRUE);
12595 /*-----------------------------------------------------------------*/
12596 /* genJumpTab - generates code for jump table */
12597 /*-----------------------------------------------------------------*/
12598 static void genJumpTab (iCode *ic)
12603 pCodeOp *jt_offs_hi;
12608 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12609 /* get the condition into accumulator */
12610 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12612 /* multiply by three */
12613 pic16_emitcode("add","a,acc");
12614 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12616 jtab = newiTempLabel(NULL);
12617 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12618 pic16_emitcode("jmp","@a+dptr");
12619 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12622 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12623 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12625 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12626 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12627 pic16_emitpLabel(jtab->key);
12631 jt_offs = pic16_popGetTempReg(0);
12632 jt_offs_hi = pic16_popGetTempReg(1);
12633 jt_label = pic16_popGetLabel (jtab->key);
12634 //fprintf (stderr, "Creating jump table...\n");
12636 // calculate offset into jump table (idx * sizeof (GOTO))
12637 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12638 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12639 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12640 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12641 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12642 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12643 pic16_emitpcode(POC_MOVWF , jt_offs);
12645 // prepare PCLATx (set to first entry in jump table)
12646 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12647 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12648 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12649 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12650 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12652 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12653 pic16_emitpcode(POC_ADDWF , jt_offs);
12654 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12655 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12657 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12659 // release temporaries and prepare jump into table (new PCL --> WREG)
12660 pic16_emitpcode(POC_MOVFW , jt_offs);
12661 pic16_popReleaseTempReg (jt_offs_hi, 1);
12662 pic16_popReleaseTempReg (jt_offs, 0);
12664 // jump into the table
12665 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12667 pic16_emitpLabelFORCE(jtab->key);
12670 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12671 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12673 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12674 /* now generate the jump labels */
12675 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12676 jtab = setNextItem(IC_JTLABELS(ic))) {
12677 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12678 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12681 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12685 /*-----------------------------------------------------------------*/
12686 /* genMixedOperation - gen code for operators between mixed types */
12687 /*-----------------------------------------------------------------*/
12689 TSD - Written for the PIC port - but this unfortunately is buggy.
12690 This routine is good in that it is able to efficiently promote
12691 types to different (larger) sizes. Unfortunately, the temporary
12692 variables that are optimized out by this routine are sometimes
12693 used in other places. So until I know how to really parse the
12694 iCode tree, I'm going to not be using this routine :(.
12696 static int genMixedOperation (iCode *ic)
12699 operand *result = IC_RESULT(ic);
12700 sym_link *ctype = operandType(IC_LEFT(ic));
12701 operand *right = IC_RIGHT(ic);
12707 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12709 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12715 nextright = IC_RIGHT(nextic);
12716 nextleft = IC_LEFT(nextic);
12717 nextresult = IC_RESULT(nextic);
12719 pic16_aopOp(right,ic,FALSE);
12720 pic16_aopOp(result,ic,FALSE);
12721 pic16_aopOp(nextright, nextic, FALSE);
12722 pic16_aopOp(nextleft, nextic, FALSE);
12723 pic16_aopOp(nextresult, nextic, FALSE);
12725 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12727 operand *t = right;
12731 pic16_emitcode(";remove right +","");
12733 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12735 operand *t = right;
12739 pic16_emitcode(";remove left +","");
12743 big = AOP_SIZE(nextleft);
12744 small = AOP_SIZE(nextright);
12746 switch(nextic->op) {
12749 pic16_emitcode(";optimize a +","");
12750 /* if unsigned or not an integral type */
12751 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12752 pic16_emitcode(";add a bit to something","");
12755 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12757 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12758 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12759 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12761 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12769 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12770 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12771 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12774 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12776 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12777 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12778 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12779 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12780 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12783 pic16_emitcode("rlf","known_zero,w");
12790 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12791 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12792 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12794 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12804 pic16_freeAsmop(right,NULL,ic,TRUE);
12805 pic16_freeAsmop(result,NULL,ic,TRUE);
12806 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12807 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12809 nextic->generated = 1;
12816 /*-----------------------------------------------------------------*/
12817 /* genCast - gen code for casting */
12818 /*-----------------------------------------------------------------*/
12819 static void genCast (iCode *ic)
12821 operand *result = IC_RESULT(ic);
12822 sym_link *ctype = operandType(IC_LEFT(ic));
12823 sym_link *rtype = operandType(IC_RIGHT(ic));
12824 sym_link *restype = operandType(IC_RESULT(ic));
12825 operand *right = IC_RIGHT(ic);
12831 /* if they are equivalent then do nothing */
12832 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12835 pic16_aopOp(result,ic,FALSE);
12836 pic16_aopOp(right,ic,FALSE) ;
12838 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12841 /* if the result is a bit */
12842 if (AOP_TYPE(result) == AOP_CRY) {
12844 /* if the right size is a literal then
12845 * we know what the value is */
12846 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12848 if (AOP_TYPE(right) == AOP_LIT) {
12849 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12850 pic16_popGet(AOP(result),0));
12852 if (((int) operandLitValue(right)))
12853 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12854 AOP(result)->aopu.aop_dir,
12855 AOP(result)->aopu.aop_dir);
12857 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12858 AOP(result)->aopu.aop_dir,
12859 AOP(result)->aopu.aop_dir);
12863 /* the right is also a bit variable */
12864 if (AOP_TYPE(right) == AOP_CRY) {
12866 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12868 pic16_emitcode("clrc","");
12869 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12870 AOP(right)->aopu.aop_dir,
12871 AOP(right)->aopu.aop_dir);
12872 pic16_aopPut(AOP(result),"c",0);
12876 /* we need to or */
12877 if (AOP_TYPE(right) == AOP_REG) {
12878 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12879 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12880 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12882 pic16_toBoolean(right);
12883 pic16_aopPut(AOP(result),"a",0);
12887 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12890 size = AOP_SIZE(result);
12892 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12894 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12895 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12896 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12899 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12904 if(IS_BITFIELD(getSpec(restype))
12905 && IS_BITFIELD(getSpec(rtype))) {
12906 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12909 /* if they are the same size : or less */
12910 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12912 /* if they are in the same place */
12913 if (pic16_sameRegs(AOP(right),AOP(result)))
12916 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12918 if (IS_PTR_CONST(rtype))
12920 if (IS_CODEPTR(rtype))
12922 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12925 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12927 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12929 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12932 if(AOP_TYPE(right) == AOP_IMMD) {
12933 pCodeOp *pcop0, *pcop1, *pcop2;
12934 symbol *sym = OP_SYMBOL( right );
12936 size = AOP_SIZE(result);
12938 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12940 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12942 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12945 pic16_emitpcode(POC_MOVLW, pcop0);
12946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12947 pic16_emitpcode(POC_MOVLW, pcop1);
12948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12949 pic16_emitpcode(POC_MOVLW, pcop2);
12950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12953 pic16_emitpcode(POC_MOVLW, pcop0);
12954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12955 pic16_emitpcode(POC_MOVLW, pcop1);
12956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12958 pic16_emitpcode(POC_MOVLW, pcop0);
12959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12963 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12964 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12965 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12966 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12968 if(AOP_SIZE(result) <2)
12969 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12971 /* if they in different places then copy */
12972 size = AOP_SIZE(result);
12975 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12983 /* if the result is of type pointer */
12984 if (IS_PTR(ctype)) {
12986 sym_link *type = operandType(right);
12987 sym_link *etype = getSpec(type);
12989 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12991 /* pointer to generic pointer */
12992 if (IS_GENPTR(ctype)) {
12996 p_type = DCL_TYPE(type);
12998 /* we have to go by the storage class */
12999 p_type = PTR_TYPE(SPEC_OCLS(etype));
13001 /* if (SPEC_OCLS(etype)->codesp ) */
13002 /* p_type = CPOINTER ; */
13004 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13005 /* p_type = FPOINTER ; */
13007 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13008 /* p_type = PPOINTER; */
13010 /* if (SPEC_OCLS(etype) == idata ) */
13011 /* p_type = IPOINTER ; */
13013 /* p_type = POINTER ; */
13016 /* the first two bytes are known */
13017 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13018 size = GPTRSIZE - 1;
13021 if(offset < AOP_SIZE(right)) {
13022 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13023 pic16_mov2f(AOP(result), AOP(right), offset);
13025 if ((AOP_TYPE(right) == AOP_PCODE) &&
13026 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13027 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13031 pic16_aopPut(AOP(result),
13032 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13037 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13040 /* the last byte depending on type */
13044 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13045 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13046 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13050 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13054 pic16_emitcode(";BUG!? ","%d",__LINE__);
13058 pic16_emitcode(";BUG!? ","%d",__LINE__);
13063 if (GPTRSIZE > AOP_SIZE(right)) {
13064 // assume data pointer... THIS MIGHT BE WRONG!
13065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13068 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13073 /* this should never happen */
13074 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13075 "got unknown pointer type");
13078 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13084 /* just copy the pointers */
13085 size = AOP_SIZE(result);
13088 pic16_aopPut(AOP(result),
13089 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13098 /* so we now know that the size of destination is greater
13099 than the size of the source.
13100 Now, if the next iCode is an operator then we might be
13101 able to optimize the operation without performing a cast.
13103 if(genMixedOperation(ic))
13106 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13108 /* we move to result for the size of source */
13109 size = AOP_SIZE(right);
13114 pic16_mov2f(AOP(result), AOP(right), offset);
13118 /* now depending on the sign of the destination */
13119 size = AOP_SIZE(result) - AOP_SIZE(right);
13120 /* if unsigned or not an integral type */
13121 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13123 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13125 /* we need to extend the sign :( */
13128 /* Save one instruction of casting char to int */
13129 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13130 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13131 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13133 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13136 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13138 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13140 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13143 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13148 pic16_freeAsmop(right,NULL,ic,TRUE);
13149 pic16_freeAsmop(result,NULL,ic,TRUE);
13153 /*-----------------------------------------------------------------*/
13154 /* genDjnz - generate decrement & jump if not zero instrucion */
13155 /*-----------------------------------------------------------------*/
13156 static int genDjnz (iCode *ic, iCode *ifx)
13158 symbol *lbl, *lbl1;
13159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13164 /* if the if condition has a false label
13165 then we cannot save */
13169 /* if the minus is not of the form
13171 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13172 !IS_OP_LITERAL(IC_RIGHT(ic)))
13175 if (operandLitValue(IC_RIGHT(ic)) != 1)
13178 /* if the size of this greater than one then no
13180 if (getSize(operandType(IC_RESULT(ic))) > 1)
13183 /* otherwise we can save BIG */
13184 lbl = newiTempLabel(NULL);
13185 lbl1= newiTempLabel(NULL);
13187 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13189 if (IS_AOP_PREG(IC_RESULT(ic))) {
13190 pic16_emitcode("dec","%s",
13191 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13192 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13193 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13197 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13198 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13200 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13201 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13205 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13206 ifx->generated = 1;
13210 /*-----------------------------------------------------------------*/
13211 /* genReceive - generate code for a receive iCode */
13212 /*-----------------------------------------------------------------*/
13213 static void genReceive (iCode *ic)
13219 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13220 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13222 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13224 if (isOperandInFarSpace(IC_RESULT(ic))
13225 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13226 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13228 int size = getSize(operandType(IC_RESULT(ic)));
13229 int offset = pic16_fReturnSizePic - size;
13233 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13234 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13238 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13240 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13241 size = AOP_SIZE(IC_RESULT(ic));
13244 pic16_emitcode ("pop","acc");
13245 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13248 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13250 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13253 /* set pseudo stack pointer to where it should be - dw*/
13254 GpsuedoStkPtr = ic->parmBytes;
13256 /* setting GpsuedoStkPtr has side effects here: */
13257 assignResultValue(IC_RESULT(ic), 0);
13260 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13263 /*-----------------------------------------------------------------*/
13264 /* genDummyRead - generate code for dummy read of volatiles */
13265 /*-----------------------------------------------------------------*/
13267 genDummyRead (iCode * ic)
13273 if (op && IS_SYMOP(op)) {
13274 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13275 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13278 pic16_aopOp (op, ic, FALSE);
13279 for (i=0; i < AOP_SIZE(op); i++) {
13280 // may need to protect this from the peepholer -- this is not nice but works...
13281 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13282 pic16_mov2w (AOP(op),i);
13283 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13285 pic16_freeAsmop (op, NULL, ic, TRUE);
13287 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13291 /*-----------------------------------------------------------------*/
13292 /* genpic16Code - generate code for pic16 based controllers */
13293 /*-----------------------------------------------------------------*/
13295 * At this point, ralloc.c has gone through the iCode and attempted
13296 * to optimize in a way suitable for a PIC. Now we've got to generate
13297 * PIC instructions that correspond to the iCode.
13299 * Once the instructions are generated, we'll pass through both the
13300 * peep hole optimizer and the pCode optimizer.
13301 *-----------------------------------------------------------------*/
13303 void genpic16Code (iCode *lic)
13308 lineHead = lineCurr = NULL;
13310 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13311 pic16_addpBlock(pb);
13314 /* if debug information required */
13315 if (options.debug && currFunc) {
13317 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13322 for (ic = lic ; ic ; ic = ic->next ) {
13324 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13325 if ( cln != ic->lineno ) {
13326 if ( options.debug ) {
13327 debugFile->writeCLine (ic);
13330 if(!options.noCcodeInAsm) {
13331 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13332 printCLine(ic->filename, ic->lineno)));
13338 if(options.iCodeInAsm) {
13341 /* insert here code to print iCode as comment */
13342 l = Safe_strdup(printILine(ic));
13343 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13346 /* if the result is marked as
13347 * spilt and rematerializable or code for
13348 * this has already been generated then
13350 if (resultRemat(ic) || ic->generated )
13353 /* depending on the operation */
13372 /* IPOP happens only when trying to restore a
13373 * spilt live range, if there is an ifx statement
13374 * following this pop then the if statement might
13375 * be using some of the registers being popped which
13376 * would destroy the contents of the register so
13377 * we need to check for this condition and handle it */
13379 && ic->next->op == IFX
13380 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13381 genIfx (ic->next,ic);
13399 genEndFunction (ic);
13415 pic16_genPlus (ic) ;
13419 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13420 pic16_genMinus (ic);
13436 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13440 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13446 /* note these two are xlated by algebraic equivalence
13447 * during parsing SDCC.y */
13448 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13449 "got '>=' or '<=' shouldn't have come here");
13453 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13465 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13469 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13473 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13497 genRightShift (ic);
13500 case GET_VALUE_AT_ADDRESS:
13505 if (POINTER_SET(ic))
13532 addSet(&_G.sendSet,ic);
13535 case DUMMY_READ_VOLATILE:
13545 /* now we are ready to call the
13546 peep hole optimizer */
13547 if (!options.nopeep)
13548 peepHole (&lineHead);
13550 /* now do the actual printing */
13551 printLine (lineHead, codeOutFile);
13554 DFPRINTF((stderr,"printing pBlock\n\n"));
13555 pic16_printpBlock(stdout,pb);