1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
142 static char *accUse[] = {"WREG"};
144 //static short rbank = -1;
158 bitVect *fregsUsed; /* registers used in function */
160 set *sregsAllocSet; /* registers used to store stack variables */
161 int stack_lat; /* stack offset latency */
163 int useWreg; /* flag when WREG is used to pass function parameter */
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
174 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
181 /*-----------------------------------------------------------------*/
182 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
183 /* exponent of 2 is returned, otherwise -1 is */
185 /* note that this is similar to the function `powof2' in SDCCsymt */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
193 if( (num & (num-1)) == 0) {
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
208 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
210 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
213 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
215 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216 ((result) ? AOP_SIZE(result) : 0));
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
222 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
224 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
227 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
228 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
229 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
233 void pic16_emitpcomment (char *fmt, ...)
236 char lb[INITIAL_INLINEASM];
242 vsprintf(lb+1,fmt,ap);
244 while (isspace(*lbp)) lbp++;
247 lineCurr = (lineCurr ?
248 connectLine(lineCurr,newLineNode(lb)) :
249 (lineHead = newLineNode(lb)));
250 lineCurr->isInline = _G.inLine;
251 lineCurr->isDebug = _G.debugLine;
253 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
256 // fprintf(stderr, "%s\n", lb);
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
262 char lb[INITIAL_INLINEASM];
265 if(!pic16_debug_verbose)
272 sprintf(lb,"%s\t",inst);
274 sprintf(lb,"%s",inst);
275 vsprintf(lb+(strlen(lb)),fmt,ap);
279 while (isspace(*lbp)) lbp++;
282 lineCurr = (lineCurr ?
283 connectLine(lineCurr,newLineNode(lb)) :
284 (lineHead = newLineNode(lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
288 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
291 // fprintf(stderr, "%s\n", lb);
296 void pic16_emitpLabel(int key)
298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
301 void pic16_emitpLabelFORCE(int key)
303 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
306 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
310 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
312 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
315 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
318 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
320 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
323 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
326 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
332 #define pic16_emitcode DEBUGpic16_emitcode
334 /*-----------------------------------------------------------------*/
335 /* pic16_emitcode - writes the code into a file : for now it is simple */
336 /*-----------------------------------------------------------------*/
337 void pic16_emitcode (char *inst,char *fmt, ...)
340 char lb[INITIAL_INLINEASM];
347 sprintf(lb,"%s\t",inst);
349 sprintf(lb,"%s",inst);
350 vsprintf(lb+(strlen(lb)),fmt,ap);
354 while (isspace(*lbp)) lbp++;
357 lineCurr = (lineCurr ?
358 connectLine(lineCurr,newLineNode(lb)) :
359 (lineHead = newLineNode(lb)));
360 lineCurr->isInline = _G.inLine;
361 lineCurr->isDebug = _G.debugLine;
363 // VR fprintf(stderr, "lb = <%s>\n", lbp);
365 // if(pic16_debug_verbose)
366 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
373 /*-----------------------------------------------------------------*/
374 /* pic16_emitDebuggerSymbol - associate the current code location */
375 /* with a debugger symbol */
376 /*-----------------------------------------------------------------*/
378 pic16_emitDebuggerSymbol (char * debugSym)
381 pic16_emitcode (";", "%s ==.", debugSym);
386 /*-----------------------------------------------------------------*/
387 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
388 /*-----------------------------------------------------------------*/
389 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
391 // bool r0iu = FALSE , r1iu = FALSE;
392 // bool r0ou = FALSE , r1ou = FALSE;
393 bool fsr0iu = FALSE, fsr0ou;
394 bool fsr2iu = FALSE, fsr2ou;
396 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
399 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
400 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
402 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
403 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
405 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
406 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
407 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
410 if(!fsr0iu && !fsr0ou) {
411 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
412 (*aopp)->type = AOP_FSR0;
414 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
416 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
420 /* no usage of FSR2 */
421 if(!fsr2iu && !fsr2ou) {
422 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
423 (*aopp)->type = AOP_FSR2;
425 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
429 /* now we know they both have usage */
430 /* if fsr0 not used in this instruction */
432 if (!_G.fsr0Pushed) {
433 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
434 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
438 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
439 (*aopp)->type = AOP_FSR0;
441 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
443 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
447 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
452 /* the logic: if r0 & r1 used in the instruction
453 then we are in trouble otherwise */
455 /* first check if r0 & r1 are used by this
456 instruction, in which case we are in trouble */
457 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
458 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
463 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
464 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
466 /* if no usage of r0 then return it */
467 if (!r0iu && !r0ou) {
468 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
469 (*aopp)->type = AOP_R0;
471 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
474 /* if no usage of r1 then return it */
475 if (!r1iu && !r1ou) {
476 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477 (*aopp)->type = AOP_R1;
479 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
482 /* now we know they both have usage */
483 /* if r0 not used in this instruction */
485 /* push it if not already pushed */
487 //pic16_emitcode ("push","%s",
488 // pic16_regWithIdx(R0_IDX)->dname);
492 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
493 (*aopp)->type = AOP_R0;
495 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
498 /* if r1 not used then */
501 /* push it if not already pushed */
503 //pic16_emitcode ("push","%s",
504 // pic16_regWithIdx(R1_IDX)->dname);
508 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
509 (*aopp)->type = AOP_R1;
510 return pic16_regWithIdx(R1_IDX);
514 /* I said end of world but not quite end of world yet */
515 /* if this is a result then we can push it on the stack*/
517 (*aopp)->type = AOP_STK;
521 /* other wise this is true end of the world */
522 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
523 "getFreePtr should never reach here");
528 /*-----------------------------------------------------------------*/
529 /* newAsmop - creates a new asmOp */
530 /*-----------------------------------------------------------------*/
531 static asmop *newAsmop (short type)
535 aop = Safe_calloc(1,sizeof(asmop));
540 static void genSetDPTR(int n)
544 pic16_emitcode(";", "Select standard DPTR");
545 pic16_emitcode("mov", "dps, #0x00");
549 pic16_emitcode(";", "Select alternate DPTR");
550 pic16_emitcode("mov", "dps, #0x01");
554 /*-----------------------------------------------------------------*/
555 /* resolveIfx - converts an iCode ifx into a form more useful for */
556 /* generating code */
557 /*-----------------------------------------------------------------*/
558 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
562 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
568 resIfx->condition = 1; /* assume that the ifx is true */
569 resIfx->generated = 0; /* indicate that the ifx has not been used */
572 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
575 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
576 __FUNCTION__,__LINE__,resIfx->lbl->key);
581 resIfx->lbl = IC_TRUE(ifx);
583 resIfx->lbl = IC_FALSE(ifx);
584 resIfx->condition = 0;
589 DEBUGpic16_emitcode("; +++","ifx true is non-null");
591 DEBUGpic16_emitcode("; +++","ifx true is null");
593 DEBUGpic16_emitcode("; +++","ifx false is non-null");
595 DEBUGpic16_emitcode("; +++","ifx false is null");
599 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
603 /*-----------------------------------------------------------------*/
604 /* pointerCode - returns the code for a pointer type */
605 /*-----------------------------------------------------------------*/
606 static int pointerCode (sym_link *etype)
609 return PTR_TYPE(SPEC_OCLS(etype));
614 /*-----------------------------------------------------------------*/
615 /* aopForSym - for a true symbol */
616 /*-----------------------------------------------------------------*/
617 static asmop *aopForSym (iCode *ic, operand *op, bool result)
619 symbol *sym=OP_SYMBOL(op);
621 memmap *space= SPEC_OCLS(sym->etype);
625 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
627 // sym = OP_SYMBOL(op);
629 /* if already has one */
631 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
636 /* if symbol was initially placed onStack then we must re-place it
637 * to direct memory, since pic16 does not have a specific stack */
639 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
647 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
649 sym->aop = aop = newAsmop (AOP_PAGED);
650 aop->aopu.aop_dir = sym->rname ;
651 aop->size = getSize(sym->type);
652 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
653 pic16_allocDirReg( IC_LEFT(ic) );
661 /* assign depending on the storage class */
662 /* if it is on the stack or indirectly addressable */
663 /* space we need to assign either r0 or r1 to it */
664 if (sym->onStack) // || sym->iaccess)
669 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
670 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
672 /* acquire a temporary register -- it is saved in function */
674 sym->aop = aop = newAsmop(AOP_STA);
675 aop->aopu.stk.stk = sym->stack;
676 aop->size = getSize(sym->type);
679 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
680 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
681 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
682 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
684 for(i=0;i<aop->size;i++)
685 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
686 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
688 if(1 && ic->op == SEND) {
690 /* if SEND do the send here */
693 for(i=0;i<aop->size;i++) {
694 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
695 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
700 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
703 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
705 // we do not need to load the value if it is to be defined...
706 if (result) return aop;
709 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
712 for(i=0;i<aop->size;i++) {
714 /* initialise for stack access via frame pointer */
715 // operands on stack are accessible via "FSR2 + index" with index
716 // starting at 2 for arguments and growing from 0 downwards for
717 // local variables (index == 0 is not assigned so we add one here)
719 int soffs = sym->stack;
725 if(1 && ic->op == SEND) {
726 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
727 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
728 pic16_popCopyReg( pic16_frame_plusw ),
729 pic16_popCopyReg(pic16_stack_postdec )));
731 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
733 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
739 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
746 /* now assign the address of the variable to
747 the pointer register */
748 if (aop->type != AOP_STK) {
752 pic16_emitcode("push","acc");
754 pic16_emitcode("mov","a,_bp");
755 pic16_emitcode("add","a,#0x%02x",
757 ((char)(sym->stack - _G.nRegsSaved )) :
758 ((char)sym->stack)) & 0xff);
759 pic16_emitcode("mov","%s,a",
760 aop->aopu.aop_ptr->name);
763 pic16_emitcode("pop","acc");
765 pic16_emitcode("mov","%s,#%s",
766 aop->aopu.aop_ptr->name,
768 aop->paged = space->paged;
770 aop->aopu.aop_stk = sym->stack;
778 if (sym->onStack && options.stack10bit)
780 /* It's on the 10 bit stack, which is located in
784 //DEBUGpic16_emitcode(";","%d",__LINE__);
787 pic16_emitcode("push","acc");
789 pic16_emitcode("mov","a,_bp");
790 pic16_emitcode("add","a,#0x%02x",
792 ((char)(sym->stack - _G.nRegsSaved )) :
793 ((char)sym->stack)) & 0xff);
796 pic16_emitcode ("mov","dpx1,#0x40");
797 pic16_emitcode ("mov","dph1,#0x00");
798 pic16_emitcode ("mov","dpl1, a");
802 pic16_emitcode("pop","acc");
804 sym->aop = aop = newAsmop(AOP_DPTR2);
805 aop->size = getSize(sym->type);
811 /* special case for a function */
812 if (IS_FUNC(sym->type)) {
813 sym->aop = aop = newAsmop(AOP_PCODE);
814 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
815 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
816 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
817 PCOI(aop->aopu.pcop)->index = 0;
818 aop->size = FPTRSIZE;
819 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
826 //DEBUGpic16_emitcode(";","%d",__LINE__);
827 /* if in bit space */
828 if (IN_BITSPACE(space)) {
829 sym->aop = aop = newAsmop (AOP_CRY);
830 aop->aopu.aop_dir = sym->rname ;
831 aop->size = getSize(sym->type);
832 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
835 /* if it is in direct space */
836 if (IN_DIRSPACE(space)) {
837 sym->aop = aop = newAsmop (AOP_DIR);
838 aop->aopu.aop_dir = sym->rname ;
839 aop->size = getSize(sym->type);
840 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841 pic16_allocDirReg( IC_LEFT(ic) );
846 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
847 sym->aop = aop = newAsmop (AOP_DIR);
848 aop->aopu.aop_dir = sym->rname ;
849 aop->size = getSize(sym->type);
850 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851 pic16_allocDirReg( IC_LEFT(ic) );
856 /* only remaining is far space */
857 sym->aop = aop = newAsmop(AOP_PCODE);
859 /* change the next if to 1 to revert to good old immediate code */
860 if(IN_CODESPACE(space)) {
861 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
862 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
863 PCOI(aop->aopu.pcop)->index = 0;
865 /* try to allocate via direct register */
866 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
867 // aop->size = getSize( sym->type );
870 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
871 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
874 if(!pic16_allocDirReg (IC_LEFT(ic)))
878 if(IN_DIRSPACE( space ))
880 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
881 aop->size = FPTRSIZE;
882 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
883 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
884 else if(sym->onStack) {
887 if(SPEC_SCLS(sym->etype) == S_PDATA) {
888 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
889 aop->size = FPTRSIZE;
894 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
896 /* if it is in code space */
897 if (IN_CODESPACE(space))
903 /*-----------------------------------------------------------------*/
904 /* aopForRemat - rematerialzes an object */
905 /*-----------------------------------------------------------------*/
906 static asmop *aopForRemat (operand *op) // x symbol *sym)
908 symbol *sym = OP_SYMBOL(op);
910 iCode *ic = NULL, *oldic;
911 asmop *aop = newAsmop(AOP_PCODE);
918 ic = sym->rematiCode;
920 if(IS_OP_POINTER(op)) {
921 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
927 // pic16_emitpcomment("ic: %s\n", printILine(ic));
930 val += (int) operandLitValue(IC_RIGHT(ic));
931 } else if (ic->op == '-') {
932 val -= (int) operandLitValue(IC_RIGHT(ic));
936 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
939 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
942 if(!op->isaddr)viaimmd++; else viaimmd=0;
944 /* set the following if to 1 to revert to good old immediate code */
945 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
948 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
950 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
953 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
955 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
958 PCOI(aop->aopu.pcop)->index = val;
960 aop->size = getSize( sym->type );
962 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
964 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
965 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
967 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
971 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
972 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
974 val, IS_PTR_CONST(operandType(op)));
976 val, IS_CODEPTR(operandType(op)));
979 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
981 pic16_allocDirReg (IC_LEFT(ic));
983 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
990 static int aopIdx (asmop *aop, int offset)
995 if(aop->type != AOP_REG)
998 return aop->aopu.aop_reg[offset]->rIdx;
1003 /*-----------------------------------------------------------------*/
1004 /* regsInCommon - two operands have some registers in common */
1005 /*-----------------------------------------------------------------*/
1006 static bool regsInCommon (operand *op1, operand *op2)
1008 symbol *sym1, *sym2;
1011 /* if they have registers in common */
1012 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1015 sym1 = OP_SYMBOL(op1);
1016 sym2 = OP_SYMBOL(op2);
1018 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1021 for (i = 0 ; i < sym1->nRegs ; i++) {
1026 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1030 if (sym2->regs[j] == sym1->regs[i])
1038 /*-----------------------------------------------------------------*/
1039 /* operandsEqu - equivalent */
1040 /*-----------------------------------------------------------------*/
1041 static bool operandsEqu ( operand *op1, operand *op2)
1043 symbol *sym1, *sym2;
1045 /* if they not symbols */
1046 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1049 sym1 = OP_SYMBOL(op1);
1050 sym2 = OP_SYMBOL(op2);
1052 /* if both are itemps & one is spilt
1053 and the other is not then false */
1054 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1055 sym1->isspilt != sym2->isspilt )
1058 /* if they are the same */
1062 if (sym1->rname[0] && sym2->rname[0]
1063 && strcmp (sym1->rname, sym2->rname) == 0)
1067 /* if left is a tmp & right is not */
1068 if (IS_ITEMP(op1) &&
1071 (sym1->usl.spillLoc == sym2))
1074 if (IS_ITEMP(op2) &&
1078 (sym2->usl.spillLoc == sym1))
1084 /*-----------------------------------------------------------------*/
1085 /* pic16_sameRegs - two asmops have the same registers */
1086 /*-----------------------------------------------------------------*/
1087 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1094 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1095 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1097 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1099 if (aop1->type != AOP_REG ||
1100 aop2->type != AOP_REG )
1103 /* This is a bit too restrictive if one is a subset of the other...
1104 if (aop1->size != aop2->size )
1108 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1109 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1111 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1112 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1119 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1121 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1122 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1124 if(aop1 == aop2)return TRUE;
1125 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1127 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1133 /*-----------------------------------------------------------------*/
1134 /* pic16_aopOp - allocates an asmop for an operand : */
1135 /*-----------------------------------------------------------------*/
1136 void pic16_aopOp (operand *op, iCode *ic, bool result)
1145 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1147 /* if this a literal */
1148 if (IS_OP_LITERAL(op)) {
1149 op->aop = aop = newAsmop(AOP_LIT);
1150 aop->aopu.aop_lit = op->operand.valOperand;
1151 aop->size = getSize(operandType(op));
1156 sym_link *type = operandType(op);
1158 if(IS_PTR_CONST(type))
1160 if(IS_CODEPTR(type))
1162 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1165 /* if already has a asmop then continue */
1169 /* if the underlying symbol has a aop */
1170 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1171 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1172 op->aop = OP_SYMBOL(op)->aop;
1176 /* if this is a true symbol */
1177 if (IS_TRUE_SYMOP(op)) {
1178 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1179 op->aop = aopForSym(ic, op, result);
1183 /* this is a temporary : this has
1189 e) can be a return use only */
1191 sym = OP_SYMBOL(op);
1193 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1194 /* if the type is a conditional */
1195 if (sym->regType == REG_CND) {
1196 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1201 /* if it is spilt then two situations
1203 b) has a spill location */
1204 if (sym->isspilt || sym->nRegs == 0) {
1206 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1207 DEBUGpic16_emitcode(";","%d",__LINE__);
1208 /* rematerialize it NOW */
1211 sym->aop = op->aop = aop = aopForRemat (op);
1212 // aop->size = getSize(sym->type);
1213 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1220 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1221 aop->size = getSize(sym->type);
1222 for ( i = 0 ; i < 1 ; i++ ) {
1223 aop->aopu.aop_str[i] = accUse[i];
1224 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1226 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1227 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1235 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1236 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1237 //pic16_allocDirReg (IC_LEFT(ic));
1238 aop->size = getSize(sym->type);
1243 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1244 aop->size = getSize(sym->type);
1245 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1246 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1248 DEBUGpic16_emitcode(";","%d",__LINE__);
1252 /* else spill location */
1253 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1254 /* force a new aop if sizes differ */
1255 sym->usl.spillLoc->aop = NULL;
1259 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1260 __FUNCTION__,__LINE__,
1261 sym->usl.spillLoc->rname,
1262 sym->rname, sym->usl.spillLoc->offset);
1265 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1266 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1267 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1268 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1270 sym->usl.spillLoc->offset, op);
1272 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1273 DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1274 assert (getSize(sym->type) <= 1);
1275 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
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 static void 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 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)));
3679 /* mark the end of this tiny function */
3680 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3682 sprintf(asymname, "%s", sym->rname);
3688 abSym = Safe_calloc(1, sizeof(absSym));
3689 strcpy(abSym->name, asymname);
3691 switch( FUNC_INTNO(sym->type) ) {
3692 case 0: abSym->address = 0x000000; break;
3693 case 1: abSym->address = 0x000008; break;
3694 case 2: abSym->address = 0x000018; break;
3697 // fprintf(stderr, "no interrupt number is given\n");
3698 abSym->address = -1; break;
3701 /* relocate interrupt vectors if needed */
3702 if(abSym->address != -1)
3703 abSym->address += pic16_options.ivt_loc;
3705 addSet(&absSymSet, abSym);
3709 /* create the function header */
3710 pic16_emitcode(";","-----------------------------------------");
3711 pic16_emitcode(";"," function %s",sym->name);
3712 pic16_emitcode(";","-----------------------------------------");
3714 pic16_emitcode("","%s:",sym->rname);
3715 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3720 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3721 if(!strcmp(ab->name, sym->rname)) {
3722 pic16_pBlockConvert2Absolute(pb);
3728 if(IFFUNC_ISNAKED(ftype)) {
3729 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3733 /* if critical function then turn interrupts off */
3734 if (IFFUNC_ISCRITICAL(ftype)) {
3735 //pic16_emitcode("clr","ea");
3738 currFunc = sym; /* update the currFunc symbol */
3739 _G.fregsUsed = sym->regsUsed;
3740 _G.sregsAlloc = newBitVect(128);
3743 /* if this is an interrupt service routine then
3744 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3745 if (IFFUNC_ISISR(sym->type)) {
3746 _G.usefastretfie = 1; /* use shadow registers by default */
3748 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3749 if(!FUNC_ISSHADOWREGS(sym->type)) {
3750 /* do not save WREG,STATUS,BSR for high priority interrupts
3751 * because they are stored in the hardware shadow registers already */
3752 _G.usefastretfie = 0;
3753 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3758 /* these should really be optimized somehow, because not all
3759 * interrupt handlers modify them */
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3765 // pic16_pBlockConvert2ISR(pb);
3768 /* emit code to setup stack frame if user enabled,
3769 * and function is not main() */
3771 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3772 if(strcmp(sym->name, "main")) {
3774 || !options.ommitFramePtr
3776 || IFFUNC_ARGS(sym->type)
3777 || FUNC_HASSTACKPARM(sym->etype)
3779 /* setup the stack frame */
3780 if(STACK_MODEL_LARGE)
3781 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3782 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3784 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3785 if(STACK_MODEL_LARGE)
3786 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3790 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3793 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3795 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3796 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3798 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3801 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3802 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3809 /* if callee-save to be used for this function
3810 * then save the registers being used in this function */
3811 // if (IFFUNC_CALLEESAVES(sym->type))
3815 /* if any registers used */
3816 if (sym->regsUsed) {
3817 /* save the registers used */
3818 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3819 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3820 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3821 if (bitVectBitValue(sym->regsUsed,i)) {
3822 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3825 if(!pic16_regWithIdx(i)->wasUsed) {
3826 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3827 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3828 pic16_regWithIdx(i)->wasUsed = 1;
3832 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3836 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3837 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3840 /*-----------------------------------------------------------------*/
3841 /* genEndFunction - generates epilogue for functions */
3842 /*-----------------------------------------------------------------*/
3843 static void genEndFunction (iCode *ic)
3845 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3849 if(IFFUNC_ISNAKED(sym->type)) {
3850 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3856 /* add code for ISCRITICAL */
3857 if(IFFUNC_ISCRITICAL(sym->type)) {
3858 /* if critical function, turn on interrupts */
3860 /* TODO: add code here -- VR */
3863 // sym->regsUsed = _G.fregsUsed;
3865 /* now we need to restore the registers */
3866 /* if any registers used */
3868 /* first restore registers that might be used for stack access */
3869 if(_G.sregsAllocSet) {
3872 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3873 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3874 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3878 if (sym->regsUsed) {
3881 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3882 /* restore registers used */
3883 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3884 for ( i = sym->regsUsed->size; i >= 0; i--) {
3885 if (bitVectBitValue(sym->regsUsed,i)) {
3886 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3890 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3895 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3897 if (sym->stack == 1) {
3898 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3899 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3901 // we have to add more than one...
3902 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3903 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3904 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3906 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3907 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3908 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3912 if(strcmp(sym->name, "main")) {
3914 || !options.ommitFramePtr
3916 || IFFUNC_ARGS(sym->type)
3917 || FUNC_HASSTACKPARM(sym->etype)
3919 /* restore stack frame */
3920 if(STACK_MODEL_LARGE)
3921 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3922 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3928 if (IFFUNC_ISISR(sym->type)) {
3929 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3930 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3931 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3934 if(!FUNC_ISSHADOWREGS(sym->type)) {
3935 /* do not restore interrupt vector for WREG,STATUS,BSR
3936 * for high priority interrupt, see genFunction */
3937 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3938 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3939 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3941 // _G.interruptvector = 0; /* sanity check */
3944 /* if debug then send end of function */
3945 /* if (options.debug && currFunc) */
3947 debugFile->writeEndFunction (currFunc, ic, 1);
3950 if(_G.usefastretfie)
3951 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3953 pic16_emitpcodeNULLop(POC_RETFIE);
3955 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3957 _G.usefastretfie = 0;
3961 if (IFFUNC_ISCRITICAL(sym->type)) {
3962 pic16_emitcode("setb","ea");
3965 /* if debug then send end of function */
3967 debugFile->writeEndFunction (currFunc, ic, 1);
3970 /* insert code to restore stack frame, if user enabled it
3971 * and function is not main() */
3974 pic16_emitpcodeNULLop(POC_RETURN);
3976 /* Mark the end of a function */
3977 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3981 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3983 unsigned long lit=1;
3988 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3989 if(AOP_TYPE(op) == AOP_LIT) {
3990 if(!IS_FLOAT(operandType( op ))) {
3991 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3994 unsigned long lit_int;
3998 /* take care if literal is a float */
3999 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4005 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4006 pic16_emitpcode(POC_CLRF, dest);
4008 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4009 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4012 if(dest->type == PO_WREG && (offset == 0)) {
4013 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4016 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement */
4022 /*-----------------------------------------------------------------*/
4023 static void genRet (iCode *ic)
4029 /* if we have no return value then
4030 * just generate the "ret" */
4035 /* we have something to return then
4036 * move the return value into place */
4037 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4038 size = AOP_SIZE(IC_LEFT(ic));
4042 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4045 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4048 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4050 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4053 /* >32-bits, setup stack and FSR0 */
4055 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4056 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4058 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4060 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4065 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4066 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4068 if(STACK_MODEL_LARGE) {
4069 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4070 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4072 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4077 /* old code, left here for reference -- VR */
4081 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4083 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4084 pic16_emitpcomment("push %s",l);
4087 DEBUGpic16_emitcode(";", "%d", __LINE__);
4088 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4089 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4091 if (strcmp(fReturn[offset],l)) {
4092 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4093 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4094 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4096 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4100 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4110 if (strcmp(fReturn[pushed],"a"))
4111 pic16_emitcode("pop",fReturn[pushed]);
4113 pic16_emitcode("pop","acc");
4119 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4122 /* generate a jump to the return label
4123 * if the next is not the return statement */
4124 if (!(ic->next && ic->next->op == LABEL
4125 && IC_LABEL(ic->next) == returnLabel)) {
4127 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4128 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4132 /*-----------------------------------------------------------------*/
4133 /* genLabel - generates a label */
4134 /*-----------------------------------------------------------------*/
4135 static void genLabel (iCode *ic)
4139 /* special case never generate */
4140 if (IC_LABEL(ic) == entryLabel)
4143 pic16_emitpLabel(IC_LABEL(ic)->key);
4144 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4147 /*-----------------------------------------------------------------*/
4148 /* genGoto - generates a goto */
4149 /*-----------------------------------------------------------------*/
4151 static void genGoto (iCode *ic)
4154 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4155 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4159 /*-----------------------------------------------------------------*/
4160 /* genMultbits :- multiplication of bits */
4161 /*-----------------------------------------------------------------*/
4162 static void genMultbits (operand *left,
4168 if(!pic16_sameRegs(AOP(result),AOP(right)))
4169 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4171 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4172 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4173 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneByte : 8 bit multiplication & division */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneByte (operand *left,
4187 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4190 /* (if two literals, the value is computed before) */
4191 /* if one literal, literal on the right */
4192 if (AOP_TYPE(left) == AOP_LIT){
4198 /* size is already checked in genMult == 1 */
4199 // size = AOP_SIZE(result);
4201 if (AOP_TYPE(right) == AOP_LIT){
4202 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4203 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4204 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4208 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213 pic16_genMult8X8_8 (left, right,result);
4216 /*-----------------------------------------------------------------*/
4217 /* genMultOneWord : 16 bit multiplication */
4218 /*-----------------------------------------------------------------*/
4219 static void genMultOneWord (operand *left,
4224 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4225 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4227 /* (if two literals, the value is computed before)
4228 * if one literal, literal on the right */
4229 if (AOP_TYPE(left) == AOP_LIT){
4235 /* size is checked already == 2 */
4236 // size = AOP_SIZE(result);
4238 if (AOP_TYPE(right) == AOP_LIT) {
4239 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4240 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4241 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4242 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4244 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4245 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4246 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4247 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4250 pic16_genMult16X16_16(left, right,result);
4253 /*-----------------------------------------------------------------*/
4254 /* genMultOneLong : 32 bit multiplication */
4255 /*-----------------------------------------------------------------*/
4256 static void genMultOneLong (operand *left,
4261 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4262 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4264 /* (if two literals, the value is computed before)
4265 * if one literal, literal on the right */
4266 if (AOP_TYPE(left) == AOP_LIT){
4272 /* size is checked already == 4 */
4273 // size = AOP_SIZE(result);
4275 if (AOP_TYPE(right) == AOP_LIT) {
4276 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4277 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4278 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4279 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4281 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4282 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4283 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4284 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4287 pic16_genMult32X32_32(left, right,result);
4292 /*-----------------------------------------------------------------*/
4293 /* genMult - generates code for multiplication */
4294 /*-----------------------------------------------------------------*/
4295 static void genMult (iCode *ic)
4297 operand *left = IC_LEFT(ic);
4298 operand *right = IC_RIGHT(ic);
4299 operand *result= IC_RESULT(ic);
4302 /* assign the amsops */
4303 pic16_aopOp (left,ic,FALSE);
4304 pic16_aopOp (right,ic,FALSE);
4305 pic16_aopOp (result,ic,TRUE);
4307 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4309 /* special cases first *
4311 if (AOP_TYPE(left) == AOP_CRY
4312 && AOP_TYPE(right)== AOP_CRY) {
4313 genMultbits(left,right,result);
4317 /* if both are of size == 1 */
4318 if(AOP_SIZE(left) == 1
4319 && AOP_SIZE(right) == 1) {
4320 genMultOneByte(left,right,result);
4324 /* if both are of size == 2 */
4325 if(AOP_SIZE(left) == 2
4326 && AOP_SIZE(right) == 2) {
4327 genMultOneWord(left, right, result);
4331 /* if both are of size == 4 */
4332 if(AOP_SIZE(left) == 4
4333 && AOP_SIZE(right) == 4) {
4334 genMultOneLong(left, right, result);
4338 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4341 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4342 /* should have been converted to function call */
4346 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4347 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348 pic16_freeAsmop(result,NULL,ic,TRUE);
4351 /*-----------------------------------------------------------------*/
4352 /* genDivbits :- division of bits */
4353 /*-----------------------------------------------------------------*/
4354 static void genDivbits (operand *left,
4361 /* the result must be bit */
4362 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4363 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4367 pic16_emitcode("div","ab");
4368 pic16_emitcode("rrc","a");
4369 pic16_aopPut(AOP(result),"c",0);
4372 /*-----------------------------------------------------------------*/
4373 /* genDivOneByte : 8 bit division */
4374 /*-----------------------------------------------------------------*/
4375 static void genDivOneByte (operand *left,
4379 sym_link *opetype = operandType(result);
4384 /* result = divident / divisor
4385 * - divident may be a register or a literal,
4386 * - divisor may be a register or a literal,
4387 * so there are 3 cases (literal / literal is optimized
4388 * by the front-end) to handle.
4389 * In addition we must handle signed and unsigned, which
4390 * result in 6 final different cases -- VR */
4394 size = AOP_SIZE(result) - 1;
4396 /* signed or unsigned */
4397 if (SPEC_USIGN(opetype)) {
4398 pCodeOp *pct1, /* count */
4401 symbol *label1, *label2, *label3;;
4404 /* unsigned is easy */
4406 pct1 = pic16_popGetTempReg(1);
4407 pct2 = pic16_popGetTempReg(1);
4408 pct3 = pic16_popGetTempReg(1);
4410 label1 = newiTempLabel(NULL);
4411 label2 = newiTempLabel(NULL);
4412 label3 = newiTempLabel(NULL);
4414 /* the following algorithm is extracted from divuint.c */
4416 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4417 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4419 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4421 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4423 pic16_emitpLabel(label1->key);
4426 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4430 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4434 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4436 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4439 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4440 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4441 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4443 pic16_emitpLabel( label3->key );
4444 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4445 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4449 pic16_emitpLabel(label2->key);
4450 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4451 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4452 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4454 /* result is in wreg */
4455 if(AOP_TYPE(result) != AOP_ACC)
4456 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4458 pic16_popReleaseTempReg( pct3, 1);
4459 pic16_popReleaseTempReg( pct2, 1);
4460 pic16_popReleaseTempReg( pct1, 1);
4465 /* signed is a little bit more difficult */
4467 /* save the signs of the operands */
4468 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4470 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4471 pic16_emitcode("push","acc"); /* save it on the stack */
4473 /* now sign adjust for both left & right */
4474 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4476 lbl = newiTempLabel(NULL);
4477 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4478 pic16_emitcode("cpl","a");
4479 pic16_emitcode("inc","a");
4480 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4481 pic16_emitcode("mov","b,a");
4483 /* sign adjust left side */
4484 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4487 lbl = newiTempLabel(NULL);
4488 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4489 pic16_emitcode("cpl","a");
4490 pic16_emitcode("inc","a");
4491 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4493 /* now the division */
4494 pic16_emitcode("div","ab");
4495 /* we are interested in the lower order
4497 pic16_emitcode("mov","b,a");
4498 lbl = newiTempLabel(NULL);
4499 pic16_emitcode("pop","acc");
4500 /* if there was an over flow we don't
4501 adjust the sign of the result */
4502 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4503 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4505 pic16_emitcode("clr","a");
4506 pic16_emitcode("subb","a,b");
4507 pic16_emitcode("mov","b,a");
4508 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4510 /* now we are done */
4511 pic16_aopPut(AOP(result),"b",0);
4513 pic16_emitcode("mov","c,b.7");
4514 pic16_emitcode("subb","a,acc");
4517 pic16_aopPut(AOP(result),"a",offset++);
4521 /*-----------------------------------------------------------------*/
4522 /* genDiv - generates code for division */
4523 /*-----------------------------------------------------------------*/
4524 static void genDiv (iCode *ic)
4526 operand *left = IC_LEFT(ic);
4527 operand *right = IC_RIGHT(ic);
4528 operand *result= IC_RESULT(ic);
4531 /* Division is a very lengthy algorithm, so it is better
4532 * to call support routines than inlining algorithm.
4533 * Division functions written here just in case someone
4534 * wants to inline and not use the support libraries -- VR */
4538 /* assign the amsops */
4539 pic16_aopOp (left,ic,FALSE);
4540 pic16_aopOp (right,ic,FALSE);
4541 pic16_aopOp (result,ic,TRUE);
4543 /* special cases first */
4545 if (AOP_TYPE(left) == AOP_CRY &&
4546 AOP_TYPE(right)== AOP_CRY) {
4547 genDivbits(left,right,result);
4551 /* if both are of size == 1 */
4552 if (AOP_SIZE(left) == 1 &&
4553 AOP_SIZE(right) == 1 ) {
4554 genDivOneByte(left,right,result);
4558 /* should have been converted to function call */
4561 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4562 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4563 pic16_freeAsmop(result,NULL,ic,TRUE);
4566 /*-----------------------------------------------------------------*/
4567 /* genModbits :- modulus of bits */
4568 /*-----------------------------------------------------------------*/
4569 static void genModbits (operand *left,
4577 werror(W_POSSBUG2, __FILE__, __LINE__);
4578 /* the result must be bit */
4579 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4580 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4584 pic16_emitcode("div","ab");
4585 pic16_emitcode("mov","a,b");
4586 pic16_emitcode("rrc","a");
4587 pic16_aopPut(AOP(result),"c",0);
4590 /*-----------------------------------------------------------------*/
4591 /* genModOneByte : 8 bit modulus */
4592 /*-----------------------------------------------------------------*/
4593 static void genModOneByte (operand *left,
4597 sym_link *opetype = operandType(result);
4602 werror(W_POSSBUG2, __FILE__, __LINE__);
4604 /* signed or unsigned */
4605 if (SPEC_USIGN(opetype)) {
4606 /* unsigned is easy */
4607 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4608 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4610 pic16_emitcode("div","ab");
4611 pic16_aopPut(AOP(result),"b",0);
4615 /* signed is a little bit more difficult */
4617 /* save the signs of the operands */
4618 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4621 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4622 pic16_emitcode("push","acc"); /* save it on the stack */
4624 /* now sign adjust for both left & right */
4625 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4628 lbl = newiTempLabel(NULL);
4629 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4630 pic16_emitcode("cpl","a");
4631 pic16_emitcode("inc","a");
4632 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4633 pic16_emitcode("mov","b,a");
4635 /* sign adjust left side */
4636 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4639 lbl = newiTempLabel(NULL);
4640 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4641 pic16_emitcode("cpl","a");
4642 pic16_emitcode("inc","a");
4643 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4645 /* now the multiplication */
4646 pic16_emitcode("div","ab");
4647 /* we are interested in the lower order
4649 lbl = newiTempLabel(NULL);
4650 pic16_emitcode("pop","acc");
4651 /* if there was an over flow we don't
4652 adjust the sign of the result */
4653 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4654 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4656 pic16_emitcode("clr","a");
4657 pic16_emitcode("subb","a,b");
4658 pic16_emitcode("mov","b,a");
4659 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4661 /* now we are done */
4662 pic16_aopPut(AOP(result),"b",0);
4666 /*-----------------------------------------------------------------*/
4667 /* genMod - generates code for division */
4668 /*-----------------------------------------------------------------*/
4669 static void genMod (iCode *ic)
4671 operand *left = IC_LEFT(ic);
4672 operand *right = IC_RIGHT(ic);
4673 operand *result= IC_RESULT(ic);
4677 /* assign the amsops */
4678 pic16_aopOp (left,ic,FALSE);
4679 pic16_aopOp (right,ic,FALSE);
4680 pic16_aopOp (result,ic,TRUE);
4682 /* special cases first */
4684 if (AOP_TYPE(left) == AOP_CRY &&
4685 AOP_TYPE(right)== AOP_CRY) {
4686 genModbits(left,right,result);
4690 /* if both are of size == 1 */
4691 if (AOP_SIZE(left) == 1 &&
4692 AOP_SIZE(right) == 1 ) {
4693 genModOneByte(left,right,result);
4697 /* should have been converted to function call */
4701 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4702 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4703 pic16_freeAsmop(result,NULL,ic,TRUE);
4706 /*-----------------------------------------------------------------*/
4707 /* genIfxJump :- will create a jump depending on the ifx */
4708 /*-----------------------------------------------------------------*/
4710 note: May need to add parameter to indicate when a variable is in bit space.
4712 static void genIfxJump (iCode *ic, char *jval)
4716 /* if true label then we jump if condition
4718 if ( IC_TRUE(ic) ) {
4720 if(strcmp(jval,"a") == 0)
4722 else if (strcmp(jval,"c") == 0)
4725 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4726 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4730 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4734 /* false label is present */
4735 if(strcmp(jval,"a") == 0)
4737 else if (strcmp(jval,"c") == 0)
4740 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4741 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4744 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4745 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4750 /* mark the icode as generated */
4754 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4758 /* if true label then we jump if condition
4760 if ( IC_TRUE(ic) ) {
4761 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4762 pic16_emitpcode(POC_BTFSC, jop);
4764 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4765 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4768 /* false label is present */
4769 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4770 pic16_emitpcode(POC_BTFSS, jop);
4772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4773 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4777 /* mark the icode as generated */
4784 /*-----------------------------------------------------------------*/
4786 /*-----------------------------------------------------------------*/
4787 static void genSkip(iCode *ifx,int status_bit)
4789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4793 if ( IC_TRUE(ifx) ) {
4794 switch(status_bit) {
4809 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4810 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4814 switch(status_bit) {
4828 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4829 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4836 /*-----------------------------------------------------------------*/
4838 /*-----------------------------------------------------------------*/
4839 static void genSkipc(resolvedIfx *rifx)
4841 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4851 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4852 rifx->generated = 1;
4855 #if !(USE_SIMPLE_GENCMP)
4856 /*-----------------------------------------------------------------*/
4858 /*-----------------------------------------------------------------*/
4859 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4861 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4866 if( (rifx->condition ^ invert_condition) & 1)
4871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4872 rifx->generated = 1;
4877 /*-----------------------------------------------------------------*/
4879 /*-----------------------------------------------------------------*/
4880 static void genSkipz(iCode *ifx, int condition)
4891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4893 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4896 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4898 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4903 #if !(USE_SIMPLE_GENCMP)
4904 /*-----------------------------------------------------------------*/
4906 /*-----------------------------------------------------------------*/
4907 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4913 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4915 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4918 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4919 rifx->generated = 1;
4924 /*-----------------------------------------------------------------*/
4925 /* genChkZeroes :- greater or less than comparison */
4926 /* For each byte in a literal that is zero, inclusive or the */
4927 /* the corresponding byte in the operand with W */
4928 /* returns true if any of the bytes are zero */
4929 /*-----------------------------------------------------------------*/
4930 static int genChkZeroes(operand *op, int lit, int size)
4937 i = (lit >> (size*8)) & 0xff;
4941 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4943 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4953 /*-----------------------------------------------------------------*/
4954 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4955 /* aop (if it's NOT a literal) or from lit (if */
4956 /* aop is a literal) */
4957 /*-----------------------------------------------------------------*/
4958 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4959 if (aop->type == AOP_LIT) {
4960 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4962 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4966 /*-----------------------------------------------------------------*/
4967 /* genCmp :- greater or less than comparison */
4968 /*-----------------------------------------------------------------*/
4970 #if USE_SIMPLE_GENCMP /* { */
4972 /* genCmp performs a left < right comparison, stores
4973 * the outcome in result (if != NULL) and generates
4974 * control flow code for the ifx (if != NULL).
4976 * This version leaves in sequences like
4977 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4978 * which should be optmized by the peephole
4979 * optimizer - RN 2005-01-01 */
4980 static void genCmp (operand *left,operand *right,
4981 operand *result, iCode *ifx, int sign)
4994 assert (AOP_SIZE(left) == AOP_SIZE(right));
4995 assert (left && right);
4997 size = AOP_SIZE(right) - 1;
4998 mask = (0x100UL << (size*8)) - 1;
4999 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5004 resolveIfx (&rIfx, ifx);
5006 /* handle for special cases */
5007 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5010 /**********************************************************************
5011 * handle bits - bit compares are promoted to int compares seemingly! *
5012 **********************************************************************/
5014 // THIS IS COMPLETELY UNTESTED!
5015 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5016 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5017 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5018 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5021 // 1 < {0,1} is false --> clear C by skipping the next instruction
5022 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5023 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5024 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5025 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5026 emitCLRC; // only skipped for left=0 && right=1
5028 goto correct_result_in_carry;
5032 /*************************************************
5033 * make sure that left is register (or the like) *
5034 *************************************************/
5035 if (!isAOP_REGlike(left)) {
5036 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5037 assert (isAOP_LIT(left));
5038 assert (isAOP_REGlike(right));
5039 // swap left and right
5040 // left < right <==> right > left <==> (right >= left + 1)
5041 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5043 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5044 // MAXVALUE < right? always false
5045 if (performedLt) emitCLRC; else emitSETC;
5046 goto correct_result_in_carry;
5049 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5050 // that's why we handled it above.
5057 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5058 } else if (isAOP_LIT(right)) {
5059 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5062 assert (isAOP_REGlike(left)); // left must be register or the like
5063 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5065 /*************************************************
5066 * special cases go here *
5067 *************************************************/
5069 if (isAOP_LIT(right)) {
5071 // unsigned comparison to a literal
5072 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5074 // unsigned left < 0? always false
5075 if (performedLt) emitCLRC; else emitSETC;
5076 goto correct_result_in_carry;
5079 // signed comparison to a literal
5080 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5081 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5082 // signed left < 0x80000000? always false
5083 if (performedLt) emitCLRC; else emitSETC;
5084 goto correct_result_in_carry;
5085 } else if (lit == 0) {
5086 // compare left < 0; set CARRY if SIGNBIT(left) is set
5087 if (performedLt) emitSETC; else emitCLRC;
5088 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5089 if (performedLt) emitCLRC; else emitSETC;
5090 goto correct_result_in_carry;
5093 } // right is literal
5095 /*************************************************
5096 * perform a general case comparison *
5097 * make sure we get CARRY==1 <==> left >= right *
5098 *************************************************/
5099 // compare most significant bytes
5100 //DEBUGpc ("comparing bytes at offset %d", size);
5102 // unsigned comparison
5103 mov2w_regOrLit (AOP(right), lit, size);
5104 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5106 // signed comparison
5107 // (add 2^n to both operands then perform an unsigned comparison)
5108 if (isAOP_LIT(right)) {
5109 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5110 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5112 if (litbyte == 0x80) {
5113 // left >= 0x80 -- always true, but more bytes to come
5114 pic16_mov2w (AOP(left), size);
5115 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5118 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5119 pic16_mov2w (AOP(left), size);
5120 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5121 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5124 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5125 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5126 pic16_mov2w (AOP(left), size);
5127 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5128 pic16_emitpcode (POC_MOVWF, pctemp);
5129 pic16_mov2w (AOP(right), size);
5130 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131 pic16_emitpcode (POC_SUBFW, pctemp);
5132 //pic16_popReleaseTempReg(pctemp, 1);
5136 // compare remaining bytes (treat as unsigned case from above)
5137 templbl = newiTempLabel ( NULL );
5140 //DEBUGpc ("comparing bytes at offset %d", offs);
5141 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5142 mov2w_regOrLit (AOP(right), lit, offs);
5143 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5145 pic16_emitpLabel (templbl->key);
5146 goto result_in_carry;
5150 /****************************************************
5151 * now CARRY contains the result of the comparison: *
5152 * SUBWF sets CARRY iff *
5153 * F-W >= 0 <==> F >= W <==> !(F < W) *
5154 * (F=left, W=right) *
5155 ****************************************************/
5158 if (result && AOP_TYPE(result) != AOP_CRY) {
5159 // value will be stored
5162 // value wil only be used in the following genSkipc()
5163 rIfx.condition ^= 1;
5167 correct_result_in_carry:
5169 // assign result to variable (if neccessary)
5170 if (result && AOP_TYPE(result) != AOP_CRY) {
5171 //DEBUGpc ("assign result");
5172 size = AOP_SIZE(result);
5174 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5176 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5179 // perform conditional jump
5181 //DEBUGpc ("generate control flow");
5190 static void genCmp (operand *left,operand *right,
5191 operand *result, iCode *ifx, int sign)
5193 int size; //, offset = 0 ;
5194 unsigned long lit = 0L,i = 0;
5195 resolvedIfx rFalseIfx;
5196 // resolvedIfx rTrueIfx;
5198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5201 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5202 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5208 resolveIfx(&rFalseIfx,ifx);
5209 truelbl = newiTempLabel(NULL);
5210 size = max(AOP_SIZE(left),AOP_SIZE(right));
5212 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5216 /* if literal is on the right then swap with left */
5217 if ((AOP_TYPE(right) == AOP_LIT)) {
5218 operand *tmp = right ;
5219 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5220 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5223 lit = (lit - 1) & mask;
5226 rFalseIfx.condition ^= 1;
5229 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5230 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5234 //if(IC_TRUE(ifx) == NULL)
5235 /* if left & right are bit variables */
5236 if (AOP_TYPE(left) == AOP_CRY &&
5237 AOP_TYPE(right) == AOP_CRY ) {
5238 assert (0 && "bit variables used in genCmp");
5239 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5240 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5242 /* subtract right from left if at the
5243 end the carry flag is set then we know that
5244 left is greater than right */
5246 symbol *lbl = newiTempLabel(NULL);
5249 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5250 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5254 if(AOP_TYPE(right) == AOP_LIT) {
5256 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5258 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5265 genSkipCond(&rFalseIfx,left,size-1,7);
5267 /* no need to compare to 0...*/
5268 /* NOTE: this is a de-generate compare that most certainly
5269 * creates some dead code. */
5270 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5272 if(ifx) ifx->generated = 1;
5279 //i = (lit >> (size*8)) & 0xff;
5280 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5282 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5284 i = ((0-lit) & 0xff);
5287 /* lit is 0x7f, all signed chars are less than
5288 * this except for 0x7f itself */
5289 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5290 genSkipz2(&rFalseIfx,0);
5292 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5293 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5294 genSkipc(&rFalseIfx);
5299 genSkipz2(&rFalseIfx,1);
5301 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5302 genSkipc(&rFalseIfx);
5306 if(ifx) ifx->generated = 1;
5310 /* chars are out of the way. now do ints and longs */
5313 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5320 genSkipCond(&rFalseIfx,left,size,7);
5321 if(ifx) ifx->generated = 1;
5326 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5328 //rFalseIfx.condition ^= 1;
5329 //genSkipCond(&rFalseIfx,left,size,7);
5330 //rFalseIfx.condition ^= 1;
5332 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5333 if(rFalseIfx.condition)
5334 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5336 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5338 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5339 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5340 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5343 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5345 if(rFalseIfx.condition) {
5347 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5353 genSkipc(&rFalseIfx);
5354 pic16_emitpLabel(truelbl->key);
5355 if(ifx) ifx->generated = 1;
5362 if( (lit & 0xff) == 0) {
5363 /* lower byte is zero */
5364 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5365 i = ((lit >> 8) & 0xff) ^0x80;
5366 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5367 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5368 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5369 genSkipc(&rFalseIfx);
5372 if(ifx) ifx->generated = 1;
5377 /* Special cases for signed longs */
5378 if( (lit & 0xffffff) == 0) {
5379 /* lower byte is zero */
5380 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5381 i = ((lit >> 8*3) & 0xff) ^0x80;
5382 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5383 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5384 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5385 genSkipc(&rFalseIfx);
5388 if(ifx) ifx->generated = 1;
5396 if(lit & (0x80 << (size*8))) {
5397 /* lit is negative */
5398 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5400 //genSkipCond(&rFalseIfx,left,size,7);
5402 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5404 if(rFalseIfx.condition)
5405 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5407 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5411 /* lit is positive */
5412 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5413 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5414 if(rFalseIfx.condition)
5415 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5417 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5422 This works, but is only good for ints.
5423 It also requires a "known zero" register.
5424 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5425 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5426 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5427 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5428 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5429 genSkipc(&rFalseIfx);
5431 pic16_emitpLabel(truelbl->key);
5432 if(ifx) ifx->generated = 1;
5436 /* There are no more special cases, so perform a general compare */
5438 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5439 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5443 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5445 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447 //rFalseIfx.condition ^= 1;
5448 genSkipc(&rFalseIfx);
5450 pic16_emitpLabel(truelbl->key);
5452 if(ifx) ifx->generated = 1;
5459 /* sign is out of the way. So now do an unsigned compare */
5460 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5463 /* General case - compare to an unsigned literal on the right.*/
5465 i = (lit >> (size*8)) & 0xff;
5466 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5467 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5469 i = (lit >> (size*8)) & 0xff;
5472 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5476 /* this byte of the lit is zero,
5477 *if it's not the last then OR in the variable */
5479 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5484 pic16_emitpLabel(lbl->key);
5485 // pic16_emitpLabel(truelbl->key);
5486 //if(emitFinalCheck)
5487 genSkipc(&rFalseIfx);
5489 pic16_emitpLabel(truelbl->key);
5491 if(ifx) ifx->generated = 1;
5498 if(AOP_TYPE(left) == AOP_LIT) {
5499 //symbol *lbl = newiTempLabel(NULL);
5501 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5504 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5507 if((lit == 0) && (sign == 0)){
5510 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5512 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5514 genSkipz2(&rFalseIfx,0);
5515 if(ifx) ifx->generated = 1;
5522 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5523 /* degenerate compare can never be true */
5524 if(rFalseIfx.condition == 0)
5525 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5527 if(ifx) ifx->generated = 1;
5532 /* signed comparisons to a literal byte */
5534 int lp1 = (lit+1) & 0xff;
5536 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5539 rFalseIfx.condition ^= 1;
5540 genSkipCond(&rFalseIfx,right,0,7);
5543 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5544 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5545 genSkipz2(&rFalseIfx,1);
5548 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5549 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5550 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5551 rFalseIfx.condition ^= 1;
5552 genSkipc(&rFalseIfx);
5556 /* unsigned comparisons to a literal byte */
5558 switch(lit & 0xff ) {
5560 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5561 genSkipz2(&rFalseIfx,0);
5564 rFalseIfx.condition ^= 1;
5565 genSkipCond(&rFalseIfx,right,0,7);
5569 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5570 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5572 rFalseIfx.condition ^= 1;
5573 if (AOP_TYPE(result) == AOP_CRY)
5574 genSkipc(&rFalseIfx);
5576 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5577 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5583 if(ifx) ifx->generated = 1;
5584 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5590 /* Size is greater than 1 */
5598 /* this means lit = 0xffffffff, or -1 */
5601 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5602 rFalseIfx.condition ^= 1;
5603 genSkipCond(&rFalseIfx,right,size,7);
5604 if(ifx) ifx->generated = 1;
5606 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5615 if(rFalseIfx.condition) {
5616 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5617 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5620 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5622 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5626 if(rFalseIfx.condition) {
5627 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5628 pic16_emitpLabel(truelbl->key);
5630 rFalseIfx.condition ^= 1;
5631 genSkipCond(&rFalseIfx,right,s,7);
5634 if(ifx) ifx->generated = 1;
5636 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5642 if((size == 1) && (0 == (lp1&0xff))) {
5643 /* lower byte of signed word is zero */
5644 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5645 i = ((lp1 >> 8) & 0xff) ^0x80;
5646 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5647 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5648 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5650 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5652 if(ifx) ifx->generated = 1;
5655 rFalseIfx.condition ^= 1;
5656 genSkipc(&rFalseIfx);
5657 if(ifx) ifx->generated = 1;
5663 if(lit & (0x80 << (size*8))) {
5664 /* Lit is less than zero */
5665 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5666 //rFalseIfx.condition ^= 1;
5667 //genSkipCond(&rFalseIfx,left,size,7);
5668 //rFalseIfx.condition ^= 1;
5669 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5670 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5672 if(rFalseIfx.condition)
5673 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5675 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5679 /* Lit is greater than or equal to zero */
5680 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5681 //rFalseIfx.condition ^= 1;
5682 //genSkipCond(&rFalseIfx,right,size,7);
5683 //rFalseIfx.condition ^= 1;
5685 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5686 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5689 if(rFalseIfx.condition)
5690 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5692 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5697 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5703 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705 rFalseIfx.condition ^= 1;
5706 //rFalseIfx.condition = 1;
5707 genSkipc(&rFalseIfx);
5709 pic16_emitpLabel(truelbl->key);
5711 if(ifx) ifx->generated = 1;
5714 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5721 /* compare word or long to an unsigned literal on the right.*/
5726 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5729 break; /* handled above */
5732 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5734 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5735 genSkipz2(&rFalseIfx,0);
5739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5744 if(rFalseIfx.condition)
5745 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5747 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5750 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5751 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5753 rFalseIfx.condition ^= 1;
5754 genSkipc(&rFalseIfx);
5757 pic16_emitpLabel(truelbl->key);
5759 if(ifx) ifx->generated = 1;
5761 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5770 i = (lit >> (size*8)) & 0xff;
5772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5773 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5776 i = (lit >> (size*8)) & 0xff;
5779 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5781 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5783 /* this byte of the lit is zero,
5784 * if it's not the last then OR in the variable */
5786 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5791 pic16_emitpLabel(lbl->key);
5793 rFalseIfx.condition ^= 1;
5795 genSkipc(&rFalseIfx);
5799 pic16_emitpLabel(truelbl->key);
5800 if(ifx) ifx->generated = 1;
5802 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5808 /* Compare two variables */
5810 DEBUGpic16_emitcode(";sign","%d",sign);
5814 /* Sigh. thus sucks... */
5818 pctemp = pic16_popGetTempReg(1);
5819 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5820 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5822 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5823 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5824 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5825 pic16_popReleaseTempReg(pctemp, 1);
5827 /* Signed char comparison */
5828 /* Special thanks to Nikolai Golovchenko for this snippet */
5829 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5830 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5831 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5832 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5833 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5834 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5837 genSkipc(&rFalseIfx);
5839 if(ifx) ifx->generated = 1;
5841 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5850 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5854 /* The rest of the bytes of a multi-byte compare */
5858 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5861 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5862 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5867 pic16_emitpLabel(lbl->key);
5869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5870 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5871 (AOP_TYPE(result) == AOP_REG)) {
5872 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5873 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5875 genSkipc(&rFalseIfx);
5877 //genSkipc(&rFalseIfx);
5878 if(ifx) ifx->generated = 1;
5881 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889 if ((AOP_TYPE(result) != AOP_CRY)
5890 && AOP_SIZE(result)) {
5891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5893 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5895 pic16_outBitC(result);
5897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5898 /* if the result is used in the next
5899 ifx conditional branch then generate
5900 code a little differently */
5902 genIfxJump (ifx,"c");
5904 pic16_outBitC(result);
5905 /* leave the result in acc */
5910 #elif 0 /* VR version of genCmp() */ /* } else { */
5912 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5913 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5914 operand *result, int offset, int invert_op)
5918 /* check condition, > or < ?? */
5919 if(rIfx->condition != 0)invert_op ^= 1;
5921 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5923 if(!ifx)invert_op ^= 1;
5925 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5926 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5929 if(!invert_op)return POC_CPFSGT;
5930 else return POC_CPFSLT;
5933 static int compareAopfirstpass=1;
5935 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5936 operand *oper, int offset, operand *result,
5937 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5943 /* invert if there is a result to be loaded, in order to fit,
5944 * SETC/CLRC sequence */
5945 if(AOP_SIZE(result))invert_op ^= 1;
5947 // if(sign && !offset)invert_op ^= 1;
5949 // if(sign)invert_op ^= 1;
5951 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5953 if(AOP_SIZE(result) && compareAopfirstpass) {
5956 pic16_emitpcode(POC_SETF, pcop2);
5961 pic16_emitpcode(POC_CLRF, pcop2);
5967 compareAopfirstpass = 0;
5969 /* there is a bug when comparing operands with size > 1,
5970 * because higher bytes can be equal and test should be performed
5971 * to the next lower byte, current algorithm, considers operands
5972 * inequal in these cases! -- VR 20041107 */
5976 pic16_emitpcode(op, pcop);
5978 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5981 if((!sign || !offset) && AOP_SIZE(result)) {
5984 pic16_emitpcode(POC_CLRF, pcop2);
5989 pic16_emitpcode(POC_SETF, pcop2);
5994 /* don't emit final branch (offset == 0) */
5998 pic16_emitpcode(POC_RRCF, pcop2);
6000 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6003 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6004 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6005 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6007 truelbl = newiTempLabel( NULL );
6008 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6009 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6010 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6012 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6013 pic16_emitpLabel(truelbl->key);
6015 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020 static void genCmp (operand *left, operand *right,
6021 operand *result, iCode *ifx, int sign)
6025 resolvedIfx rFalseIfx;
6026 symbol *falselbl, *tlbl;
6030 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6032 resolveIfx(&rFalseIfx, ifx);
6033 size = max(AOP_SIZE(left), AOP_SIZE(right));
6035 /* if left & right are bit variables */
6036 if(AOP_TYPE(left) == AOP_CRY
6037 && AOP_TYPE(right) == AOP_CRY ) {
6039 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6040 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6042 werror(W_POSSBUG2, __FILE__, __LINE__);
6046 /* if literal is on the right then swap with left */
6047 if((AOP_TYPE(right) == AOP_LIT)) {
6048 operand *tmp = right ;
6049 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6051 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6053 // lit = (lit - 1) & mask;
6056 rFalseIfx.condition ^= 1; /* reverse compare */
6058 if ((AOP_TYPE(left) == AOP_LIT)) {
6059 /* float compares are handled by support functions */
6060 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6063 /* actual comparing algorithm */
6064 // size = AOP_SIZE( right );
6066 falselbl = newiTempLabel( NULL );
6067 if(AOP_TYPE(left) == AOP_LIT) {
6068 /* compare to literal */
6069 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6072 pCodeOp *pct, *pct2;
6075 /* signed compare */
6076 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6078 pct = pic16_popCopyReg(&pic16_pc_prodl);
6079 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6080 tlbl = newiTempLabel( NULL );
6082 /* first compare signs:
6083 * a. if both are positive, compare just like unsigned
6084 * b. if both are negative, invert cmpop, compare just like unsigned
6085 * c. if different signs, determine the result directly */
6091 tlbl1 = newiTempLabel( NULL );
6092 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6096 /* literal is zero or positive:
6097 * a. if carry is zero, too, continue compare,
6098 * b. if carry is set, then continue depending on cmpop ^ condition:
6099 * 1. '<' return false (literal < variable),
6100 * 2. '>' return true (literal > variable) */
6101 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6102 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6105 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6106 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6110 /* literal is negative:
6111 * a. if carry is set, too, continue compare,
6112 * b. if carry is zero, then continue depending on cmpop ^ condition:
6113 * 1. '<' return true (literal < variable),
6114 * 2. '>' return false (literal > variable) */
6115 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6116 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6118 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6119 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6124 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6126 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6132 pic16_emitpLabel( tlbl1->key );
6135 compareAopfirstpass=1;
6136 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6137 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6138 // pic16_emitpcode(POC_MOVWF, pct);
6140 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6141 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6142 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6143 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6147 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6148 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6149 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6150 // pic16_emitpcode(POC_MOVWF, pct);
6152 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6153 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6154 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6155 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6156 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6160 if(ifx)ifx->generated = 1;
6162 if(AOP_SIZE(result)) {
6163 pic16_emitpLabel(tlbl->key);
6164 pic16_emitpLabel(falselbl->key);
6165 pic16_outBitOp( result, pct2 );
6167 pic16_emitpLabel(tlbl->key);
6171 /* unsigned compare */
6172 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6174 compareAopfirstpass=1;
6177 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6178 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6181 if(ifx)ifx->generated = 1;
6183 if(AOP_SIZE(result)) {
6184 pic16_emitpLabel(falselbl->key);
6185 pic16_outBitC( result );
6190 /* compare registers */
6191 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6195 pCodeOp *pct, *pct2;
6197 /* signed compare */
6198 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6200 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6201 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6202 tlbl = newiTempLabel( NULL );
6204 compareAopfirstpass=1;
6207 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6208 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6209 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6210 pic16_emitpcode(POC_MOVWF, pct);
6212 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6213 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6214 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6216 /* WREG already holds left + 0x80 */
6217 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6220 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6221 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6222 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6223 pic16_emitpcode(POC_MOVWF, pct);
6225 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6226 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6229 /* WREG already holds left + 0x80 */
6230 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6231 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6234 if(ifx)ifx->generated = 1;
6236 if(AOP_SIZE(result)) {
6237 pic16_emitpLabel(tlbl->key);
6238 pic16_emitpLabel(falselbl->key);
6239 pic16_outBitOp( result, pct2 );
6241 pic16_emitpLabel(tlbl->key);
6245 /* unsigned compare */
6246 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6248 compareAopfirstpass=1;
6251 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6252 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6256 if(ifx)ifx->generated = 1;
6257 if(AOP_SIZE(result)) {
6259 pic16_emitpLabel(falselbl->key);
6260 pic16_outBitC( result );
6271 /*-----------------------------------------------------------------*/
6272 /* genCmpGt :- greater than comparison */
6273 /*-----------------------------------------------------------------*/
6274 static void genCmpGt (iCode *ic, iCode *ifx)
6276 operand *left, *right, *result;
6277 sym_link *letype , *retype;
6283 right= IC_RIGHT(ic);
6284 result = IC_RESULT(ic);
6286 letype = getSpec(operandType(left));
6287 retype =getSpec(operandType(right));
6288 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6289 /* assign the amsops */
6290 pic16_aopOp (left,ic,FALSE);
6291 pic16_aopOp (right,ic,FALSE);
6292 pic16_aopOp (result,ic,TRUE);
6294 genCmp(right, left, result, ifx, sign);
6296 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6297 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298 pic16_freeAsmop(result,NULL,ic,TRUE);
6301 /*-----------------------------------------------------------------*/
6302 /* genCmpLt - less than comparisons */
6303 /*-----------------------------------------------------------------*/
6304 static void genCmpLt (iCode *ic, iCode *ifx)
6306 operand *left, *right, *result;
6307 sym_link *letype , *retype;
6313 right= IC_RIGHT(ic);
6314 result = IC_RESULT(ic);
6316 letype = getSpec(operandType(left));
6317 retype =getSpec(operandType(right));
6318 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6320 /* assign the amsops */
6321 pic16_aopOp (left,ic,FALSE);
6322 pic16_aopOp (right,ic,FALSE);
6323 pic16_aopOp (result,ic,TRUE);
6325 genCmp(left, right, result, ifx, sign);
6327 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6328 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329 pic16_freeAsmop(result,NULL,ic,TRUE);
6334 // FIXME reenable literal optimisation when the pic16 port is stable
6336 /*-----------------------------------------------------------------*/
6337 /* genc16bit2lit - compare a 16 bit value to a literal */
6338 /*-----------------------------------------------------------------*/
6339 static void genc16bit2lit(operand *op, int lit, int offset)
6343 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6344 if( (lit&0xff) == 0)
6349 switch( BYTEofLONG(lit,i)) {
6351 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6354 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6357 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6360 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6366 switch( BYTEofLONG(lit,i)) {
6368 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6372 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6376 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6379 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6381 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6390 /*-----------------------------------------------------------------*/
6391 /* gencjneshort - compare and jump if not equal */
6392 /*-----------------------------------------------------------------*/
6393 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6395 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6397 int res_offset = 0; /* the result may be a different size then left or right */
6398 int res_size = AOP_SIZE(result);
6400 symbol *lbl, *lbl_done;
6402 unsigned long lit = 0L;
6403 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6405 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6406 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6408 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6409 resolveIfx(&rIfx,ifx);
6410 lbl = newiTempLabel(NULL);
6411 lbl_done = newiTempLabel(NULL);
6414 /* if the left side is a literal or
6415 if the right is in a pointer register and left
6417 if ((AOP_TYPE(left) == AOP_LIT) ||
6418 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6423 if(AOP_TYPE(right) == AOP_LIT)
6424 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6426 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6427 preserve_result = 1;
6429 if(result && !preserve_result)
6432 for(i = 0; i < AOP_SIZE(result); i++)
6433 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6437 /* if the right side is a literal then anything goes */
6438 if (AOP_TYPE(right) == AOP_LIT &&
6439 AOP_TYPE(left) != AOP_DIR ) {
6442 genc16bit2lit(left, lit, 0);
6444 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6450 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6451 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6453 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6459 if(res_offset < res_size-1)
6467 /* if the right side is in a register or in direct space or
6468 if the left is a pointer register & right is not */
6469 else if (AOP_TYPE(right) == AOP_REG ||
6470 AOP_TYPE(right) == AOP_DIR ||
6471 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6472 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6473 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6474 int lbl_key = lbl->key;
6477 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6478 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6480 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6481 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6482 __FUNCTION__,__LINE__);
6486 /* switch(size) { */
6488 /* genc16bit2lit(left, lit, 0); */
6490 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6495 if((AOP_TYPE(left) == AOP_DIR) &&
6496 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6498 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6499 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6501 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6503 switch (lit & 0xff) {
6505 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6508 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6509 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6510 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6514 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6516 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6521 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6522 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6527 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6530 if(AOP_TYPE(result) == AOP_CRY) {
6531 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6536 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6538 /* fix me. probably need to check result size too */
6539 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6544 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6545 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6552 if(res_offset < res_size-1)
6557 } else if(AOP_TYPE(right) == AOP_REG &&
6558 AOP_TYPE(left) != AOP_DIR){
6561 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6562 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6563 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6568 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6570 if(res_offset < res_size-1)
6575 /* right is a pointer reg need both a & b */
6577 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6579 pic16_emitcode("mov","b,%s",l);
6580 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6581 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6586 if(result && preserve_result)
6589 for(i = 0; i < AOP_SIZE(result); i++)
6590 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6593 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6595 if(result && preserve_result)
6596 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6599 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6601 pic16_emitpLabel(lbl->key);
6603 if(result && preserve_result)
6606 for(i = 0; i < AOP_SIZE(result); i++)
6607 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6609 pic16_emitpLabel(lbl_done->key);
6612 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6620 /*-----------------------------------------------------------------*/
6621 /* gencjne - compare and jump if not equal */
6622 /*-----------------------------------------------------------------*/
6623 static void gencjne(operand *left, operand *right, iCode *ifx)
6625 symbol *tlbl = newiTempLabel(NULL);
6627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6628 gencjneshort(left, right, lbl);
6630 pic16_emitcode("mov","a,%s",one);
6631 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6632 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6633 pic16_emitcode("clr","a");
6634 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6636 pic16_emitpLabel(lbl->key);
6637 pic16_emitpLabel(tlbl->key);
6643 /*-----------------------------------------------------------------*/
6644 /* is_LitOp - check if operand has to be treated as literal */
6645 /*-----------------------------------------------------------------*/
6646 static bool is_LitOp(operand *op)
6648 return ((AOP_TYPE(op) == AOP_LIT)
6649 || ( (AOP_TYPE(op) == AOP_PCODE)
6650 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6651 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6654 /*-----------------------------------------------------------------*/
6655 /* is_LitAOp - check if operand has to be treated as literal */
6656 /*-----------------------------------------------------------------*/
6657 static bool is_LitAOp(asmop *aop)
6659 return ((aop->type == AOP_LIT)
6660 || ( (aop->type == AOP_PCODE)
6661 && ( (aop->aopu.pcop->type == PO_LITERAL)
6662 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6667 /*-----------------------------------------------------------------*/
6668 /* genCmpEq - generates code for equal to */
6669 /*-----------------------------------------------------------------*/
6670 static void genCmpEq (iCode *ic, iCode *ifx)
6672 operand *left, *right, *result;
6673 symbol *falselbl = newiTempLabel(NULL);
6674 symbol *donelbl = newiTempLabel(NULL);
6676 int preserve_result = 0;
6677 int generate_result = 0;
6679 unsigned long lit = -1;
6683 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6684 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6685 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6687 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6689 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6691 werror(W_POSSBUG2, __FILE__, __LINE__);
6692 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6693 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6697 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6699 operand *tmp = right ;
6704 if (AOP_TYPE(right) == AOP_LIT) {
6705 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6708 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6709 preserve_result = 1;
6711 if(result && AOP_SIZE(result))
6712 generate_result = 1;
6714 if(generate_result && !preserve_result)
6716 for(i = 0; i < AOP_SIZE(result); i++)
6717 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6720 for(i=0; i < AOP_SIZE(left); i++)
6722 if(AOP_TYPE(left) != AOP_ACC)
6725 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6727 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6729 if(is_LitOp(right)) {
6730 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6731 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6734 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6736 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6741 if(generate_result && preserve_result)
6743 for(i = 0; i < AOP_SIZE(result); i++)
6744 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6748 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6750 if(generate_result && preserve_result)
6751 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6753 if(ifx && IC_TRUE(ifx))
6754 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6756 if(ifx && IC_FALSE(ifx))
6757 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6759 pic16_emitpLabel(falselbl->key);
6763 if(ifx && IC_FALSE(ifx))
6764 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6766 if(generate_result && preserve_result)
6768 for(i = 0; i < AOP_SIZE(result); i++)
6769 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6772 pic16_emitpLabel(donelbl->key);
6778 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6779 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6780 pic16_freeAsmop(result,NULL,ic,TRUE);
6786 // old version kept for reference
6788 /*-----------------------------------------------------------------*/
6789 /* genCmpEq - generates code for equal to */
6790 /*-----------------------------------------------------------------*/
6791 static void genCmpEq (iCode *ic, iCode *ifx)
6793 operand *left, *right, *result;
6794 unsigned long lit = 0L;
6796 symbol *falselbl = newiTempLabel(NULL);
6799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6802 DEBUGpic16_emitcode ("; ifx is non-null","");
6804 DEBUGpic16_emitcode ("; ifx is null","");
6806 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6807 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6808 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6810 size = max(AOP_SIZE(left),AOP_SIZE(right));
6812 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6814 /* if literal, literal on the right or
6815 if the right is in a pointer register and left
6817 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6818 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6819 operand *tmp = right ;
6825 if(ifx && !AOP_SIZE(result)){
6827 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6828 /* if they are both bit variables */
6829 if (AOP_TYPE(left) == AOP_CRY &&
6830 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6831 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6832 if(AOP_TYPE(right) == AOP_LIT){
6833 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6835 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6836 pic16_emitcode("cpl","c");
6837 } else if(lit == 1L) {
6838 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840 pic16_emitcode("clr","c");
6842 /* AOP_TYPE(right) == AOP_CRY */
6844 symbol *lbl = newiTempLabel(NULL);
6845 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6846 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6847 pic16_emitcode("cpl","c");
6848 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6850 /* if true label then we jump if condition
6852 tlbl = newiTempLabel(NULL);
6853 if ( IC_TRUE(ifx) ) {
6854 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6855 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6857 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6858 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6860 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6863 /* left and right are both bit variables, result is carry */
6866 resolveIfx(&rIfx,ifx);
6868 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6869 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6870 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6871 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6876 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6878 /* They're not both bit variables. Is the right a literal? */
6879 if(AOP_TYPE(right) == AOP_LIT) {
6880 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6885 switch(lit & 0xff) {
6887 if ( IC_TRUE(ifx) ) {
6888 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6890 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6892 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6893 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6897 if ( IC_TRUE(ifx) ) {
6898 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6900 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6902 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6903 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6907 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6909 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6914 /* end of size == 1 */
6918 genc16bit2lit(left,lit,offset);
6921 /* end of size == 2 */
6926 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6927 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6928 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6929 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6932 /* search for patterns that can be optimized */
6934 genc16bit2lit(left,lit,0);
6938 emitSKPZ; // if hi word unequal
6940 emitSKPNZ; // if hi word equal
6942 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6943 genc16bit2lit(left,lit,2);
6946 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6947 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6951 pic16_emitpLabel(falselbl->key);
6960 } else if(AOP_TYPE(right) == AOP_CRY ) {
6961 /* we know the left is not a bit, but that the right is */
6962 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6963 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6964 pic16_popGet(AOP(right),offset));
6965 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6967 /* if the two are equal, then W will be 0 and the Z bit is set
6968 * we could test Z now, or go ahead and check the high order bytes if
6969 * the variable we're comparing is larger than a byte. */
6972 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6974 if ( IC_TRUE(ifx) ) {
6976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6977 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6981 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6985 /* They're both variables that are larger than bits */
6988 tlbl = newiTempLabel(NULL);
6991 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6992 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6994 if ( IC_TRUE(ifx) ) {
6998 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7001 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7005 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7009 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7014 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7017 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7021 if(s>1 && IC_TRUE(ifx)) {
7022 pic16_emitpLabel(tlbl->key);
7023 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7027 /* mark the icode as generated */
7032 /* if they are both bit variables */
7033 if (AOP_TYPE(left) == AOP_CRY &&
7034 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7035 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7036 if(AOP_TYPE(right) == AOP_LIT){
7037 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7039 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7040 pic16_emitcode("cpl","c");
7041 } else if(lit == 1L) {
7042 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044 pic16_emitcode("clr","c");
7046 /* AOP_TYPE(right) == AOP_CRY */
7048 symbol *lbl = newiTempLabel(NULL);
7049 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7050 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7051 pic16_emitcode("cpl","c");
7052 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7055 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7056 pic16_outBitC(result);
7060 genIfxJump (ifx,"c");
7063 /* if the result is used in an arithmetic operation
7064 then put the result in place */
7065 pic16_outBitC(result);
7068 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7069 gencjne(left,right,result,ifx);
7072 gencjne(left,right,newiTempLabel(NULL));
7074 if(IC_TRUE(ifx)->key)
7075 gencjne(left,right,IC_TRUE(ifx)->key);
7077 gencjne(left,right,IC_FALSE(ifx)->key);
7081 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7082 pic16_aopPut(AOP(result),"a",0);
7087 genIfxJump (ifx,"a");
7091 /* if the result is used in an arithmetic operation
7092 then put the result in place */
7094 if (AOP_TYPE(result) != AOP_CRY)
7095 pic16_outAcc(result);
7097 /* leave the result in acc */
7101 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7102 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7103 pic16_freeAsmop(result,NULL,ic,TRUE);
7107 /*-----------------------------------------------------------------*/
7108 /* ifxForOp - returns the icode containing the ifx for operand */
7109 /*-----------------------------------------------------------------*/
7110 static iCode *ifxForOp ( operand *op, iCode *ic )
7114 /* if true symbol then needs to be assigned */
7115 if (IS_TRUE_SYMOP(op))
7118 /* if this has register type condition and
7119 the next instruction is ifx with the same operand
7120 and live to of the operand is upto the ifx only then */
7122 && ic->next->op == IFX
7123 && IC_COND(ic->next)->key == op->key
7124 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7126 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7132 ic->next->op == IFX &&
7133 IC_COND(ic->next)->key == op->key) {
7134 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7139 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7141 ic->next->op == IFX)
7142 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7145 ic->next->op == IFX &&
7146 IC_COND(ic->next)->key == op->key) {
7147 DEBUGpic16_emitcode ("; "," key is okay");
7148 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7149 OP_SYMBOL(op)->liveTo,
7154 /* the code below is completely untested
7155 * it just allows ulong2fs.c compile -- VR */
7158 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7159 __FILE__, __FUNCTION__, __LINE__);
7161 /* if this has register type condition and
7162 the next instruction is ifx with the same operand
7163 and live to of the operand is upto the ifx only then */
7165 ic->next->op == IFX &&
7166 IC_COND(ic->next)->key == op->key &&
7167 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7171 ic->next->op == IFX &&
7172 IC_COND(ic->next)->key == op->key) {
7173 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7177 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7178 __FILE__, __FUNCTION__, __LINE__);
7180 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7185 /*-----------------------------------------------------------------*/
7186 /* genAndOp - for && operation */
7187 /*-----------------------------------------------------------------*/
7188 static void genAndOp (iCode *ic)
7190 operand *left,*right, *result;
7195 /* note here that && operations that are in an
7196 if statement are taken away by backPatchLabels
7197 only those used in arthmetic operations remain */
7198 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7199 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7200 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7202 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7204 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7205 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7206 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7208 /* if both are bit variables */
7209 /* if (AOP_TYPE(left) == AOP_CRY && */
7210 /* AOP_TYPE(right) == AOP_CRY ) { */
7211 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7212 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7213 /* pic16_outBitC(result); */
7215 /* tlbl = newiTempLabel(NULL); */
7216 /* pic16_toBoolean(left); */
7217 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7218 /* pic16_toBoolean(right); */
7219 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7220 /* pic16_outBitAcc(result); */
7223 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7224 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7225 pic16_freeAsmop(result,NULL,ic,TRUE);
7229 /*-----------------------------------------------------------------*/
7230 /* genOrOp - for || operation */
7231 /*-----------------------------------------------------------------*/
7234 modified this code, but it doesn't appear to ever get called
7237 static void genOrOp (iCode *ic)
7239 operand *left,*right, *result;
7244 /* note here that || operations that are in an
7245 if statement are taken away by backPatchLabels
7246 only those used in arthmetic operations remain */
7247 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7248 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7249 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7251 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7253 /* if both are bit variables */
7254 if (AOP_TYPE(left) == AOP_CRY &&
7255 AOP_TYPE(right) == AOP_CRY ) {
7256 pic16_emitcode("clrc","");
7257 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7258 AOP(left)->aopu.aop_dir,
7259 AOP(left)->aopu.aop_dir);
7260 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7261 AOP(right)->aopu.aop_dir,
7262 AOP(right)->aopu.aop_dir);
7263 pic16_emitcode("setc","");
7266 tlbl = newiTempLabel(NULL);
7267 pic16_toBoolean(left);
7269 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7270 pic16_toBoolean(right);
7271 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7273 pic16_outBitAcc(result);
7276 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7277 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7278 pic16_freeAsmop(result,NULL,ic,TRUE);
7281 /*-----------------------------------------------------------------*/
7282 /* isLiteralBit - test if lit == 2^n */
7283 /*-----------------------------------------------------------------*/
7284 static int isLiteralBit(unsigned long lit)
7286 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7287 0x100L,0x200L,0x400L,0x800L,
7288 0x1000L,0x2000L,0x4000L,0x8000L,
7289 0x10000L,0x20000L,0x40000L,0x80000L,
7290 0x100000L,0x200000L,0x400000L,0x800000L,
7291 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7292 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7295 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7296 for(idx = 0; idx < 32; idx++)
7302 /*-----------------------------------------------------------------*/
7303 /* continueIfTrue - */
7304 /*-----------------------------------------------------------------*/
7305 static void continueIfTrue (iCode *ic)
7309 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7313 /*-----------------------------------------------------------------*/
7315 /*-----------------------------------------------------------------*/
7316 static void jumpIfTrue (iCode *ic)
7320 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7324 /*-----------------------------------------------------------------*/
7325 /* jmpTrueOrFalse - */
7326 /*-----------------------------------------------------------------*/
7327 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7329 // ugly but optimized by peephole
7332 symbol *nlbl = newiTempLabel(NULL);
7333 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7334 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7335 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7336 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7338 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7339 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7344 /*-----------------------------------------------------------------*/
7345 /* genAnd - code for and */
7346 /*-----------------------------------------------------------------*/
7347 static void genAnd (iCode *ic, iCode *ifx)
7349 operand *left, *right, *result;
7351 unsigned long lit = 0L;
7357 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7358 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7359 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7361 resolveIfx(&rIfx,ifx);
7363 /* if left is a literal & right is not then exchange them */
7364 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7365 AOP_NEEDSACC(left)) {
7366 operand *tmp = right ;
7371 /* if result = right then exchange them */
7372 if(pic16_sameRegs(AOP(result),AOP(right))){
7373 operand *tmp = right ;
7378 /* if right is bit then exchange them */
7379 if (AOP_TYPE(right) == AOP_CRY &&
7380 AOP_TYPE(left) != AOP_CRY){
7381 operand *tmp = right ;
7385 if(AOP_TYPE(right) == AOP_LIT)
7386 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7388 size = AOP_SIZE(result);
7390 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7393 // result = bit & yy;
7394 if (AOP_TYPE(left) == AOP_CRY){
7395 // c = bit & literal;
7396 if(AOP_TYPE(right) == AOP_LIT){
7398 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7401 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7404 if(size && (AOP_TYPE(result) == AOP_CRY)){
7405 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7408 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7412 pic16_emitcode("clr","c");
7415 if (AOP_TYPE(right) == AOP_CRY){
7417 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7418 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7423 pic16_emitcode("rrc","a");
7424 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7430 pic16_outBitC(result);
7432 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7433 genIfxJump(ifx, "c");
7437 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7438 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7439 if((AOP_TYPE(right) == AOP_LIT) &&
7440 (AOP_TYPE(result) == AOP_CRY) &&
7441 (AOP_TYPE(left) != AOP_CRY)){
7442 int posbit = isLiteralBit(lit);
7446 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7449 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7455 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7456 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7458 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7462 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7463 size = AOP_SIZE(left);
7466 int bp = posbit, ofs=0;
7473 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7474 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7478 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7479 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7481 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7488 symbol *tlbl = newiTempLabel(NULL);
7489 int sizel = AOP_SIZE(left);
7495 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7497 /* patch provided by Aaron Colwell */
7498 if((posbit = isLiteralBit(bytelit)) != 0) {
7499 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7500 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7501 (posbit-1),0, PO_GPR_REGISTER));
7503 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7504 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7506 if (bytelit == 0xff) {
7507 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7508 * a peephole could optimize it out -- VR */
7509 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7511 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7512 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7515 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7516 pic16_popGetLabel(tlbl->key));
7520 /* old code, left here for reference -- VR 09/2004 */
7521 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7523 if((posbit = isLiteralBit(bytelit)) != 0)
7524 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7526 if(bytelit != 0x0FFL)
7527 pic16_emitcode("anl","a,%s",
7528 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7529 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7535 // bit = left & literal
7538 pic16_emitpLabel(tlbl->key);
7540 // if(left & literal)
7543 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7546 pic16_emitpLabel(tlbl->key);
7551 pic16_outBitC(result);
7555 /* if left is same as result */
7556 if(pic16_sameRegs(AOP(result),AOP(left))){
7558 for(;size--; offset++,lit>>=8) {
7559 if(AOP_TYPE(right) == AOP_LIT){
7560 switch(lit & 0xff) {
7562 /* and'ing with 0 has clears the result */
7563 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7564 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7567 /* and'ing with 0xff is a nop when the result and left are the same */
7572 int p = pic16_my_powof2( (~lit) & 0xff );
7574 /* only one bit is set in the literal, so use a bcf instruction */
7575 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7576 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7579 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7580 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7581 if(know_W != (lit&0xff))
7582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7584 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7589 if (AOP_TYPE(left) == AOP_ACC) {
7590 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7592 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7593 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7600 // left & result in different registers
7601 if(AOP_TYPE(result) == AOP_CRY){
7603 // if(size), result in bit
7604 // if(!size && ifx), conditional oper: if(left & right)
7605 symbol *tlbl = newiTempLabel(NULL);
7606 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7608 pic16_emitcode("setb","c");
7610 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7611 pic16_emitcode("anl","a,%s",
7612 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7613 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7618 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7619 pic16_outBitC(result);
7621 jmpTrueOrFalse(ifx, tlbl);
7623 for(;(size--);offset++) {
7625 // result = left & right
7626 if(AOP_TYPE(right) == AOP_LIT){
7627 int t = (lit >> (offset*8)) & 0x0FFL;
7630 pic16_emitcode("clrf","%s",
7631 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7632 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7635 pic16_emitcode("movf","%s,w",
7636 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7637 pic16_emitcode("movwf","%s",
7638 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7639 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7640 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7643 pic16_emitcode("movlw","0x%x",t);
7644 pic16_emitcode("andwf","%s,w",
7645 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7646 pic16_emitcode("movwf","%s",
7647 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7649 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7650 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7651 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7656 if (AOP_TYPE(left) == AOP_ACC) {
7657 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7658 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7660 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7661 pic16_emitcode("andwf","%s,w",
7662 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7663 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7664 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7666 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7667 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7673 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7674 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675 pic16_freeAsmop(result,NULL,ic,TRUE);
7678 /*-----------------------------------------------------------------*/
7679 /* genOr - code for or */
7680 /*-----------------------------------------------------------------*/
7681 static void genOr (iCode *ic, iCode *ifx)
7683 operand *left, *right, *result;
7685 unsigned long lit = 0L;
7687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7689 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7690 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7691 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7693 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7695 /* if left is a literal & right is not then exchange them */
7696 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7697 AOP_NEEDSACC(left)) {
7698 operand *tmp = right ;
7703 /* if result = right then exchange them */
7704 if(pic16_sameRegs(AOP(result),AOP(right))){
7705 operand *tmp = right ;
7710 /* if right is bit then exchange them */
7711 if (AOP_TYPE(right) == AOP_CRY &&
7712 AOP_TYPE(left) != AOP_CRY){
7713 operand *tmp = right ;
7718 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7720 if(AOP_TYPE(right) == AOP_LIT)
7721 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7723 size = AOP_SIZE(result);
7727 if (AOP_TYPE(left) == AOP_CRY){
7728 if(AOP_TYPE(right) == AOP_LIT){
7729 // c = bit & literal;
7731 // lit != 0 => result = 1
7732 if(AOP_TYPE(result) == AOP_CRY){
7734 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7735 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7736 // AOP(result)->aopu.aop_dir,
7737 // AOP(result)->aopu.aop_dir);
7739 continueIfTrue(ifx);
7743 // lit == 0 => result = left
7744 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7746 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7749 if (AOP_TYPE(right) == AOP_CRY){
7750 if(pic16_sameRegs(AOP(result),AOP(left))){
7752 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7753 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7754 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7756 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7757 AOP(result)->aopu.aop_dir,
7758 AOP(result)->aopu.aop_dir);
7759 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7760 AOP(right)->aopu.aop_dir,
7761 AOP(right)->aopu.aop_dir);
7762 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7763 AOP(result)->aopu.aop_dir,
7764 AOP(result)->aopu.aop_dir);
7766 if( AOP_TYPE(result) == AOP_ACC) {
7767 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7768 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7769 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7774 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7775 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7776 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7777 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7779 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7780 AOP(result)->aopu.aop_dir,
7781 AOP(result)->aopu.aop_dir);
7782 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7783 AOP(right)->aopu.aop_dir,
7784 AOP(right)->aopu.aop_dir);
7785 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7786 AOP(left)->aopu.aop_dir,
7787 AOP(left)->aopu.aop_dir);
7788 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7789 AOP(result)->aopu.aop_dir,
7790 AOP(result)->aopu.aop_dir);
7795 symbol *tlbl = newiTempLabel(NULL);
7796 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7799 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7800 if( AOP_TYPE(right) == AOP_ACC) {
7801 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7803 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7804 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7809 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7810 pic16_emitcode(";XXX setb","c");
7811 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7812 AOP(left)->aopu.aop_dir,tlbl->key+100);
7813 pic16_toBoolean(right);
7814 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7815 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7816 jmpTrueOrFalse(ifx, tlbl);
7820 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7827 pic16_outBitC(result);
7829 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7830 genIfxJump(ifx, "c");
7834 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7835 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7836 if((AOP_TYPE(right) == AOP_LIT) &&
7837 (AOP_TYPE(result) == AOP_CRY) &&
7838 (AOP_TYPE(left) != AOP_CRY)){
7840 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7843 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7845 continueIfTrue(ifx);
7848 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849 // lit = 0, result = boolean(left)
7851 pic16_emitcode(";XXX setb","c");
7852 pic16_toBoolean(right);
7854 symbol *tlbl = newiTempLabel(NULL);
7855 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7857 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7859 genIfxJump (ifx,"a");
7863 pic16_outBitC(result);
7867 /* if left is same as result */
7868 if(pic16_sameRegs(AOP(result),AOP(left))){
7870 for(;size--; offset++,lit>>=8) {
7871 if(AOP_TYPE(right) == AOP_LIT){
7872 if((lit & 0xff) == 0)
7873 /* or'ing with 0 has no effect */
7876 int p = pic16_my_powof2(lit & 0xff);
7878 /* only one bit is set in the literal, so use a bsf instruction */
7879 pic16_emitpcode(POC_BSF,
7880 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7882 if(know_W != (lit & 0xff))
7883 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7884 know_W = lit & 0xff;
7885 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7890 if (AOP_TYPE(left) == AOP_ACC) {
7891 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7892 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7895 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7897 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7904 // left & result in different registers
7905 if(AOP_TYPE(result) == AOP_CRY){
7907 // if(size), result in bit
7908 // if(!size && ifx), conditional oper: if(left | right)
7909 symbol *tlbl = newiTempLabel(NULL);
7910 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7911 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7915 pic16_emitcode(";XXX setb","c");
7917 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7918 pic16_emitcode(";XXX orl","a,%s",
7919 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7925 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7926 pic16_outBitC(result);
7928 jmpTrueOrFalse(ifx, tlbl);
7929 } else for(;(size--);offset++){
7931 // result = left & right
7932 if(AOP_TYPE(right) == AOP_LIT){
7933 int t = (lit >> (offset*8)) & 0x0FFL;
7936 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7939 pic16_emitcode("movf","%s,w",
7940 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7941 pic16_emitcode("movwf","%s",
7942 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7945 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7946 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7949 pic16_emitcode("movlw","0x%x",t);
7950 pic16_emitcode("iorwf","%s,w",
7951 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7952 pic16_emitcode("movwf","%s",
7953 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7959 // faster than result <- left, anl result,right
7960 // and better if result is SFR
7961 if (AOP_TYPE(left) == AOP_ACC) {
7962 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7963 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7966 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7968 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7969 pic16_emitcode("iorwf","%s,w",
7970 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7973 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7978 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7979 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7980 pic16_freeAsmop(result,NULL,ic,TRUE);
7983 /*-----------------------------------------------------------------*/
7984 /* genXor - code for xclusive or */
7985 /*-----------------------------------------------------------------*/
7986 static void genXor (iCode *ic, iCode *ifx)
7988 operand *left, *right, *result;
7990 unsigned long lit = 0L;
7992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7994 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7995 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7996 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7998 /* if left is a literal & right is not ||
7999 if left needs acc & right does not */
8000 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8001 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8002 operand *tmp = right ;
8007 /* if result = right then exchange them */
8008 if(pic16_sameRegs(AOP(result),AOP(right))){
8009 operand *tmp = right ;
8014 /* if right is bit then exchange them */
8015 if (AOP_TYPE(right) == AOP_CRY &&
8016 AOP_TYPE(left) != AOP_CRY){
8017 operand *tmp = right ;
8021 if(AOP_TYPE(right) == AOP_LIT)
8022 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8024 size = AOP_SIZE(result);
8028 if (AOP_TYPE(left) == AOP_CRY){
8029 if(AOP_TYPE(right) == AOP_LIT){
8030 // c = bit & literal;
8032 // lit>>1 != 0 => result = 1
8033 if(AOP_TYPE(result) == AOP_CRY){
8035 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8036 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8038 continueIfTrue(ifx);
8041 pic16_emitcode("setb","c");
8045 // lit == 0, result = left
8046 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8048 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8050 // lit == 1, result = not(left)
8051 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8052 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8053 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8054 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8057 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8058 pic16_emitcode("cpl","c");
8065 symbol *tlbl = newiTempLabel(NULL);
8066 if (AOP_TYPE(right) == AOP_CRY){
8068 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8071 int sizer = AOP_SIZE(right);
8073 // if val>>1 != 0, result = 1
8074 pic16_emitcode("setb","c");
8076 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8078 // test the msb of the lsb
8079 pic16_emitcode("anl","a,#0xfe");
8080 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8084 pic16_emitcode("rrc","a");
8086 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8087 pic16_emitcode("cpl","c");
8088 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8093 pic16_outBitC(result);
8095 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8096 genIfxJump(ifx, "c");
8100 if(pic16_sameRegs(AOP(result),AOP(left))){
8101 /* if left is same as result */
8102 for(;size--; offset++) {
8103 if(AOP_TYPE(right) == AOP_LIT){
8104 int t = (lit >> (offset*8)) & 0x0FFL;
8108 if (IS_AOP_PREG(left)) {
8109 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8110 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8111 pic16_aopPut(AOP(result),"a",offset);
8113 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8114 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8115 pic16_emitcode("xrl","%s,%s",
8116 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8117 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8120 if (AOP_TYPE(left) == AOP_ACC)
8121 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8123 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8124 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8126 if (IS_AOP_PREG(left)) {
8127 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8128 pic16_aopPut(AOP(result),"a",offset);
8130 pic16_emitcode("xrl","%s,a",
8131 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8137 // left & result in different registers
8138 if(AOP_TYPE(result) == AOP_CRY){
8140 // if(size), result in bit
8141 // if(!size && ifx), conditional oper: if(left ^ right)
8142 symbol *tlbl = newiTempLabel(NULL);
8143 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8145 pic16_emitcode("setb","c");
8147 if((AOP_TYPE(right) == AOP_LIT) &&
8148 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8149 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8151 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8152 pic16_emitcode("xrl","a,%s",
8153 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8160 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8161 pic16_outBitC(result);
8163 jmpTrueOrFalse(ifx, tlbl);
8164 } else for(;(size--);offset++){
8166 // result = left & right
8167 if(AOP_TYPE(right) == AOP_LIT){
8168 int t = (lit >> (offset*8)) & 0x0FFL;
8171 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8173 pic16_emitcode("movf","%s,w",
8174 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8175 pic16_emitcode("movwf","%s",
8176 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8179 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181 pic16_emitcode("comf","%s,w",
8182 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183 pic16_emitcode("movwf","%s",
8184 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8188 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8189 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8190 pic16_emitcode("movlw","0x%x",t);
8191 pic16_emitcode("xorwf","%s,w",
8192 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8193 pic16_emitcode("movwf","%s",
8194 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8200 // faster than result <- left, anl result,right
8201 // and better if result is SFR
8202 if (AOP_TYPE(left) == AOP_ACC) {
8203 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8204 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8206 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8207 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8208 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8209 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8211 if ( AOP_TYPE(result) != AOP_ACC){
8212 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8213 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8219 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8220 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8221 pic16_freeAsmop(result,NULL,ic,TRUE);
8224 /*-----------------------------------------------------------------*/
8225 /* genInline - write the inline code out */
8226 /*-----------------------------------------------------------------*/
8227 static void genInline (iCode *ic)
8229 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"))) {
8246 cbuf = Safe_strdup( buffer );
8254 cbuf = Safe_strdup(buffer);
8255 cblen = strlen(buffer)+1;
8256 memset(cbuf, 0, cblen);
8261 if(*bp != '%')*bp1++ = *bp++;
8267 if(i>elementsInSet(asmInlineMap))break;
8270 s = indexSet(asmInlineMap, i);
8271 DEBUGpc("searching symbol s = `%s'", s);
8272 sym = findSym(SymbolTab, NULL, s);
8275 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8277 strcat(bp1, sym->rname);
8283 if(strlen(bp1) > cblen - 16) {
8284 int i = strlen(cbuf);
8286 cbuf = realloc(cbuf, cblen);
8287 memset(cbuf+i, 0, 50);
8293 buffer = Safe_strdup( cbuf );
8299 /* emit each line as a code */
8305 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8313 /* print label, use this special format with NULL directive
8314 * to denote that the argument should not be indented with tab */
8315 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8322 if ((bp1 != bp) && *bp1)
8323 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8328 _G.inLine -= (!options.asmpeep);
8331 /*-----------------------------------------------------------------*/
8332 /* genRRC - rotate right with carry */
8333 /*-----------------------------------------------------------------*/
8334 static void genRRC (iCode *ic)
8336 operand *left , *result ;
8337 int size, offset = 0, same;
8339 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8341 /* rotate right with carry */
8343 result=IC_RESULT(ic);
8344 pic16_aopOp (left,ic,FALSE);
8345 pic16_aopOp (result,ic,TRUE);
8347 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8349 same = pic16_sameRegs(AOP(result),AOP(left));
8351 size = AOP_SIZE(result);
8353 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8355 /* get the lsb and put it into the carry */
8356 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8363 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8365 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8366 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8372 pic16_freeAsmop(left,NULL,ic,TRUE);
8373 pic16_freeAsmop(result,NULL,ic,TRUE);
8376 /*-----------------------------------------------------------------*/
8377 /* genRLC - generate code for rotate left with carry */
8378 /*-----------------------------------------------------------------*/
8379 static void genRLC (iCode *ic)
8381 operand *left , *result ;
8382 int size, offset = 0;
8385 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8386 /* rotate right with carry */
8388 result=IC_RESULT(ic);
8389 pic16_aopOp (left,ic,FALSE);
8390 pic16_aopOp (result,ic,TRUE);
8392 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8394 same = pic16_sameRegs(AOP(result),AOP(left));
8396 /* move it to the result */
8397 size = AOP_SIZE(result);
8399 /* get the msb and put it into the carry */
8400 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8407 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8409 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8410 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8417 pic16_freeAsmop(left,NULL,ic,TRUE);
8418 pic16_freeAsmop(result,NULL,ic,TRUE);
8422 /* gpasm can get the highest order bit with HIGH/UPPER
8423 * so the following probably is not needed -- VR */
8425 /*-----------------------------------------------------------------*/
8426 /* genGetHbit - generates code get highest order bit */
8427 /*-----------------------------------------------------------------*/
8428 static void genGetHbit (iCode *ic)
8430 operand *left, *result;
8432 result=IC_RESULT(ic);
8433 pic16_aopOp (left,ic,FALSE);
8434 pic16_aopOp (result,ic,FALSE);
8436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8437 /* get the highest order byte into a */
8438 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8439 if(AOP_TYPE(result) == AOP_CRY){
8440 pic16_emitcode("rlc","a");
8441 pic16_outBitC(result);
8444 pic16_emitcode("rl","a");
8445 pic16_emitcode("anl","a,#0x01");
8446 pic16_outAcc(result);
8450 pic16_freeAsmop(left,NULL,ic,TRUE);
8451 pic16_freeAsmop(result,NULL,ic,TRUE);
8455 /*-----------------------------------------------------------------*/
8456 /* AccRol - rotate left accumulator by known count */
8457 /*-----------------------------------------------------------------*/
8458 static void AccRol (int shCount)
8460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8461 shCount &= 0x0007; // shCount : 0..7
8466 pic16_emitcode("rl","a");
8469 pic16_emitcode("rl","a");
8470 pic16_emitcode("rl","a");
8473 pic16_emitcode("swap","a");
8474 pic16_emitcode("rr","a");
8477 pic16_emitcode("swap","a");
8480 pic16_emitcode("swap","a");
8481 pic16_emitcode("rl","a");
8484 pic16_emitcode("rr","a");
8485 pic16_emitcode("rr","a");
8488 pic16_emitcode("rr","a");
8494 /*-----------------------------------------------------------------*/
8495 /* AccLsh - left shift accumulator by known count */
8496 /*-----------------------------------------------------------------*/
8497 static void AccLsh (int shCount)
8499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8505 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8509 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8513 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8534 /*-----------------------------------------------------------------*/
8535 /* AccRsh - right shift accumulator by known count */
8536 /*-----------------------------------------------------------------*/
8537 static void AccRsh (int shCount, int andmask)
8539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8544 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8547 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8548 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8552 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8558 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8573 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8577 /*-----------------------------------------------------------------*/
8578 /* AccSRsh - signed right shift accumulator by known count */
8579 /*-----------------------------------------------------------------*/
8580 static void AccSRsh (int shCount)
8583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8586 pic16_emitcode("mov","c,acc.7");
8587 pic16_emitcode("rrc","a");
8588 } else if(shCount == 2){
8589 pic16_emitcode("mov","c,acc.7");
8590 pic16_emitcode("rrc","a");
8591 pic16_emitcode("mov","c,acc.7");
8592 pic16_emitcode("rrc","a");
8594 tlbl = newiTempLabel(NULL);
8595 /* rotate right accumulator */
8596 AccRol(8 - shCount);
8597 /* and kill the higher order bits */
8598 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8599 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8600 pic16_emitcode("orl","a,#0x%02x",
8601 (unsigned char)~SRMask[shCount]);
8602 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8608 /*-----------------------------------------------------------------*/
8609 /* shiftR1Left2Result - shift right one byte from left to result */
8610 /*-----------------------------------------------------------------*/
8611 static void shiftR1Left2ResultSigned (operand *left, int offl,
8612 operand *result, int offr,
8617 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8619 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8623 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8625 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8627 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8634 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8636 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8638 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8639 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8641 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8648 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8650 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8651 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8654 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8655 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8656 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8658 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8659 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8661 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8665 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8666 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8667 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8668 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8678 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8680 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8681 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8687 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8689 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8690 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8691 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8692 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8694 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8696 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8698 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8705 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8707 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8711 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8719 /*-----------------------------------------------------------------*/
8720 /* shiftR1Left2Result - shift right one byte from left to result */
8721 /*-----------------------------------------------------------------*/
8722 static void shiftR1Left2Result (operand *left, int offl,
8723 operand *result, int offr,
8724 int shCount, int sign)
8728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8730 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8732 /* Copy the msb into the carry if signed. */
8734 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8744 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8746 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8753 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8755 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8756 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8764 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8767 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8771 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8777 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8778 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8779 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8784 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8785 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8793 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8794 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8795 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8801 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8802 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8803 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8812 /*-----------------------------------------------------------------*/
8813 /* shiftL1Left2Result - shift left one byte from left to result */
8814 /*-----------------------------------------------------------------*/
8815 static void shiftL1Left2Result (operand *left, int offl,
8816 operand *result, int offr, int shCount)
8821 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8823 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8824 DEBUGpic16_emitcode ("; ***","same = %d",same);
8825 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8827 /* shift left accumulator */
8828 //AccLsh(shCount); // don't comment out just yet...
8829 // pic16_aopPut(AOP(result),"a",offr);
8833 /* Shift left 1 bit position */
8834 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8836 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8838 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8839 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8843 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8844 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8845 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8846 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8849 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8850 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8851 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8853 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8857 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8858 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8861 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8862 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8863 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8868 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8869 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8875 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8880 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8885 /*-----------------------------------------------------------------*/
8886 /* movLeft2Result - move byte from left to result */
8887 /*-----------------------------------------------------------------*/
8888 static void movLeft2Result (operand *left, int offl,
8889 operand *result, int offr)
8892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8893 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8894 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8896 if (*l == '@' && (IS_AOP_PREG(result))) {
8897 pic16_emitcode("mov","a,%s",l);
8898 pic16_aopPut(AOP(result),"a",offr);
8900 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8901 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906 /*-----------------------------------------------------------------*/
8907 /* shiftL2Left2Result - shift left two bytes from left to result */
8908 /*-----------------------------------------------------------------*/
8909 static void shiftL2Left2Result (operand *left, int offl,
8910 operand *result, int offr, int shCount)
8912 int same = pic16_sameRegs(AOP(result), AOP(left));
8915 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8917 if (same && (offl != offr)) { // shift bytes
8920 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8921 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8923 } else { // just treat as different later on
8936 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8937 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8942 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8943 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8950 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8951 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8952 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8957 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8962 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8963 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8968 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8974 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8976 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8977 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8988 /* note, use a mov/add for the shift since the mov has a
8989 chance of getting optimized out */
8990 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8992 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8994 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8998 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8999 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9005 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9006 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9008 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9011 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9017 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9021 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9022 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9029 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9030 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9036 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9037 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9038 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9039 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9045 /*-----------------------------------------------------------------*/
9046 /* shiftR2Left2Result - shift right two bytes from left to result */
9047 /*-----------------------------------------------------------------*/
9048 static void shiftR2Left2Result (operand *left, int offl,
9049 operand *result, int offr,
9050 int shCount, int sign)
9052 int same = pic16_sameRegs(AOP(result), AOP(left));
9054 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9056 if (same && (offl != offr)) { // shift right bytes
9059 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9060 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9062 } else { // just treat as different later on
9074 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9079 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9082 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9083 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9084 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9090 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9093 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9094 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9101 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9102 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9106 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9107 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9108 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9110 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9111 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9112 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9115 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9116 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9117 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9118 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9123 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9127 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9128 pic16_emitpcode(POC_BTFSC,
9129 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9130 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9138 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9139 pic16_emitpcode(POC_RLCF, 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));
9143 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9146 pic16_emitpcode(POC_BTFSC,
9147 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9148 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9150 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9151 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9152 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9156 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9158 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9162 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9164 pic16_emitpcode(POC_BTFSC,
9165 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9166 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9168 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9169 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9177 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9179 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9182 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9184 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9189 /*-----------------------------------------------------------------*/
9190 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9191 /*-----------------------------------------------------------------*/
9192 static void shiftLLeftOrResult (operand *left, int offl,
9193 operand *result, int offr, int shCount)
9195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9197 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9198 /* shift left accumulator */
9200 /* or with result */
9201 /* back to result */
9202 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9205 /*-----------------------------------------------------------------*/
9206 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9207 /*-----------------------------------------------------------------*/
9208 static void shiftRLeftOrResult (operand *left, int offl,
9209 operand *result, int offr, int shCount)
9211 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9213 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9214 /* shift right accumulator */
9216 /* or with result */
9217 /* back to result */
9218 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9221 /*-----------------------------------------------------------------*/
9222 /* genlshOne - left shift a one byte quantity by known count */
9223 /*-----------------------------------------------------------------*/
9224 static void genlshOne (operand *result, operand *left, int shCount)
9226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9227 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9230 /*-----------------------------------------------------------------*/
9231 /* genlshTwo - left shift two bytes by known amount != 0 */
9232 /*-----------------------------------------------------------------*/
9233 static void genlshTwo (operand *result,operand *left, int shCount)
9237 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9238 size = pic16_getDataSize(result);
9240 /* if shCount >= 8 */
9246 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9248 movLeft2Result(left, LSB, result, MSB16);
9250 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9253 /* 1 <= shCount <= 7 */
9256 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9258 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9262 /*-----------------------------------------------------------------*/
9263 /* shiftLLong - shift left one long from left to result */
9264 /* offr = LSB or MSB16 */
9265 /*-----------------------------------------------------------------*/
9266 static void shiftLLong (operand *left, operand *result, int offr )
9268 int size = AOP_SIZE(result);
9269 int same = pic16_sameRegs(AOP(left),AOP(result));
9272 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9274 if (same && (offr == MSB16)) { //shift one byte
9275 for(i=size-1;i>=MSB16;i--) {
9276 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9277 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9280 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9283 if (size > LSB+offr ){
9285 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9287 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9288 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9292 if(size > MSB16+offr){
9294 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9296 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9297 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9301 if(size > MSB24+offr){
9303 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9305 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9306 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9310 if(size > MSB32+offr){
9312 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9314 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9315 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9319 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9323 /*-----------------------------------------------------------------*/
9324 /* genlshFour - shift four byte by a known amount != 0 */
9325 /*-----------------------------------------------------------------*/
9326 static void genlshFour (operand *result, operand *left, int shCount)
9330 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9331 size = AOP_SIZE(result);
9333 /* if shifting more that 3 bytes */
9334 if (shCount >= 24 ) {
9337 /* lowest order of left goes to the highest
9338 order of the destination */
9339 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9341 movLeft2Result(left, LSB, result, MSB32);
9343 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9344 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9345 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9350 /* more than two bytes */
9351 else if ( shCount >= 16 ) {
9352 /* lower order two bytes goes to higher order two bytes */
9354 /* if some more remaining */
9356 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9358 movLeft2Result(left, MSB16, result, MSB32);
9359 movLeft2Result(left, LSB, result, MSB24);
9361 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9362 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9366 /* if more than 1 byte */
9367 else if ( shCount >= 8 ) {
9368 /* lower order three bytes goes to higher order three bytes */
9372 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9374 movLeft2Result(left, LSB, result, MSB16);
9376 else{ /* size = 4 */
9378 movLeft2Result(left, MSB24, result, MSB32);
9379 movLeft2Result(left, MSB16, result, MSB24);
9380 movLeft2Result(left, LSB, result, MSB16);
9381 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9383 else if(shCount == 1)
9384 shiftLLong(left, result, MSB16);
9386 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9387 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9388 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9389 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9394 /* 1 <= shCount <= 7 */
9395 else if(shCount <= 3)
9397 shiftLLong(left, result, LSB);
9398 while(--shCount >= 1)
9399 shiftLLong(result, result, LSB);
9401 /* 3 <= shCount <= 7, optimize */
9403 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9404 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9405 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9409 /*-----------------------------------------------------------------*/
9410 /* genLeftShiftLiteral - left shifting by known count */
9411 /*-----------------------------------------------------------------*/
9412 void pic16_genLeftShiftLiteral (operand *left,
9417 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9421 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9422 pic16_freeAsmop(right,NULL,ic,TRUE);
9424 pic16_aopOp(left,ic,FALSE);
9425 pic16_aopOp(result,ic,TRUE);
9427 size = getSize(operandType(result));
9430 pic16_emitcode("; shift left ","result %d, left %d",size,
9434 /* I suppose that the left size >= result size */
9437 movLeft2Result(left, size, result, size);
9441 else if(shCount >= (size * 8))
9443 pic16_aopPut(AOP(result),zero,size);
9447 genlshOne (result,left,shCount);
9452 genlshTwo (result,left,shCount);
9456 genlshFour (result,left,shCount);
9460 pic16_freeAsmop(left,NULL,ic,TRUE);
9461 pic16_freeAsmop(result,NULL,ic,TRUE);
9464 /*-----------------------------------------------------------------*
9465 * genMultiAsm - repeat assembly instruction for size of register.
9466 * if endian == 1, then the high byte (i.e base address + size of
9467 * register) is used first else the low byte is used first;
9468 *-----------------------------------------------------------------*/
9469 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9474 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9487 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9493 #if !(USE_GENERIC_SIGNED_SHIFT)
9494 /*-----------------------------------------------------------------*/
9495 /* genLeftShift - generates code for left shifting */
9496 /*-----------------------------------------------------------------*/
9497 static void genLeftShift (iCode *ic)
9499 operand *left,*right, *result;
9502 symbol *tlbl , *tlbl1;
9505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9507 right = IC_RIGHT(ic);
9509 result = IC_RESULT(ic);
9511 pic16_aopOp(right,ic,FALSE);
9513 /* if the shift count is known then do it
9514 as efficiently as possible */
9515 if (AOP_TYPE(right) == AOP_LIT) {
9516 pic16_genLeftShiftLiteral (left,right,result,ic);
9520 /* shift count is unknown then we have to form
9521 * a loop. Get the loop count in WREG : Note: we take
9522 * only the lower order byte since shifting
9523 * more than 32 bits make no sense anyway, ( the
9524 * largest size of an object can be only 32 bits ) */
9526 pic16_aopOp(left,ic,FALSE);
9527 pic16_aopOp(result,ic,FALSE);
9529 /* now move the left to the result if they are not the
9530 * same, and if size > 1,
9531 * and if right is not same to result (!!!) -- VR */
9532 if (!pic16_sameRegs(AOP(left),AOP(result))
9533 && (AOP_SIZE(result) > 1)) {
9535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9537 size = AOP_SIZE(result);
9542 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9543 if (*l == '@' && (IS_AOP_PREG(result))) {
9545 pic16_emitcode("mov","a,%s",l);
9546 pic16_aopPut(AOP(result),"a",offset);
9550 /* we don't know if left is a literal or a register, take care -- VR */
9551 mov2f(AOP(result), AOP(left), offset);
9557 size = AOP_SIZE(result);
9559 /* if it is only one byte then */
9561 if(optimized_for_speed) {
9562 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9563 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9564 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9565 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9566 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9567 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9568 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9569 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9570 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9571 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9572 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9573 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9576 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9578 tlbl = newiTempLabel(NULL);
9581 /* this is already done, why change it? */
9582 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9583 mov2f(AOP(result), AOP(left), 0);
9587 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9588 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9589 pic16_emitpLabel(tlbl->key);
9590 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9591 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9593 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9598 if (pic16_sameRegs(AOP(left),AOP(result))) {
9600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9602 tlbl = newiTempLabel(NULL);
9603 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9604 genMultiAsm(POC_RRCF, result, size,1);
9605 pic16_emitpLabel(tlbl->key);
9606 genMultiAsm(POC_RLCF, result, size,0);
9607 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9609 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9613 //tlbl = newiTempLabel(NULL);
9615 //tlbl1 = newiTempLabel(NULL);
9617 //reAdjustPreg(AOP(result));
9619 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9620 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9621 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9623 //pic16_emitcode("add","a,acc");
9624 //pic16_aopPut(AOP(result),"a",offset++);
9626 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9628 // pic16_emitcode("rlc","a");
9629 // pic16_aopPut(AOP(result),"a",offset++);
9631 //reAdjustPreg(AOP(result));
9633 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9634 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9637 tlbl = newiTempLabel(NULL);
9638 tlbl1= newiTempLabel(NULL);
9640 size = AOP_SIZE(result);
9643 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9645 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9647 /* offset should be 0, 1 or 3 */
9649 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9651 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9653 pic16_emitpcode(POC_MOVWF, pctemp);
9656 pic16_emitpLabel(tlbl->key);
9659 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9661 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9663 pic16_emitpcode(POC_DECFSZ, pctemp);
9664 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9665 pic16_emitpLabel(tlbl1->key);
9667 pic16_popReleaseTempReg(pctemp,1);
9671 pic16_freeAsmop (right,NULL,ic,TRUE);
9672 pic16_freeAsmop(left,NULL,ic,TRUE);
9673 pic16_freeAsmop(result,NULL,ic,TRUE);
9679 #error old code (left here for reference)
9680 /*-----------------------------------------------------------------*/
9681 /* genLeftShift - generates code for left shifting */
9682 /*-----------------------------------------------------------------*/
9683 static void genLeftShift (iCode *ic)
9685 operand *left,*right, *result;
9688 symbol *tlbl , *tlbl1;
9691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9693 right = IC_RIGHT(ic);
9695 result = IC_RESULT(ic);
9697 pic16_aopOp(right,ic,FALSE);
9699 /* if the shift count is known then do it
9700 as efficiently as possible */
9701 if (AOP_TYPE(right) == AOP_LIT) {
9702 pic16_genLeftShiftLiteral (left,right,result,ic);
9706 /* shift count is unknown then we have to form
9707 a loop get the loop count in B : Note: we take
9708 only the lower order byte since shifting
9709 more that 32 bits make no sense anyway, ( the
9710 largest size of an object can be only 32 bits ) */
9713 pic16_aopOp(left,ic,FALSE);
9714 pic16_aopOp(result,ic,FALSE);
9716 /* now move the left to the result if they are not the
9718 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9719 AOP_SIZE(result) > 1) {
9721 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9723 size = AOP_SIZE(result);
9726 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9727 if (*l == '@' && (IS_AOP_PREG(result))) {
9729 pic16_emitcode("mov","a,%s",l);
9730 pic16_aopPut(AOP(result),"a",offset);
9733 /* we don't know if left is a literal or a register, take care -- VR */
9734 mov2f(AOP(result), AOP(left), offset);
9740 size = AOP_SIZE(result);
9742 /* if it is only one byte then */
9744 if(optimized_for_speed) {
9745 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9746 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9747 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9750 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9751 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9752 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9753 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9754 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9755 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9756 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9761 tlbl = newiTempLabel(NULL);
9762 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9763 mov2f(AOP(result), AOP(left), 0);
9765 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9766 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9769 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9770 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9771 pic16_emitpLabel(tlbl->key);
9772 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9773 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9780 if (pic16_sameRegs(AOP(left),AOP(result))) {
9782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9784 tlbl = newiTempLabel(NULL);
9785 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9786 genMultiAsm(POC_RRCF, result, size,1);
9787 pic16_emitpLabel(tlbl->key);
9788 genMultiAsm(POC_RLCF, result, size,0);
9789 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9791 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9795 //tlbl = newiTempLabel(NULL);
9797 //tlbl1 = newiTempLabel(NULL);
9799 //reAdjustPreg(AOP(result));
9801 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9802 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9803 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9805 //pic16_emitcode("add","a,acc");
9806 //pic16_aopPut(AOP(result),"a",offset++);
9808 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9810 // pic16_emitcode("rlc","a");
9811 // pic16_aopPut(AOP(result),"a",offset++);
9813 //reAdjustPreg(AOP(result));
9815 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9816 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9819 tlbl = newiTempLabel(NULL);
9820 tlbl1= newiTempLabel(NULL);
9822 size = AOP_SIZE(result);
9825 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9827 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9829 /* offset should be 0, 1 or 3 */
9831 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9833 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9835 pic16_emitpcode(POC_MOVWF, pctemp);
9838 pic16_emitpLabel(tlbl->key);
9841 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9843 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9845 pic16_emitpcode(POC_DECFSZ, pctemp);
9846 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9847 pic16_emitpLabel(tlbl1->key);
9849 pic16_popReleaseTempReg(pctemp,1);
9853 pic16_freeAsmop (right,NULL,ic,TRUE);
9854 pic16_freeAsmop(left,NULL,ic,TRUE);
9855 pic16_freeAsmop(result,NULL,ic,TRUE);
9859 /*-----------------------------------------------------------------*/
9860 /* genrshOne - right shift a one byte quantity by known count */
9861 /*-----------------------------------------------------------------*/
9862 static void genrshOne (operand *result, operand *left,
9863 int shCount, int sign)
9865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9866 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9869 /*-----------------------------------------------------------------*/
9870 /* genrshTwo - right shift two bytes by known amount != 0 */
9871 /*-----------------------------------------------------------------*/
9872 static void genrshTwo (operand *result,operand *left,
9873 int shCount, int sign)
9875 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9876 /* if shCount >= 8 */
9880 shiftR1Left2Result(left, MSB16, result, LSB,
9883 movLeft2Result(left, MSB16, result, LSB);
9885 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9888 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9889 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9893 /* 1 <= shCount <= 7 */
9895 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9898 /*-----------------------------------------------------------------*/
9899 /* shiftRLong - shift right one long from left to result */
9900 /* offl = LSB or MSB16 */
9901 /*-----------------------------------------------------------------*/
9902 static void shiftRLong (operand *left, int offl,
9903 operand *result, int sign)
9905 int size = AOP_SIZE(result);
9906 int same = pic16_sameRegs(AOP(left),AOP(result));
9908 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9910 if (same && (offl == MSB16)) { //shift one byte right
9911 for(i=MSB16;i<size;i++) {
9912 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9913 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9918 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9924 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9926 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9927 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9931 /* add sign of "a" */
9932 pic16_addSign(result, MSB32, sign);
9936 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9938 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9943 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9945 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9950 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9953 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9959 /*-----------------------------------------------------------------*/
9960 /* genrshFour - shift four byte by a known amount != 0 */
9961 /*-----------------------------------------------------------------*/
9962 static void genrshFour (operand *result, operand *left,
9963 int shCount, int sign)
9965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9966 /* if shifting more that 3 bytes */
9967 if(shCount >= 24 ) {
9970 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9972 movLeft2Result(left, MSB32, result, LSB);
9974 pic16_addSign(result, MSB16, sign);
9976 else if(shCount >= 16){
9979 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9981 movLeft2Result(left, MSB24, result, LSB);
9982 movLeft2Result(left, MSB32, result, MSB16);
9984 pic16_addSign(result, MSB24, sign);
9986 else if(shCount >= 8){
9989 shiftRLong(left, MSB16, result, sign);
9990 else if(shCount == 0){
9991 movLeft2Result(left, MSB16, result, LSB);
9992 movLeft2Result(left, MSB24, result, MSB16);
9993 movLeft2Result(left, MSB32, result, MSB24);
9994 pic16_addSign(result, MSB32, sign);
9996 else{ //shcount >= 2
9997 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9998 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9999 /* the last shift is signed */
10000 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10001 pic16_addSign(result, MSB32, sign);
10004 else{ /* 1 <= shCount <= 7 */
10006 shiftRLong(left, LSB, result, sign);
10008 shiftRLong(result, LSB, result, sign);
10011 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10012 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10013 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10018 /*-----------------------------------------------------------------*/
10019 /* genRightShiftLiteral - right shifting by known count */
10020 /*-----------------------------------------------------------------*/
10021 static void genRightShiftLiteral (operand *left,
10027 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10028 int lsize,res_size;
10030 pic16_freeAsmop(right,NULL,ic,TRUE);
10032 pic16_aopOp(left,ic,FALSE);
10033 pic16_aopOp(result,ic,TRUE);
10035 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10038 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10042 lsize = pic16_getDataSize(left);
10043 res_size = pic16_getDataSize(result);
10044 /* test the LEFT size !!! */
10046 /* I suppose that the left size >= result size */
10048 assert (res_size <= lsize);
10049 while (res_size--) {
10050 mov2f (AOP(result), AOP(left), res_size);
10054 else if(shCount >= (lsize * 8)){
10056 if(res_size == 1) {
10057 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10059 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10060 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10066 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10067 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10074 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10079 switch (res_size) {
10081 genrshOne (result,left,shCount,sign);
10085 genrshTwo (result,left,shCount,sign);
10089 genrshFour (result,left,shCount,sign);
10097 pic16_freeAsmop(left,NULL,ic,TRUE);
10098 pic16_freeAsmop(result,NULL,ic,TRUE);
10101 #if !(USE_GENERIC_SIGNED_SHIFT)
10102 /*-----------------------------------------------------------------*/
10103 /* genSignedRightShift - right shift of signed number */
10104 /*-----------------------------------------------------------------*/
10105 static void genSignedRightShift (iCode *ic)
10107 operand *right, *left, *result;
10110 symbol *tlbl, *tlbl1 ;
10113 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10115 /* we do it the hard way put the shift count in b
10116 and loop thru preserving the sign */
10117 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10119 right = IC_RIGHT(ic);
10120 left = IC_LEFT(ic);
10121 result = IC_RESULT(ic);
10123 pic16_aopOp(right,ic,FALSE);
10124 pic16_aopOp(left,ic,FALSE);
10125 pic16_aopOp(result,ic,FALSE);
10128 if ( AOP_TYPE(right) == AOP_LIT) {
10129 genRightShiftLiteral (left,right,result,ic,1);
10132 /* shift count is unknown then we have to form
10133 a loop get the loop count in B : Note: we take
10134 only the lower order byte since shifting
10135 more that 32 bits make no sense anyway, ( the
10136 largest size of an object can be only 32 bits ) */
10138 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10139 //pic16_emitcode("inc","b");
10140 //pic16_freeAsmop (right,NULL,ic,TRUE);
10141 //pic16_aopOp(left,ic,FALSE);
10142 //pic16_aopOp(result,ic,FALSE);
10144 /* now move the left to the result if they are not the
10146 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10147 AOP_SIZE(result) > 1) {
10149 size = AOP_SIZE(result);
10153 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10154 if (*l == '@' && IS_AOP_PREG(result)) {
10156 pic16_emitcode("mov","a,%s",l);
10157 pic16_aopPut(AOP(result),"a",offset);
10159 pic16_aopPut(AOP(result),l,offset);
10161 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10162 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10168 /* mov the highest order bit to OVR */
10169 tlbl = newiTempLabel(NULL);
10170 tlbl1= newiTempLabel(NULL);
10172 size = AOP_SIZE(result);
10175 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10177 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10179 /* offset should be 0, 1 or 3 */
10180 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10182 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10184 pic16_emitpcode(POC_MOVWF, pctemp);
10187 pic16_emitpLabel(tlbl->key);
10189 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10190 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10193 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10196 pic16_emitpcode(POC_DECFSZ, pctemp);
10197 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10198 pic16_emitpLabel(tlbl1->key);
10200 pic16_popReleaseTempReg(pctemp,1);
10202 size = AOP_SIZE(result);
10204 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10205 pic16_emitcode("rlc","a");
10206 pic16_emitcode("mov","ov,c");
10207 /* if it is only one byte then */
10209 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10211 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10212 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10213 pic16_emitcode("mov","c,ov");
10214 pic16_emitcode("rrc","a");
10215 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10216 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10217 pic16_aopPut(AOP(result),"a",0);
10221 reAdjustPreg(AOP(result));
10222 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10223 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10224 pic16_emitcode("mov","c,ov");
10226 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10228 pic16_emitcode("rrc","a");
10229 pic16_aopPut(AOP(result),"a",offset--);
10231 reAdjustPreg(AOP(result));
10232 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10233 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10238 pic16_freeAsmop(left,NULL,ic,TRUE);
10239 pic16_freeAsmop(result,NULL,ic,TRUE);
10240 pic16_freeAsmop(right,NULL,ic,TRUE);
10244 #if !(USE_GENERIC_SIGNED_SHIFT)
10245 #warning This implementation of genRightShift() is incomplete!
10246 /*-----------------------------------------------------------------*/
10247 /* genRightShift - generate code for right shifting */
10248 /*-----------------------------------------------------------------*/
10249 static void genRightShift (iCode *ic)
10251 operand *right, *left, *result;
10255 symbol *tlbl, *tlbl1 ;
10257 /* if signed then we do it the hard way preserve the
10258 sign bit moving it inwards */
10259 letype = getSpec(operandType(IC_LEFT(ic)));
10260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10262 if (!SPEC_USIGN(letype)) {
10263 genSignedRightShift (ic);
10267 /* signed & unsigned types are treated the same : i.e. the
10268 signed is NOT propagated inwards : quoting from the
10269 ANSI - standard : "for E1 >> E2, is equivalent to division
10270 by 2**E2 if unsigned or if it has a non-negative value,
10271 otherwise the result is implementation defined ", MY definition
10272 is that the sign does not get propagated */
10274 right = IC_RIGHT(ic);
10275 left = IC_LEFT(ic);
10276 result = IC_RESULT(ic);
10278 pic16_aopOp(right,ic,FALSE);
10280 /* if the shift count is known then do it
10281 as efficiently as possible */
10282 if (AOP_TYPE(right) == AOP_LIT) {
10283 genRightShiftLiteral (left,right,result,ic, 0);
10287 /* shift count is unknown then we have to form
10288 a loop get the loop count in B : Note: we take
10289 only the lower order byte since shifting
10290 more that 32 bits make no sense anyway, ( the
10291 largest size of an object can be only 32 bits ) */
10293 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10294 pic16_emitcode("inc","b");
10295 pic16_aopOp(left,ic,FALSE);
10296 pic16_aopOp(result,ic,FALSE);
10298 /* now move the left to the result if they are not the
10300 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10301 AOP_SIZE(result) > 1) {
10303 size = AOP_SIZE(result);
10306 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10307 if (*l == '@' && IS_AOP_PREG(result)) {
10309 pic16_emitcode("mov","a,%s",l);
10310 pic16_aopPut(AOP(result),"a",offset);
10312 pic16_aopPut(AOP(result),l,offset);
10317 tlbl = newiTempLabel(NULL);
10318 tlbl1= newiTempLabel(NULL);
10319 size = AOP_SIZE(result);
10322 /* if it is only one byte then */
10325 tlbl = newiTempLabel(NULL);
10326 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10327 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10328 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10331 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10332 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10333 pic16_emitpLabel(tlbl->key);
10334 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10337 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10342 reAdjustPreg(AOP(result));
10343 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10344 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10347 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10349 pic16_emitcode("rrc","a");
10350 pic16_aopPut(AOP(result),"a",offset--);
10352 reAdjustPreg(AOP(result));
10354 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10355 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10358 pic16_freeAsmop(left,NULL,ic,TRUE);
10359 pic16_freeAsmop (right,NULL,ic,TRUE);
10360 pic16_freeAsmop(result,NULL,ic,TRUE);
10364 #if (USE_GENERIC_SIGNED_SHIFT)
10365 /*-----------------------------------------------------------------*/
10366 /* genGenericShift - generates code for left or right shifting */
10367 /*-----------------------------------------------------------------*/
10368 static void genGenericShift (iCode *ic, int isShiftLeft) {
10369 operand *left,*right, *result;
10371 int sign, signedCount;
10372 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10373 PIC_OPCODE pos_shift, neg_shift;
10377 right = IC_RIGHT(ic);
10378 left = IC_LEFT(ic);
10379 result = IC_RESULT(ic);
10381 pic16_aopOp(right,ic,FALSE);
10382 pic16_aopOp(left,ic,FALSE);
10383 pic16_aopOp(result,ic,TRUE);
10385 sign = !SPEC_USIGN(operandType (left));
10386 signedCount = !SPEC_USIGN(operandType (right));
10388 /* if the shift count is known then do it
10389 as efficiently as possible */
10390 if (AOP_TYPE(right) == AOP_LIT) {
10391 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10392 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10393 // we should modify right->aopu.aop_lit here!
10394 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10395 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10397 pic16_genLeftShiftLiteral (left,right,result,ic);
10399 genRightShiftLiteral (left,right,result,ic, sign);
10402 } // if (right is literal)
10404 /* shift count is unknown then we have to form a loop.
10405 * Note: we take only the lower order byte since shifting
10406 * more than 32 bits make no sense anyway, ( the
10407 * largest size of an object can be only 32 bits )
10408 * Note: we perform arithmetic shifts if the left operand is
10409 * signed and we do an (effective) right shift, i. e. we
10410 * shift in the sign bit from the left. */
10412 label_complete = newiTempLabel ( NULL );
10413 label_loop_pos = newiTempLabel ( NULL );
10414 label_loop_neg = NULL;
10415 label_negative = NULL;
10416 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10417 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10420 // additional labels needed
10421 label_loop_neg = newiTempLabel ( NULL );
10422 label_negative = newiTempLabel ( NULL );
10425 // copy source to result -- this will effectively truncate the left operand to the size of result!
10426 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10427 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10428 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10429 mov2f (AOP(result),AOP(left), offset);
10432 // if result is longer than left, fill with zeros (or sign)
10433 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10434 if (sign && AOP_SIZE(left) > 0) {
10435 // shift signed operand -- fill with sign
10436 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10437 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10438 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10439 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10440 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10443 // shift unsigned operand -- fill result with zeros
10444 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10445 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10448 } // if (size mismatch)
10450 pic16_mov2w (AOP(right), 0);
10451 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10452 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10455 // perform a shift by one (shift count is positive)
10456 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10457 // 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])
10458 pic16_emitpLabel (label_loop_pos->key);
10460 if (sign && (pos_shift == POC_RRCF)) {
10461 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10464 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10465 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10466 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10468 // perform a shift by one (shift count is positive)
10469 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10470 // 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])
10471 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10472 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10474 pic16_emitpLabel (label_loop_pos->key);
10475 if (sign && (pos_shift == POC_RRCF)) {
10476 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10479 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10480 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10481 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10482 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10486 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10488 pic16_emitpLabel (label_negative->key);
10489 // perform a shift by -1 (shift count is negative)
10490 // 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)
10492 pic16_emitpLabel (label_loop_neg->key);
10493 if (sign && (neg_shift == POC_RRCF)) {
10494 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10497 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10498 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10499 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10500 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10501 } // if (signedCount)
10503 pic16_emitpLabel (label_complete->key);
10506 pic16_freeAsmop (right,NULL,ic,TRUE);
10507 pic16_freeAsmop(left,NULL,ic,TRUE);
10508 pic16_freeAsmop(result,NULL,ic,TRUE);
10511 static void genLeftShift (iCode *ic) {
10512 genGenericShift (ic, 1);
10515 static void genRightShift (iCode *ic) {
10516 genGenericShift (ic, 0);
10521 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10522 void pic16_loadFSR0(operand *op, int lit)
10524 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10525 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10527 assert (!OP_SYMBOL(op)->remat);
10528 // set up FSR0 with address of result
10529 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10530 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10534 /*-----------------------------------------------------------------*/
10535 /* genUnpackBits - generates code for unpacking bits */
10536 /*-----------------------------------------------------------------*/
10537 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10541 sym_link *etype, *letype;
10542 int blen=0, bstr=0;
10546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10547 etype = getSpec(operandType(result));
10548 letype = getSpec(operandType(left));
10550 // if(IS_BITFIELD(etype)) {
10551 blen = SPEC_BLEN(etype);
10552 bstr = SPEC_BSTR(etype);
10555 lbstr = SPEC_BSTR( letype );
10558 if((blen == 1) && (bstr < 8)) {
10559 /* it is a single bit, so use the appropriate bit instructions */
10560 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10562 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10564 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10565 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10566 /* workaround to reduce the extra lfsr instruction */
10567 pic16_emitpcode(POC_BTFSC,
10568 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10570 pic16_loadFSR0 (left, 0);
10571 pic16_emitpcode(POC_BTFSC,
10572 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10575 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10577 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10583 /* the following call to pic16_loadFSR0 is temporary until
10584 * optimization to handle single bit assignments is added
10585 * to the function. Until then use the old safe way! -- VR */
10587 if (OP_SYMBOL(left)->remat) {
10588 // access symbol directly
10589 pic16_mov2w (AOP(left), 0);
10591 pic16_loadFSR0( left, 0 );
10593 /* read the first byte */
10600 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10603 pic16_emitcode("clr","a");
10604 pic16_emitcode("movc","a","@a+dptr");
10610 /* if we have bitdisplacement then it fits */
10611 /* into this byte completely or if length is */
10612 /* less than a byte */
10613 if ((shCnt = SPEC_BSTR(etype)) ||
10614 (SPEC_BLEN(etype) <= 8)) {
10616 /* shift right acc */
10619 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10620 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10622 /* VR -- normally I would use the following, but since we use the hack,
10623 * to avoid the masking from AccRsh, why not mask it right now? */
10626 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10635 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10636 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10639 /* bit field did not fit in a byte */
10640 rlen = SPEC_BLEN(etype) - 8;
10641 pic16_aopPut(AOP(result),"a",offset++);
10648 pic16_emitcode("inc","%s",rname);
10649 pic16_emitcode("mov","a,@%s",rname);
10653 pic16_emitcode("inc","%s",rname);
10654 pic16_emitcode("movx","a,@%s",rname);
10658 pic16_emitcode("inc","dptr");
10659 pic16_emitcode("movx","a,@dptr");
10663 pic16_emitcode("clr","a");
10664 pic16_emitcode("inc","dptr");
10665 pic16_emitcode("movc","a","@a+dptr");
10669 pic16_emitcode("inc","dptr");
10670 pic16_emitcode("lcall","__gptrget");
10675 /* if we are done */
10679 pic16_aopPut(AOP(result),"a",offset++);
10684 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10685 pic16_aopPut(AOP(result),"a",offset);
10692 static void genDataPointerGet(operand *left,
10696 int size, offset = 0, leoffset=0 ;
10698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10699 pic16_aopOp(result, ic, TRUE);
10703 size = AOP_SIZE(result);
10704 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10708 /* The following tests may save a redudant movff instruction when
10709 * accessing unions */
10711 /* if they are the same */
10712 if (operandsEqu (left, result)) {
10713 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10719 /* if they are the same registers */
10720 if (pic16_sameRegs(AOP(left),AOP(result))) {
10721 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10727 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10728 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10729 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10736 if ( AOP_TYPE(left) == AOP_PCODE) {
10737 fprintf(stderr,"genDataPointerGet %s, %d\n",
10738 AOP(left)->aopu.pcop->name,
10739 (AOP(left)->aopu.pcop->type == PO_DIR)?
10740 PCOR(AOP(left)->aopu.pcop)->instance:
10741 PCOI(AOP(left)->aopu.pcop)->offset);
10745 if(AOP(left)->aopu.pcop->type == PO_DIR)
10746 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10748 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10751 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10753 // pic16_DumpOp("(result)",result);
10754 if(is_LitAOp(AOP(result))) {
10755 pic16_mov2w(AOP(left), offset); // patch 8
10756 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10758 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10759 pic16_popGet(AOP(left), offset), //patch 8
10760 pic16_popGet(AOP(result), offset)));
10768 pic16_freeAsmop(result,NULL,ic,TRUE);
10773 /*-----------------------------------------------------------------*/
10774 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10775 /*-----------------------------------------------------------------*/
10776 static void genNearPointerGet (operand *left,
10780 // asmop *aop = NULL;
10781 //regs *preg = NULL ;
10782 sym_link *rtype, *retype;
10783 sym_link *ltype = operandType(left);
10787 rtype = operandType(result);
10788 retype= getSpec(rtype);
10790 pic16_aopOp(left,ic,FALSE);
10792 // pic16_DumpOp("(left)",left);
10793 // pic16_DumpOp("(result)",result);
10795 /* if left is rematerialisable and
10796 * result is not bit variable type and
10797 * the left is pointer to data space i.e
10798 * lower 128 bytes of space */
10800 if (AOP_TYPE(left) == AOP_PCODE
10801 && !IS_BITFIELD(retype)
10802 && DCL_TYPE(ltype) == POINTER) {
10804 genDataPointerGet (left,result,ic);
10805 pic16_freeAsmop(left, NULL, ic, TRUE);
10809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10810 pic16_aopOp (result,ic,TRUE);
10812 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10815 if(IS_BITFIELD( retype )
10816 && (SPEC_BLEN(operandType(result))==1)
10820 int bitstrt, bytestrt;
10822 /* if this is bitfield of size 1, see if we are checking the value
10823 * of a single bit in an if-statement,
10824 * if yes, then don't generate usual code, but execute the
10825 * genIfx directly -- VR */
10829 /* CHECK: if next iCode is IFX
10830 * and current result operand is nextic's conditional operand
10831 * and current result operand live ranges ends at nextic's key number
10833 if((nextic->op == IFX)
10834 && (result == IC_COND(nextic))
10835 && (OP_LIVETO(result) == nextic->seq)
10836 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10838 /* everything is ok then */
10839 /* find a way to optimize the genIfx iCode */
10841 bytestrt = SPEC_BSTR(operandType(result))/8;
10842 bitstrt = SPEC_BSTR(operandType(result))%8;
10844 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10846 genIfxpCOpJump(nextic, jop);
10848 pic16_freeAsmop(left, NULL, ic, TRUE);
10849 pic16_freeAsmop(result, NULL, ic, TRUE);
10856 /* if the value is already in a pointer register
10857 * then don't need anything more */
10858 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10859 /* otherwise get a free pointer register */
10860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10865 /* if bitfield then unpack the bits */
10866 if (IS_BITFIELD(retype))
10867 genUnpackBits (result, left, NULL, POINTER);
10869 /* we have can just get the values */
10870 int size = AOP_SIZE(result);
10873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10875 pic16_loadFSR0( left, 0 );
10879 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10880 pic16_popGet(AOP(result), offset++)));
10882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10883 pic16_popGet(AOP(result), offset++)));
10889 /* now some housekeeping stuff */
10891 /* we had to allocate for this iCode */
10892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10893 pic16_freeAsmop(NULL,aop,ic,TRUE);
10895 /* we did not allocate which means left
10896 * already in a pointer register, then
10897 * if size > 0 && this could be used again
10898 * we have to point it back to where it
10900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10901 if (AOP_SIZE(result) > 1
10902 && !OP_SYMBOL(left)->remat
10903 && ( OP_SYMBOL(left)->liveTo > ic->seq
10905 // int size = AOP_SIZE(result) - 1;
10907 // pic16_emitcode("dec","%s",rname);
10913 pic16_freeAsmop(left,NULL,ic,TRUE);
10914 pic16_freeAsmop(result,NULL,ic,TRUE);
10917 /*-----------------------------------------------------------------*/
10918 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10919 /*-----------------------------------------------------------------*/
10920 static void genPagedPointerGet (operand *left,
10925 regs *preg = NULL ;
10927 sym_link *rtype, *retype;
10929 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10931 rtype = operandType(result);
10932 retype= getSpec(rtype);
10934 pic16_aopOp(left,ic,FALSE);
10936 /* if the value is already in a pointer register
10937 then don't need anything more */
10938 if (!AOP_INPREG(AOP(left))) {
10939 /* otherwise get a free pointer register */
10941 preg = getFreePtr(ic,&aop,FALSE);
10942 pic16_emitcode("mov","%s,%s",
10944 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10945 rname = preg->name ;
10947 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10949 pic16_freeAsmop(left,NULL,ic,TRUE);
10950 pic16_aopOp (result,ic,TRUE);
10952 /* if bitfield then unpack the bits */
10953 if (IS_BITFIELD(retype))
10954 genUnpackBits (result,left,rname,PPOINTER);
10956 /* we have can just get the values */
10957 int size = AOP_SIZE(result);
10962 pic16_emitcode("movx","a,@%s",rname);
10963 pic16_aopPut(AOP(result),"a",offset);
10968 pic16_emitcode("inc","%s",rname);
10972 /* now some housekeeping stuff */
10974 /* we had to allocate for this iCode */
10975 pic16_freeAsmop(NULL,aop,ic,TRUE);
10977 /* we did not allocate which means left
10978 already in a pointer register, then
10979 if size > 0 && this could be used again
10980 we have to point it back to where it
10982 if (AOP_SIZE(result) > 1 &&
10983 !OP_SYMBOL(left)->remat &&
10984 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10986 int size = AOP_SIZE(result) - 1;
10988 pic16_emitcode("dec","%s",rname);
10993 pic16_freeAsmop(result,NULL,ic,TRUE);
10998 /*-----------------------------------------------------------------*/
10999 /* genFarPointerGet - gget value from far space */
11000 /*-----------------------------------------------------------------*/
11001 static void genFarPointerGet (operand *left,
11002 operand *result, iCode *ic)
11005 sym_link *retype = getSpec(operandType(result));
11007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11009 pic16_aopOp(left,ic,FALSE);
11011 /* if the operand is already in dptr
11012 then we do nothing else we move the value to dptr */
11013 if (AOP_TYPE(left) != AOP_STR) {
11014 /* if this is remateriazable */
11015 if (AOP_TYPE(left) == AOP_IMMD)
11016 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11017 else { /* we need to get it byte by byte */
11018 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11019 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11020 if (options.model == MODEL_FLAT24)
11022 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11026 /* so dptr know contains the address */
11027 pic16_freeAsmop(left,NULL,ic,TRUE);
11028 pic16_aopOp(result,ic,TRUE);
11030 /* if bit then unpack */
11031 if (IS_BITFIELD(retype))
11032 genUnpackBits(result,left,"dptr",FPOINTER);
11034 size = AOP_SIZE(result);
11038 pic16_emitcode("movx","a,@dptr");
11039 pic16_aopPut(AOP(result),"a",offset++);
11041 pic16_emitcode("inc","dptr");
11045 pic16_freeAsmop(result,NULL,ic,TRUE);
11049 /*-----------------------------------------------------------------*/
11050 /* genCodePointerGet - get value from code space */
11051 /*-----------------------------------------------------------------*/
11052 static void genCodePointerGet (operand *left,
11053 operand *result, iCode *ic)
11056 sym_link *retype = getSpec(operandType(result));
11058 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11060 pic16_aopOp(left,ic,FALSE);
11062 /* if the operand is already in dptr
11063 then we do nothing else we move the value to dptr */
11064 if (AOP_TYPE(left) != AOP_STR) {
11065 /* if this is remateriazable */
11066 if (AOP_TYPE(left) == AOP_IMMD)
11067 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11068 else { /* we need to get it byte by byte */
11069 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11070 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11071 if (options.model == MODEL_FLAT24)
11073 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11077 /* so dptr know contains the address */
11078 pic16_freeAsmop(left,NULL,ic,TRUE);
11079 pic16_aopOp(result,ic,FALSE);
11081 /* if bit then unpack */
11082 if (IS_BITFIELD(retype))
11083 genUnpackBits(result,left,"dptr",CPOINTER);
11085 size = AOP_SIZE(result);
11089 pic16_emitcode("clr","a");
11090 pic16_emitcode("movc","a,@a+dptr");
11091 pic16_aopPut(AOP(result),"a",offset++);
11093 pic16_emitcode("inc","dptr");
11097 pic16_freeAsmop(result,NULL,ic,TRUE);
11102 /*-----------------------------------------------------------------*/
11103 /* genGenPointerGet - gget value from generic pointer space */
11104 /*-----------------------------------------------------------------*/
11105 static void genGenPointerGet (operand *left,
11106 operand *result, iCode *ic)
11108 int size, offset, lit;
11109 sym_link *retype = getSpec(operandType(result));
11111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11112 pic16_aopOp(left,ic,FALSE);
11113 pic16_aopOp(result,ic,FALSE);
11114 size = AOP_SIZE(result);
11116 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11118 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11120 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11121 // load FSR0 from immediate
11122 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11124 // pic16_loadFSR0( left );
11129 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11131 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11138 else { /* we need to get it byte by byte */
11139 // set up FSR0 with address from left
11140 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11141 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11147 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11149 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11156 /* if bit then unpack */
11157 if (IS_BITFIELD(retype))
11158 genUnpackBits(result,left,"BAD",GPOINTER);
11161 pic16_freeAsmop(left,NULL,ic,TRUE);
11162 pic16_freeAsmop(result,NULL,ic,TRUE);
11168 /*-----------------------------------------------------------------*/
11169 /* genGenPointerGet - gget value from generic pointer space */
11170 /*-----------------------------------------------------------------*/
11171 static void genGenPointerGet (operand *left,
11172 operand *result, iCode *ic)
11174 int size, offset, lit;
11175 sym_link *retype = getSpec(operandType(result));
11177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11178 pic16_aopOp(left,ic,FALSE);
11179 pic16_aopOp(result,ic,TRUE);
11180 size = AOP_SIZE(result);
11182 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11184 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11186 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11187 // load FSR0 from immediate
11188 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11190 werror(W_POSSBUG2, __FILE__, __LINE__);
11195 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11197 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11204 } else { /* we need to get it byte by byte */
11206 /* set up WREG:PRODL:FSR0L with address from left */
11207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11208 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11209 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11211 pic16_callGenericPointerRW(0, size);
11213 assignResultValue(result, 1);
11218 /* if bit then unpack */
11219 if (IS_BITFIELD(retype))
11220 genUnpackBits(result,left,"BAD",GPOINTER);
11223 pic16_freeAsmop(left,NULL,ic,TRUE);
11224 pic16_freeAsmop(result,NULL,ic,TRUE);
11227 /*-----------------------------------------------------------------*/
11228 /* genConstPointerGet - get value from const generic pointer space */
11229 /*-----------------------------------------------------------------*/
11230 static void genConstPointerGet (operand *left,
11231 operand *result, iCode *ic)
11233 //sym_link *retype = getSpec(operandType(result));
11234 // symbol *albl = newiTempLabel(NULL); // patch 15
11235 // symbol *blbl = newiTempLabel(NULL); //
11236 // PIC_OPCODE poc; // patch 15
11240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11241 pic16_aopOp(left,ic,FALSE);
11242 pic16_aopOp(result,ic,TRUE);
11243 size = AOP_SIZE(result);
11245 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11247 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11249 // set up table pointer
11250 if( (AOP_TYPE(left) == AOP_PCODE)
11251 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11252 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11254 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11255 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11256 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11257 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11258 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11261 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11262 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11263 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11267 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11272 pic16_freeAsmop(left,NULL,ic,TRUE);
11273 pic16_freeAsmop(result,NULL,ic,TRUE);
11277 /*-----------------------------------------------------------------*/
11278 /* genPointerGet - generate code for pointer get */
11279 /*-----------------------------------------------------------------*/
11280 static void genPointerGet (iCode *ic)
11282 operand *left, *result ;
11283 sym_link *type, *etype;
11288 left = IC_LEFT(ic);
11289 result = IC_RESULT(ic) ;
11291 /* depending on the type of pointer we need to
11292 move it to the correct pointer register */
11293 type = operandType(left);
11294 etype = getSpec(type);
11297 if (IS_PTR_CONST(type))
11299 if (IS_CODEPTR(type))
11301 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11303 /* if left is of type of pointer then it is simple */
11304 if (IS_PTR(type) && !IS_FUNC(type->next))
11305 p_type = DCL_TYPE(type);
11307 /* we have to go by the storage class */
11308 p_type = PTR_TYPE(SPEC_OCLS(etype));
11310 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11312 if (SPEC_OCLS(etype)->codesp ) {
11313 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11314 //p_type = CPOINTER ;
11316 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11317 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11318 /*p_type = FPOINTER ;*/
11320 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11321 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11322 /* p_type = PPOINTER; */
11324 if (SPEC_OCLS(etype) == idata ) {
11325 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11326 /* p_type = IPOINTER; */
11328 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11329 /* p_type = POINTER ; */
11333 /* now that we have the pointer type we assign
11334 the pointer values */
11338 genNearPointerGet (left,result,ic);
11342 genPagedPointerGet(left,result,ic);
11346 genFarPointerGet (left,result,ic);
11350 genConstPointerGet (left,result,ic);
11351 //pic16_emitcodePointerGet (left,result,ic);
11356 if (IS_PTR_CONST(type))
11357 genConstPointerGet (left,result,ic);
11360 genGenPointerGet (left,result,ic);
11364 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11365 "genPointerGet: illegal pointer type");
11370 /*-----------------------------------------------------------------*/
11371 /* genPackBits - generates code for packed bit storage */
11372 /*-----------------------------------------------------------------*/
11373 static void genPackBits (sym_link *etype , operand *result,
11375 char *rname, int p_type)
11383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11384 blen = SPEC_BLEN(etype);
11385 bstr = SPEC_BSTR(etype);
11387 retype = getSpec(operandType(right));
11389 if(AOP_TYPE(right) == AOP_LIT) {
11390 if((blen == 1) && (bstr < 8)) {
11392 /* it is a single bit, so use the appropriate bit instructions */
11394 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11396 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11397 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11398 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11399 /* workaround to reduce the extra lfsr instruction */
11401 pic16_emitpcode(POC_BSF,
11402 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11404 pic16_emitpcode(POC_BCF,
11405 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11408 pic16_loadFSR0(result, 0);
11410 pic16_emitpcode(POC_BSF,
11411 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11413 pic16_emitpcode(POC_BCF,
11414 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11420 /* move literal to W */
11421 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11424 if(IS_BITFIELD(retype)
11425 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11429 rblen = SPEC_BLEN( retype );
11430 rbstr = SPEC_BSTR( retype );
11433 if(IS_BITFIELD(etype)) {
11434 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11435 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11437 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11440 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11442 if(IS_BITFIELD(etype)) {
11443 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11445 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11448 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11452 /* move right to W */
11453 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11456 /* if the bit length is less than or */
11457 /* it exactly fits a byte then */
11458 if((shCnt=SPEC_BSTR(etype))
11459 || SPEC_BLEN(etype) <= 8 ) {
11460 int fsr0_setup = 0;
11462 if (blen != 8 || bstr != 0) {
11463 // we need to combine the value with the old value
11464 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11466 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11467 SPEC_BSTR(etype), SPEC_BLEN(etype));
11469 /* shift left acc */
11472 /* using PRODH as a temporary register here */
11473 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11475 if (OP_SYMBOL(result)->remat) {
11476 // access symbol directly
11477 pic16_mov2w (AOP(result), 0);
11479 /* get old value */
11483 pic16_loadFSR0( result, 0 );
11485 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11486 // pic16_emitcode ("mov","b,a");
11487 // pic16_emitcode("mov","a,@%s",rname);
11491 if (AOP(result)->aopu.aop_reg[2]) {
11492 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11493 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11494 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11495 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11497 pic16_callGenericPointerRW(0, 1);
11499 // data pointer (just 2 byte given)
11500 pic16_loadFSR0( result, 0 );
11502 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11505 // warnings will be emitted below
11506 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11507 //werror(W_POSSBUG2, __FILE__, __LINE__);
11511 assert (0 && "invalid pointer type specified");
11516 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11517 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11518 (unsigned char)(0xff >> (8-bstr))) ));
11519 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11520 } // if (blen != 8 || bstr != 0)
11522 /* write new value back */
11523 if (OP_SYMBOL(result)->remat) {
11524 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11529 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11534 if (AOP(result)->aopu.aop_reg[2]) {
11535 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11536 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11537 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11538 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11539 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11541 pic16_callGenericPointerRW(1, 1);
11543 // data pointer (just 2 byte given)
11544 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11545 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11548 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11549 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11550 werror(W_POSSBUG2, __FILE__, __LINE__);
11554 assert (0 && "invalid pointer type specified");
11565 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11566 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11571 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11572 rLen = SPEC_BLEN(etype)-8;
11574 /* now generate for lengths greater than one byte */
11578 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11584 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11590 pic16_emitcode("movx","@dptr,a");
11595 DEBUGpic16_emitcode(";lcall","__gptrput");
11603 pic16_mov2w(AOP(right), offset++);
11606 /* last last was not complete */
11608 /* save the byte & read byte */
11611 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11612 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11617 pic16_emitcode ("mov","b,a");
11618 pic16_emitcode("movx","a,@dptr");
11622 pic16_emitcode ("push","b");
11623 pic16_emitcode ("push","acc");
11624 pic16_emitcode ("lcall","__gptrget");
11625 pic16_emitcode ("pop","b");
11631 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11632 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11633 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11634 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11635 // pic16_emitcode ("orl","a,b");
11638 // if (p_type == GPOINTER)
11639 // pic16_emitcode("pop","b");
11644 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11645 // pic16_emitcode("mov","@%s,a",rname);
11649 pic16_emitcode("movx","@dptr,a");
11653 DEBUGpic16_emitcode(";lcall","__gptrput");
11660 // pic16_freeAsmop(right, NULL, ic, TRUE);
11662 /*-----------------------------------------------------------------*/
11663 /* genDataPointerSet - remat pointer to data space */
11664 /*-----------------------------------------------------------------*/
11665 static void genDataPointerSet(operand *right,
11669 int size, offset = 0, resoffset=0 ;
11671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11672 pic16_aopOp(right,ic,FALSE);
11674 size = AOP_SIZE(right);
11676 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11679 if ( AOP_TYPE(result) == AOP_PCODE) {
11680 fprintf(stderr,"genDataPointerSet %s, %d\n",
11681 AOP(result)->aopu.pcop->name,
11682 (AOP(result)->aopu.pcop->type == PO_DIR)?
11683 PCOR(AOP(result)->aopu.pcop)->instance:
11684 PCOI(AOP(result)->aopu.pcop)->offset);
11688 if(AOP(result)->aopu.pcop->type == PO_DIR)
11689 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11692 if (AOP_TYPE(right) == AOP_LIT) {
11695 if(!IS_FLOAT(operandType( right )))
11696 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11699 unsigned long lit_int;
11703 /* take care if literal is a float */
11704 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11705 lit = info.lit_int;
11708 lit = lit >> (8*offset);
11710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11713 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11716 pic16_mov2w(AOP(right), offset);
11717 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11723 pic16_freeAsmop(right,NULL,ic,TRUE);
11728 /*-----------------------------------------------------------------*/
11729 /* genNearPointerSet - pic16_emitcode for near pointer put */
11730 /*-----------------------------------------------------------------*/
11731 static void genNearPointerSet (operand *right,
11737 sym_link *ptype = operandType(result);
11738 sym_link *resetype;
11740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11741 retype= getSpec(operandType(right));
11742 resetype = getSpec(operandType(result));
11744 pic16_aopOp(result,ic,FALSE);
11746 /* if the result is rematerializable &
11747 * in data space & not a bit variable */
11749 /* and result is not a bit variable */
11750 if (AOP_TYPE(result) == AOP_PCODE
11751 // && AOP_TYPE(result) == AOP_IMMD
11752 && DCL_TYPE(ptype) == POINTER
11753 && !IS_BITFIELD(retype)
11754 && !IS_BITFIELD(resetype)) {
11756 genDataPointerSet (right,result,ic);
11757 pic16_freeAsmop(result,NULL,ic,TRUE);
11761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11762 pic16_aopOp(right,ic,FALSE);
11763 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11765 /* if the value is already in a pointer register
11766 * then don't need anything more */
11767 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11768 /* otherwise get a free pointer register */
11769 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11776 /* if bitfield then unpack the bits */
11777 if (IS_BITFIELD(resetype)) {
11778 genPackBits (resetype, result, right, NULL, POINTER);
11780 /* we have can just get the values */
11781 int size = AOP_SIZE(right);
11784 pic16_loadFSR0(result, 0);
11786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11788 if (AOP_TYPE(right) == AOP_LIT) {
11789 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11791 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11793 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11795 } else { // no literal
11797 pic16_emitpcode(POC_MOVFF,
11798 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11799 pic16_popCopyReg(&pic16_pc_postinc0)));
11801 pic16_emitpcode(POC_MOVFF,
11802 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11803 pic16_popCopyReg(&pic16_pc_indf0)));
11810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11811 /* now some housekeeping stuff */
11813 /* we had to allocate for this iCode */
11814 pic16_freeAsmop(NULL,aop,ic,TRUE);
11816 /* we did not allocate which means left
11817 * already in a pointer register, then
11818 * if size > 0 && this could be used again
11819 * we have to point it back to where it
11821 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11822 if (AOP_SIZE(right) > 1
11823 && !OP_SYMBOL(result)->remat
11824 && ( OP_SYMBOL(result)->liveTo > ic->seq
11827 int size = AOP_SIZE(right) - 1;
11830 pic16_emitcode("decf","fsr0,f");
11831 //pic16_emitcode("dec","%s",rname);
11835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11838 pic16_freeAsmop(right,NULL,ic,TRUE);
11839 pic16_freeAsmop(result,NULL,ic,TRUE);
11842 /*-----------------------------------------------------------------*/
11843 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11844 /*-----------------------------------------------------------------*/
11845 static void genPagedPointerSet (operand *right,
11850 regs *preg = NULL ;
11854 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11856 retype= getSpec(operandType(right));
11858 pic16_aopOp(result,ic,FALSE);
11860 /* if the value is already in a pointer register
11861 then don't need anything more */
11862 if (!AOP_INPREG(AOP(result))) {
11863 /* otherwise get a free pointer register */
11865 preg = getFreePtr(ic,&aop,FALSE);
11866 pic16_emitcode("mov","%s,%s",
11868 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11869 rname = preg->name ;
11871 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11873 pic16_freeAsmop(result,NULL,ic,TRUE);
11874 pic16_aopOp (right,ic,FALSE);
11876 /* if bitfield then unpack the bits */
11877 if (IS_BITFIELD(retype))
11878 genPackBits (retype,result,right,rname,PPOINTER);
11880 /* we have can just get the values */
11881 int size = AOP_SIZE(right);
11885 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11888 pic16_emitcode("movx","@%s,a",rname);
11891 pic16_emitcode("inc","%s",rname);
11897 /* now some housekeeping stuff */
11899 /* we had to allocate for this iCode */
11900 pic16_freeAsmop(NULL,aop,ic,TRUE);
11902 /* we did not allocate which means left
11903 already in a pointer register, then
11904 if size > 0 && this could be used again
11905 we have to point it back to where it
11907 if (AOP_SIZE(right) > 1 &&
11908 !OP_SYMBOL(result)->remat &&
11909 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11911 int size = AOP_SIZE(right) - 1;
11913 pic16_emitcode("dec","%s",rname);
11918 pic16_freeAsmop(right,NULL,ic,TRUE);
11923 /*-----------------------------------------------------------------*/
11924 /* genFarPointerSet - set value from far space */
11925 /*-----------------------------------------------------------------*/
11926 static void genFarPointerSet (operand *right,
11927 operand *result, iCode *ic)
11930 sym_link *retype = getSpec(operandType(right));
11932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11933 pic16_aopOp(result,ic,FALSE);
11935 /* if the operand is already in dptr
11936 then we do nothing else we move the value to dptr */
11937 if (AOP_TYPE(result) != AOP_STR) {
11938 /* if this is remateriazable */
11939 if (AOP_TYPE(result) == AOP_IMMD)
11940 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11941 else { /* we need to get it byte by byte */
11942 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11943 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11944 if (options.model == MODEL_FLAT24)
11946 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11950 /* so dptr know contains the address */
11951 pic16_freeAsmop(result,NULL,ic,TRUE);
11952 pic16_aopOp(right,ic,FALSE);
11954 /* if bit then unpack */
11955 if (IS_BITFIELD(retype))
11956 genPackBits(retype,result,right,"dptr",FPOINTER);
11958 size = AOP_SIZE(right);
11962 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11964 pic16_emitcode("movx","@dptr,a");
11966 pic16_emitcode("inc","dptr");
11970 pic16_freeAsmop(right,NULL,ic,TRUE);
11973 /*-----------------------------------------------------------------*/
11974 /* genGenPointerSet - set value from generic pointer space */
11975 /*-----------------------------------------------------------------*/
11977 static void genGenPointerSet (operand *right,
11978 operand *result, iCode *ic)
11980 int i, size, offset, lit;
11981 sym_link *retype = getSpec(operandType(right));
11983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11985 pic16_aopOp(result,ic,FALSE);
11986 pic16_aopOp(right,ic,FALSE);
11987 size = AOP_SIZE(right);
11990 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11992 /* if the operand is already in dptr
11993 then we do nothing else we move the value to dptr */
11994 if (AOP_TYPE(result) != AOP_STR) {
11995 /* if this is remateriazable */
11996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11997 // WARNING: anythig until "else" is untested!
11998 if (AOP_TYPE(result) == AOP_IMMD) {
11999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12000 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12001 // load FSR0 from immediate
12002 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12008 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12014 else { /* we need to get it byte by byte */
12015 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12016 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12018 // set up FSR0 with address of result
12019 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12020 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12022 /* hack hack! see if this the FSR. If so don't load W */
12023 if(AOP_TYPE(right) != AOP_ACC) {
12025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12027 if(AOP_TYPE(right) == AOP_LIT)
12030 // note: pic16_popGet handles sign extension
12031 for(i=0;i<size;i++) {
12032 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12034 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12036 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12041 for(i=0;i<size;i++) {
12043 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12044 pic16_popCopyReg(&pic16_pc_postinc0)));
12046 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12047 pic16_popCopyReg(&pic16_pc_indf0)));
12053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12054 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12056 } // if (AOP_TYPE(result) != AOP_IMMD)
12058 } // if (AOP_TYPE(result) != AOP_STR)
12059 /* so dptr know contains the address */
12062 /* if bit then unpack */
12063 if (IS_BITFIELD(retype))
12064 genPackBits(retype,result,right,"dptr",GPOINTER);
12066 size = AOP_SIZE(right);
12069 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12071 // set up FSR0 with address of result
12072 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12073 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12076 if (AOP_TYPE(right) == AOP_LIT) {
12077 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12079 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12081 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12083 } else { // no literal
12085 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12087 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12095 pic16_freeAsmop(right,NULL,ic,TRUE);
12096 pic16_freeAsmop(result,NULL,ic,TRUE);
12100 static void genGenPointerSet (operand *right,
12101 operand *result, iCode *ic)
12104 sym_link *retype = getSpec(operandType(right));
12106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12108 pic16_aopOp(result,ic,FALSE);
12109 pic16_aopOp(right,ic,FALSE);
12110 size = AOP_SIZE(right);
12112 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12115 /* if bit then unpack */
12116 if (IS_BITFIELD(retype)) {
12117 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12118 genPackBits(retype,result,right,"dptr",GPOINTER);
12122 size = AOP_SIZE(right);
12124 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12128 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12130 /* value of right+0 is placed on stack, which will be retrieved
12131 * by the support function this restoring the stack. The important
12132 * thing is that there is no need to manually restore stack pointer
12134 pushaop(AOP(right), 0);
12135 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12136 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12137 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12138 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12140 /* load address to write to in WREG:FSR0H:FSR0L */
12141 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12142 pic16_popCopyReg(&pic16_pc_fsr0l)));
12143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12144 pic16_popCopyReg(&pic16_pc_prodl)));
12145 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12147 pic16_callGenericPointerRW(1, size);
12150 pic16_freeAsmop(right,NULL,ic,TRUE);
12151 pic16_freeAsmop(result,NULL,ic,TRUE);
12154 /*-----------------------------------------------------------------*/
12155 /* genPointerSet - stores the value into a pointer location */
12156 /*-----------------------------------------------------------------*/
12157 static void genPointerSet (iCode *ic)
12159 operand *right, *result ;
12160 sym_link *type, *etype;
12165 right = IC_RIGHT(ic);
12166 result = IC_RESULT(ic) ;
12168 /* depending on the type of pointer we need to
12169 move it to the correct pointer register */
12170 type = operandType(result);
12171 etype = getSpec(type);
12172 /* if left is of type of pointer then it is simple */
12173 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12174 p_type = DCL_TYPE(type);
12177 /* we have to go by the storage class */
12178 p_type = PTR_TYPE(SPEC_OCLS(etype));
12180 /* if (SPEC_OCLS(etype)->codesp ) { */
12181 /* p_type = CPOINTER ; */
12184 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12185 /* p_type = FPOINTER ; */
12187 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12188 /* p_type = PPOINTER ; */
12190 /* if (SPEC_OCLS(etype) == idata ) */
12191 /* p_type = IPOINTER ; */
12193 /* p_type = POINTER ; */
12196 /* now that we have the pointer type we assign
12197 the pointer values */
12201 genNearPointerSet (right,result,ic);
12205 genPagedPointerSet (right,result,ic);
12209 genFarPointerSet (right,result,ic);
12213 genGenPointerSet (right,result,ic);
12217 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12218 "genPointerSet: illegal pointer type");
12222 /*-----------------------------------------------------------------*/
12223 /* genIfx - generate code for Ifx statement */
12224 /*-----------------------------------------------------------------*/
12225 static void genIfx (iCode *ic, iCode *popIc)
12227 operand *cond = IC_COND(ic);
12232 pic16_aopOp(cond,ic,FALSE);
12234 /* get the value into acc */
12235 if (AOP_TYPE(cond) != AOP_CRY)
12236 pic16_toBoolean(cond);
12239 /* the result is now in the accumulator */
12240 pic16_freeAsmop(cond,NULL,ic,TRUE);
12242 /* if there was something to be popped then do it */
12246 /* if the condition is a bit variable */
12247 if (isbit && IS_ITEMP(cond) &&
12249 genIfxJump(ic,"c");
12250 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12252 if (isbit && !IS_ITEMP(cond))
12253 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12255 genIfxJump(ic,"a");
12260 /*-----------------------------------------------------------------*/
12261 /* genAddrOf - generates code for address of */
12262 /*-----------------------------------------------------------------*/
12263 static void genAddrOf (iCode *ic)
12265 operand *result, *left;
12267 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12268 pCodeOp *pcop0, *pcop1, *pcop2;
12272 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12274 sym = OP_SYMBOL( IC_LEFT(ic) );
12277 /* get address of symbol on stack */
12278 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12280 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12281 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12284 // operands on stack are accessible via "FSR2 + index" with index
12285 // starting at 2 for arguments and growing from 0 downwards for
12286 // local variables (index == 0 is not assigned so we add one here)
12288 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12290 assert (soffs < 0);
12293 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12294 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12295 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12296 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12297 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12298 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12299 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12305 // if(pic16_debug_verbose) {
12306 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12307 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12310 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12311 size = AOP_SIZE(IC_RESULT(ic));
12313 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12314 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12315 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12318 pic16_emitpcode(POC_MOVLW, pcop0);
12319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12320 pic16_emitpcode(POC_MOVLW, pcop1);
12321 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12322 pic16_emitpcode(POC_MOVLW, pcop2);
12323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12326 pic16_emitpcode(POC_MOVLW, pcop0);
12327 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12328 pic16_emitpcode(POC_MOVLW, pcop1);
12329 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12331 pic16_emitpcode(POC_MOVLW, pcop0);
12332 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12335 pic16_freeAsmop(left, NULL, ic, FALSE);
12337 pic16_freeAsmop(result,NULL,ic,TRUE);
12342 /*-----------------------------------------------------------------*/
12343 /* genFarFarAssign - assignment when both are in far space */
12344 /*-----------------------------------------------------------------*/
12345 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12347 int size = AOP_SIZE(right);
12350 /* first push the right side on to the stack */
12352 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12354 pic16_emitcode ("push","acc");
12357 pic16_freeAsmop(right,NULL,ic,FALSE);
12358 /* now assign DPTR to result */
12359 pic16_aopOp(result,ic,FALSE);
12360 size = AOP_SIZE(result);
12362 pic16_emitcode ("pop","acc");
12363 pic16_aopPut(AOP(result),"a",--offset);
12365 pic16_freeAsmop(result,NULL,ic,FALSE);
12370 /*-----------------------------------------------------------------*/
12371 /* genAssign - generate code for assignment */
12372 /*-----------------------------------------------------------------*/
12373 static void genAssign (iCode *ic)
12375 operand *result, *right;
12376 int size, offset,know_W;
12377 unsigned long lit = 0L;
12379 result = IC_RESULT(ic);
12380 right = IC_RIGHT(ic) ;
12384 /* if they are the same */
12385 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12388 /* reversed order operands are aopOp'ed so that result operand
12389 * is effective in case right is a stack symbol. This maneauver
12390 * allows to use the _G.resDirect flag later */
12391 pic16_aopOp(result,ic,TRUE);
12392 pic16_aopOp(right,ic,FALSE);
12394 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12396 /* if they are the same registers */
12397 if (pic16_sameRegs(AOP(right),AOP(result)))
12400 /* if the result is a bit */
12401 if (AOP_TYPE(result) == AOP_CRY) {
12402 /* if the right size is a literal then
12403 we know what the value is */
12404 if (AOP_TYPE(right) == AOP_LIT) {
12406 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12407 pic16_popGet(AOP(result),0));
12409 if (((int) operandLitValue(right)))
12410 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12411 AOP(result)->aopu.aop_dir,
12412 AOP(result)->aopu.aop_dir);
12414 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12415 AOP(result)->aopu.aop_dir,
12416 AOP(result)->aopu.aop_dir);
12420 /* the right is also a bit variable */
12421 if (AOP_TYPE(right) == AOP_CRY) {
12422 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12423 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12424 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12426 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12427 AOP(result)->aopu.aop_dir,
12428 AOP(result)->aopu.aop_dir);
12429 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12430 AOP(right)->aopu.aop_dir,
12431 AOP(right)->aopu.aop_dir);
12432 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12433 AOP(result)->aopu.aop_dir,
12434 AOP(result)->aopu.aop_dir);
12438 /* we need to or */
12439 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12440 pic16_toBoolean(right);
12442 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12443 //pic16_aopPut(AOP(result),"a",0);
12447 /* bit variables done */
12449 size = AOP_SIZE(result);
12452 if(AOP_TYPE(right) == AOP_LIT) {
12453 if(!IS_FLOAT(operandType( right )))
12454 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12457 unsigned long lit_int;
12461 /* take care if literal is a float */
12462 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12463 lit = info.lit_int;
12467 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12468 // sizeof(unsigned long int), sizeof(float));
12471 if (AOP_TYPE(right) == AOP_REG) {
12472 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12475 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12480 if(AOP_TYPE(right) != AOP_LIT
12481 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12482 && !IS_FUNC(OP_SYM_TYPE(right))
12484 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12485 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12487 // set up table pointer
12488 if(is_LitOp(right)) {
12489 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12490 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12491 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12492 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12493 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12494 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12495 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12497 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12499 pic16_popCopyReg(&pic16_pc_tblptrl)));
12500 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12501 pic16_popCopyReg(&pic16_pc_tblptrh)));
12502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12503 pic16_popCopyReg(&pic16_pc_tblptru)));
12506 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12508 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12509 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12510 pic16_popGet(AOP(result),offset)));
12514 size = getSize(OP_SYM_ETYPE(right));
12515 if(AOP_SIZE(result) > size) {
12516 size = AOP_SIZE(result) - size;
12518 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12528 /* VR - What is this?! */
12529 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12530 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12531 if(aopIdx(AOP(result),0) == 4) {
12533 /* this is a workaround to save value of right into wreg too,
12534 * value of wreg is going to be used later */
12535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12536 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12537 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12541 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12547 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12548 if(AOP_TYPE(right) == AOP_LIT) {
12550 if(know_W != (lit&0xff))
12551 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12553 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12555 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12559 } else if (AOP_TYPE(right) == AOP_CRY) {
12560 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12562 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12563 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12564 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12566 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12567 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12568 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12570 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12572 if(!_G.resDirect) /* use this aopForSym feature */
12573 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12580 pic16_freeAsmop (right,NULL,ic,FALSE);
12581 pic16_freeAsmop (result,NULL,ic,TRUE);
12584 /*-----------------------------------------------------------------*/
12585 /* genJumpTab - generates code for jump table */
12586 /*-----------------------------------------------------------------*/
12587 static void genJumpTab (iCode *ic)
12592 pCodeOp *jt_offs_hi;
12597 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12598 /* get the condition into accumulator */
12599 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12601 /* multiply by three */
12602 pic16_emitcode("add","a,acc");
12603 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12605 jtab = newiTempLabel(NULL);
12606 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12607 pic16_emitcode("jmp","@a+dptr");
12608 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12611 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12612 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12614 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12615 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12616 pic16_emitpLabel(jtab->key);
12620 jt_offs = pic16_popGetTempReg(0);
12621 jt_offs_hi = pic16_popGetTempReg(1);
12622 jt_label = pic16_popGetLabel (jtab->key);
12623 //fprintf (stderr, "Creating jump table...\n");
12625 // calculate offset into jump table (idx * sizeof (GOTO))
12626 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12627 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12628 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12629 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12630 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12631 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12632 pic16_emitpcode(POC_MOVWF , jt_offs);
12634 // prepare PCLATx (set to first entry in jump table)
12635 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12636 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12637 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12638 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12639 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12641 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12642 pic16_emitpcode(POC_ADDWF , jt_offs);
12643 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12644 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12646 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12648 // release temporaries and prepare jump into table (new PCL --> WREG)
12649 pic16_emitpcode(POC_MOVFW , jt_offs);
12650 pic16_popReleaseTempReg (jt_offs_hi, 1);
12651 pic16_popReleaseTempReg (jt_offs, 0);
12653 // jump into the table
12654 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12656 pic16_emitpLabelFORCE(jtab->key);
12659 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12660 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12662 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12663 /* now generate the jump labels */
12664 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12665 jtab = setNextItem(IC_JTLABELS(ic))) {
12666 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12667 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12670 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12674 /*-----------------------------------------------------------------*/
12675 /* genMixedOperation - gen code for operators between mixed types */
12676 /*-----------------------------------------------------------------*/
12678 TSD - Written for the PIC port - but this unfortunately is buggy.
12679 This routine is good in that it is able to efficiently promote
12680 types to different (larger) sizes. Unfortunately, the temporary
12681 variables that are optimized out by this routine are sometimes
12682 used in other places. So until I know how to really parse the
12683 iCode tree, I'm going to not be using this routine :(.
12685 static int genMixedOperation (iCode *ic)
12688 operand *result = IC_RESULT(ic);
12689 sym_link *ctype = operandType(IC_LEFT(ic));
12690 operand *right = IC_RIGHT(ic);
12696 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12698 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12704 nextright = IC_RIGHT(nextic);
12705 nextleft = IC_LEFT(nextic);
12706 nextresult = IC_RESULT(nextic);
12708 pic16_aopOp(right,ic,FALSE);
12709 pic16_aopOp(result,ic,FALSE);
12710 pic16_aopOp(nextright, nextic, FALSE);
12711 pic16_aopOp(nextleft, nextic, FALSE);
12712 pic16_aopOp(nextresult, nextic, FALSE);
12714 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12716 operand *t = right;
12720 pic16_emitcode(";remove right +","");
12722 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12724 operand *t = right;
12728 pic16_emitcode(";remove left +","");
12732 big = AOP_SIZE(nextleft);
12733 small = AOP_SIZE(nextright);
12735 switch(nextic->op) {
12738 pic16_emitcode(";optimize a +","");
12739 /* if unsigned or not an integral type */
12740 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12741 pic16_emitcode(";add a bit to something","");
12744 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12746 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12747 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12748 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12750 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12758 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12759 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12763 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12766 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12767 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12768 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12769 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12772 pic16_emitcode("rlf","known_zero,w");
12779 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12780 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12781 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12783 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12793 pic16_freeAsmop(right,NULL,ic,TRUE);
12794 pic16_freeAsmop(result,NULL,ic,TRUE);
12795 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12796 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12798 nextic->generated = 1;
12805 /*-----------------------------------------------------------------*/
12806 /* genCast - gen code for casting */
12807 /*-----------------------------------------------------------------*/
12808 static void genCast (iCode *ic)
12810 operand *result = IC_RESULT(ic);
12811 sym_link *ctype = operandType(IC_LEFT(ic));
12812 sym_link *rtype = operandType(IC_RIGHT(ic));
12813 sym_link *restype = operandType(IC_RESULT(ic));
12814 operand *right = IC_RIGHT(ic);
12820 /* if they are equivalent then do nothing */
12821 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12824 pic16_aopOp(result,ic,FALSE);
12825 pic16_aopOp(right,ic,FALSE) ;
12827 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12830 /* if the result is a bit */
12831 if (AOP_TYPE(result) == AOP_CRY) {
12833 /* if the right size is a literal then
12834 * we know what the value is */
12835 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12837 if (AOP_TYPE(right) == AOP_LIT) {
12838 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12839 pic16_popGet(AOP(result),0));
12841 if (((int) operandLitValue(right)))
12842 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12843 AOP(result)->aopu.aop_dir,
12844 AOP(result)->aopu.aop_dir);
12846 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12847 AOP(result)->aopu.aop_dir,
12848 AOP(result)->aopu.aop_dir);
12852 /* the right is also a bit variable */
12853 if (AOP_TYPE(right) == AOP_CRY) {
12855 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12857 pic16_emitcode("clrc","");
12858 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12859 AOP(right)->aopu.aop_dir,
12860 AOP(right)->aopu.aop_dir);
12861 pic16_aopPut(AOP(result),"c",0);
12865 /* we need to or */
12866 if (AOP_TYPE(right) == AOP_REG) {
12867 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12868 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12869 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12871 pic16_toBoolean(right);
12872 pic16_aopPut(AOP(result),"a",0);
12876 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12879 size = AOP_SIZE(result);
12881 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12883 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12884 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12885 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12888 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12893 if(IS_BITFIELD(getSpec(restype))
12894 && IS_BITFIELD(getSpec(rtype))) {
12895 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12898 /* if they are the same size : or less */
12899 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12901 /* if they are in the same place */
12902 if (pic16_sameRegs(AOP(right),AOP(result)))
12905 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12907 if (IS_PTR_CONST(rtype))
12909 if (IS_CODEPTR(rtype))
12911 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12914 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12916 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12918 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12921 if(AOP_TYPE(right) == AOP_IMMD) {
12922 pCodeOp *pcop0, *pcop1, *pcop2;
12923 symbol *sym = OP_SYMBOL( right );
12925 size = AOP_SIZE(result);
12927 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12929 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12931 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12934 pic16_emitpcode(POC_MOVLW, pcop0);
12935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12936 pic16_emitpcode(POC_MOVLW, pcop1);
12937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12938 pic16_emitpcode(POC_MOVLW, pcop2);
12939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12942 pic16_emitpcode(POC_MOVLW, pcop0);
12943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12944 pic16_emitpcode(POC_MOVLW, pcop1);
12945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12947 pic16_emitpcode(POC_MOVLW, pcop0);
12948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12952 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12953 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12955 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12957 if(AOP_SIZE(result) <2)
12958 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12960 /* if they in different places then copy */
12961 size = AOP_SIZE(result);
12964 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12965 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12972 /* if the result is of type pointer */
12973 if (IS_PTR(ctype)) {
12975 sym_link *type = operandType(right);
12976 sym_link *etype = getSpec(type);
12978 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12980 /* pointer to generic pointer */
12981 if (IS_GENPTR(ctype)) {
12985 p_type = DCL_TYPE(type);
12987 /* we have to go by the storage class */
12988 p_type = PTR_TYPE(SPEC_OCLS(etype));
12990 /* if (SPEC_OCLS(etype)->codesp ) */
12991 /* p_type = CPOINTER ; */
12993 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12994 /* p_type = FPOINTER ; */
12996 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12997 /* p_type = PPOINTER; */
12999 /* if (SPEC_OCLS(etype) == idata ) */
13000 /* p_type = IPOINTER ; */
13002 /* p_type = POINTER ; */
13005 /* the first two bytes are known */
13006 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13007 size = GPTRSIZE - 1;
13010 if(offset < AOP_SIZE(right)) {
13011 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13012 mov2f(AOP(result), AOP(right), offset);
13014 if ((AOP_TYPE(right) == AOP_PCODE) &&
13015 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13016 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13020 pic16_aopPut(AOP(result),
13021 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13026 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13029 /* the last byte depending on type */
13033 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13034 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13035 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13039 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13043 pic16_emitcode(";BUG!? ","%d",__LINE__);
13047 pic16_emitcode(";BUG!? ","%d",__LINE__);
13052 if (GPTRSIZE > AOP_SIZE(right)) {
13053 // assume data pointer... THIS MIGHT BE WRONG!
13054 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13057 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13062 /* this should never happen */
13063 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13064 "got unknown pointer type");
13067 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13073 /* just copy the pointers */
13074 size = AOP_SIZE(result);
13077 pic16_aopPut(AOP(result),
13078 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13087 /* so we now know that the size of destination is greater
13088 than the size of the source.
13089 Now, if the next iCode is an operator then we might be
13090 able to optimize the operation without performing a cast.
13092 if(genMixedOperation(ic))
13095 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13097 /* we move to result for the size of source */
13098 size = AOP_SIZE(right);
13103 mov2f(AOP(result), AOP(right), offset);
13107 /* now depending on the sign of the destination */
13108 size = AOP_SIZE(result) - AOP_SIZE(right);
13109 /* if unsigned or not an integral type */
13110 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13112 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13114 /* we need to extend the sign :( */
13117 /* Save one instruction of casting char to int */
13118 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13119 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13120 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13122 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13125 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13127 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13129 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13132 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13137 pic16_freeAsmop(right,NULL,ic,TRUE);
13138 pic16_freeAsmop(result,NULL,ic,TRUE);
13142 /*-----------------------------------------------------------------*/
13143 /* genDjnz - generate decrement & jump if not zero instrucion */
13144 /*-----------------------------------------------------------------*/
13145 static int genDjnz (iCode *ic, iCode *ifx)
13147 symbol *lbl, *lbl1;
13148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13153 /* if the if condition has a false label
13154 then we cannot save */
13158 /* if the minus is not of the form
13160 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13161 !IS_OP_LITERAL(IC_RIGHT(ic)))
13164 if (operandLitValue(IC_RIGHT(ic)) != 1)
13167 /* if the size of this greater than one then no
13169 if (getSize(operandType(IC_RESULT(ic))) > 1)
13172 /* otherwise we can save BIG */
13173 lbl = newiTempLabel(NULL);
13174 lbl1= newiTempLabel(NULL);
13176 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13178 if (IS_AOP_PREG(IC_RESULT(ic))) {
13179 pic16_emitcode("dec","%s",
13180 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13181 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13182 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13186 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13187 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13189 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13190 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13194 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13195 ifx->generated = 1;
13199 /*-----------------------------------------------------------------*/
13200 /* genReceive - generate code for a receive iCode */
13201 /*-----------------------------------------------------------------*/
13202 static void genReceive (iCode *ic)
13208 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13209 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13211 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13213 if (isOperandInFarSpace(IC_RESULT(ic))
13214 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13215 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13217 int size = getSize(operandType(IC_RESULT(ic)));
13218 int offset = pic16_fReturnSizePic - size;
13222 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13223 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13227 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13229 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13230 size = AOP_SIZE(IC_RESULT(ic));
13233 pic16_emitcode ("pop","acc");
13234 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13237 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13239 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13242 /* set pseudo stack pointer to where it should be - dw*/
13243 GpsuedoStkPtr = ic->parmBytes;
13245 /* setting GpsuedoStkPtr has side effects here: */
13246 assignResultValue(IC_RESULT(ic), 0);
13249 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13252 /*-----------------------------------------------------------------*/
13253 /* genDummyRead - generate code for dummy read of volatiles */
13254 /*-----------------------------------------------------------------*/
13256 genDummyRead (iCode * ic)
13262 if (op && IS_SYMOP(op)) {
13263 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13264 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13267 pic16_aopOp (op, ic, FALSE);
13268 for (i=0; i < AOP_SIZE(op); i++) {
13269 // may need to protect this from the peepholer -- this is not nice but works...
13270 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13271 pic16_mov2w (AOP(op),i);
13272 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13274 pic16_freeAsmop (op, NULL, ic, TRUE);
13276 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13280 /*-----------------------------------------------------------------*/
13281 /* genpic16Code - generate code for pic16 based controllers */
13282 /*-----------------------------------------------------------------*/
13284 * At this point, ralloc.c has gone through the iCode and attempted
13285 * to optimize in a way suitable for a PIC. Now we've got to generate
13286 * PIC instructions that correspond to the iCode.
13288 * Once the instructions are generated, we'll pass through both the
13289 * peep hole optimizer and the pCode optimizer.
13290 *-----------------------------------------------------------------*/
13292 void genpic16Code (iCode *lic)
13297 lineHead = lineCurr = NULL;
13299 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13300 pic16_addpBlock(pb);
13303 /* if debug information required */
13304 if (options.debug && currFunc) {
13306 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13311 for (ic = lic ; ic ; ic = ic->next ) {
13313 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13314 if ( cln != ic->lineno ) {
13315 if ( options.debug ) {
13316 debugFile->writeCLine (ic);
13319 if(!options.noCcodeInAsm) {
13320 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13321 printCLine(ic->filename, ic->lineno)));
13327 if(options.iCodeInAsm) {
13330 /* insert here code to print iCode as comment */
13331 l = Safe_strdup(printILine(ic));
13332 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13335 /* if the result is marked as
13336 * spilt and rematerializable or code for
13337 * this has already been generated then
13339 if (resultRemat(ic) || ic->generated )
13342 /* depending on the operation */
13361 /* IPOP happens only when trying to restore a
13362 * spilt live range, if there is an ifx statement
13363 * following this pop then the if statement might
13364 * be using some of the registers being popped which
13365 * would destroy the contents of the register so
13366 * we need to check for this condition and handle it */
13368 && ic->next->op == IFX
13369 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13370 genIfx (ic->next,ic);
13388 genEndFunction (ic);
13404 pic16_genPlus (ic) ;
13408 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13409 pic16_genMinus (ic);
13425 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13429 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13435 /* note these two are xlated by algebraic equivalence
13436 * during parsing SDCC.y */
13437 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13438 "got '>=' or '<=' shouldn't have come here");
13442 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13454 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13458 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13462 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13486 genRightShift (ic);
13489 case GET_VALUE_AT_ADDRESS:
13494 if (POINTER_SET(ic))
13521 addSet(&_G.sendSet,ic);
13524 case DUMMY_READ_VOLATILE:
13534 /* now we are ready to call the
13535 peep hole optimizer */
13536 if (!options.nopeep)
13537 peepHole (&lineHead);
13539 /* now do the actual printing */
13540 printLine (lineHead, codeOutFile);
13543 DFPRINTF((stderr,"printing pBlock\n\n"));
13544 pic16_printpBlock(stdout,pb);