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 pcor->pcop.type = pc->pcop.type;
1796 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1797 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1799 pcor->pcop.name = NULL;
1802 pcor->rIdx = pc->rIdx;
1804 pcor->instance = pc->instance;
1806 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1811 /*-----------------------------------------------------------------*/
1812 /* pic16_popGetLit - asm operator to pcode operator conversion */
1813 /*-----------------------------------------------------------------*/
1814 pCodeOp *pic16_popGetLit(int lit)
1816 return pic16_newpCodeOpLit(lit);
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1821 /*-----------------------------------------------------------------*/
1822 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1824 return pic16_newpCodeOpLit2(lit, arg2);
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1833 return pic16_newpCodeOpImmd(name, offset,index, 0);
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGet - asm operator to pcode operator conversion */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetWithString(char *str)
1846 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1850 pcop = pic16_newpCodeOp(str,PO_STR);
1855 /*-----------------------------------------------------------------*/
1856 /* pic16_popRegFromString - */
1857 /*-----------------------------------------------------------------*/
1858 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1861 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862 pcop->type = PO_DIR;
1864 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1865 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1870 pcop->name = Safe_calloc(1,strlen(str)+1);
1871 strcpy(pcop->name,str);
1873 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1875 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1877 /* make sure that register doesn't exist,
1878 * and operand isn't NULL
1879 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1880 if((PCOR(pcop)->r == NULL)
1882 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1883 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1884 // __FUNCTION__, __LINE__, str, size, offset);
1886 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1887 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1890 PCOR(pcop)->instance = offset;
1895 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1899 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1901 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1902 PCOR(pcop)->rIdx = rIdx;
1903 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1905 PCOR(pcop)->r->isFree = 0;
1906 PCOR(pcop)->r->wasUsed = 1;
1908 pcop->type = PCOR(pcop)->r->pc_type;
1913 /*---------------------------------------------------------------------------------*/
1914 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1916 /*---------------------------------------------------------------------------------*/
1917 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1922 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1924 /* comment the following check, so errors to throw up */
1925 // if(!pcop2)return NULL;
1927 temp = pic16_popGet(aop_dst, offset);
1928 pcop2->pcop2 = temp;
1935 /*--------------------------------------------------------------------------------.-*/
1936 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1937 /* VR 030601 , adapted by Hans Dorn */
1938 /*--------------------------------------------------------------------------------.-*/
1939 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1943 pcop2 = (pCodeOpReg2 *)src;
1951 /*---------------------------------------------------------------------------------*/
1952 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1953 /* movff instruction */
1954 /*---------------------------------------------------------------------------------*/
1955 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1960 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1961 pcop2->pcop2 = pic16_popCopyReg(dst);
1963 /* the pCodeOp may be already allocated */
1964 pcop2 = (pCodeOpReg2 *)(src);
1965 pcop2->pcop2 = (pCodeOp *)(dst);
1972 /*-----------------------------------------------------------------*/
1973 /* pic16_popGet - asm operator to pcode operator conversion */
1974 /*-----------------------------------------------------------------*/
1975 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1977 //char *s = buffer ;
1982 /* offset is greater than
1985 // if (offset > (aop->size - 1) &&
1986 // aop->type != AOP_LIT)
1987 // return NULL; //zero;
1989 /* depending on type */
1990 switch (aop->type) {
1996 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1997 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2004 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2005 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2006 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2007 PCOR(pcop)->r->wasUsed = 1;
2008 PCOR(pcop)->r->isFree = 0;
2010 PCOR(pcop)->instance = offset;
2011 pcop->type = PCOR(pcop)->r->pc_type;
2015 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2016 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2019 /* pCodeOp is already allocated from aopForSym */
2020 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2021 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2027 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2029 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2031 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2033 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034 PCOR(pcop)->rIdx = rIdx;
2035 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2036 PCOR(pcop)->r->wasUsed=1;
2037 PCOR(pcop)->r->isFree=0;
2039 PCOR(pcop)->instance = offset;
2040 pcop->type = PCOR(pcop)->r->pc_type;
2041 // rs = aop->aopu.aop_reg[offset]->name;
2042 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2046 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2047 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2053 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2054 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2058 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2065 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2066 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2068 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2070 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2071 // pcop->type = PO_GPR_REGISTER;
2072 PCOR(pcop)->rIdx = rIdx;
2073 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2074 PCOR(pcop)->r->wasUsed=1;
2075 PCOR(pcop)->r->isFree=0;
2077 PCOR(pcop)->instance = offset;
2078 pcop->type = PCOR(pcop)->r->pc_type;
2080 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2081 rs = aop->aopu.aop_reg[offset]->name;
2082 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2087 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2089 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2090 PCOR(pcop)->instance = offset;
2091 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2092 //if(PCOR(pcop)->r == NULL)
2093 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2097 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2098 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2101 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2102 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2105 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2107 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108 pcop->type = PCOR(pcop)->r->pc_type;
2109 pcop->name = PCOR(pcop)->r->name;
2115 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2117 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2118 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2119 switch( aop->aopu.pcop->type ) {
2120 case PO_DIR: PCOR(pcop)->instance += offset; break;
2121 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2126 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2127 assert( 0 ); /* should never reach here */;
2132 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2133 "pic16_popGet got unsupported aop->type");
2136 /*-----------------------------------------------------------------*/
2137 /* pic16_aopPut - puts a string for a aop */
2138 /*-----------------------------------------------------------------*/
2139 void pic16_aopPut (asmop *aop, char *s, int offset)
2146 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2148 if (aop->size && offset > ( aop->size - 1)) {
2149 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2150 "pic16_aopPut got offset > aop->size");
2154 /* will assign value to value */
2155 /* depending on where it is ofcourse */
2156 switch (aop->type) {
2159 sprintf(d,"(%s + %d)",
2160 aop->aopu.aop_dir,offset);
2161 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2164 sprintf(d,"%s",aop->aopu.aop_dir);
2167 DEBUGpic16_emitcode(";","%d",__LINE__);
2169 pic16_emitcode("movf","%s,w",s);
2170 pic16_emitcode("movwf","%s",d);
2173 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2174 if(offset >= aop->size) {
2175 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2178 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2181 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2188 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2189 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2192 strcmp(s,"r0") == 0 ||
2193 strcmp(s,"r1") == 0 ||
2194 strcmp(s,"r2") == 0 ||
2195 strcmp(s,"r3") == 0 ||
2196 strcmp(s,"r4") == 0 ||
2197 strcmp(s,"r5") == 0 ||
2198 strcmp(s,"r6") == 0 ||
2199 strcmp(s,"r7") == 0 )
2200 pic16_emitcode("mov","%s,%s ; %d",
2201 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2205 if(strcmp(s,"W")==0 )
2206 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2208 pic16_emitcode("movwf","%s",
2209 aop->aopu.aop_reg[offset]->name);
2211 if(strcmp(s,zero)==0) {
2212 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2214 } else if(strcmp(s,"W")==0) {
2215 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2216 pcop->type = PO_GPR_REGISTER;
2218 PCOR(pcop)->rIdx = -1;
2219 PCOR(pcop)->r = NULL;
2221 DEBUGpic16_emitcode(";","%d",__LINE__);
2222 pcop->name = Safe_strdup(s);
2223 pic16_emitpcode(POC_MOVFW,pcop);
2224 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2225 } else if(strcmp(s,one)==0) {
2226 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2227 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2229 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2237 if (aop->type == AOP_DPTR2)
2243 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244 "pic16_aopPut writting to code space");
2248 while (offset > aop->coff) {
2250 pic16_emitcode ("inc","dptr");
2253 while (offset < aop->coff) {
2255 pic16_emitcode("lcall","__decdptr");
2260 /* if not in accumulater */
2263 pic16_emitcode ("movx","@dptr,a");
2265 if (aop->type == AOP_DPTR2)
2273 while (offset > aop->coff) {
2275 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2277 while (offset < aop->coff) {
2279 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2285 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2290 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2292 if (strcmp(s,"r0") == 0 ||
2293 strcmp(s,"r1") == 0 ||
2294 strcmp(s,"r2") == 0 ||
2295 strcmp(s,"r3") == 0 ||
2296 strcmp(s,"r4") == 0 ||
2297 strcmp(s,"r5") == 0 ||
2298 strcmp(s,"r6") == 0 ||
2299 strcmp(s,"r7") == 0 ) {
2301 sprintf(buffer,"a%s",s);
2302 pic16_emitcode("mov","@%s,%s",
2303 aop->aopu.aop_ptr->name,buffer);
2305 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2310 if (strcmp(s,"a") == 0)
2311 pic16_emitcode("push","acc");
2313 pic16_emitcode("push","%s",s);
2318 /* if bit variable */
2319 if (!aop->aopu.aop_dir) {
2320 pic16_emitcode("clr","a");
2321 pic16_emitcode("rlc","a");
2324 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2327 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2330 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2332 lbl = newiTempLabel(NULL);
2334 if (strcmp(s,"a")) {
2337 pic16_emitcode("clr","c");
2338 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2339 pic16_emitcode("cpl","c");
2340 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2341 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2348 if (strcmp(aop->aopu.aop_str[offset],s))
2349 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2354 if (!offset && (strcmp(s,"acc") == 0))
2357 if (strcmp(aop->aopu.aop_str[offset],s))
2358 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2362 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2363 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2364 // "pic16_aopPut got unsupported aop->type");
2370 /*-----------------------------------------------------------------*/
2371 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2372 /*-----------------------------------------------------------------*/
2373 void pic16_mov2w (asmop *aop, int offset)
2375 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2378 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2380 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2383 static void mov2f(asmop *dst, asmop *src, int offset)
2385 if(is_LitAOp(src)) {
2386 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2387 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2389 if(pic16_sameRegsOfs(src, dst, offset))return;
2390 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2391 pic16_popGet(dst, offset)));
2395 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2397 if(is_LitAOp(src)) {
2398 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2399 pic16_emitpcode(POC_MOVWF, dst);
2401 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2405 void pic16_testStackOverflow(void)
2407 #define GSTACK_TEST_NAME "_gstack_test"
2409 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2414 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2415 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2416 // strcpy(sym->rname, GSTACK_TEST_NAME);
2417 checkAddSym(&externs, sym);
2422 /* push pcop into stack */
2423 void pic16_pushpCodeOp(pCodeOp *pcop)
2425 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2426 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2427 if(pic16_options.gstack)
2428 pic16_testStackOverflow();
2432 /* pop pcop from stack */
2433 void pic16_poppCodeOp(pCodeOp *pcop)
2435 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2436 if(pic16_options.gstack)
2437 pic16_testStackOverflow();
2441 /*-----------------------------------------------------------------*/
2442 /* pushw - pushes wreg to stack */
2443 /*-----------------------------------------------------------------*/
2446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2447 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2448 if(pic16_options.gstack)
2449 pic16_testStackOverflow();
2453 /*-----------------------------------------------------------------*/
2454 /* pushaop - pushes aop to stack */
2455 /*-----------------------------------------------------------------*/
2456 void pushaop(asmop *aop, int offset)
2458 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2460 if(is_LitAOp(aop)) {
2461 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2462 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2464 pic16_emitpcode(POC_MOVFF,
2465 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2468 if(pic16_options.gstack)
2469 pic16_testStackOverflow();
2472 /*-----------------------------------------------------------------*/
2473 /* popaop - pops aop from stack */
2474 /*-----------------------------------------------------------------*/
2475 void popaop(asmop *aop, int offset)
2477 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2478 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2479 if(pic16_options.gstack)
2480 pic16_testStackOverflow();
2483 void popaopidx(asmop *aop, int offset, int index)
2487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2489 if(STACK_MODEL_LARGE)ofs++;
2491 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2492 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2493 if(pic16_options.gstack)
2494 pic16_testStackOverflow();
2497 #if !(USE_GENERIC_SIGNED_SHIFT)
2498 /*-----------------------------------------------------------------*/
2499 /* reAdjustPreg - points a register back to where it should */
2500 /*-----------------------------------------------------------------*/
2501 static void reAdjustPreg (asmop *aop)
2505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2507 if ((size = aop->size) <= 1)
2510 switch (aop->type) {
2514 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2518 if (aop->type == AOP_DPTR2)
2524 pic16_emitcode("lcall","__decdptr");
2527 if (aop->type == AOP_DPTR2)
2539 /*-----------------------------------------------------------------*/
2540 /* opIsGptr: returns non-zero if the passed operand is */
2541 /* a generic pointer type. */
2542 /*-----------------------------------------------------------------*/
2543 static int opIsGptr(operand *op)
2545 sym_link *type = operandType(op);
2547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2548 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2556 /*-----------------------------------------------------------------*/
2557 /* pic16_getDataSize - get the operand data size */
2558 /*-----------------------------------------------------------------*/
2559 int pic16_getDataSize(operand *op)
2561 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2564 return AOP_SIZE(op);
2566 // tsd- in the pic port, the genptr size is 1, so this code here
2567 // fails. ( in the 8051 port, the size was 4).
2570 size = AOP_SIZE(op);
2571 if (size == GPTRSIZE)
2573 sym_link *type = operandType(op);
2574 if (IS_GENPTR(type))
2576 /* generic pointer; arithmetic operations
2577 * should ignore the high byte (pointer type).
2580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2587 /*-----------------------------------------------------------------*/
2588 /* pic16_outAcc - output Acc */
2589 /*-----------------------------------------------------------------*/
2590 void pic16_outAcc(operand *result)
2593 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2594 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2597 size = pic16_getDataSize(result);
2599 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2602 /* unsigned or positive */
2604 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2609 /*-----------------------------------------------------------------*/
2610 /* pic16_outBitC - output a bit C */
2611 /* Move to result the value of Carry flag -- VR */
2612 /*-----------------------------------------------------------------*/
2613 void pic16_outBitC(operand *result)
2617 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2619 /* if the result is bit */
2620 if (AOP_TYPE(result) == AOP_CRY) {
2621 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2622 pic16_aopPut(AOP(result),"c",0);
2625 i = AOP_SIZE(result);
2627 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2629 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2633 /*-----------------------------------------------------------------*/
2634 /* pic16_outBitOp - output a bit from Op */
2635 /* Move to result the value of set/clr op -- VR */
2636 /*-----------------------------------------------------------------*/
2637 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2643 /* if the result is bit */
2644 if (AOP_TYPE(result) == AOP_CRY) {
2645 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2646 pic16_aopPut(AOP(result),"c",0);
2649 i = AOP_SIZE(result);
2651 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2653 pic16_emitpcode(POC_RRCF, pcop);
2654 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2658 /*-----------------------------------------------------------------*/
2659 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2660 /*-----------------------------------------------------------------*/
2661 void pic16_toBoolean(operand *oper)
2663 int size = AOP_SIZE(oper) - 1;
2666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2668 if ( AOP_TYPE(oper) != AOP_ACC) {
2669 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2672 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2677 #if !defined(GEN_Not)
2678 /*-----------------------------------------------------------------*/
2679 /* genNot - generate code for ! operation */
2680 /*-----------------------------------------------------------------*/
2681 static void pic16_genNot (iCode *ic)
2687 /* assign asmOps to operand & result */
2688 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2689 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2691 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2692 /* if in bit space then a special case */
2693 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2694 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2695 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2696 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2698 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2699 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2700 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2705 size = AOP_SIZE(IC_LEFT(ic));
2707 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2708 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2709 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2712 pic16_toBoolean(IC_LEFT(ic));
2714 tlbl = newiTempLabel(NULL);
2715 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2716 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2717 pic16_outBitC(IC_RESULT(ic));
2720 /* release the aops */
2721 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2722 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2727 #if !defined(GEN_Cpl)
2728 /*-----------------------------------------------------------------*/
2729 /* genCpl - generate code for complement */
2730 /*-----------------------------------------------------------------*/
2731 static void pic16_genCpl (iCode *ic)
2737 /* assign asmOps to operand & result */
2738 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2739 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2741 /* if both are in bit space then
2743 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2744 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2746 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2747 pic16_emitcode("cpl","c");
2748 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2752 size = AOP_SIZE(IC_RESULT(ic));
2755 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2757 pic16_emitcode("cpl","a");
2758 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2760 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2761 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2763 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2772 /* release the aops */
2773 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2774 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2778 /*-----------------------------------------------------------------*/
2779 /* genUminusFloat - unary minus for floating points */
2780 /*-----------------------------------------------------------------*/
2781 static void genUminusFloat(operand *op,operand *result)
2783 int size ,offset =0 ;
2786 /* for this we just need to flip the
2787 first it then copy the rest in place */
2788 size = AOP_SIZE(op);
2791 mov2f(AOP(result), AOP(op), offset);
2795 /* toggle the MSB's highest bit */
2796 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2799 /*-----------------------------------------------------------------*/
2800 /* genUminus - unary minus code generation */
2801 /*-----------------------------------------------------------------*/
2802 static void genUminus (iCode *ic)
2805 sym_link *optype, *rtype;
2812 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2813 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2815 /* if both in bit space then special case */
2816 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2817 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2819 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2820 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2821 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2825 optype = operandType(IC_LEFT(ic));
2826 rtype = operandType(IC_RESULT(ic));
2828 /* if float then do float stuff */
2829 if (IS_FLOAT(optype)) {
2830 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2834 /* otherwise subtract from zero by taking the 2's complement */
2835 size = AOP_SIZE(IC_LEFT(ic));
2836 label = newiTempLabel ( NULL );
2838 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2839 for (i=size-1; i > 0; i--) {
2840 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2842 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2843 for (i=1; i < size; i++) {
2844 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2845 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2848 for (i=size-1; i >= 0; i--) {
2849 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2850 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2853 for (i=0; i < size-2; i++) {
2854 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2855 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2857 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2859 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2862 pic16_emitpLabel (label->key);
2865 /* release the aops */
2866 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2867 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2871 /*-----------------------------------------------------------------*/
2872 /* saveRegisters - will look for a call and save the registers */
2873 /*-----------------------------------------------------------------*/
2874 static void saveRegisters(iCode *lic)
2881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2883 for (ic = lic ; ic ; ic = ic->next)
2884 if (ic->op == CALL || ic->op == PCALL)
2888 fprintf(stderr,"found parameter push with no function call\n");
2892 /* if the registers have been saved already then
2894 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2897 /* find the registers in use at this time
2898 and push them away to safety */
2899 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2903 if (options.useXstack) {
2904 if (bitVectBitValue(rsave,R0_IDX))
2905 pic16_emitcode("mov","b,r0");
2906 pic16_emitcode("mov","r0,%s",spname);
2907 for (i = 0 ; i < pic16_nRegs ; i++) {
2908 if (bitVectBitValue(rsave,i)) {
2910 pic16_emitcode("mov","a,b");
2912 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2913 pic16_emitcode("movx","@r0,a");
2914 pic16_emitcode("inc","r0");
2917 pic16_emitcode("mov","%s,r0",spname);
2918 if (bitVectBitValue(rsave,R0_IDX))
2919 pic16_emitcode("mov","r0,b");
2921 //for (i = 0 ; i < pic16_nRegs ; i++) {
2922 // if (bitVectBitValue(rsave,i))
2923 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2926 dtype = operandType(IC_LEFT(ic));
2927 if (currFunc && dtype &&
2928 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2929 IFFUNC_ISISR(currFunc->type) &&
2932 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2935 /*-----------------------------------------------------------------*/
2936 /* unsaveRegisters - pop the pushed registers */
2937 /*-----------------------------------------------------------------*/
2938 static void unsaveRegisters (iCode *ic)
2943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2944 /* find the registers in use at this time
2945 and push them away to safety */
2946 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2949 if (options.useXstack) {
2950 pic16_emitcode("mov","r0,%s",spname);
2951 for (i = pic16_nRegs ; i >= 0 ; i--) {
2952 if (bitVectBitValue(rsave,i)) {
2953 pic16_emitcode("dec","r0");
2954 pic16_emitcode("movx","a,@r0");
2956 pic16_emitcode("mov","b,a");
2958 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2962 pic16_emitcode("mov","%s,r0",spname);
2963 if (bitVectBitValue(rsave,R0_IDX))
2964 pic16_emitcode("mov","r0,b");
2966 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2967 // if (bitVectBitValue(rsave,i))
2968 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2975 /*-----------------------------------------------------------------*/
2977 /*-----------------------------------------------------------------*/
2978 static void pushSide(operand * oper, int size)
2981 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2983 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2984 if (AOP_TYPE(oper) != AOP_REG &&
2985 AOP_TYPE(oper) != AOP_DIR &&
2987 pic16_emitcode("mov","a,%s",l);
2988 pic16_emitcode("push","acc");
2990 pic16_emitcode("push","%s",l);
2995 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2997 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2998 pic16_emitpcode(POC_MOVFW, src);
2999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3001 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3002 src, pic16_popGet(AOP(op), offset)));
3007 /*-----------------------------------------------------------------*/
3008 /* assignResultValue - assign results to oper, rescall==1 is */
3009 /* called from genCall() or genPcall() */
3010 /*-----------------------------------------------------------------*/
3011 static void assignResultValue(operand * oper, int rescall)
3013 int size = AOP_SIZE(oper);
3017 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3018 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3021 /* assign result from a call/pcall function() */
3023 /* function results are stored in a special order,
3024 * see top of file with Function return policy, or manual */
3027 /* 8-bits, result in WREG */
3028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3031 /* 16-bits, result in PRODL:WREG */
3032 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3036 /* 24-bits, result in PRODH:PRODL:WREG */
3037 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3041 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3042 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3046 /* >32-bits, result on stack, and FSR0 points to beginning.
3047 * Fix stack when done */
3049 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3051 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3052 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3054 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3059 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3060 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3061 if(STACK_MODEL_LARGE) {
3063 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3067 int areg = 0; /* matching argument register */
3069 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3070 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3073 /* its called from genReceive (probably) -- VR */
3074 /* I hope this code will not be called from somewhere else in the future!
3075 * We manually set the pseudo stack pointer in genReceive. - dw
3077 if(!GpsuedoStkPtr && _G.useWreg) {
3078 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3080 /* The last byte in the assignment is in W */
3081 if(areg <= GpsuedoStkPtr) {
3083 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3085 // debugf("receive from WREG\n", 0);
3087 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3090 _G.stack_lat = AOP_SIZE(oper)-1;
3095 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3096 // debugf("receive from STACK\n", 0);
3103 /*-----------------------------------------------------------------*/
3104 /* genIpush - generate code for pushing this gets a little complex */
3105 /*-----------------------------------------------------------------*/
3106 static void genIpush (iCode *ic)
3108 // int size, offset=0;
3111 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3114 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3116 /* send to stack as normal */
3117 addSet(&_G.sendSet,ic);
3118 // addSetHead(&_G.sendSet,ic);
3119 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3124 int size, offset = 0 ;
3128 /* if this is not a parm push : ie. it is spill push
3129 and spill push is always done on the local stack */
3130 if (!ic->parmPush) {
3132 /* and the item is spilt then do nothing */
3133 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3136 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3137 size = AOP_SIZE(IC_LEFT(ic));
3138 /* push it on the stack */
3140 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3145 pic16_emitcode("push","%s",l);
3150 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3154 /*-----------------------------------------------------------------*/
3155 /* genIpop - recover the registers: can happen only for spilling */
3156 /*-----------------------------------------------------------------*/
3157 static void genIpop (iCode *ic)
3160 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3165 /* if the temp was not pushed then */
3166 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3169 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3170 size = AOP_SIZE(IC_LEFT(ic));
3173 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3176 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3181 /*-----------------------------------------------------------------*/
3182 /* unsaverbank - restores the resgister bank from stack */
3183 /*-----------------------------------------------------------------*/
3184 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3186 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3192 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3194 if (options.useXstack) {
3196 r = getFreePtr(ic,&aop,FALSE);
3199 pic16_emitcode("mov","%s,_spx",r->name);
3200 pic16_emitcode("movx","a,@%s",r->name);
3201 pic16_emitcode("mov","psw,a");
3202 pic16_emitcode("dec","%s",r->name);
3205 pic16_emitcode ("pop","psw");
3208 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3209 if (options.useXstack) {
3210 pic16_emitcode("movx","a,@%s",r->name);
3211 //pic16_emitcode("mov","(%s+%d),a",
3212 // regspic16[i].base,8*bank+regspic16[i].offset);
3213 pic16_emitcode("dec","%s",r->name);
3216 pic16_emitcode("pop",""); //"(%s+%d)",
3217 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3220 if (options.useXstack) {
3222 pic16_emitcode("mov","_spx,%s",r->name);
3223 pic16_freeAsmop(NULL,aop,ic,TRUE);
3229 /*-----------------------------------------------------------------*/
3230 /* saverbank - saves an entire register bank on the stack */
3231 /*-----------------------------------------------------------------*/
3232 static void saverbank (int bank, iCode *ic, bool pushPsw)
3234 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3241 if (options.useXstack) {
3244 r = getFreePtr(ic,&aop,FALSE);
3245 pic16_emitcode("mov","%s,_spx",r->name);
3249 for (i = 0 ; i < pic16_nRegs ;i++) {
3250 if (options.useXstack) {
3251 pic16_emitcode("inc","%s",r->name);
3252 //pic16_emitcode("mov","a,(%s+%d)",
3253 // regspic16[i].base,8*bank+regspic16[i].offset);
3254 pic16_emitcode("movx","@%s,a",r->name);
3256 pic16_emitcode("push","");// "(%s+%d)",
3257 //regspic16[i].base,8*bank+regspic16[i].offset);
3261 if (options.useXstack) {
3262 pic16_emitcode("mov","a,psw");
3263 pic16_emitcode("movx","@%s,a",r->name);
3264 pic16_emitcode("inc","%s",r->name);
3265 pic16_emitcode("mov","_spx,%s",r->name);
3266 pic16_freeAsmop (NULL,aop,ic,TRUE);
3269 pic16_emitcode("push","psw");
3271 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3279 static int wparamCmp(void *p1, void *p2)
3281 return (!strcmp((char *)p1, (char *)p2));
3284 int inWparamList(char *s)
3286 return isinSetWith(wparamList, s, wparamCmp);
3290 /*-----------------------------------------------------------------*/
3291 /* genCall - generates a call statement */
3292 /*-----------------------------------------------------------------*/
3293 static void genCall (iCode *ic)
3303 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3304 /* if caller saves & we have not saved then */
3305 // if (!ic->regsSaved)
3306 // saveRegisters(ic);
3308 /* initialise stackParms for IPUSH pushes */
3309 // stackParms = psuedoStkPtr;
3310 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3311 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3312 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3315 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3318 /* if send set is not empty the assign */
3321 int psuedoStkPtr=-1;
3322 int firstTimeThruLoop = 1;
3325 /* reverse sendSet if function is not reentrant */
3326 if(!IFFUNC_ISREENT(ftype))
3327 _G.sendSet = reverseSet(_G.sendSet);
3329 /* First figure how many parameters are getting passed */
3333 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3337 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3338 size = AOP_SIZE(IC_LEFT(sic));
3342 /* pass the last byte through WREG */
3346 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3347 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3348 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3350 if(!firstTimeThruLoop) {
3351 /* If this is not the first time we've been through the loop
3352 * then we need to save the parameter in a temporary
3353 * register. The last byte of the last parameter is
3357 // --psuedoStkPtr; // sanity check
3361 firstTimeThruLoop=0;
3363 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3368 /* all arguments are passed via stack */
3372 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3373 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3374 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3376 // pushaop(AOP(IC_LEFT(sic)), size);
3377 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3384 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3388 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3389 pushw(); /* save last parameter to stack if functions has varargs */
3393 } else use_wreg = 0;
3395 _G.stackRegSet = _G.sendSet;
3400 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3404 /* if we need to assign a result value */
3405 if ((IS_ITEMP(IC_RESULT(ic))
3406 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3407 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3408 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3411 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3414 assignResultValue(IC_RESULT(ic), 1);
3416 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3417 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3419 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3422 if(!stackParms && ic->parmBytes) {
3423 stackParms = ic->parmBytes;
3426 stackParms -= use_wreg;
3429 if(stackParms == 1) {
3430 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3432 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3433 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3435 if(STACK_MODEL_LARGE) {
3437 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3442 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3445 /* adjust the stack for parameters if required */
3446 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3449 /* if register bank was saved then pop them */
3451 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3453 /* if we hade saved some registers then unsave them */
3454 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3455 unsaveRegisters (ic);
3461 /*-----------------------------------------------------------------*/
3462 /* genPcall - generates a call by pointer statement */
3463 /* new version, created from genCall - HJD */
3464 /*-----------------------------------------------------------------*/
3465 static void genPcall (iCode *ic)
3467 sym_link *ftype, *fntype;
3469 symbol *retlbl = newiTempLabel(NULL);
3470 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3474 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3475 fntype = operandType( IC_LEFT(ic) )->next;
3477 /* if send set is not empty the assign */
3480 int psuedoStkPtr=-1;
3482 /* reverse sendSet if function is not reentrant */
3483 if(!IFFUNC_ISREENT(fntype))
3484 _G.sendSet = reverseSet(_G.sendSet);
3488 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3491 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3492 size = AOP_SIZE(IC_LEFT(sic));
3495 /* all parameters are passed via stack, since WREG is clobbered
3496 * by the calling sequence */
3498 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3500 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3502 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3506 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3509 _G.stackRegSet = _G.sendSet;
3513 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3515 // push return address
3516 // push $ on return stack, then replace with retlbl
3518 /* Thanks to Thorsten Klose for pointing out that the following
3519 * snippet should be interrupt safe */
3520 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3521 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3523 pic16_emitpcodeNULLop(POC_PUSH);
3525 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3526 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3527 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3528 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3529 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3533 /* restore interrupt control register */
3534 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3537 /* make the call by writing the pointer into pc */
3538 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3539 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3541 // note: MOVFF to PCL not allowed
3542 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3543 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3546 /* return address is here: (X) */
3547 pic16_emitpLabelFORCE(retlbl->key);
3549 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3552 /* if we need assign a result value */
3553 if ((IS_ITEMP(IC_RESULT(ic))
3554 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3555 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3556 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3559 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3562 assignResultValue(IC_RESULT(ic), 1);
3564 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3565 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3567 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3570 // stackParms -= use_wreg;
3573 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3574 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3575 if(STACK_MODEL_LARGE) {
3577 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3582 /*-----------------------------------------------------------------*/
3583 /* resultRemat - result is rematerializable */
3584 /*-----------------------------------------------------------------*/
3585 static int resultRemat (iCode *ic)
3587 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 if (SKIP_IC(ic) || ic->op == IFX)
3591 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3592 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3593 if (sym->remat && !POINTER_SET(ic))
3600 #if defined(__BORLANDC__) || defined(_MSC_VER)
3601 #define STRCASECMP stricmp
3603 #define STRCASECMP strcasecmp
3607 /*-----------------------------------------------------------------*/
3608 /* inExcludeList - return 1 if the string is in exclude Reg list */
3609 /*-----------------------------------------------------------------*/
3610 static bool inExcludeList(char *s)
3612 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3616 if (options.excludeRegs[i] &&
3617 STRCASECMP(options.excludeRegs[i],"none") == 0)
3620 for ( i = 0 ; options.excludeRegs[i]; i++) {
3621 if (options.excludeRegs[i] &&
3622 STRCASECMP(s,options.excludeRegs[i]) == 0)
3629 /*-----------------------------------------------------------------*/
3630 /* genFunction - generated code for function entry */
3631 /*-----------------------------------------------------------------*/
3632 static void genFunction (iCode *ic)
3638 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3640 pic16_labelOffset += (max_key+4);
3645 ftype = operandType(IC_LEFT(ic));
3646 sym = OP_SYMBOL(IC_LEFT(ic));
3648 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3649 /* create an absolute section at the interrupt vector:
3650 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3655 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3657 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3658 sprintf(asymname, "ivec_%s", sym->name);
3660 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3662 /* when an interrupt is declared as naked, do not emit the special
3663 * wrapper segment at vector address. The user should take care for
3664 * this instead. -- VR */
3666 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) =! INTNO_UNSPEC)) {
3667 asym = newSymbol(asymname, 0);
3668 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3669 pic16_addpBlock( apb );
3671 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3672 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3673 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3675 /* mark the end of this tiny function */
3676 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3678 sprintf(asymname, "%s", sym->rname);
3684 abSym = Safe_calloc(1, sizeof(absSym));
3685 strcpy(abSym->name, asymname);
3687 switch( FUNC_INTNO(sym->type) ) {
3688 case 0: abSym->address = 0x000000; break;
3689 case 1: abSym->address = 0x000008; break;
3690 case 2: abSym->address = 0x000018; break;
3693 // fprintf(stderr, "no interrupt number is given\n");
3694 abSym->address = -1; break;
3697 /* relocate interrupt vectors if needed */
3698 if(abSym->address != -1)
3699 abSym->address += pic16_options.ivt_loc;
3701 addSet(&absSymSet, abSym);
3705 /* create the function header */
3706 pic16_emitcode(";","-----------------------------------------");
3707 pic16_emitcode(";"," function %s",sym->name);
3708 pic16_emitcode(";","-----------------------------------------");
3710 pic16_emitcode("","%s:",sym->rname);
3711 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3716 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3717 if(!strcmp(ab->name, sym->rname)) {
3718 pic16_pBlockConvert2Absolute(pb);
3724 if(IFFUNC_ISNAKED(ftype)) {
3725 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3729 /* if critical function then turn interrupts off */
3730 if (IFFUNC_ISCRITICAL(ftype)) {
3731 //pic16_emitcode("clr","ea");
3734 currFunc = sym; /* update the currFunc symbol */
3735 _G.fregsUsed = sym->regsUsed;
3736 _G.sregsAlloc = newBitVect(128);
3739 /* if this is an interrupt service routine then
3740 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3741 if (IFFUNC_ISISR(sym->type)) {
3742 _G.usefastretfie = 1; /* use shadow registers by default */
3744 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3745 if(!FUNC_ISSHADOWREGS(sym->type)) {
3746 /* do not save WREG,STATUS,BSR for high priority interrupts
3747 * because they are stored in the hardware shadow registers already */
3748 _G.usefastretfie = 0;
3749 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3750 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3751 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3754 /* these should really be optimized somehow, because not all
3755 * interrupt handlers modify them */
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3758 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3759 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761 // pic16_pBlockConvert2ISR(pb);
3764 /* emit code to setup stack frame if user enabled,
3765 * and function is not main() */
3767 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3768 if(strcmp(sym->name, "main")) {
3770 || !options.ommitFramePtr
3772 || IFFUNC_ARGS(sym->type)
3773 || FUNC_HASSTACKPARM(sym->etype)
3775 /* setup the stack frame */
3776 if(STACK_MODEL_LARGE)
3777 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3778 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3780 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3781 if(STACK_MODEL_LARGE)
3782 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3786 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3789 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3791 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3792 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3794 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3797 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3798 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3805 /* if callee-save to be used for this function
3806 * then save the registers being used in this function */
3807 // if (IFFUNC_CALLEESAVES(sym->type))
3811 /* if any registers used */
3812 if (sym->regsUsed) {
3813 /* save the registers used */
3814 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3815 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3816 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3817 if (bitVectBitValue(sym->regsUsed,i)) {
3818 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3821 if(!pic16_regWithIdx(i)->wasUsed) {
3822 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3823 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3824 pic16_regWithIdx(i)->wasUsed = 1;
3828 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3832 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3833 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3836 /*-----------------------------------------------------------------*/
3837 /* genEndFunction - generates epilogue for functions */
3838 /*-----------------------------------------------------------------*/
3839 static void genEndFunction (iCode *ic)
3841 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3845 if(IFFUNC_ISNAKED(sym->type)) {
3846 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3852 /* add code for ISCRITICAL */
3853 if(IFFUNC_ISCRITICAL(sym->type)) {
3854 /* if critical function, turn on interrupts */
3856 /* TODO: add code here -- VR */
3859 // sym->regsUsed = _G.fregsUsed;
3861 /* now we need to restore the registers */
3862 /* if any registers used */
3864 /* first restore registers that might be used for stack access */
3865 if(_G.sregsAllocSet) {
3868 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3869 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3870 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3874 if (sym->regsUsed) {
3877 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3878 /* restore registers used */
3879 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3880 for ( i = sym->regsUsed->size; i >= 0; i--) {
3881 if (bitVectBitValue(sym->regsUsed,i)) {
3882 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3886 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3891 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3893 if (sym->stack == 1) {
3894 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3895 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3897 // we have to add more than one...
3898 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3899 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3900 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3902 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3903 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3904 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3908 if(strcmp(sym->name, "main")) {
3910 || !options.ommitFramePtr
3912 || IFFUNC_ARGS(sym->type)
3913 || FUNC_HASSTACKPARM(sym->etype)
3915 /* restore stack frame */
3916 if(STACK_MODEL_LARGE)
3917 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3918 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3924 if (IFFUNC_ISISR(sym->type)) {
3925 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3926 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3927 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3928 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3930 if(!FUNC_ISSHADOWREGS(sym->type)) {
3931 /* do not restore interrupt vector for WREG,STATUS,BSR
3932 * for high priority interrupt, see genFunction */
3933 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3934 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3935 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3937 // _G.interruptvector = 0; /* sanity check */
3940 /* if debug then send end of function */
3941 /* if (options.debug && currFunc) */
3943 debugFile->writeEndFunction (currFunc, ic, 1);
3946 if(_G.usefastretfie)
3947 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3949 pic16_emitpcodeNULLop(POC_RETFIE);
3951 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3953 _G.usefastretfie = 0;
3957 if (IFFUNC_ISCRITICAL(sym->type)) {
3958 pic16_emitcode("setb","ea");
3961 /* if debug then send end of function */
3963 debugFile->writeEndFunction (currFunc, ic, 1);
3966 /* insert code to restore stack frame, if user enabled it
3967 * and function is not main() */
3970 pic16_emitpcodeNULLop(POC_RETURN);
3972 /* Mark the end of a function */
3973 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3977 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3979 unsigned long lit=1;
3984 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3985 if(AOP_TYPE(op) == AOP_LIT) {
3986 if(!IS_FLOAT(operandType( op ))) {
3987 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3990 unsigned long lit_int;
3994 /* take care if literal is a float */
3995 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4001 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4002 pic16_emitpcode(POC_CLRF, dest);
4004 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4005 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4008 if(dest->type == PO_WREG && (offset == 0)) {
4009 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4012 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4016 /*-----------------------------------------------------------------*/
4017 /* genRet - generate code for return statement */
4018 /*-----------------------------------------------------------------*/
4019 static void genRet (iCode *ic)
4025 /* if we have no return value then
4026 * just generate the "ret" */
4031 /* we have something to return then
4032 * move the return value into place */
4033 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4034 size = AOP_SIZE(IC_LEFT(ic));
4038 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4041 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4044 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4046 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4049 /* >32-bits, setup stack and FSR0 */
4051 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4052 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4054 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4056 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4061 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4062 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4064 if(STACK_MODEL_LARGE) {
4065 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4066 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4068 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4073 /* old code, left here for reference -- VR */
4077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4079 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4080 pic16_emitpcomment("push %s",l);
4083 DEBUGpic16_emitcode(";", "%d", __LINE__);
4084 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4085 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4087 if (strcmp(fReturn[offset],l)) {
4088 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4089 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4090 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4092 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4096 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4106 if (strcmp(fReturn[pushed],"a"))
4107 pic16_emitcode("pop",fReturn[pushed]);
4109 pic16_emitcode("pop","acc");
4115 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4118 /* generate a jump to the return label
4119 * if the next is not the return statement */
4120 if (!(ic->next && ic->next->op == LABEL
4121 && IC_LABEL(ic->next) == returnLabel)) {
4123 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4124 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4128 /*-----------------------------------------------------------------*/
4129 /* genLabel - generates a label */
4130 /*-----------------------------------------------------------------*/
4131 static void genLabel (iCode *ic)
4135 /* special case never generate */
4136 if (IC_LABEL(ic) == entryLabel)
4139 pic16_emitpLabel(IC_LABEL(ic)->key);
4140 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4143 /*-----------------------------------------------------------------*/
4144 /* genGoto - generates a goto */
4145 /*-----------------------------------------------------------------*/
4147 static void genGoto (iCode *ic)
4150 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4151 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4155 /*-----------------------------------------------------------------*/
4156 /* genMultbits :- multiplication of bits */
4157 /*-----------------------------------------------------------------*/
4158 static void genMultbits (operand *left,
4164 if(!pic16_sameRegs(AOP(result),AOP(right)))
4165 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4167 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4168 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4169 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4174 /*-----------------------------------------------------------------*/
4175 /* genMultOneByte : 8 bit multiplication & division */
4176 /*-----------------------------------------------------------------*/
4177 static void genMultOneByte (operand *left,
4183 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4184 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4186 /* (if two literals, the value is computed before) */
4187 /* if one literal, literal on the right */
4188 if (AOP_TYPE(left) == AOP_LIT){
4194 /* size is already checked in genMult == 1 */
4195 // size = AOP_SIZE(result);
4197 if (AOP_TYPE(right) == AOP_LIT){
4198 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4199 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4200 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4201 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4203 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4204 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4206 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4209 pic16_genMult8X8_8 (left, right,result);
4212 /*-----------------------------------------------------------------*/
4213 /* genMultOneWord : 16 bit multiplication */
4214 /*-----------------------------------------------------------------*/
4215 static void genMultOneWord (operand *left,
4220 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4221 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4223 /* (if two literals, the value is computed before)
4224 * if one literal, literal on the right */
4225 if (AOP_TYPE(left) == AOP_LIT){
4231 /* size is checked already == 2 */
4232 // size = AOP_SIZE(result);
4234 if (AOP_TYPE(right) == AOP_LIT) {
4235 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4236 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4237 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4238 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4240 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4241 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4242 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4243 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4246 pic16_genMult16X16_16(left, right,result);
4249 /*-----------------------------------------------------------------*/
4250 /* genMultOneLong : 32 bit multiplication */
4251 /*-----------------------------------------------------------------*/
4252 static void genMultOneLong (operand *left,
4257 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4258 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4260 /* (if two literals, the value is computed before)
4261 * if one literal, literal on the right */
4262 if (AOP_TYPE(left) == AOP_LIT){
4268 /* size is checked already == 4 */
4269 // size = AOP_SIZE(result);
4271 if (AOP_TYPE(right) == AOP_LIT) {
4272 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4273 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4274 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4275 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4277 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4278 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4279 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4280 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4283 pic16_genMult32X32_32(left, right,result);
4288 /*-----------------------------------------------------------------*/
4289 /* genMult - generates code for multiplication */
4290 /*-----------------------------------------------------------------*/
4291 static void genMult (iCode *ic)
4293 operand *left = IC_LEFT(ic);
4294 operand *right = IC_RIGHT(ic);
4295 operand *result= IC_RESULT(ic);
4298 /* assign the amsops */
4299 pic16_aopOp (left,ic,FALSE);
4300 pic16_aopOp (right,ic,FALSE);
4301 pic16_aopOp (result,ic,TRUE);
4303 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4305 /* special cases first *
4307 if (AOP_TYPE(left) == AOP_CRY
4308 && AOP_TYPE(right)== AOP_CRY) {
4309 genMultbits(left,right,result);
4313 /* if both are of size == 1 */
4314 if(AOP_SIZE(left) == 1
4315 && AOP_SIZE(right) == 1) {
4316 genMultOneByte(left,right,result);
4320 /* if both are of size == 2 */
4321 if(AOP_SIZE(left) == 2
4322 && AOP_SIZE(right) == 2) {
4323 genMultOneWord(left, right, result);
4327 /* if both are of size == 4 */
4328 if(AOP_SIZE(left) == 4
4329 && AOP_SIZE(right) == 4) {
4330 genMultOneLong(left, right, result);
4334 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4337 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4338 /* should have been converted to function call */
4342 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4343 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4344 pic16_freeAsmop(result,NULL,ic,TRUE);
4347 /*-----------------------------------------------------------------*/
4348 /* genDivbits :- division of bits */
4349 /*-----------------------------------------------------------------*/
4350 static void genDivbits (operand *left,
4357 /* the result must be bit */
4358 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4359 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4363 pic16_emitcode("div","ab");
4364 pic16_emitcode("rrc","a");
4365 pic16_aopPut(AOP(result),"c",0);
4368 /*-----------------------------------------------------------------*/
4369 /* genDivOneByte : 8 bit division */
4370 /*-----------------------------------------------------------------*/
4371 static void genDivOneByte (operand *left,
4375 sym_link *opetype = operandType(result);
4380 /* result = divident / divisor
4381 * - divident may be a register or a literal,
4382 * - divisor may be a register or a literal,
4383 * so there are 3 cases (literal / literal is optimized
4384 * by the front-end) to handle.
4385 * In addition we must handle signed and unsigned, which
4386 * result in 6 final different cases -- VR */
4390 size = AOP_SIZE(result) - 1;
4392 /* signed or unsigned */
4393 if (SPEC_USIGN(opetype)) {
4394 pCodeOp *pct1, /* count */
4397 symbol *label1, *label2, *label3;;
4400 /* unsigned is easy */
4402 pct1 = pic16_popGetTempReg(1);
4403 pct2 = pic16_popGetTempReg(1);
4404 pct3 = pic16_popGetTempReg(1);
4406 label1 = newiTempLabel(NULL);
4407 label2 = newiTempLabel(NULL);
4408 label3 = newiTempLabel(NULL);
4410 /* the following algorithm is extracted from divuint.c */
4412 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4413 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4415 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4417 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4419 pic16_emitpLabel(label1->key);
4422 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4426 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4430 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4432 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4433 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4435 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4436 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4437 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4439 pic16_emitpLabel( label3->key );
4440 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4441 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4445 pic16_emitpLabel(label2->key);
4446 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4447 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4448 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4450 /* result is in wreg */
4451 if(AOP_TYPE(result) != AOP_ACC)
4452 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4454 pic16_popReleaseTempReg( pct3, 1);
4455 pic16_popReleaseTempReg( pct2, 1);
4456 pic16_popReleaseTempReg( pct1, 1);
4461 /* signed is a little bit more difficult */
4463 /* save the signs of the operands */
4464 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4466 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4467 pic16_emitcode("push","acc"); /* save it on the stack */
4469 /* now sign adjust for both left & right */
4470 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4472 lbl = newiTempLabel(NULL);
4473 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4474 pic16_emitcode("cpl","a");
4475 pic16_emitcode("inc","a");
4476 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4477 pic16_emitcode("mov","b,a");
4479 /* sign adjust left side */
4480 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4483 lbl = newiTempLabel(NULL);
4484 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4485 pic16_emitcode("cpl","a");
4486 pic16_emitcode("inc","a");
4487 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4489 /* now the division */
4490 pic16_emitcode("div","ab");
4491 /* we are interested in the lower order
4493 pic16_emitcode("mov","b,a");
4494 lbl = newiTempLabel(NULL);
4495 pic16_emitcode("pop","acc");
4496 /* if there was an over flow we don't
4497 adjust the sign of the result */
4498 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4499 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4501 pic16_emitcode("clr","a");
4502 pic16_emitcode("subb","a,b");
4503 pic16_emitcode("mov","b,a");
4504 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4506 /* now we are done */
4507 pic16_aopPut(AOP(result),"b",0);
4509 pic16_emitcode("mov","c,b.7");
4510 pic16_emitcode("subb","a,acc");
4513 pic16_aopPut(AOP(result),"a",offset++);
4517 /*-----------------------------------------------------------------*/
4518 /* genDiv - generates code for division */
4519 /*-----------------------------------------------------------------*/
4520 static void genDiv (iCode *ic)
4522 operand *left = IC_LEFT(ic);
4523 operand *right = IC_RIGHT(ic);
4524 operand *result= IC_RESULT(ic);
4527 /* Division is a very lengthy algorithm, so it is better
4528 * to call support routines than inlining algorithm.
4529 * Division functions written here just in case someone
4530 * wants to inline and not use the support libraries -- VR */
4534 /* assign the amsops */
4535 pic16_aopOp (left,ic,FALSE);
4536 pic16_aopOp (right,ic,FALSE);
4537 pic16_aopOp (result,ic,TRUE);
4539 /* special cases first */
4541 if (AOP_TYPE(left) == AOP_CRY &&
4542 AOP_TYPE(right)== AOP_CRY) {
4543 genDivbits(left,right,result);
4547 /* if both are of size == 1 */
4548 if (AOP_SIZE(left) == 1 &&
4549 AOP_SIZE(right) == 1 ) {
4550 genDivOneByte(left,right,result);
4554 /* should have been converted to function call */
4557 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4558 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4559 pic16_freeAsmop(result,NULL,ic,TRUE);
4562 /*-----------------------------------------------------------------*/
4563 /* genModbits :- modulus of bits */
4564 /*-----------------------------------------------------------------*/
4565 static void genModbits (operand *left,
4573 werror(W_POSSBUG2, __FILE__, __LINE__);
4574 /* the result must be bit */
4575 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4576 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4580 pic16_emitcode("div","ab");
4581 pic16_emitcode("mov","a,b");
4582 pic16_emitcode("rrc","a");
4583 pic16_aopPut(AOP(result),"c",0);
4586 /*-----------------------------------------------------------------*/
4587 /* genModOneByte : 8 bit modulus */
4588 /*-----------------------------------------------------------------*/
4589 static void genModOneByte (operand *left,
4593 sym_link *opetype = operandType(result);
4598 werror(W_POSSBUG2, __FILE__, __LINE__);
4600 /* signed or unsigned */
4601 if (SPEC_USIGN(opetype)) {
4602 /* unsigned is easy */
4603 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4604 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4606 pic16_emitcode("div","ab");
4607 pic16_aopPut(AOP(result),"b",0);
4611 /* signed is a little bit more difficult */
4613 /* save the signs of the operands */
4614 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4617 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4618 pic16_emitcode("push","acc"); /* save it on the stack */
4620 /* now sign adjust for both left & right */
4621 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4624 lbl = newiTempLabel(NULL);
4625 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4626 pic16_emitcode("cpl","a");
4627 pic16_emitcode("inc","a");
4628 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4629 pic16_emitcode("mov","b,a");
4631 /* sign adjust left side */
4632 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4635 lbl = newiTempLabel(NULL);
4636 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4637 pic16_emitcode("cpl","a");
4638 pic16_emitcode("inc","a");
4639 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4641 /* now the multiplication */
4642 pic16_emitcode("div","ab");
4643 /* we are interested in the lower order
4645 lbl = newiTempLabel(NULL);
4646 pic16_emitcode("pop","acc");
4647 /* if there was an over flow we don't
4648 adjust the sign of the result */
4649 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4650 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4652 pic16_emitcode("clr","a");
4653 pic16_emitcode("subb","a,b");
4654 pic16_emitcode("mov","b,a");
4655 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4657 /* now we are done */
4658 pic16_aopPut(AOP(result),"b",0);
4662 /*-----------------------------------------------------------------*/
4663 /* genMod - generates code for division */
4664 /*-----------------------------------------------------------------*/
4665 static void genMod (iCode *ic)
4667 operand *left = IC_LEFT(ic);
4668 operand *right = IC_RIGHT(ic);
4669 operand *result= IC_RESULT(ic);
4673 /* assign the amsops */
4674 pic16_aopOp (left,ic,FALSE);
4675 pic16_aopOp (right,ic,FALSE);
4676 pic16_aopOp (result,ic,TRUE);
4678 /* special cases first */
4680 if (AOP_TYPE(left) == AOP_CRY &&
4681 AOP_TYPE(right)== AOP_CRY) {
4682 genModbits(left,right,result);
4686 /* if both are of size == 1 */
4687 if (AOP_SIZE(left) == 1 &&
4688 AOP_SIZE(right) == 1 ) {
4689 genModOneByte(left,right,result);
4693 /* should have been converted to function call */
4697 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4698 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699 pic16_freeAsmop(result,NULL,ic,TRUE);
4702 /*-----------------------------------------------------------------*/
4703 /* genIfxJump :- will create a jump depending on the ifx */
4704 /*-----------------------------------------------------------------*/
4706 note: May need to add parameter to indicate when a variable is in bit space.
4708 static void genIfxJump (iCode *ic, char *jval)
4712 /* if true label then we jump if condition
4714 if ( IC_TRUE(ic) ) {
4716 if(strcmp(jval,"a") == 0)
4718 else if (strcmp(jval,"c") == 0)
4721 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4722 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4725 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4726 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4730 /* false label is present */
4731 if(strcmp(jval,"a") == 0)
4733 else if (strcmp(jval,"c") == 0)
4736 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4737 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4740 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4741 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4746 /* mark the icode as generated */
4750 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4754 /* if true label then we jump if condition
4756 if ( IC_TRUE(ic) ) {
4757 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4758 pic16_emitpcode(POC_BTFSC, jop);
4760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4761 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4764 /* false label is present */
4765 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4766 pic16_emitpcode(POC_BTFSS, jop);
4768 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4769 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4773 /* mark the icode as generated */
4780 /*-----------------------------------------------------------------*/
4782 /*-----------------------------------------------------------------*/
4783 static void genSkip(iCode *ifx,int status_bit)
4785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4789 if ( IC_TRUE(ifx) ) {
4790 switch(status_bit) {
4805 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4806 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4810 switch(status_bit) {
4824 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4825 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4832 /*-----------------------------------------------------------------*/
4834 /*-----------------------------------------------------------------*/
4835 static void genSkipc(resolvedIfx *rifx)
4837 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4847 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4848 rifx->generated = 1;
4851 #if !(USE_SIMPLE_GENCMP)
4852 /*-----------------------------------------------------------------*/
4854 /*-----------------------------------------------------------------*/
4855 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4857 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4862 if( (rifx->condition ^ invert_condition) & 1)
4867 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4868 rifx->generated = 1;
4873 /*-----------------------------------------------------------------*/
4875 /*-----------------------------------------------------------------*/
4876 static void genSkipz(iCode *ifx, int condition)
4887 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4892 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4894 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4899 #if !(USE_SIMPLE_GENCMP)
4900 /*-----------------------------------------------------------------*/
4902 /*-----------------------------------------------------------------*/
4903 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4909 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4911 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4914 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4915 rifx->generated = 1;
4920 /*-----------------------------------------------------------------*/
4921 /* genChkZeroes :- greater or less than comparison */
4922 /* For each byte in a literal that is zero, inclusive or the */
4923 /* the corresponding byte in the operand with W */
4924 /* returns true if any of the bytes are zero */
4925 /*-----------------------------------------------------------------*/
4926 static int genChkZeroes(operand *op, int lit, int size)
4933 i = (lit >> (size*8)) & 0xff;
4937 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4939 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4949 /*-----------------------------------------------------------------*/
4950 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4951 /* aop (if it's NOT a literal) or from lit (if */
4952 /* aop is a literal) */
4953 /*-----------------------------------------------------------------*/
4954 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4955 if (aop->type == AOP_LIT) {
4956 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4958 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4962 /*-----------------------------------------------------------------*/
4963 /* genCmp :- greater or less than comparison */
4964 /*-----------------------------------------------------------------*/
4966 #if USE_SIMPLE_GENCMP /* { */
4968 /* genCmp performs a left < right comparison, stores
4969 * the outcome in result (if != NULL) and generates
4970 * control flow code for the ifx (if != NULL).
4972 * This version leaves in sequences like
4973 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4974 * which should be optmized by the peephole
4975 * optimizer - RN 2005-01-01 */
4976 static void genCmp (operand *left,operand *right,
4977 operand *result, iCode *ifx, int sign)
4990 assert (AOP_SIZE(left) == AOP_SIZE(right));
4991 assert (left && right);
4993 size = AOP_SIZE(right) - 1;
4994 mask = (0x100UL << (size*8)) - 1;
4995 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5000 resolveIfx (&rIfx, ifx);
5002 /* handle for special cases */
5003 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5006 /**********************************************************************
5007 * handle bits - bit compares are promoted to int compares seemingly! *
5008 **********************************************************************/
5010 // THIS IS COMPLETELY UNTESTED!
5011 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5012 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5013 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5014 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5017 // 1 < {0,1} is false --> clear C by skipping the next instruction
5018 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5019 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5020 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5021 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5022 emitCLRC; // only skipped for left=0 && right=1
5024 goto correct_result_in_carry;
5028 /*************************************************
5029 * make sure that left is register (or the like) *
5030 *************************************************/
5031 if (!isAOP_REGlike(left)) {
5032 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5033 assert (isAOP_LIT(left));
5034 assert (isAOP_REGlike(right));
5035 // swap left and right
5036 // left < right <==> right > left <==> (right >= left + 1)
5037 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5039 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5040 // MAXVALUE < right? always false
5041 if (performedLt) emitCLRC; else emitSETC;
5042 goto correct_result_in_carry;
5045 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5046 // that's why we handled it above.
5053 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5054 } else if (isAOP_LIT(right)) {
5055 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5058 assert (isAOP_REGlike(left)); // left must be register or the like
5059 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5061 /*************************************************
5062 * special cases go here *
5063 *************************************************/
5065 if (isAOP_LIT(right)) {
5067 // unsigned comparison to a literal
5068 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5070 // unsigned left < 0? always false
5071 if (performedLt) emitCLRC; else emitSETC;
5072 goto correct_result_in_carry;
5075 // signed comparison to a literal
5076 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5077 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5078 // signed left < 0x80000000? always false
5079 if (performedLt) emitCLRC; else emitSETC;
5080 goto correct_result_in_carry;
5081 } else if (lit == 0) {
5082 // compare left < 0; set CARRY if SIGNBIT(left) is set
5083 if (performedLt) emitSETC; else emitCLRC;
5084 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5085 if (performedLt) emitCLRC; else emitSETC;
5086 goto correct_result_in_carry;
5089 } // right is literal
5091 /*************************************************
5092 * perform a general case comparison *
5093 * make sure we get CARRY==1 <==> left >= right *
5094 *************************************************/
5095 // compare most significant bytes
5096 //DEBUGpc ("comparing bytes at offset %d", size);
5098 // unsigned comparison
5099 mov2w_regOrLit (AOP(right), lit, size);
5100 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5102 // signed comparison
5103 // (add 2^n to both operands then perform an unsigned comparison)
5104 if (isAOP_LIT(right)) {
5105 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5106 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5108 if (litbyte == 0x80) {
5109 // left >= 0x80 -- always true, but more bytes to come
5110 pic16_mov2w (AOP(left), size);
5111 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5114 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5115 pic16_mov2w (AOP(left), size);
5116 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5117 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5120 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5121 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5122 pic16_mov2w (AOP(left), size);
5123 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124 pic16_emitpcode (POC_MOVWF, pctemp);
5125 pic16_mov2w (AOP(right), size);
5126 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127 pic16_emitpcode (POC_SUBFW, pctemp);
5128 //pic16_popReleaseTempReg(pctemp, 1);
5132 // compare remaining bytes (treat as unsigned case from above)
5133 templbl = newiTempLabel ( NULL );
5136 //DEBUGpc ("comparing bytes at offset %d", offs);
5137 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5138 mov2w_regOrLit (AOP(right), lit, offs);
5139 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5141 pic16_emitpLabel (templbl->key);
5142 goto result_in_carry;
5146 /****************************************************
5147 * now CARRY contains the result of the comparison: *
5148 * SUBWF sets CARRY iff *
5149 * F-W >= 0 <==> F >= W <==> !(F < W) *
5150 * (F=left, W=right) *
5151 ****************************************************/
5154 if (result && AOP_TYPE(result) != AOP_CRY) {
5155 // value will be stored
5158 // value wil only be used in the following genSkipc()
5159 rIfx.condition ^= 1;
5163 correct_result_in_carry:
5165 // assign result to variable (if neccessary)
5166 if (result && AOP_TYPE(result) != AOP_CRY) {
5167 //DEBUGpc ("assign result");
5168 size = AOP_SIZE(result);
5170 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5172 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5175 // perform conditional jump
5177 //DEBUGpc ("generate control flow");
5186 static void genCmp (operand *left,operand *right,
5187 operand *result, iCode *ifx, int sign)
5189 int size; //, offset = 0 ;
5190 unsigned long lit = 0L,i = 0;
5191 resolvedIfx rFalseIfx;
5192 // resolvedIfx rTrueIfx;
5194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5197 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5198 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5204 resolveIfx(&rFalseIfx,ifx);
5205 truelbl = newiTempLabel(NULL);
5206 size = max(AOP_SIZE(left),AOP_SIZE(right));
5208 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5212 /* if literal is on the right then swap with left */
5213 if ((AOP_TYPE(right) == AOP_LIT)) {
5214 operand *tmp = right ;
5215 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5216 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5219 lit = (lit - 1) & mask;
5222 rFalseIfx.condition ^= 1;
5225 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5226 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5230 //if(IC_TRUE(ifx) == NULL)
5231 /* if left & right are bit variables */
5232 if (AOP_TYPE(left) == AOP_CRY &&
5233 AOP_TYPE(right) == AOP_CRY ) {
5234 assert (0 && "bit variables used in genCmp");
5235 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5236 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5238 /* subtract right from left if at the
5239 end the carry flag is set then we know that
5240 left is greater than right */
5242 symbol *lbl = newiTempLabel(NULL);
5245 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5246 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5250 if(AOP_TYPE(right) == AOP_LIT) {
5252 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5254 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5261 genSkipCond(&rFalseIfx,left,size-1,7);
5263 /* no need to compare to 0...*/
5264 /* NOTE: this is a de-generate compare that most certainly
5265 * creates some dead code. */
5266 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5268 if(ifx) ifx->generated = 1;
5275 //i = (lit >> (size*8)) & 0xff;
5276 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5278 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5280 i = ((0-lit) & 0xff);
5283 /* lit is 0x7f, all signed chars are less than
5284 * this except for 0x7f itself */
5285 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5286 genSkipz2(&rFalseIfx,0);
5288 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5289 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5290 genSkipc(&rFalseIfx);
5295 genSkipz2(&rFalseIfx,1);
5297 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5298 genSkipc(&rFalseIfx);
5302 if(ifx) ifx->generated = 1;
5306 /* chars are out of the way. now do ints and longs */
5309 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5316 genSkipCond(&rFalseIfx,left,size,7);
5317 if(ifx) ifx->generated = 1;
5322 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5324 //rFalseIfx.condition ^= 1;
5325 //genSkipCond(&rFalseIfx,left,size,7);
5326 //rFalseIfx.condition ^= 1;
5328 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5329 if(rFalseIfx.condition)
5330 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5332 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5334 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5335 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5336 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5339 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5341 if(rFalseIfx.condition) {
5343 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5349 genSkipc(&rFalseIfx);
5350 pic16_emitpLabel(truelbl->key);
5351 if(ifx) ifx->generated = 1;
5358 if( (lit & 0xff) == 0) {
5359 /* lower byte is zero */
5360 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5361 i = ((lit >> 8) & 0xff) ^0x80;
5362 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5363 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5364 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5365 genSkipc(&rFalseIfx);
5368 if(ifx) ifx->generated = 1;
5373 /* Special cases for signed longs */
5374 if( (lit & 0xffffff) == 0) {
5375 /* lower byte is zero */
5376 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5377 i = ((lit >> 8*3) & 0xff) ^0x80;
5378 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5379 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5380 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5381 genSkipc(&rFalseIfx);
5384 if(ifx) ifx->generated = 1;
5392 if(lit & (0x80 << (size*8))) {
5393 /* lit is negative */
5394 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5396 //genSkipCond(&rFalseIfx,left,size,7);
5398 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5400 if(rFalseIfx.condition)
5401 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5403 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5407 /* lit is positive */
5408 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5409 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5410 if(rFalseIfx.condition)
5411 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5413 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5418 This works, but is only good for ints.
5419 It also requires a "known zero" register.
5420 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5421 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5422 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5423 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5424 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5425 genSkipc(&rFalseIfx);
5427 pic16_emitpLabel(truelbl->key);
5428 if(ifx) ifx->generated = 1;
5432 /* There are no more special cases, so perform a general compare */
5434 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5435 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5439 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5441 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5443 //rFalseIfx.condition ^= 1;
5444 genSkipc(&rFalseIfx);
5446 pic16_emitpLabel(truelbl->key);
5448 if(ifx) ifx->generated = 1;
5455 /* sign is out of the way. So now do an unsigned compare */
5456 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5459 /* General case - compare to an unsigned literal on the right.*/
5461 i = (lit >> (size*8)) & 0xff;
5462 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5463 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5465 i = (lit >> (size*8)) & 0xff;
5468 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5472 /* this byte of the lit is zero,
5473 *if it's not the last then OR in the variable */
5475 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5480 pic16_emitpLabel(lbl->key);
5481 // pic16_emitpLabel(truelbl->key);
5482 //if(emitFinalCheck)
5483 genSkipc(&rFalseIfx);
5485 pic16_emitpLabel(truelbl->key);
5487 if(ifx) ifx->generated = 1;
5494 if(AOP_TYPE(left) == AOP_LIT) {
5495 //symbol *lbl = newiTempLabel(NULL);
5497 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5500 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5503 if((lit == 0) && (sign == 0)){
5506 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5508 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5510 genSkipz2(&rFalseIfx,0);
5511 if(ifx) ifx->generated = 1;
5518 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5519 /* degenerate compare can never be true */
5520 if(rFalseIfx.condition == 0)
5521 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5523 if(ifx) ifx->generated = 1;
5528 /* signed comparisons to a literal byte */
5530 int lp1 = (lit+1) & 0xff;
5532 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5535 rFalseIfx.condition ^= 1;
5536 genSkipCond(&rFalseIfx,right,0,7);
5539 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5540 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5541 genSkipz2(&rFalseIfx,1);
5544 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5545 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5546 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5547 rFalseIfx.condition ^= 1;
5548 genSkipc(&rFalseIfx);
5552 /* unsigned comparisons to a literal byte */
5554 switch(lit & 0xff ) {
5556 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5557 genSkipz2(&rFalseIfx,0);
5560 rFalseIfx.condition ^= 1;
5561 genSkipCond(&rFalseIfx,right,0,7);
5565 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5566 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5567 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5568 rFalseIfx.condition ^= 1;
5569 if (AOP_TYPE(result) == AOP_CRY)
5570 genSkipc(&rFalseIfx);
5572 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5573 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5579 if(ifx) ifx->generated = 1;
5580 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5586 /* Size is greater than 1 */
5594 /* this means lit = 0xffffffff, or -1 */
5597 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5598 rFalseIfx.condition ^= 1;
5599 genSkipCond(&rFalseIfx,right,size,7);
5600 if(ifx) ifx->generated = 1;
5602 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5611 if(rFalseIfx.condition) {
5612 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5613 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5616 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5618 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5622 if(rFalseIfx.condition) {
5623 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5624 pic16_emitpLabel(truelbl->key);
5626 rFalseIfx.condition ^= 1;
5627 genSkipCond(&rFalseIfx,right,s,7);
5630 if(ifx) ifx->generated = 1;
5632 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5638 if((size == 1) && (0 == (lp1&0xff))) {
5639 /* lower byte of signed word is zero */
5640 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5641 i = ((lp1 >> 8) & 0xff) ^0x80;
5642 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5643 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5644 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5646 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5648 if(ifx) ifx->generated = 1;
5651 rFalseIfx.condition ^= 1;
5652 genSkipc(&rFalseIfx);
5653 if(ifx) ifx->generated = 1;
5659 if(lit & (0x80 << (size*8))) {
5660 /* Lit is less than zero */
5661 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5662 //rFalseIfx.condition ^= 1;
5663 //genSkipCond(&rFalseIfx,left,size,7);
5664 //rFalseIfx.condition ^= 1;
5665 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5666 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5668 if(rFalseIfx.condition)
5669 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5671 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5675 /* Lit is greater than or equal to zero */
5676 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5677 //rFalseIfx.condition ^= 1;
5678 //genSkipCond(&rFalseIfx,right,size,7);
5679 //rFalseIfx.condition ^= 1;
5681 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5682 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5685 if(rFalseIfx.condition)
5686 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5688 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5692 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5693 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5697 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5699 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701 rFalseIfx.condition ^= 1;
5702 //rFalseIfx.condition = 1;
5703 genSkipc(&rFalseIfx);
5705 pic16_emitpLabel(truelbl->key);
5707 if(ifx) ifx->generated = 1;
5710 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5717 /* compare word or long to an unsigned literal on the right.*/
5722 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5725 break; /* handled above */
5728 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5730 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5731 genSkipz2(&rFalseIfx,0);
5735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5737 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5740 if(rFalseIfx.condition)
5741 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5743 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5746 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5747 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5749 rFalseIfx.condition ^= 1;
5750 genSkipc(&rFalseIfx);
5753 pic16_emitpLabel(truelbl->key);
5755 if(ifx) ifx->generated = 1;
5757 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5765 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5766 i = (lit >> (size*8)) & 0xff;
5768 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5769 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5772 i = (lit >> (size*8)) & 0xff;
5775 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5777 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5779 /* this byte of the lit is zero,
5780 * if it's not the last then OR in the variable */
5782 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5787 pic16_emitpLabel(lbl->key);
5789 rFalseIfx.condition ^= 1;
5791 genSkipc(&rFalseIfx);
5795 pic16_emitpLabel(truelbl->key);
5796 if(ifx) ifx->generated = 1;
5798 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5804 /* Compare two variables */
5806 DEBUGpic16_emitcode(";sign","%d",sign);
5810 /* Sigh. thus sucks... */
5814 pctemp = pic16_popGetTempReg(1);
5815 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5816 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5817 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5818 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5819 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5820 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821 pic16_popReleaseTempReg(pctemp, 1);
5823 /* Signed char comparison */
5824 /* Special thanks to Nikolai Golovchenko for this snippet */
5825 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5826 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5827 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5828 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5829 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5830 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5832 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5833 genSkipc(&rFalseIfx);
5835 if(ifx) ifx->generated = 1;
5837 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5845 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5846 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5850 /* The rest of the bytes of a multi-byte compare */
5854 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5857 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5858 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5863 pic16_emitpLabel(lbl->key);
5865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5866 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5867 (AOP_TYPE(result) == AOP_REG)) {
5868 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5869 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5871 genSkipc(&rFalseIfx);
5873 //genSkipc(&rFalseIfx);
5874 if(ifx) ifx->generated = 1;
5877 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5885 if ((AOP_TYPE(result) != AOP_CRY)
5886 && AOP_SIZE(result)) {
5887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5889 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5891 pic16_outBitC(result);
5893 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5894 /* if the result is used in the next
5895 ifx conditional branch then generate
5896 code a little differently */
5898 genIfxJump (ifx,"c");
5900 pic16_outBitC(result);
5901 /* leave the result in acc */
5906 #elif 0 /* VR version of genCmp() */ /* } else { */
5908 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5909 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5910 operand *result, int offset, int invert_op)
5914 /* check condition, > or < ?? */
5915 if(rIfx->condition != 0)invert_op ^= 1;
5917 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5919 if(!ifx)invert_op ^= 1;
5921 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5922 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5925 if(!invert_op)return POC_CPFSGT;
5926 else return POC_CPFSLT;
5929 static int compareAopfirstpass=1;
5931 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5932 operand *oper, int offset, operand *result,
5933 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5939 /* invert if there is a result to be loaded, in order to fit,
5940 * SETC/CLRC sequence */
5941 if(AOP_SIZE(result))invert_op ^= 1;
5943 // if(sign && !offset)invert_op ^= 1;
5945 // if(sign)invert_op ^= 1;
5947 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5949 if(AOP_SIZE(result) && compareAopfirstpass) {
5952 pic16_emitpcode(POC_SETF, pcop2);
5957 pic16_emitpcode(POC_CLRF, pcop2);
5963 compareAopfirstpass = 0;
5965 /* there is a bug when comparing operands with size > 1,
5966 * because higher bytes can be equal and test should be performed
5967 * to the next lower byte, current algorithm, considers operands
5968 * inequal in these cases! -- VR 20041107 */
5972 pic16_emitpcode(op, pcop);
5974 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5977 if((!sign || !offset) && AOP_SIZE(result)) {
5980 pic16_emitpcode(POC_CLRF, pcop2);
5985 pic16_emitpcode(POC_SETF, pcop2);
5990 /* don't emit final branch (offset == 0) */
5994 pic16_emitpcode(POC_RRCF, pcop2);
5996 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5999 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6000 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6001 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6003 truelbl = newiTempLabel( NULL );
6004 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6005 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6006 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6008 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6009 pic16_emitpLabel(truelbl->key);
6011 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016 static void genCmp (operand *left, operand *right,
6017 operand *result, iCode *ifx, int sign)
6021 resolvedIfx rFalseIfx;
6022 symbol *falselbl, *tlbl;
6026 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6028 resolveIfx(&rFalseIfx, ifx);
6029 size = max(AOP_SIZE(left), AOP_SIZE(right));
6031 /* if left & right are bit variables */
6032 if(AOP_TYPE(left) == AOP_CRY
6033 && AOP_TYPE(right) == AOP_CRY ) {
6035 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6036 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6038 werror(W_POSSBUG2, __FILE__, __LINE__);
6042 /* if literal is on the right then swap with left */
6043 if((AOP_TYPE(right) == AOP_LIT)) {
6044 operand *tmp = right ;
6045 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6047 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6049 // lit = (lit - 1) & mask;
6052 rFalseIfx.condition ^= 1; /* reverse compare */
6054 if ((AOP_TYPE(left) == AOP_LIT)) {
6055 /* float compares are handled by support functions */
6056 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6059 /* actual comparing algorithm */
6060 // size = AOP_SIZE( right );
6062 falselbl = newiTempLabel( NULL );
6063 if(AOP_TYPE(left) == AOP_LIT) {
6064 /* compare to literal */
6065 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6068 pCodeOp *pct, *pct2;
6071 /* signed compare */
6072 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6074 pct = pic16_popCopyReg(&pic16_pc_prodl);
6075 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6076 tlbl = newiTempLabel( NULL );
6078 /* first compare signs:
6079 * a. if both are positive, compare just like unsigned
6080 * b. if both are negative, invert cmpop, compare just like unsigned
6081 * c. if different signs, determine the result directly */
6087 tlbl1 = newiTempLabel( NULL );
6088 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6092 /* literal is zero or positive:
6093 * a. if carry is zero, too, continue compare,
6094 * b. if carry is set, then continue depending on cmpop ^ condition:
6095 * 1. '<' return false (literal < variable),
6096 * 2. '>' return true (literal > variable) */
6097 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6098 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6101 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6102 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6106 /* literal is negative:
6107 * a. if carry is set, too, continue compare,
6108 * b. if carry is zero, then continue depending on cmpop ^ condition:
6109 * 1. '<' return true (literal < variable),
6110 * 2. '>' return false (literal > variable) */
6111 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6112 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6114 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6115 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6120 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6122 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6123 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6128 pic16_emitpLabel( tlbl1->key );
6131 compareAopfirstpass=1;
6132 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6133 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6134 // pic16_emitpcode(POC_MOVWF, pct);
6136 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6137 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6138 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6139 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6143 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6144 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6145 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 // pic16_emitpcode(POC_MOVWF, pct);
6148 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6150 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6151 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6152 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6156 if(ifx)ifx->generated = 1;
6158 if(AOP_SIZE(result)) {
6159 pic16_emitpLabel(tlbl->key);
6160 pic16_emitpLabel(falselbl->key);
6161 pic16_outBitOp( result, pct2 );
6163 pic16_emitpLabel(tlbl->key);
6167 /* unsigned compare */
6168 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6170 compareAopfirstpass=1;
6173 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6174 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6177 if(ifx)ifx->generated = 1;
6179 if(AOP_SIZE(result)) {
6180 pic16_emitpLabel(falselbl->key);
6181 pic16_outBitC( result );
6186 /* compare registers */
6187 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6191 pCodeOp *pct, *pct2;
6193 /* signed compare */
6194 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6196 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6197 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6198 tlbl = newiTempLabel( NULL );
6200 compareAopfirstpass=1;
6203 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6204 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6206 pic16_emitpcode(POC_MOVWF, pct);
6208 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6209 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6210 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6212 /* WREG already holds left + 0x80 */
6213 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6216 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6217 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219 pic16_emitpcode(POC_MOVWF, pct);
6221 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6222 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6223 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6225 /* WREG already holds left + 0x80 */
6226 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6227 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6230 if(ifx)ifx->generated = 1;
6232 if(AOP_SIZE(result)) {
6233 pic16_emitpLabel(tlbl->key);
6234 pic16_emitpLabel(falselbl->key);
6235 pic16_outBitOp( result, pct2 );
6237 pic16_emitpLabel(tlbl->key);
6241 /* unsigned compare */
6242 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6244 compareAopfirstpass=1;
6247 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6248 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6252 if(ifx)ifx->generated = 1;
6253 if(AOP_SIZE(result)) {
6255 pic16_emitpLabel(falselbl->key);
6256 pic16_outBitC( result );
6267 /*-----------------------------------------------------------------*/
6268 /* genCmpGt :- greater than comparison */
6269 /*-----------------------------------------------------------------*/
6270 static void genCmpGt (iCode *ic, iCode *ifx)
6272 operand *left, *right, *result;
6273 sym_link *letype , *retype;
6279 right= IC_RIGHT(ic);
6280 result = IC_RESULT(ic);
6282 letype = getSpec(operandType(left));
6283 retype =getSpec(operandType(right));
6284 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6285 /* assign the amsops */
6286 pic16_aopOp (left,ic,FALSE);
6287 pic16_aopOp (right,ic,FALSE);
6288 pic16_aopOp (result,ic,TRUE);
6290 genCmp(right, left, result, ifx, sign);
6292 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6293 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6294 pic16_freeAsmop(result,NULL,ic,TRUE);
6297 /*-----------------------------------------------------------------*/
6298 /* genCmpLt - less than comparisons */
6299 /*-----------------------------------------------------------------*/
6300 static void genCmpLt (iCode *ic, iCode *ifx)
6302 operand *left, *right, *result;
6303 sym_link *letype , *retype;
6309 right= IC_RIGHT(ic);
6310 result = IC_RESULT(ic);
6312 letype = getSpec(operandType(left));
6313 retype =getSpec(operandType(right));
6314 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6316 /* assign the amsops */
6317 pic16_aopOp (left,ic,FALSE);
6318 pic16_aopOp (right,ic,FALSE);
6319 pic16_aopOp (result,ic,TRUE);
6321 genCmp(left, right, result, ifx, sign);
6323 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6324 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6325 pic16_freeAsmop(result,NULL,ic,TRUE);
6330 // FIXME reenable literal optimisation when the pic16 port is stable
6332 /*-----------------------------------------------------------------*/
6333 /* genc16bit2lit - compare a 16 bit value to a literal */
6334 /*-----------------------------------------------------------------*/
6335 static void genc16bit2lit(operand *op, int lit, int offset)
6339 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6340 if( (lit&0xff) == 0)
6345 switch( BYTEofLONG(lit,i)) {
6347 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6353 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6356 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6357 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6362 switch( BYTEofLONG(lit,i)) {
6364 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6368 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6372 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6375 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6377 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6386 /*-----------------------------------------------------------------*/
6387 /* gencjneshort - compare and jump if not equal */
6388 /*-----------------------------------------------------------------*/
6389 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6391 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6393 int res_offset = 0; /* the result may be a different size then left or right */
6394 int res_size = AOP_SIZE(result);
6396 symbol *lbl, *lbl_done;
6398 unsigned long lit = 0L;
6399 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6401 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6402 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6404 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6405 resolveIfx(&rIfx,ifx);
6406 lbl = newiTempLabel(NULL);
6407 lbl_done = newiTempLabel(NULL);
6410 /* if the left side is a literal or
6411 if the right is in a pointer register and left
6413 if ((AOP_TYPE(left) == AOP_LIT) ||
6414 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6419 if(AOP_TYPE(right) == AOP_LIT)
6420 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6422 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6423 preserve_result = 1;
6425 if(result && !preserve_result)
6428 for(i = 0; i < AOP_SIZE(result); i++)
6429 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6433 /* if the right side is a literal then anything goes */
6434 if (AOP_TYPE(right) == AOP_LIT &&
6435 AOP_TYPE(left) != AOP_DIR ) {
6438 genc16bit2lit(left, lit, 0);
6440 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6446 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6447 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6449 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6453 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6455 if(res_offset < res_size-1)
6463 /* if the right side is in a register or in direct space or
6464 if the left is a pointer register & right is not */
6465 else if (AOP_TYPE(right) == AOP_REG ||
6466 AOP_TYPE(right) == AOP_DIR ||
6467 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6468 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6469 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6470 int lbl_key = lbl->key;
6473 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6474 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6476 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6477 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6478 __FUNCTION__,__LINE__);
6482 /* switch(size) { */
6484 /* genc16bit2lit(left, lit, 0); */
6486 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6491 if((AOP_TYPE(left) == AOP_DIR) &&
6492 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6494 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6495 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6497 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6499 switch (lit & 0xff) {
6501 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6505 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6506 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6510 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6511 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6517 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6518 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6523 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6526 if(AOP_TYPE(result) == AOP_CRY) {
6527 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6532 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6534 /* fix me. probably need to check result size too */
6535 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6540 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6541 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6548 if(res_offset < res_size-1)
6553 } else if(AOP_TYPE(right) == AOP_REG &&
6554 AOP_TYPE(left) != AOP_DIR){
6557 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6558 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6559 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6564 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6566 if(res_offset < res_size-1)
6571 /* right is a pointer reg need both a & b */
6573 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6575 pic16_emitcode("mov","b,%s",l);
6576 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6577 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6582 if(result && preserve_result)
6585 for(i = 0; i < AOP_SIZE(result); i++)
6586 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6589 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6591 if(result && preserve_result)
6592 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6595 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6597 pic16_emitpLabel(lbl->key);
6599 if(result && preserve_result)
6602 for(i = 0; i < AOP_SIZE(result); i++)
6603 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6605 pic16_emitpLabel(lbl_done->key);
6608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6616 /*-----------------------------------------------------------------*/
6617 /* gencjne - compare and jump if not equal */
6618 /*-----------------------------------------------------------------*/
6619 static void gencjne(operand *left, operand *right, iCode *ifx)
6621 symbol *tlbl = newiTempLabel(NULL);
6623 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6624 gencjneshort(left, right, lbl);
6626 pic16_emitcode("mov","a,%s",one);
6627 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6628 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6629 pic16_emitcode("clr","a");
6630 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6632 pic16_emitpLabel(lbl->key);
6633 pic16_emitpLabel(tlbl->key);
6639 /*-----------------------------------------------------------------*/
6640 /* is_LitOp - check if operand has to be treated as literal */
6641 /*-----------------------------------------------------------------*/
6642 static bool is_LitOp(operand *op)
6644 return ((AOP_TYPE(op) == AOP_LIT)
6645 || ( (AOP_TYPE(op) == AOP_PCODE)
6646 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6647 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitAOp - check if operand has to be treated as literal */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitAOp(asmop *aop)
6655 return ((aop->type == AOP_LIT)
6656 || ( (aop->type == AOP_PCODE)
6657 && ( (aop->aopu.pcop->type == PO_LITERAL)
6658 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6663 /*-----------------------------------------------------------------*/
6664 /* genCmpEq - generates code for equal to */
6665 /*-----------------------------------------------------------------*/
6666 static void genCmpEq (iCode *ic, iCode *ifx)
6668 operand *left, *right, *result;
6669 symbol *falselbl = newiTempLabel(NULL);
6670 symbol *donelbl = newiTempLabel(NULL);
6672 int preserve_result = 0;
6673 int generate_result = 0;
6675 unsigned long lit = -1;
6679 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6680 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6681 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6683 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6685 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6687 werror(W_POSSBUG2, __FILE__, __LINE__);
6688 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6689 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6693 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6695 operand *tmp = right ;
6700 if (AOP_TYPE(right) == AOP_LIT) {
6701 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6704 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6705 preserve_result = 1;
6707 if(result && AOP_SIZE(result))
6708 generate_result = 1;
6710 if(generate_result && !preserve_result)
6712 for(i = 0; i < AOP_SIZE(result); i++)
6713 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6716 for(i=0; i < AOP_SIZE(left); i++)
6718 if(AOP_TYPE(left) != AOP_ACC)
6721 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6723 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6725 if(is_LitOp(right)) {
6726 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6727 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6730 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6732 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6737 if(generate_result && preserve_result)
6739 for(i = 0; i < AOP_SIZE(result); i++)
6740 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6744 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6746 if(generate_result && preserve_result)
6747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6749 if(ifx && IC_TRUE(ifx))
6750 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6752 if(ifx && IC_FALSE(ifx))
6753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6755 pic16_emitpLabel(falselbl->key);
6759 if(ifx && IC_FALSE(ifx))
6760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6762 if(generate_result && preserve_result)
6764 for(i = 0; i < AOP_SIZE(result); i++)
6765 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6768 pic16_emitpLabel(donelbl->key);
6774 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6775 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6776 pic16_freeAsmop(result,NULL,ic,TRUE);
6782 // old version kept for reference
6784 /*-----------------------------------------------------------------*/
6785 /* genCmpEq - generates code for equal to */
6786 /*-----------------------------------------------------------------*/
6787 static void genCmpEq (iCode *ic, iCode *ifx)
6789 operand *left, *right, *result;
6790 unsigned long lit = 0L;
6792 symbol *falselbl = newiTempLabel(NULL);
6795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6798 DEBUGpic16_emitcode ("; ifx is non-null","");
6800 DEBUGpic16_emitcode ("; ifx is null","");
6802 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6803 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6804 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6806 size = max(AOP_SIZE(left),AOP_SIZE(right));
6808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6810 /* if literal, literal on the right or
6811 if the right is in a pointer register and left
6813 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6814 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6815 operand *tmp = right ;
6821 if(ifx && !AOP_SIZE(result)){
6823 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6824 /* if they are both bit variables */
6825 if (AOP_TYPE(left) == AOP_CRY &&
6826 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6827 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6828 if(AOP_TYPE(right) == AOP_LIT){
6829 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6831 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832 pic16_emitcode("cpl","c");
6833 } else if(lit == 1L) {
6834 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6836 pic16_emitcode("clr","c");
6838 /* AOP_TYPE(right) == AOP_CRY */
6840 symbol *lbl = newiTempLabel(NULL);
6841 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6843 pic16_emitcode("cpl","c");
6844 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6846 /* if true label then we jump if condition
6848 tlbl = newiTempLabel(NULL);
6849 if ( IC_TRUE(ifx) ) {
6850 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6851 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6853 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6854 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6856 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6859 /* left and right are both bit variables, result is carry */
6862 resolveIfx(&rIfx,ifx);
6864 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6865 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6866 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6867 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6872 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6874 /* They're not both bit variables. Is the right a literal? */
6875 if(AOP_TYPE(right) == AOP_LIT) {
6876 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6881 switch(lit & 0xff) {
6883 if ( IC_TRUE(ifx) ) {
6884 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6886 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6888 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6893 if ( IC_TRUE(ifx) ) {
6894 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6896 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6898 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6905 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6910 /* end of size == 1 */
6914 genc16bit2lit(left,lit,offset);
6917 /* end of size == 2 */
6922 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6923 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6924 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6925 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6928 /* search for patterns that can be optimized */
6930 genc16bit2lit(left,lit,0);
6934 emitSKPZ; // if hi word unequal
6936 emitSKPNZ; // if hi word equal
6938 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6939 genc16bit2lit(left,lit,2);
6942 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6943 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6947 pic16_emitpLabel(falselbl->key);
6956 } else if(AOP_TYPE(right) == AOP_CRY ) {
6957 /* we know the left is not a bit, but that the right is */
6958 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6959 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6960 pic16_popGet(AOP(right),offset));
6961 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6963 /* if the two are equal, then W will be 0 and the Z bit is set
6964 * we could test Z now, or go ahead and check the high order bytes if
6965 * the variable we're comparing is larger than a byte. */
6968 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6970 if ( IC_TRUE(ifx) ) {
6972 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6973 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6977 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6981 /* They're both variables that are larger than bits */
6984 tlbl = newiTempLabel(NULL);
6987 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6988 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6990 if ( IC_TRUE(ifx) ) {
6994 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6996 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6997 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7001 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7004 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7005 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7010 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7013 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7017 if(s>1 && IC_TRUE(ifx)) {
7018 pic16_emitpLabel(tlbl->key);
7019 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7023 /* mark the icode as generated */
7028 /* if they are both bit variables */
7029 if (AOP_TYPE(left) == AOP_CRY &&
7030 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7031 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7032 if(AOP_TYPE(right) == AOP_LIT){
7033 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7035 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036 pic16_emitcode("cpl","c");
7037 } else if(lit == 1L) {
7038 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7040 pic16_emitcode("clr","c");
7042 /* AOP_TYPE(right) == AOP_CRY */
7044 symbol *lbl = newiTempLabel(NULL);
7045 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7047 pic16_emitcode("cpl","c");
7048 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7051 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7052 pic16_outBitC(result);
7056 genIfxJump (ifx,"c");
7059 /* if the result is used in an arithmetic operation
7060 then put the result in place */
7061 pic16_outBitC(result);
7064 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7065 gencjne(left,right,result,ifx);
7068 gencjne(left,right,newiTempLabel(NULL));
7070 if(IC_TRUE(ifx)->key)
7071 gencjne(left,right,IC_TRUE(ifx)->key);
7073 gencjne(left,right,IC_FALSE(ifx)->key);
7077 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7078 pic16_aopPut(AOP(result),"a",0);
7083 genIfxJump (ifx,"a");
7087 /* if the result is used in an arithmetic operation
7088 then put the result in place */
7090 if (AOP_TYPE(result) != AOP_CRY)
7091 pic16_outAcc(result);
7093 /* leave the result in acc */
7097 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7098 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7099 pic16_freeAsmop(result,NULL,ic,TRUE);
7103 /*-----------------------------------------------------------------*/
7104 /* ifxForOp - returns the icode containing the ifx for operand */
7105 /*-----------------------------------------------------------------*/
7106 static iCode *ifxForOp ( operand *op, iCode *ic )
7110 /* if true symbol then needs to be assigned */
7111 if (IS_TRUE_SYMOP(op))
7114 /* if this has register type condition and
7115 the next instruction is ifx with the same operand
7116 and live to of the operand is upto the ifx only then */
7118 && ic->next->op == IFX
7119 && IC_COND(ic->next)->key == op->key
7120 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7122 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7128 ic->next->op == IFX &&
7129 IC_COND(ic->next)->key == op->key) {
7130 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7135 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7137 ic->next->op == IFX)
7138 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7141 ic->next->op == IFX &&
7142 IC_COND(ic->next)->key == op->key) {
7143 DEBUGpic16_emitcode ("; "," key is okay");
7144 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7145 OP_SYMBOL(op)->liveTo,
7150 /* the code below is completely untested
7151 * it just allows ulong2fs.c compile -- VR */
7154 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7155 __FILE__, __FUNCTION__, __LINE__);
7157 /* if this has register type condition and
7158 the next instruction is ifx with the same operand
7159 and live to of the operand is upto the ifx only then */
7161 ic->next->op == IFX &&
7162 IC_COND(ic->next)->key == op->key &&
7163 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7167 ic->next->op == IFX &&
7168 IC_COND(ic->next)->key == op->key) {
7169 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7173 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7174 __FILE__, __FUNCTION__, __LINE__);
7176 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7181 /*-----------------------------------------------------------------*/
7182 /* genAndOp - for && operation */
7183 /*-----------------------------------------------------------------*/
7184 static void genAndOp (iCode *ic)
7186 operand *left,*right, *result;
7191 /* note here that && operations that are in an
7192 if statement are taken away by backPatchLabels
7193 only those used in arthmetic operations remain */
7194 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7195 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7196 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7198 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7200 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7201 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7202 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7204 /* if both are bit variables */
7205 /* if (AOP_TYPE(left) == AOP_CRY && */
7206 /* AOP_TYPE(right) == AOP_CRY ) { */
7207 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7208 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7209 /* pic16_outBitC(result); */
7211 /* tlbl = newiTempLabel(NULL); */
7212 /* pic16_toBoolean(left); */
7213 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7214 /* pic16_toBoolean(right); */
7215 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7216 /* pic16_outBitAcc(result); */
7219 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7220 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7221 pic16_freeAsmop(result,NULL,ic,TRUE);
7225 /*-----------------------------------------------------------------*/
7226 /* genOrOp - for || operation */
7227 /*-----------------------------------------------------------------*/
7230 modified this code, but it doesn't appear to ever get called
7233 static void genOrOp (iCode *ic)
7235 operand *left,*right, *result;
7240 /* note here that || operations that are in an
7241 if statement are taken away by backPatchLabels
7242 only those used in arthmetic operations remain */
7243 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7244 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7245 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7247 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7249 /* if both are bit variables */
7250 if (AOP_TYPE(left) == AOP_CRY &&
7251 AOP_TYPE(right) == AOP_CRY ) {
7252 pic16_emitcode("clrc","");
7253 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7254 AOP(left)->aopu.aop_dir,
7255 AOP(left)->aopu.aop_dir);
7256 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7257 AOP(right)->aopu.aop_dir,
7258 AOP(right)->aopu.aop_dir);
7259 pic16_emitcode("setc","");
7262 tlbl = newiTempLabel(NULL);
7263 pic16_toBoolean(left);
7265 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7266 pic16_toBoolean(right);
7267 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7269 pic16_outBitAcc(result);
7272 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7273 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7274 pic16_freeAsmop(result,NULL,ic,TRUE);
7277 /*-----------------------------------------------------------------*/
7278 /* isLiteralBit - test if lit == 2^n */
7279 /*-----------------------------------------------------------------*/
7280 static int isLiteralBit(unsigned long lit)
7282 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7283 0x100L,0x200L,0x400L,0x800L,
7284 0x1000L,0x2000L,0x4000L,0x8000L,
7285 0x10000L,0x20000L,0x40000L,0x80000L,
7286 0x100000L,0x200000L,0x400000L,0x800000L,
7287 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7288 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7291 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7292 for(idx = 0; idx < 32; idx++)
7298 /*-----------------------------------------------------------------*/
7299 /* continueIfTrue - */
7300 /*-----------------------------------------------------------------*/
7301 static void continueIfTrue (iCode *ic)
7305 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7309 /*-----------------------------------------------------------------*/
7311 /*-----------------------------------------------------------------*/
7312 static void jumpIfTrue (iCode *ic)
7316 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7320 /*-----------------------------------------------------------------*/
7321 /* jmpTrueOrFalse - */
7322 /*-----------------------------------------------------------------*/
7323 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7325 // ugly but optimized by peephole
7328 symbol *nlbl = newiTempLabel(NULL);
7329 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7330 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7331 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7332 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7334 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7335 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7340 /*-----------------------------------------------------------------*/
7341 /* genAnd - code for and */
7342 /*-----------------------------------------------------------------*/
7343 static void genAnd (iCode *ic, iCode *ifx)
7345 operand *left, *right, *result;
7347 unsigned long lit = 0L;
7353 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7354 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7355 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7357 resolveIfx(&rIfx,ifx);
7359 /* if left is a literal & right is not then exchange them */
7360 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7361 AOP_NEEDSACC(left)) {
7362 operand *tmp = right ;
7367 /* if result = right then exchange them */
7368 if(pic16_sameRegs(AOP(result),AOP(right))){
7369 operand *tmp = right ;
7374 /* if right is bit then exchange them */
7375 if (AOP_TYPE(right) == AOP_CRY &&
7376 AOP_TYPE(left) != AOP_CRY){
7377 operand *tmp = right ;
7381 if(AOP_TYPE(right) == AOP_LIT)
7382 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7384 size = AOP_SIZE(result);
7386 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7389 // result = bit & yy;
7390 if (AOP_TYPE(left) == AOP_CRY){
7391 // c = bit & literal;
7392 if(AOP_TYPE(right) == AOP_LIT){
7394 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7397 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7400 if(size && (AOP_TYPE(result) == AOP_CRY)){
7401 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7404 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7408 pic16_emitcode("clr","c");
7411 if (AOP_TYPE(right) == AOP_CRY){
7413 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7414 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7417 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7419 pic16_emitcode("rrc","a");
7420 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7426 pic16_outBitC(result);
7428 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7429 genIfxJump(ifx, "c");
7433 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7434 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7435 if((AOP_TYPE(right) == AOP_LIT) &&
7436 (AOP_TYPE(result) == AOP_CRY) &&
7437 (AOP_TYPE(left) != AOP_CRY)){
7438 int posbit = isLiteralBit(lit);
7442 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7445 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7451 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7452 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7454 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7458 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7459 size = AOP_SIZE(left);
7462 int bp = posbit, ofs=0;
7469 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7470 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7474 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7475 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7477 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7484 symbol *tlbl = newiTempLabel(NULL);
7485 int sizel = AOP_SIZE(left);
7491 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7493 /* patch provided by Aaron Colwell */
7494 if((posbit = isLiteralBit(bytelit)) != 0) {
7495 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7496 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7497 (posbit-1),0, PO_GPR_REGISTER));
7499 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7500 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7502 if (bytelit == 0xff) {
7503 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7504 * a peephole could optimize it out -- VR */
7505 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7508 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7511 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7512 pic16_popGetLabel(tlbl->key));
7516 /* old code, left here for reference -- VR 09/2004 */
7517 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7519 if((posbit = isLiteralBit(bytelit)) != 0)
7520 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7522 if(bytelit != 0x0FFL)
7523 pic16_emitcode("anl","a,%s",
7524 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7525 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7531 // bit = left & literal
7534 pic16_emitpLabel(tlbl->key);
7536 // if(left & literal)
7539 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7542 pic16_emitpLabel(tlbl->key);
7547 pic16_outBitC(result);
7551 /* if left is same as result */
7552 if(pic16_sameRegs(AOP(result),AOP(left))){
7554 for(;size--; offset++,lit>>=8) {
7555 if(AOP_TYPE(right) == AOP_LIT){
7556 switch(lit & 0xff) {
7558 /* and'ing with 0 has clears the result */
7559 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7560 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7563 /* and'ing with 0xff is a nop when the result and left are the same */
7568 int p = pic16_my_powof2( (~lit) & 0xff );
7570 /* only one bit is set in the literal, so use a bcf instruction */
7571 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7572 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7575 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7576 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7577 if(know_W != (lit&0xff))
7578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7580 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7585 if (AOP_TYPE(left) == AOP_ACC) {
7586 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7588 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7589 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7596 // left & result in different registers
7597 if(AOP_TYPE(result) == AOP_CRY){
7599 // if(size), result in bit
7600 // if(!size && ifx), conditional oper: if(left & right)
7601 symbol *tlbl = newiTempLabel(NULL);
7602 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7604 pic16_emitcode("setb","c");
7606 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7607 pic16_emitcode("anl","a,%s",
7608 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7609 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7614 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7615 pic16_outBitC(result);
7617 jmpTrueOrFalse(ifx, tlbl);
7619 for(;(size--);offset++) {
7621 // result = left & right
7622 if(AOP_TYPE(right) == AOP_LIT){
7623 int t = (lit >> (offset*8)) & 0x0FFL;
7626 pic16_emitcode("clrf","%s",
7627 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7628 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7631 pic16_emitcode("movf","%s,w",
7632 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7633 pic16_emitcode("movwf","%s",
7634 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7635 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7636 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7639 pic16_emitcode("movlw","0x%x",t);
7640 pic16_emitcode("andwf","%s,w",
7641 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7642 pic16_emitcode("movwf","%s",
7643 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7645 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7646 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7647 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7652 if (AOP_TYPE(left) == AOP_ACC) {
7653 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7654 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7656 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657 pic16_emitcode("andwf","%s,w",
7658 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7659 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7660 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7662 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7663 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7669 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7670 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7671 pic16_freeAsmop(result,NULL,ic,TRUE);
7674 /*-----------------------------------------------------------------*/
7675 /* genOr - code for or */
7676 /*-----------------------------------------------------------------*/
7677 static void genOr (iCode *ic, iCode *ifx)
7679 operand *left, *right, *result;
7681 unsigned long lit = 0L;
7683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7685 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7686 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7687 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7689 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7691 /* if left is a literal & right is not then exchange them */
7692 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7693 AOP_NEEDSACC(left)) {
7694 operand *tmp = right ;
7699 /* if result = right then exchange them */
7700 if(pic16_sameRegs(AOP(result),AOP(right))){
7701 operand *tmp = right ;
7706 /* if right is bit then exchange them */
7707 if (AOP_TYPE(right) == AOP_CRY &&
7708 AOP_TYPE(left) != AOP_CRY){
7709 operand *tmp = right ;
7714 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7716 if(AOP_TYPE(right) == AOP_LIT)
7717 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7719 size = AOP_SIZE(result);
7723 if (AOP_TYPE(left) == AOP_CRY){
7724 if(AOP_TYPE(right) == AOP_LIT){
7725 // c = bit & literal;
7727 // lit != 0 => result = 1
7728 if(AOP_TYPE(result) == AOP_CRY){
7730 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7731 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7732 // AOP(result)->aopu.aop_dir,
7733 // AOP(result)->aopu.aop_dir);
7735 continueIfTrue(ifx);
7739 // lit == 0 => result = left
7740 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7742 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7745 if (AOP_TYPE(right) == AOP_CRY){
7746 if(pic16_sameRegs(AOP(result),AOP(left))){
7748 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7749 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7750 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7752 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7753 AOP(result)->aopu.aop_dir,
7754 AOP(result)->aopu.aop_dir);
7755 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7756 AOP(right)->aopu.aop_dir,
7757 AOP(right)->aopu.aop_dir);
7758 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7759 AOP(result)->aopu.aop_dir,
7760 AOP(result)->aopu.aop_dir);
7762 if( AOP_TYPE(result) == AOP_ACC) {
7763 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7764 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7765 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7766 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7770 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7771 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7772 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7773 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7775 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7776 AOP(result)->aopu.aop_dir,
7777 AOP(result)->aopu.aop_dir);
7778 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7779 AOP(right)->aopu.aop_dir,
7780 AOP(right)->aopu.aop_dir);
7781 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7782 AOP(left)->aopu.aop_dir,
7783 AOP(left)->aopu.aop_dir);
7784 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7785 AOP(result)->aopu.aop_dir,
7786 AOP(result)->aopu.aop_dir);
7791 symbol *tlbl = newiTempLabel(NULL);
7792 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7795 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7796 if( AOP_TYPE(right) == AOP_ACC) {
7797 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7799 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7800 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7805 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7806 pic16_emitcode(";XXX setb","c");
7807 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7808 AOP(left)->aopu.aop_dir,tlbl->key+100);
7809 pic16_toBoolean(right);
7810 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7811 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7812 jmpTrueOrFalse(ifx, tlbl);
7816 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7823 pic16_outBitC(result);
7825 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7826 genIfxJump(ifx, "c");
7830 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7831 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7832 if((AOP_TYPE(right) == AOP_LIT) &&
7833 (AOP_TYPE(result) == AOP_CRY) &&
7834 (AOP_TYPE(left) != AOP_CRY)){
7836 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7839 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7841 continueIfTrue(ifx);
7844 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845 // lit = 0, result = boolean(left)
7847 pic16_emitcode(";XXX setb","c");
7848 pic16_toBoolean(right);
7850 symbol *tlbl = newiTempLabel(NULL);
7851 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7853 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7855 genIfxJump (ifx,"a");
7859 pic16_outBitC(result);
7863 /* if left is same as result */
7864 if(pic16_sameRegs(AOP(result),AOP(left))){
7866 for(;size--; offset++,lit>>=8) {
7867 if(AOP_TYPE(right) == AOP_LIT){
7868 if((lit & 0xff) == 0)
7869 /* or'ing with 0 has no effect */
7872 int p = pic16_my_powof2(lit & 0xff);
7874 /* only one bit is set in the literal, so use a bsf instruction */
7875 pic16_emitpcode(POC_BSF,
7876 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7878 if(know_W != (lit & 0xff))
7879 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7880 know_W = lit & 0xff;
7881 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7886 if (AOP_TYPE(left) == AOP_ACC) {
7887 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7888 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7890 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7891 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7893 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900 // left & result in different registers
7901 if(AOP_TYPE(result) == AOP_CRY){
7903 // if(size), result in bit
7904 // if(!size && ifx), conditional oper: if(left | right)
7905 symbol *tlbl = newiTempLabel(NULL);
7906 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7907 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7911 pic16_emitcode(";XXX setb","c");
7913 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914 pic16_emitcode(";XXX orl","a,%s",
7915 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7916 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7921 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7922 pic16_outBitC(result);
7924 jmpTrueOrFalse(ifx, tlbl);
7925 } else for(;(size--);offset++){
7927 // result = left & right
7928 if(AOP_TYPE(right) == AOP_LIT){
7929 int t = (lit >> (offset*8)) & 0x0FFL;
7932 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7935 pic16_emitcode("movf","%s,w",
7936 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7937 pic16_emitcode("movwf","%s",
7938 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7941 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7942 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7945 pic16_emitcode("movlw","0x%x",t);
7946 pic16_emitcode("iorwf","%s,w",
7947 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7948 pic16_emitcode("movwf","%s",
7949 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7955 // faster than result <- left, anl result,right
7956 // and better if result is SFR
7957 if (AOP_TYPE(left) == AOP_ACC) {
7958 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7959 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7961 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7962 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7964 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965 pic16_emitcode("iorwf","%s,w",
7966 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7968 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7969 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7974 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7975 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7976 pic16_freeAsmop(result,NULL,ic,TRUE);
7979 /*-----------------------------------------------------------------*/
7980 /* genXor - code for xclusive or */
7981 /*-----------------------------------------------------------------*/
7982 static void genXor (iCode *ic, iCode *ifx)
7984 operand *left, *right, *result;
7986 unsigned long lit = 0L;
7988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7990 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7991 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7992 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7994 /* if left is a literal & right is not ||
7995 if left needs acc & right does not */
7996 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7997 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7998 operand *tmp = right ;
8003 /* if result = right then exchange them */
8004 if(pic16_sameRegs(AOP(result),AOP(right))){
8005 operand *tmp = right ;
8010 /* if right is bit then exchange them */
8011 if (AOP_TYPE(right) == AOP_CRY &&
8012 AOP_TYPE(left) != AOP_CRY){
8013 operand *tmp = right ;
8017 if(AOP_TYPE(right) == AOP_LIT)
8018 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8020 size = AOP_SIZE(result);
8024 if (AOP_TYPE(left) == AOP_CRY){
8025 if(AOP_TYPE(right) == AOP_LIT){
8026 // c = bit & literal;
8028 // lit>>1 != 0 => result = 1
8029 if(AOP_TYPE(result) == AOP_CRY){
8031 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8032 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8034 continueIfTrue(ifx);
8037 pic16_emitcode("setb","c");
8041 // lit == 0, result = left
8042 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8044 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8046 // lit == 1, result = not(left)
8047 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8048 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8049 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8050 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8053 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8054 pic16_emitcode("cpl","c");
8061 symbol *tlbl = newiTempLabel(NULL);
8062 if (AOP_TYPE(right) == AOP_CRY){
8064 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8067 int sizer = AOP_SIZE(right);
8069 // if val>>1 != 0, result = 1
8070 pic16_emitcode("setb","c");
8072 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8074 // test the msb of the lsb
8075 pic16_emitcode("anl","a,#0xfe");
8076 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8080 pic16_emitcode("rrc","a");
8082 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8083 pic16_emitcode("cpl","c");
8084 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8089 pic16_outBitC(result);
8091 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8092 genIfxJump(ifx, "c");
8096 if(pic16_sameRegs(AOP(result),AOP(left))){
8097 /* if left is same as result */
8098 for(;size--; offset++) {
8099 if(AOP_TYPE(right) == AOP_LIT){
8100 int t = (lit >> (offset*8)) & 0x0FFL;
8104 if (IS_AOP_PREG(left)) {
8105 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8106 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8107 pic16_aopPut(AOP(result),"a",offset);
8109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8110 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8111 pic16_emitcode("xrl","%s,%s",
8112 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8113 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116 if (AOP_TYPE(left) == AOP_ACC)
8117 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8119 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8120 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8122 if (IS_AOP_PREG(left)) {
8123 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8124 pic16_aopPut(AOP(result),"a",offset);
8126 pic16_emitcode("xrl","%s,a",
8127 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8133 // left & result in different registers
8134 if(AOP_TYPE(result) == AOP_CRY){
8136 // if(size), result in bit
8137 // if(!size && ifx), conditional oper: if(left ^ right)
8138 symbol *tlbl = newiTempLabel(NULL);
8139 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8141 pic16_emitcode("setb","c");
8143 if((AOP_TYPE(right) == AOP_LIT) &&
8144 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8145 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8147 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148 pic16_emitcode("xrl","a,%s",
8149 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8151 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8156 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8157 pic16_outBitC(result);
8159 jmpTrueOrFalse(ifx, tlbl);
8160 } else for(;(size--);offset++){
8162 // result = left & right
8163 if(AOP_TYPE(right) == AOP_LIT){
8164 int t = (lit >> (offset*8)) & 0x0FFL;
8167 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8168 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8169 pic16_emitcode("movf","%s,w",
8170 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8171 pic16_emitcode("movwf","%s",
8172 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8175 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177 pic16_emitcode("comf","%s,w",
8178 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179 pic16_emitcode("movwf","%s",
8180 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8184 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8185 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8186 pic16_emitcode("movlw","0x%x",t);
8187 pic16_emitcode("xorwf","%s,w",
8188 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189 pic16_emitcode("movwf","%s",
8190 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8196 // faster than result <- left, anl result,right
8197 // and better if result is SFR
8198 if (AOP_TYPE(left) == AOP_ACC) {
8199 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8200 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8202 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8203 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8204 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8205 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8207 if ( AOP_TYPE(result) != AOP_ACC){
8208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8209 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8215 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8216 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8217 pic16_freeAsmop(result,NULL,ic,TRUE);
8220 /*-----------------------------------------------------------------*/
8221 /* genInline - write the inline code out */
8222 /*-----------------------------------------------------------------*/
8223 static void genInline (iCode *ic)
8225 char *buffer, *bp, *bp1;
8228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8230 _G.inLine += (!options.asmpeep);
8232 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8233 strcpy(buffer,IC_INLINE(ic));
8235 while((bp1=strstr(bp, "\\n"))) {
8242 cbuf = Safe_strdup( buffer );
8250 cbuf = Safe_strdup(buffer);
8251 cblen = strlen(buffer)+1;
8252 memset(cbuf, 0, cblen);
8257 if(*bp != '%')*bp1++ = *bp++;
8263 if(i>elementsInSet(asmInlineMap))break;
8266 s = indexSet(asmInlineMap, i);
8267 DEBUGpc("searching symbol s = `%s'", s);
8268 sym = findSym(SymbolTab, NULL, s);
8271 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8273 strcat(bp1, sym->rname);
8279 if(strlen(bp1) > cblen - 16) {
8280 int i = strlen(cbuf);
8282 cbuf = realloc(cbuf, cblen);
8283 memset(cbuf+i, 0, 50);
8289 buffer = Safe_strdup( cbuf );
8295 /* emit each line as a code */
8301 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8309 /* print label, use this special format with NULL directive
8310 * to denote that the argument should not be indented with tab */
8311 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8318 if ((bp1 != bp) && *bp1)
8319 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8324 _G.inLine -= (!options.asmpeep);
8327 /*-----------------------------------------------------------------*/
8328 /* genRRC - rotate right with carry */
8329 /*-----------------------------------------------------------------*/
8330 static void genRRC (iCode *ic)
8332 operand *left , *result ;
8333 int size, offset = 0, same;
8335 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8337 /* rotate right with carry */
8339 result=IC_RESULT(ic);
8340 pic16_aopOp (left,ic,FALSE);
8341 pic16_aopOp (result,ic,TRUE);
8343 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8345 same = pic16_sameRegs(AOP(result),AOP(left));
8347 size = AOP_SIZE(result);
8349 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8351 /* get the lsb and put it into the carry */
8352 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8359 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8361 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8362 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8368 pic16_freeAsmop(left,NULL,ic,TRUE);
8369 pic16_freeAsmop(result,NULL,ic,TRUE);
8372 /*-----------------------------------------------------------------*/
8373 /* genRLC - generate code for rotate left with carry */
8374 /*-----------------------------------------------------------------*/
8375 static void genRLC (iCode *ic)
8377 operand *left , *result ;
8378 int size, offset = 0;
8381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8382 /* rotate right with carry */
8384 result=IC_RESULT(ic);
8385 pic16_aopOp (left,ic,FALSE);
8386 pic16_aopOp (result,ic,TRUE);
8388 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8390 same = pic16_sameRegs(AOP(result),AOP(left));
8392 /* move it to the result */
8393 size = AOP_SIZE(result);
8395 /* get the msb and put it into the carry */
8396 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8403 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8405 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8413 pic16_freeAsmop(left,NULL,ic,TRUE);
8414 pic16_freeAsmop(result,NULL,ic,TRUE);
8418 /* gpasm can get the highest order bit with HIGH/UPPER
8419 * so the following probably is not needed -- VR */
8421 /*-----------------------------------------------------------------*/
8422 /* genGetHbit - generates code get highest order bit */
8423 /*-----------------------------------------------------------------*/
8424 static void genGetHbit (iCode *ic)
8426 operand *left, *result;
8428 result=IC_RESULT(ic);
8429 pic16_aopOp (left,ic,FALSE);
8430 pic16_aopOp (result,ic,FALSE);
8432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8433 /* get the highest order byte into a */
8434 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8435 if(AOP_TYPE(result) == AOP_CRY){
8436 pic16_emitcode("rlc","a");
8437 pic16_outBitC(result);
8440 pic16_emitcode("rl","a");
8441 pic16_emitcode("anl","a,#0x01");
8442 pic16_outAcc(result);
8446 pic16_freeAsmop(left,NULL,ic,TRUE);
8447 pic16_freeAsmop(result,NULL,ic,TRUE);
8451 /*-----------------------------------------------------------------*/
8452 /* AccRol - rotate left accumulator by known count */
8453 /*-----------------------------------------------------------------*/
8454 static void AccRol (int shCount)
8456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8457 shCount &= 0x0007; // shCount : 0..7
8462 pic16_emitcode("rl","a");
8465 pic16_emitcode("rl","a");
8466 pic16_emitcode("rl","a");
8469 pic16_emitcode("swap","a");
8470 pic16_emitcode("rr","a");
8473 pic16_emitcode("swap","a");
8476 pic16_emitcode("swap","a");
8477 pic16_emitcode("rl","a");
8480 pic16_emitcode("rr","a");
8481 pic16_emitcode("rr","a");
8484 pic16_emitcode("rr","a");
8490 /*-----------------------------------------------------------------*/
8491 /* AccLsh - left shift accumulator by known count */
8492 /*-----------------------------------------------------------------*/
8493 static void AccLsh (int shCount)
8495 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8501 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8504 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8509 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8515 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8519 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8530 /*-----------------------------------------------------------------*/
8531 /* AccRsh - right shift accumulator by known count */
8532 /*-----------------------------------------------------------------*/
8533 static void AccRsh (int shCount, int andmask)
8535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8540 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8547 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8548 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8569 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8573 /*-----------------------------------------------------------------*/
8574 /* AccSRsh - signed right shift accumulator by known count */
8575 /*-----------------------------------------------------------------*/
8576 static void AccSRsh (int shCount)
8579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8582 pic16_emitcode("mov","c,acc.7");
8583 pic16_emitcode("rrc","a");
8584 } else if(shCount == 2){
8585 pic16_emitcode("mov","c,acc.7");
8586 pic16_emitcode("rrc","a");
8587 pic16_emitcode("mov","c,acc.7");
8588 pic16_emitcode("rrc","a");
8590 tlbl = newiTempLabel(NULL);
8591 /* rotate right accumulator */
8592 AccRol(8 - shCount);
8593 /* and kill the higher order bits */
8594 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8595 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8596 pic16_emitcode("orl","a,#0x%02x",
8597 (unsigned char)~SRMask[shCount]);
8598 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8604 /*-----------------------------------------------------------------*/
8605 /* shiftR1Left2Result - shift right one byte from left to result */
8606 /*-----------------------------------------------------------------*/
8607 static void shiftR1Left2ResultSigned (operand *left, int offl,
8608 operand *result, int offr,
8613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8615 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8619 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8621 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8623 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8630 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8632 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8634 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8635 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8637 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8638 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8644 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8647 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8650 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8651 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8654 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8655 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8657 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8661 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8662 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8663 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8664 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8674 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8676 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8677 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8686 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8687 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8692 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8694 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8700 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8701 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8703 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8706 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8707 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8715 /*-----------------------------------------------------------------*/
8716 /* shiftR1Left2Result - shift right one byte from left to result */
8717 /*-----------------------------------------------------------------*/
8718 static void shiftR1Left2Result (operand *left, int offl,
8719 operand *result, int offr,
8720 int shCount, int sign)
8724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8726 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8728 /* Copy the msb into the carry if signed. */
8730 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8740 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8742 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8749 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8751 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8755 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8760 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8762 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8763 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8767 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8774 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8779 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8789 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8797 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8798 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8799 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8808 /*-----------------------------------------------------------------*/
8809 /* shiftL1Left2Result - shift left one byte from left to result */
8810 /*-----------------------------------------------------------------*/
8811 static void shiftL1Left2Result (operand *left, int offl,
8812 operand *result, int offr, int shCount)
8817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8819 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8820 DEBUGpic16_emitcode ("; ***","same = %d",same);
8821 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8823 /* shift left accumulator */
8824 //AccLsh(shCount); // don't comment out just yet...
8825 // pic16_aopPut(AOP(result),"a",offr);
8829 /* Shift left 1 bit position */
8830 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8832 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8834 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8835 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8839 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8841 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8842 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8845 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8846 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8847 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8848 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8849 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8854 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8864 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8865 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8871 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8876 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8881 /*-----------------------------------------------------------------*/
8882 /* movLeft2Result - move byte from left to result */
8883 /*-----------------------------------------------------------------*/
8884 static void movLeft2Result (operand *left, int offl,
8885 operand *result, int offr)
8888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8889 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8890 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8892 if (*l == '@' && (IS_AOP_PREG(result))) {
8893 pic16_emitcode("mov","a,%s",l);
8894 pic16_aopPut(AOP(result),"a",offr);
8896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8897 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8902 /*-----------------------------------------------------------------*/
8903 /* shiftL2Left2Result - shift left two bytes from left to result */
8904 /*-----------------------------------------------------------------*/
8905 static void shiftL2Left2Result (operand *left, int offl,
8906 operand *result, int offr, int shCount)
8908 int same = pic16_sameRegs(AOP(result), AOP(left));
8911 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8913 if (same && (offl != offr)) { // shift bytes
8916 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8917 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8919 } else { // just treat as different later on
8932 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8934 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8945 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8946 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8948 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8958 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8963 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8964 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8984 /* note, use a mov/add for the shift since the mov has a
8985 chance of getting optimized out */
8986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8994 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9001 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9002 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9004 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9007 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9008 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9012 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9017 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9018 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9019 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9026 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9033 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9034 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9035 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9041 /*-----------------------------------------------------------------*/
9042 /* shiftR2Left2Result - shift right two bytes from left to result */
9043 /*-----------------------------------------------------------------*/
9044 static void shiftR2Left2Result (operand *left, int offl,
9045 operand *result, int offr,
9046 int shCount, int sign)
9048 int same = pic16_sameRegs(AOP(result), AOP(left));
9050 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9052 if (same && (offl != offr)) { // shift right bytes
9055 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9056 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9058 } else { // just treat as different later on
9070 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9075 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9076 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9078 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9079 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9081 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9090 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9098 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9099 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9101 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9103 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9104 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9106 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9107 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9108 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9110 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9111 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9112 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9113 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9119 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9123 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9124 pic16_emitpcode(POC_BTFSC,
9125 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9126 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9134 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9137 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9138 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9139 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9142 pic16_emitpcode(POC_BTFSC,
9143 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9144 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9146 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9148 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9149 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9151 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9152 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9160 pic16_emitpcode(POC_BTFSC,
9161 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9162 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9174 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9175 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9178 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9180 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9185 /*-----------------------------------------------------------------*/
9186 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9187 /*-----------------------------------------------------------------*/
9188 static void shiftLLeftOrResult (operand *left, int offl,
9189 operand *result, int offr, int shCount)
9191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9193 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9194 /* shift left accumulator */
9196 /* or with result */
9197 /* back to result */
9198 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9201 /*-----------------------------------------------------------------*/
9202 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9203 /*-----------------------------------------------------------------*/
9204 static void shiftRLeftOrResult (operand *left, int offl,
9205 operand *result, int offr, int shCount)
9207 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9209 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9210 /* shift right accumulator */
9212 /* or with result */
9213 /* back to result */
9214 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9217 /*-----------------------------------------------------------------*/
9218 /* genlshOne - left shift a one byte quantity by known count */
9219 /*-----------------------------------------------------------------*/
9220 static void genlshOne (operand *result, operand *left, int shCount)
9222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9223 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9226 /*-----------------------------------------------------------------*/
9227 /* genlshTwo - left shift two bytes by known amount != 0 */
9228 /*-----------------------------------------------------------------*/
9229 static void genlshTwo (operand *result,operand *left, int shCount)
9233 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9234 size = pic16_getDataSize(result);
9236 /* if shCount >= 8 */
9242 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9244 movLeft2Result(left, LSB, result, MSB16);
9246 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9249 /* 1 <= shCount <= 7 */
9252 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9254 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9258 /*-----------------------------------------------------------------*/
9259 /* shiftLLong - shift left one long from left to result */
9260 /* offr = LSB or MSB16 */
9261 /*-----------------------------------------------------------------*/
9262 static void shiftLLong (operand *left, operand *result, int offr )
9264 int size = AOP_SIZE(result);
9265 int same = pic16_sameRegs(AOP(left),AOP(result));
9268 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9270 if (same && (offr == MSB16)) { //shift one byte
9271 for(i=size-1;i>=MSB16;i--) {
9272 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9273 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9276 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9279 if (size > LSB+offr ){
9281 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9283 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9284 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9288 if(size > MSB16+offr){
9290 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9292 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9293 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9297 if(size > MSB24+offr){
9299 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9301 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9302 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9306 if(size > MSB32+offr){
9308 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9310 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9311 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9315 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9319 /*-----------------------------------------------------------------*/
9320 /* genlshFour - shift four byte by a known amount != 0 */
9321 /*-----------------------------------------------------------------*/
9322 static void genlshFour (operand *result, operand *left, int shCount)
9326 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9327 size = AOP_SIZE(result);
9329 /* if shifting more that 3 bytes */
9330 if (shCount >= 24 ) {
9333 /* lowest order of left goes to the highest
9334 order of the destination */
9335 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9337 movLeft2Result(left, LSB, result, MSB32);
9339 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9340 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9341 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9346 /* more than two bytes */
9347 else if ( shCount >= 16 ) {
9348 /* lower order two bytes goes to higher order two bytes */
9350 /* if some more remaining */
9352 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9354 movLeft2Result(left, MSB16, result, MSB32);
9355 movLeft2Result(left, LSB, result, MSB24);
9357 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9358 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9362 /* if more than 1 byte */
9363 else if ( shCount >= 8 ) {
9364 /* lower order three bytes goes to higher order three bytes */
9368 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9370 movLeft2Result(left, LSB, result, MSB16);
9372 else{ /* size = 4 */
9374 movLeft2Result(left, MSB24, result, MSB32);
9375 movLeft2Result(left, MSB16, result, MSB24);
9376 movLeft2Result(left, LSB, result, MSB16);
9377 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9379 else if(shCount == 1)
9380 shiftLLong(left, result, MSB16);
9382 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9383 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9384 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9385 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9390 /* 1 <= shCount <= 7 */
9391 else if(shCount <= 3)
9393 shiftLLong(left, result, LSB);
9394 while(--shCount >= 1)
9395 shiftLLong(result, result, LSB);
9397 /* 3 <= shCount <= 7, optimize */
9399 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9400 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9401 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9405 /*-----------------------------------------------------------------*/
9406 /* genLeftShiftLiteral - left shifting by known count */
9407 /*-----------------------------------------------------------------*/
9408 void pic16_genLeftShiftLiteral (operand *left,
9413 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9417 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9418 pic16_freeAsmop(right,NULL,ic,TRUE);
9420 pic16_aopOp(left,ic,FALSE);
9421 pic16_aopOp(result,ic,TRUE);
9423 size = getSize(operandType(result));
9426 pic16_emitcode("; shift left ","result %d, left %d",size,
9430 /* I suppose that the left size >= result size */
9433 movLeft2Result(left, size, result, size);
9437 else if(shCount >= (size * 8))
9439 pic16_aopPut(AOP(result),zero,size);
9443 genlshOne (result,left,shCount);
9448 genlshTwo (result,left,shCount);
9452 genlshFour (result,left,shCount);
9456 pic16_freeAsmop(left,NULL,ic,TRUE);
9457 pic16_freeAsmop(result,NULL,ic,TRUE);
9460 /*-----------------------------------------------------------------*
9461 * genMultiAsm - repeat assembly instruction for size of register.
9462 * if endian == 1, then the high byte (i.e base address + size of
9463 * register) is used first else the low byte is used first;
9464 *-----------------------------------------------------------------*/
9465 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9483 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9489 #if !(USE_GENERIC_SIGNED_SHIFT)
9490 /*-----------------------------------------------------------------*/
9491 /* genLeftShift - generates code for left shifting */
9492 /*-----------------------------------------------------------------*/
9493 static void genLeftShift (iCode *ic)
9495 operand *left,*right, *result;
9498 symbol *tlbl , *tlbl1;
9501 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9503 right = IC_RIGHT(ic);
9505 result = IC_RESULT(ic);
9507 pic16_aopOp(right,ic,FALSE);
9509 /* if the shift count is known then do it
9510 as efficiently as possible */
9511 if (AOP_TYPE(right) == AOP_LIT) {
9512 pic16_genLeftShiftLiteral (left,right,result,ic);
9516 /* shift count is unknown then we have to form
9517 * a loop. Get the loop count in WREG : Note: we take
9518 * only the lower order byte since shifting
9519 * more than 32 bits make no sense anyway, ( the
9520 * largest size of an object can be only 32 bits ) */
9522 pic16_aopOp(left,ic,FALSE);
9523 pic16_aopOp(result,ic,FALSE);
9525 /* now move the left to the result if they are not the
9526 * same, and if size > 1,
9527 * and if right is not same to result (!!!) -- VR */
9528 if (!pic16_sameRegs(AOP(left),AOP(result))
9529 && (AOP_SIZE(result) > 1)) {
9531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 size = AOP_SIZE(result);
9538 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9539 if (*l == '@' && (IS_AOP_PREG(result))) {
9541 pic16_emitcode("mov","a,%s",l);
9542 pic16_aopPut(AOP(result),"a",offset);
9546 /* we don't know if left is a literal or a register, take care -- VR */
9547 mov2f(AOP(result), AOP(left), offset);
9553 size = AOP_SIZE(result);
9555 /* if it is only one byte then */
9557 if(optimized_for_speed) {
9558 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9559 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9560 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9561 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9562 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9563 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9564 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9565 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9566 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9567 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9568 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9569 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9574 tlbl = newiTempLabel(NULL);
9577 /* this is already done, why change it? */
9578 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9579 mov2f(AOP(result), AOP(left), 0);
9583 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9584 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9585 pic16_emitpLabel(tlbl->key);
9586 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9587 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9589 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9594 if (pic16_sameRegs(AOP(left),AOP(result))) {
9596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9598 tlbl = newiTempLabel(NULL);
9599 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9600 genMultiAsm(POC_RRCF, result, size,1);
9601 pic16_emitpLabel(tlbl->key);
9602 genMultiAsm(POC_RLCF, result, size,0);
9603 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9605 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9609 //tlbl = newiTempLabel(NULL);
9611 //tlbl1 = newiTempLabel(NULL);
9613 //reAdjustPreg(AOP(result));
9615 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9616 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9617 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9619 //pic16_emitcode("add","a,acc");
9620 //pic16_aopPut(AOP(result),"a",offset++);
9622 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9624 // pic16_emitcode("rlc","a");
9625 // pic16_aopPut(AOP(result),"a",offset++);
9627 //reAdjustPreg(AOP(result));
9629 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9630 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9633 tlbl = newiTempLabel(NULL);
9634 tlbl1= newiTempLabel(NULL);
9636 size = AOP_SIZE(result);
9639 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9641 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9643 /* offset should be 0, 1 or 3 */
9645 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9647 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9649 pic16_emitpcode(POC_MOVWF, pctemp);
9652 pic16_emitpLabel(tlbl->key);
9655 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9657 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9659 pic16_emitpcode(POC_DECFSZ, pctemp);
9660 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9661 pic16_emitpLabel(tlbl1->key);
9663 pic16_popReleaseTempReg(pctemp,1);
9667 pic16_freeAsmop (right,NULL,ic,TRUE);
9668 pic16_freeAsmop(left,NULL,ic,TRUE);
9669 pic16_freeAsmop(result,NULL,ic,TRUE);
9675 #error old code (left here for reference)
9676 /*-----------------------------------------------------------------*/
9677 /* genLeftShift - generates code for left shifting */
9678 /*-----------------------------------------------------------------*/
9679 static void genLeftShift (iCode *ic)
9681 operand *left,*right, *result;
9684 symbol *tlbl , *tlbl1;
9687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9689 right = IC_RIGHT(ic);
9691 result = IC_RESULT(ic);
9693 pic16_aopOp(right,ic,FALSE);
9695 /* if the shift count is known then do it
9696 as efficiently as possible */
9697 if (AOP_TYPE(right) == AOP_LIT) {
9698 pic16_genLeftShiftLiteral (left,right,result,ic);
9702 /* shift count is unknown then we have to form
9703 a loop get the loop count in B : Note: we take
9704 only the lower order byte since shifting
9705 more that 32 bits make no sense anyway, ( the
9706 largest size of an object can be only 32 bits ) */
9709 pic16_aopOp(left,ic,FALSE);
9710 pic16_aopOp(result,ic,FALSE);
9712 /* now move the left to the result if they are not the
9714 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9715 AOP_SIZE(result) > 1) {
9717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9719 size = AOP_SIZE(result);
9722 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9723 if (*l == '@' && (IS_AOP_PREG(result))) {
9725 pic16_emitcode("mov","a,%s",l);
9726 pic16_aopPut(AOP(result),"a",offset);
9729 /* we don't know if left is a literal or a register, take care -- VR */
9730 mov2f(AOP(result), AOP(left), offset);
9736 size = AOP_SIZE(result);
9738 /* if it is only one byte then */
9740 if(optimized_for_speed) {
9741 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9742 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9743 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9744 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9746 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9747 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9748 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9749 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9750 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9751 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9752 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9757 tlbl = newiTempLabel(NULL);
9758 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9759 mov2f(AOP(result), AOP(left), 0);
9761 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9762 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9765 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9766 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9767 pic16_emitpLabel(tlbl->key);
9768 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9769 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9771 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9776 if (pic16_sameRegs(AOP(left),AOP(result))) {
9778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9780 tlbl = newiTempLabel(NULL);
9781 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9782 genMultiAsm(POC_RRCF, result, size,1);
9783 pic16_emitpLabel(tlbl->key);
9784 genMultiAsm(POC_RLCF, result, size,0);
9785 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9787 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9791 //tlbl = newiTempLabel(NULL);
9793 //tlbl1 = newiTempLabel(NULL);
9795 //reAdjustPreg(AOP(result));
9797 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9798 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9799 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9801 //pic16_emitcode("add","a,acc");
9802 //pic16_aopPut(AOP(result),"a",offset++);
9804 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9806 // pic16_emitcode("rlc","a");
9807 // pic16_aopPut(AOP(result),"a",offset++);
9809 //reAdjustPreg(AOP(result));
9811 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9812 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9815 tlbl = newiTempLabel(NULL);
9816 tlbl1= newiTempLabel(NULL);
9818 size = AOP_SIZE(result);
9821 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9823 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9825 /* offset should be 0, 1 or 3 */
9827 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9829 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9831 pic16_emitpcode(POC_MOVWF, pctemp);
9834 pic16_emitpLabel(tlbl->key);
9837 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9839 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9841 pic16_emitpcode(POC_DECFSZ, pctemp);
9842 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9843 pic16_emitpLabel(tlbl1->key);
9845 pic16_popReleaseTempReg(pctemp,1);
9849 pic16_freeAsmop (right,NULL,ic,TRUE);
9850 pic16_freeAsmop(left,NULL,ic,TRUE);
9851 pic16_freeAsmop(result,NULL,ic,TRUE);
9855 /*-----------------------------------------------------------------*/
9856 /* genrshOne - right shift a one byte quantity by known count */
9857 /*-----------------------------------------------------------------*/
9858 static void genrshOne (operand *result, operand *left,
9859 int shCount, int sign)
9861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9862 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9865 /*-----------------------------------------------------------------*/
9866 /* genrshTwo - right shift two bytes by known amount != 0 */
9867 /*-----------------------------------------------------------------*/
9868 static void genrshTwo (operand *result,operand *left,
9869 int shCount, int sign)
9871 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9872 /* if shCount >= 8 */
9876 shiftR1Left2Result(left, MSB16, result, LSB,
9879 movLeft2Result(left, MSB16, result, LSB);
9881 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9884 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9885 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9889 /* 1 <= shCount <= 7 */
9891 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9894 /*-----------------------------------------------------------------*/
9895 /* shiftRLong - shift right one long from left to result */
9896 /* offl = LSB or MSB16 */
9897 /*-----------------------------------------------------------------*/
9898 static void shiftRLong (operand *left, int offl,
9899 operand *result, int sign)
9901 int size = AOP_SIZE(result);
9902 int same = pic16_sameRegs(AOP(left),AOP(result));
9904 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9906 if (same && (offl == MSB16)) { //shift one byte right
9907 for(i=MSB16;i<size;i++) {
9908 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9909 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9914 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9920 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9922 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9927 /* add sign of "a" */
9928 pic16_addSign(result, MSB32, sign);
9932 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9934 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9955 /*-----------------------------------------------------------------*/
9956 /* genrshFour - shift four byte by a known amount != 0 */
9957 /*-----------------------------------------------------------------*/
9958 static void genrshFour (operand *result, operand *left,
9959 int shCount, int sign)
9961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9962 /* if shifting more that 3 bytes */
9963 if(shCount >= 24 ) {
9966 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9968 movLeft2Result(left, MSB32, result, LSB);
9970 pic16_addSign(result, MSB16, sign);
9972 else if(shCount >= 16){
9975 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9977 movLeft2Result(left, MSB24, result, LSB);
9978 movLeft2Result(left, MSB32, result, MSB16);
9980 pic16_addSign(result, MSB24, sign);
9982 else if(shCount >= 8){
9985 shiftRLong(left, MSB16, result, sign);
9986 else if(shCount == 0){
9987 movLeft2Result(left, MSB16, result, LSB);
9988 movLeft2Result(left, MSB24, result, MSB16);
9989 movLeft2Result(left, MSB32, result, MSB24);
9990 pic16_addSign(result, MSB32, sign);
9992 else{ //shcount >= 2
9993 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9994 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9995 /* the last shift is signed */
9996 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9997 pic16_addSign(result, MSB32, sign);
10000 else{ /* 1 <= shCount <= 7 */
10002 shiftRLong(left, LSB, result, sign);
10004 shiftRLong(result, LSB, result, sign);
10007 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10008 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10009 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10014 /*-----------------------------------------------------------------*/
10015 /* genRightShiftLiteral - right shifting by known count */
10016 /*-----------------------------------------------------------------*/
10017 static void genRightShiftLiteral (operand *left,
10023 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10024 int lsize,res_size;
10026 pic16_freeAsmop(right,NULL,ic,TRUE);
10028 pic16_aopOp(left,ic,FALSE);
10029 pic16_aopOp(result,ic,TRUE);
10031 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10034 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10038 lsize = pic16_getDataSize(left);
10039 res_size = pic16_getDataSize(result);
10040 /* test the LEFT size !!! */
10042 /* I suppose that the left size >= result size */
10044 assert (res_size <= lsize);
10045 while (res_size--) {
10046 mov2f (AOP(result), AOP(left), res_size);
10050 else if(shCount >= (lsize * 8)){
10052 if(res_size == 1) {
10053 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10055 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10056 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10062 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10070 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10075 switch (res_size) {
10077 genrshOne (result,left,shCount,sign);
10081 genrshTwo (result,left,shCount,sign);
10085 genrshFour (result,left,shCount,sign);
10093 pic16_freeAsmop(left,NULL,ic,TRUE);
10094 pic16_freeAsmop(result,NULL,ic,TRUE);
10097 #if !(USE_GENERIC_SIGNED_SHIFT)
10098 /*-----------------------------------------------------------------*/
10099 /* genSignedRightShift - right shift of signed number */
10100 /*-----------------------------------------------------------------*/
10101 static void genSignedRightShift (iCode *ic)
10103 operand *right, *left, *result;
10106 symbol *tlbl, *tlbl1 ;
10109 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10111 /* we do it the hard way put the shift count in b
10112 and loop thru preserving the sign */
10113 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10115 right = IC_RIGHT(ic);
10116 left = IC_LEFT(ic);
10117 result = IC_RESULT(ic);
10119 pic16_aopOp(right,ic,FALSE);
10120 pic16_aopOp(left,ic,FALSE);
10121 pic16_aopOp(result,ic,FALSE);
10124 if ( AOP_TYPE(right) == AOP_LIT) {
10125 genRightShiftLiteral (left,right,result,ic,1);
10128 /* shift count is unknown then we have to form
10129 a loop get the loop count in B : Note: we take
10130 only the lower order byte since shifting
10131 more that 32 bits make no sense anyway, ( the
10132 largest size of an object can be only 32 bits ) */
10134 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10135 //pic16_emitcode("inc","b");
10136 //pic16_freeAsmop (right,NULL,ic,TRUE);
10137 //pic16_aopOp(left,ic,FALSE);
10138 //pic16_aopOp(result,ic,FALSE);
10140 /* now move the left to the result if they are not the
10142 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10143 AOP_SIZE(result) > 1) {
10145 size = AOP_SIZE(result);
10149 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10150 if (*l == '@' && IS_AOP_PREG(result)) {
10152 pic16_emitcode("mov","a,%s",l);
10153 pic16_aopPut(AOP(result),"a",offset);
10155 pic16_aopPut(AOP(result),l,offset);
10157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10158 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10164 /* mov the highest order bit to OVR */
10165 tlbl = newiTempLabel(NULL);
10166 tlbl1= newiTempLabel(NULL);
10168 size = AOP_SIZE(result);
10171 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10173 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10175 /* offset should be 0, 1 or 3 */
10176 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10178 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10180 pic16_emitpcode(POC_MOVWF, pctemp);
10183 pic16_emitpLabel(tlbl->key);
10185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10186 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10189 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10192 pic16_emitpcode(POC_DECFSZ, pctemp);
10193 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10194 pic16_emitpLabel(tlbl1->key);
10196 pic16_popReleaseTempReg(pctemp,1);
10198 size = AOP_SIZE(result);
10200 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10201 pic16_emitcode("rlc","a");
10202 pic16_emitcode("mov","ov,c");
10203 /* if it is only one byte then */
10205 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10207 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10208 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10209 pic16_emitcode("mov","c,ov");
10210 pic16_emitcode("rrc","a");
10211 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10212 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10213 pic16_aopPut(AOP(result),"a",0);
10217 reAdjustPreg(AOP(result));
10218 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10219 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10220 pic16_emitcode("mov","c,ov");
10222 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10224 pic16_emitcode("rrc","a");
10225 pic16_aopPut(AOP(result),"a",offset--);
10227 reAdjustPreg(AOP(result));
10228 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10229 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10234 pic16_freeAsmop(left,NULL,ic,TRUE);
10235 pic16_freeAsmop(result,NULL,ic,TRUE);
10236 pic16_freeAsmop(right,NULL,ic,TRUE);
10240 #if !(USE_GENERIC_SIGNED_SHIFT)
10241 #warning This implementation of genRightShift() is incomplete!
10242 /*-----------------------------------------------------------------*/
10243 /* genRightShift - generate code for right shifting */
10244 /*-----------------------------------------------------------------*/
10245 static void genRightShift (iCode *ic)
10247 operand *right, *left, *result;
10251 symbol *tlbl, *tlbl1 ;
10253 /* if signed then we do it the hard way preserve the
10254 sign bit moving it inwards */
10255 letype = getSpec(operandType(IC_LEFT(ic)));
10256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10258 if (!SPEC_USIGN(letype)) {
10259 genSignedRightShift (ic);
10263 /* signed & unsigned types are treated the same : i.e. the
10264 signed is NOT propagated inwards : quoting from the
10265 ANSI - standard : "for E1 >> E2, is equivalent to division
10266 by 2**E2 if unsigned or if it has a non-negative value,
10267 otherwise the result is implementation defined ", MY definition
10268 is that the sign does not get propagated */
10270 right = IC_RIGHT(ic);
10271 left = IC_LEFT(ic);
10272 result = IC_RESULT(ic);
10274 pic16_aopOp(right,ic,FALSE);
10276 /* if the shift count is known then do it
10277 as efficiently as possible */
10278 if (AOP_TYPE(right) == AOP_LIT) {
10279 genRightShiftLiteral (left,right,result,ic, 0);
10283 /* shift count is unknown then we have to form
10284 a loop get the loop count in B : Note: we take
10285 only the lower order byte since shifting
10286 more that 32 bits make no sense anyway, ( the
10287 largest size of an object can be only 32 bits ) */
10289 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10290 pic16_emitcode("inc","b");
10291 pic16_aopOp(left,ic,FALSE);
10292 pic16_aopOp(result,ic,FALSE);
10294 /* now move the left to the result if they are not the
10296 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10297 AOP_SIZE(result) > 1) {
10299 size = AOP_SIZE(result);
10302 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10303 if (*l == '@' && IS_AOP_PREG(result)) {
10305 pic16_emitcode("mov","a,%s",l);
10306 pic16_aopPut(AOP(result),"a",offset);
10308 pic16_aopPut(AOP(result),l,offset);
10313 tlbl = newiTempLabel(NULL);
10314 tlbl1= newiTempLabel(NULL);
10315 size = AOP_SIZE(result);
10318 /* if it is only one byte then */
10321 tlbl = newiTempLabel(NULL);
10322 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10323 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10327 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10328 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10329 pic16_emitpLabel(tlbl->key);
10330 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10331 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10333 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10338 reAdjustPreg(AOP(result));
10339 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10340 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10343 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10345 pic16_emitcode("rrc","a");
10346 pic16_aopPut(AOP(result),"a",offset--);
10348 reAdjustPreg(AOP(result));
10350 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10351 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10354 pic16_freeAsmop(left,NULL,ic,TRUE);
10355 pic16_freeAsmop (right,NULL,ic,TRUE);
10356 pic16_freeAsmop(result,NULL,ic,TRUE);
10360 #if (USE_GENERIC_SIGNED_SHIFT)
10361 /*-----------------------------------------------------------------*/
10362 /* genGenericShift - generates code for left or right shifting */
10363 /*-----------------------------------------------------------------*/
10364 static void genGenericShift (iCode *ic, int isShiftLeft) {
10365 operand *left,*right, *result;
10367 int sign, signedCount;
10368 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10369 PIC_OPCODE pos_shift, neg_shift;
10373 right = IC_RIGHT(ic);
10374 left = IC_LEFT(ic);
10375 result = IC_RESULT(ic);
10377 pic16_aopOp(right,ic,FALSE);
10378 pic16_aopOp(left,ic,FALSE);
10379 pic16_aopOp(result,ic,TRUE);
10381 sign = !SPEC_USIGN(operandType (left));
10382 signedCount = !SPEC_USIGN(operandType (right));
10384 /* if the shift count is known then do it
10385 as efficiently as possible */
10386 if (AOP_TYPE(right) == AOP_LIT) {
10387 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10388 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10389 // we should modify right->aopu.aop_lit here!
10390 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10391 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10393 pic16_genLeftShiftLiteral (left,right,result,ic);
10395 genRightShiftLiteral (left,right,result,ic, sign);
10398 } // if (right is literal)
10400 /* shift count is unknown then we have to form a loop.
10401 * Note: we take only the lower order byte since shifting
10402 * more than 32 bits make no sense anyway, ( the
10403 * largest size of an object can be only 32 bits )
10404 * Note: we perform arithmetic shifts if the left operand is
10405 * signed and we do an (effective) right shift, i. e. we
10406 * shift in the sign bit from the left. */
10408 label_complete = newiTempLabel ( NULL );
10409 label_loop_pos = newiTempLabel ( NULL );
10410 label_loop_neg = NULL;
10411 label_negative = NULL;
10412 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10413 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10416 // additional labels needed
10417 label_loop_neg = newiTempLabel ( NULL );
10418 label_negative = newiTempLabel ( NULL );
10421 // copy source to result -- this will effectively truncate the left operand to the size of result!
10422 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10423 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10424 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10425 mov2f (AOP(result),AOP(left), offset);
10428 // if result is longer than left, fill with zeros (or sign)
10429 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10430 if (sign && AOP_SIZE(left) > 0) {
10431 // shift signed operand -- fill with sign
10432 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10433 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10434 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10435 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10436 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10439 // shift unsigned operand -- fill result with zeros
10440 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10441 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10444 } // if (size mismatch)
10446 pic16_mov2w (AOP(right), 0);
10447 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10448 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10451 // perform a shift by one (shift count is positive)
10452 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10453 // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3] ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10454 pic16_emitpLabel (label_loop_pos->key);
10456 if (sign && (pos_shift == POC_RRCF)) {
10457 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10460 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10461 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10462 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10464 // perform a shift by one (shift count is positive)
10465 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10466 // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6] ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10467 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10468 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10470 pic16_emitpLabel (label_loop_pos->key);
10471 if (sign && (pos_shift == POC_RRCF)) {
10472 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10475 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10476 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10477 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10478 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10482 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10484 pic16_emitpLabel (label_negative->key);
10485 // perform a shift by -1 (shift count is negative)
10486 // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4 ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10488 pic16_emitpLabel (label_loop_neg->key);
10489 if (sign && (neg_shift == POC_RRCF)) {
10490 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10493 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10494 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10497 } // if (signedCount)
10499 pic16_emitpLabel (label_complete->key);
10502 pic16_freeAsmop (right,NULL,ic,TRUE);
10503 pic16_freeAsmop(left,NULL,ic,TRUE);
10504 pic16_freeAsmop(result,NULL,ic,TRUE);
10507 static void genLeftShift (iCode *ic) {
10508 genGenericShift (ic, 1);
10511 static void genRightShift (iCode *ic) {
10512 genGenericShift (ic, 0);
10517 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10518 void pic16_loadFSR0(operand *op, int lit)
10520 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10521 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10523 assert (!OP_SYMBOL(op)->remat);
10524 // set up FSR0 with address of result
10525 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10526 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10530 /*-----------------------------------------------------------------*/
10531 /* genUnpackBits - generates code for unpacking bits */
10532 /*-----------------------------------------------------------------*/
10533 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10537 sym_link *etype, *letype;
10538 int blen=0, bstr=0;
10542 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10543 etype = getSpec(operandType(result));
10544 letype = getSpec(operandType(left));
10546 // if(IS_BITFIELD(etype)) {
10547 blen = SPEC_BLEN(etype);
10548 bstr = SPEC_BSTR(etype);
10551 lbstr = SPEC_BSTR( letype );
10554 if((blen == 1) && (bstr < 8)) {
10555 /* it is a single bit, so use the appropriate bit instructions */
10556 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10558 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10560 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10561 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10562 /* workaround to reduce the extra lfsr instruction */
10563 pic16_emitpcode(POC_BTFSC,
10564 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10566 pic16_loadFSR0 (left, 0);
10567 pic16_emitpcode(POC_BTFSC,
10568 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10571 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10573 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10579 /* the following call to pic16_loadFSR0 is temporary until
10580 * optimization to handle single bit assignments is added
10581 * to the function. Until then use the old safe way! -- VR */
10583 if (OP_SYMBOL(left)->remat) {
10584 // access symbol directly
10585 pic16_mov2w (AOP(left), 0);
10587 pic16_loadFSR0( left, 0 );
10589 /* read the first byte */
10596 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10599 pic16_emitcode("clr","a");
10600 pic16_emitcode("movc","a","@a+dptr");
10606 /* if we have bitdisplacement then it fits */
10607 /* into this byte completely or if length is */
10608 /* less than a byte */
10609 if ((shCnt = SPEC_BSTR(etype)) ||
10610 (SPEC_BLEN(etype) <= 8)) {
10612 /* shift right acc */
10615 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10616 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10618 /* VR -- normally I would use the following, but since we use the hack,
10619 * to avoid the masking from AccRsh, why not mask it right now? */
10622 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10625 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10631 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10632 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10635 /* bit field did not fit in a byte */
10636 rlen = SPEC_BLEN(etype) - 8;
10637 pic16_aopPut(AOP(result),"a",offset++);
10644 pic16_emitcode("inc","%s",rname);
10645 pic16_emitcode("mov","a,@%s",rname);
10649 pic16_emitcode("inc","%s",rname);
10650 pic16_emitcode("movx","a,@%s",rname);
10654 pic16_emitcode("inc","dptr");
10655 pic16_emitcode("movx","a,@dptr");
10659 pic16_emitcode("clr","a");
10660 pic16_emitcode("inc","dptr");
10661 pic16_emitcode("movc","a","@a+dptr");
10665 pic16_emitcode("inc","dptr");
10666 pic16_emitcode("lcall","__gptrget");
10671 /* if we are done */
10675 pic16_aopPut(AOP(result),"a",offset++);
10680 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10681 pic16_aopPut(AOP(result),"a",offset);
10688 static void genDataPointerGet(operand *left,
10692 int size, offset = 0, leoffset=0 ;
10694 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10695 pic16_aopOp(result, ic, TRUE);
10699 size = AOP_SIZE(result);
10700 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10704 /* The following tests may save a redudant movff instruction when
10705 * accessing unions */
10707 /* if they are the same */
10708 if (operandsEqu (left, result)) {
10709 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10715 /* if they are the same registers */
10716 if (pic16_sameRegs(AOP(left),AOP(result))) {
10717 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10723 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10724 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10725 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10732 if ( AOP_TYPE(left) == AOP_PCODE) {
10733 fprintf(stderr,"genDataPointerGet %s, %d\n",
10734 AOP(left)->aopu.pcop->name,
10735 (AOP(left)->aopu.pcop->type == PO_DIR)?
10736 PCOR(AOP(left)->aopu.pcop)->instance:
10737 PCOI(AOP(left)->aopu.pcop)->offset);
10741 if(AOP(left)->aopu.pcop->type == PO_DIR)
10742 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10744 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10747 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10749 // pic16_DumpOp("(result)",result);
10750 if(is_LitAOp(AOP(result))) {
10751 pic16_mov2w(AOP(left), offset); // patch 8
10752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10754 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10755 pic16_popGet(AOP(left), offset), //patch 8
10756 pic16_popGet(AOP(result), offset)));
10764 pic16_freeAsmop(result,NULL,ic,TRUE);
10769 /*-----------------------------------------------------------------*/
10770 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10771 /*-----------------------------------------------------------------*/
10772 static void genNearPointerGet (operand *left,
10776 // asmop *aop = NULL;
10777 //regs *preg = NULL ;
10778 sym_link *rtype, *retype;
10779 sym_link *ltype = operandType(left);
10783 rtype = operandType(result);
10784 retype= getSpec(rtype);
10786 pic16_aopOp(left,ic,FALSE);
10788 // pic16_DumpOp("(left)",left);
10789 // pic16_DumpOp("(result)",result);
10791 /* if left is rematerialisable and
10792 * result is not bit variable type and
10793 * the left is pointer to data space i.e
10794 * lower 128 bytes of space */
10796 if (AOP_TYPE(left) == AOP_PCODE
10797 && !IS_BITFIELD(retype)
10798 && DCL_TYPE(ltype) == POINTER) {
10800 genDataPointerGet (left,result,ic);
10801 pic16_freeAsmop(left, NULL, ic, TRUE);
10805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10806 pic16_aopOp (result,ic,TRUE);
10808 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10811 if(IS_BITFIELD( retype )
10812 && (SPEC_BLEN(operandType(result))==1)
10816 int bitstrt, bytestrt;
10818 /* if this is bitfield of size 1, see if we are checking the value
10819 * of a single bit in an if-statement,
10820 * if yes, then don't generate usual code, but execute the
10821 * genIfx directly -- VR */
10825 /* CHECK: if next iCode is IFX
10826 * and current result operand is nextic's conditional operand
10827 * and current result operand live ranges ends at nextic's key number
10829 if((nextic->op == IFX)
10830 && (result == IC_COND(nextic))
10831 && (OP_LIVETO(result) == nextic->seq)
10832 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10834 /* everything is ok then */
10835 /* find a way to optimize the genIfx iCode */
10837 bytestrt = SPEC_BSTR(operandType(result))/8;
10838 bitstrt = SPEC_BSTR(operandType(result))%8;
10840 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10842 genIfxpCOpJump(nextic, jop);
10844 pic16_freeAsmop(left, NULL, ic, TRUE);
10845 pic16_freeAsmop(result, NULL, ic, TRUE);
10852 /* if the value is already in a pointer register
10853 * then don't need anything more */
10854 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10855 /* otherwise get a free pointer register */
10856 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10861 /* if bitfield then unpack the bits */
10862 if (IS_BITFIELD(retype))
10863 genUnpackBits (result, left, NULL, POINTER);
10865 /* we have can just get the values */
10866 int size = AOP_SIZE(result);
10869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10871 pic16_loadFSR0( left, 0 );
10875 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876 pic16_popGet(AOP(result), offset++)));
10878 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879 pic16_popGet(AOP(result), offset++)));
10885 /* now some housekeeping stuff */
10887 /* we had to allocate for this iCode */
10888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10889 pic16_freeAsmop(NULL,aop,ic,TRUE);
10891 /* we did not allocate which means left
10892 * already in a pointer register, then
10893 * if size > 0 && this could be used again
10894 * we have to point it back to where it
10896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10897 if (AOP_SIZE(result) > 1
10898 && !OP_SYMBOL(left)->remat
10899 && ( OP_SYMBOL(left)->liveTo > ic->seq
10901 // int size = AOP_SIZE(result) - 1;
10903 // pic16_emitcode("dec","%s",rname);
10909 pic16_freeAsmop(left,NULL,ic,TRUE);
10910 pic16_freeAsmop(result,NULL,ic,TRUE);
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left,
10921 regs *preg = NULL ;
10923 sym_link *rtype, *retype;
10925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10927 rtype = operandType(result);
10928 retype= getSpec(rtype);
10930 pic16_aopOp(left,ic,FALSE);
10932 /* if the value is already in a pointer register
10933 then don't need anything more */
10934 if (!AOP_INPREG(AOP(left))) {
10935 /* otherwise get a free pointer register */
10937 preg = getFreePtr(ic,&aop,FALSE);
10938 pic16_emitcode("mov","%s,%s",
10940 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941 rname = preg->name ;
10943 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10945 pic16_freeAsmop(left,NULL,ic,TRUE);
10946 pic16_aopOp (result,ic,TRUE);
10948 /* if bitfield then unpack the bits */
10949 if (IS_BITFIELD(retype))
10950 genUnpackBits (result,left,rname,PPOINTER);
10952 /* we have can just get the values */
10953 int size = AOP_SIZE(result);
10958 pic16_emitcode("movx","a,@%s",rname);
10959 pic16_aopPut(AOP(result),"a",offset);
10964 pic16_emitcode("inc","%s",rname);
10968 /* now some housekeeping stuff */
10970 /* we had to allocate for this iCode */
10971 pic16_freeAsmop(NULL,aop,ic,TRUE);
10973 /* we did not allocate which means left
10974 already in a pointer register, then
10975 if size > 0 && this could be used again
10976 we have to point it back to where it
10978 if (AOP_SIZE(result) > 1 &&
10979 !OP_SYMBOL(left)->remat &&
10980 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10982 int size = AOP_SIZE(result) - 1;
10984 pic16_emitcode("dec","%s",rname);
10989 pic16_freeAsmop(result,NULL,ic,TRUE);
10994 /*-----------------------------------------------------------------*/
10995 /* genFarPointerGet - gget value from far space */
10996 /*-----------------------------------------------------------------*/
10997 static void genFarPointerGet (operand *left,
10998 operand *result, iCode *ic)
11001 sym_link *retype = getSpec(operandType(result));
11003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11005 pic16_aopOp(left,ic,FALSE);
11007 /* if the operand is already in dptr
11008 then we do nothing else we move the value to dptr */
11009 if (AOP_TYPE(left) != AOP_STR) {
11010 /* if this is remateriazable */
11011 if (AOP_TYPE(left) == AOP_IMMD)
11012 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11013 else { /* we need to get it byte by byte */
11014 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11015 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11016 if (options.model == MODEL_FLAT24)
11018 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11022 /* so dptr know contains the address */
11023 pic16_freeAsmop(left,NULL,ic,TRUE);
11024 pic16_aopOp(result,ic,TRUE);
11026 /* if bit then unpack */
11027 if (IS_BITFIELD(retype))
11028 genUnpackBits(result,left,"dptr",FPOINTER);
11030 size = AOP_SIZE(result);
11034 pic16_emitcode("movx","a,@dptr");
11035 pic16_aopPut(AOP(result),"a",offset++);
11037 pic16_emitcode("inc","dptr");
11041 pic16_freeAsmop(result,NULL,ic,TRUE);
11045 /*-----------------------------------------------------------------*/
11046 /* genCodePointerGet - get value from code space */
11047 /*-----------------------------------------------------------------*/
11048 static void genCodePointerGet (operand *left,
11049 operand *result, iCode *ic)
11052 sym_link *retype = getSpec(operandType(result));
11054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11056 pic16_aopOp(left,ic,FALSE);
11058 /* if the operand is already in dptr
11059 then we do nothing else we move the value to dptr */
11060 if (AOP_TYPE(left) != AOP_STR) {
11061 /* if this is remateriazable */
11062 if (AOP_TYPE(left) == AOP_IMMD)
11063 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11064 else { /* we need to get it byte by byte */
11065 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11066 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11067 if (options.model == MODEL_FLAT24)
11069 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11073 /* so dptr know contains the address */
11074 pic16_freeAsmop(left,NULL,ic,TRUE);
11075 pic16_aopOp(result,ic,FALSE);
11077 /* if bit then unpack */
11078 if (IS_BITFIELD(retype))
11079 genUnpackBits(result,left,"dptr",CPOINTER);
11081 size = AOP_SIZE(result);
11085 pic16_emitcode("clr","a");
11086 pic16_emitcode("movc","a,@a+dptr");
11087 pic16_aopPut(AOP(result),"a",offset++);
11089 pic16_emitcode("inc","dptr");
11093 pic16_freeAsmop(result,NULL,ic,TRUE);
11098 /*-----------------------------------------------------------------*/
11099 /* genGenPointerGet - gget value from generic pointer space */
11100 /*-----------------------------------------------------------------*/
11101 static void genGenPointerGet (operand *left,
11102 operand *result, iCode *ic)
11104 int size, offset, lit;
11105 sym_link *retype = getSpec(operandType(result));
11107 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11108 pic16_aopOp(left,ic,FALSE);
11109 pic16_aopOp(result,ic,FALSE);
11110 size = AOP_SIZE(result);
11112 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11114 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11116 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11117 // load FSR0 from immediate
11118 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11120 // pic16_loadFSR0( left );
11125 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11134 else { /* we need to get it byte by byte */
11135 // set up FSR0 with address from left
11136 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11137 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11152 /* if bit then unpack */
11153 if (IS_BITFIELD(retype))
11154 genUnpackBits(result,left,"BAD",GPOINTER);
11157 pic16_freeAsmop(left,NULL,ic,TRUE);
11158 pic16_freeAsmop(result,NULL,ic,TRUE);
11164 /*-----------------------------------------------------------------*/
11165 /* genGenPointerGet - gget value from generic pointer space */
11166 /*-----------------------------------------------------------------*/
11167 static void genGenPointerGet (operand *left,
11168 operand *result, iCode *ic)
11170 int size, offset, lit;
11171 sym_link *retype = getSpec(operandType(result));
11173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11174 pic16_aopOp(left,ic,FALSE);
11175 pic16_aopOp(result,ic,TRUE);
11176 size = AOP_SIZE(result);
11178 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11180 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11182 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11183 // load FSR0 from immediate
11184 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11186 werror(W_POSSBUG2, __FILE__, __LINE__);
11191 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11193 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11200 } else { /* we need to get it byte by byte */
11202 /* set up WREG:PRODL:FSR0L with address from left */
11203 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11204 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11205 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11207 pic16_callGenericPointerRW(0, size);
11209 assignResultValue(result, 1);
11214 /* if bit then unpack */
11215 if (IS_BITFIELD(retype))
11216 genUnpackBits(result,left,"BAD",GPOINTER);
11219 pic16_freeAsmop(left,NULL,ic,TRUE);
11220 pic16_freeAsmop(result,NULL,ic,TRUE);
11223 /*-----------------------------------------------------------------*/
11224 /* genConstPointerGet - get value from const generic pointer space */
11225 /*-----------------------------------------------------------------*/
11226 static void genConstPointerGet (operand *left,
11227 operand *result, iCode *ic)
11229 //sym_link *retype = getSpec(operandType(result));
11230 // symbol *albl = newiTempLabel(NULL); // patch 15
11231 // symbol *blbl = newiTempLabel(NULL); //
11232 // PIC_OPCODE poc; // patch 15
11236 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11237 pic16_aopOp(left,ic,FALSE);
11238 pic16_aopOp(result,ic,TRUE);
11239 size = AOP_SIZE(result);
11241 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11243 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11245 // set up table pointer
11246 if( (AOP_TYPE(left) == AOP_PCODE)
11247 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11248 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11250 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11251 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11252 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11253 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11254 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11255 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11257 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11258 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11259 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11263 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11268 pic16_freeAsmop(left,NULL,ic,TRUE);
11269 pic16_freeAsmop(result,NULL,ic,TRUE);
11273 /*-----------------------------------------------------------------*/
11274 /* genPointerGet - generate code for pointer get */
11275 /*-----------------------------------------------------------------*/
11276 static void genPointerGet (iCode *ic)
11278 operand *left, *result ;
11279 sym_link *type, *etype;
11284 left = IC_LEFT(ic);
11285 result = IC_RESULT(ic) ;
11287 /* depending on the type of pointer we need to
11288 move it to the correct pointer register */
11289 type = operandType(left);
11290 etype = getSpec(type);
11293 if (IS_PTR_CONST(type))
11295 if (IS_CODEPTR(type))
11297 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11299 /* if left is of type of pointer then it is simple */
11300 if (IS_PTR(type) && !IS_FUNC(type->next))
11301 p_type = DCL_TYPE(type);
11303 /* we have to go by the storage class */
11304 p_type = PTR_TYPE(SPEC_OCLS(etype));
11306 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11308 if (SPEC_OCLS(etype)->codesp ) {
11309 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11310 //p_type = CPOINTER ;
11312 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11313 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11314 /*p_type = FPOINTER ;*/
11316 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11317 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11318 /* p_type = PPOINTER; */
11320 if (SPEC_OCLS(etype) == idata ) {
11321 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11322 /* p_type = IPOINTER; */
11324 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11325 /* p_type = POINTER ; */
11329 /* now that we have the pointer type we assign
11330 the pointer values */
11334 genNearPointerGet (left,result,ic);
11338 genPagedPointerGet(left,result,ic);
11342 genFarPointerGet (left,result,ic);
11346 genConstPointerGet (left,result,ic);
11347 //pic16_emitcodePointerGet (left,result,ic);
11352 if (IS_PTR_CONST(type))
11353 genConstPointerGet (left,result,ic);
11356 genGenPointerGet (left,result,ic);
11360 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11361 "genPointerGet: illegal pointer type");
11366 /*-----------------------------------------------------------------*/
11367 /* genPackBits - generates code for packed bit storage */
11368 /*-----------------------------------------------------------------*/
11369 static void genPackBits (sym_link *etype , operand *result,
11371 char *rname, int p_type)
11379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11380 blen = SPEC_BLEN(etype);
11381 bstr = SPEC_BSTR(etype);
11383 retype = getSpec(operandType(right));
11385 if(AOP_TYPE(right) == AOP_LIT) {
11386 if((blen == 1) && (bstr < 8)) {
11388 /* it is a single bit, so use the appropriate bit instructions */
11390 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11392 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11393 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11394 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11395 /* workaround to reduce the extra lfsr instruction */
11397 pic16_emitpcode(POC_BSF,
11398 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11400 pic16_emitpcode(POC_BCF,
11401 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11404 pic16_loadFSR0(result, 0);
11406 pic16_emitpcode(POC_BSF,
11407 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11409 pic16_emitpcode(POC_BCF,
11410 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11416 /* move literal to W */
11417 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11420 if(IS_BITFIELD(retype)
11421 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11425 rblen = SPEC_BLEN( retype );
11426 rbstr = SPEC_BSTR( retype );
11429 if(IS_BITFIELD(etype)) {
11430 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11431 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11433 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11436 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11438 if(IS_BITFIELD(etype)) {
11439 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11441 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11444 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11448 /* move right to W */
11449 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11452 /* if the bit length is less than or */
11453 /* it exactly fits a byte then */
11454 if((shCnt=SPEC_BSTR(etype))
11455 || SPEC_BLEN(etype) <= 8 ) {
11456 int fsr0_setup = 0;
11458 if (blen != 8 || bstr != 0) {
11459 // we need to combine the value with the old value
11460 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11462 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11463 SPEC_BSTR(etype), SPEC_BLEN(etype));
11465 /* shift left acc */
11468 /* using PRODH as a temporary register here */
11469 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11471 if (OP_SYMBOL(result)->remat) {
11472 // access symbol directly
11473 pic16_mov2w (AOP(result), 0);
11475 /* get old value */
11479 pic16_loadFSR0( result, 0 );
11481 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11482 // pic16_emitcode ("mov","b,a");
11483 // pic16_emitcode("mov","a,@%s",rname);
11487 if (AOP(result)->aopu.aop_reg[2]) {
11488 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11489 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11490 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11491 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11493 pic16_callGenericPointerRW(0, 1);
11495 // data pointer (just 2 byte given)
11496 pic16_loadFSR0( result, 0 );
11498 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11501 // warnings will be emitted below
11502 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11503 //werror(W_POSSBUG2, __FILE__, __LINE__);
11507 assert (0 && "invalid pointer type specified");
11512 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11513 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11514 (unsigned char)(0xff >> (8-bstr))) ));
11515 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11516 } // if (blen != 8 || bstr != 0)
11518 /* write new value back */
11519 if (OP_SYMBOL(result)->remat) {
11520 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11525 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11526 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11530 if (AOP(result)->aopu.aop_reg[2]) {
11531 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11532 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11533 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11534 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11535 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11537 pic16_callGenericPointerRW(1, 1);
11539 // data pointer (just 2 byte given)
11540 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11541 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11544 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11545 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11546 werror(W_POSSBUG2, __FILE__, __LINE__);
11550 assert (0 && "invalid pointer type specified");
11561 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11562 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11567 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11568 rLen = SPEC_BLEN(etype)-8;
11570 /* now generate for lengths greater than one byte */
11574 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11580 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11586 pic16_emitcode("movx","@dptr,a");
11591 DEBUGpic16_emitcode(";lcall","__gptrput");
11599 pic16_mov2w(AOP(right), offset++);
11602 /* last last was not complete */
11604 /* save the byte & read byte */
11607 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11608 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11613 pic16_emitcode ("mov","b,a");
11614 pic16_emitcode("movx","a,@dptr");
11618 pic16_emitcode ("push","b");
11619 pic16_emitcode ("push","acc");
11620 pic16_emitcode ("lcall","__gptrget");
11621 pic16_emitcode ("pop","b");
11627 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11628 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11629 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11630 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11631 // pic16_emitcode ("orl","a,b");
11634 // if (p_type == GPOINTER)
11635 // pic16_emitcode("pop","b");
11640 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11641 // pic16_emitcode("mov","@%s,a",rname);
11645 pic16_emitcode("movx","@dptr,a");
11649 DEBUGpic16_emitcode(";lcall","__gptrput");
11656 // pic16_freeAsmop(right, NULL, ic, TRUE);
11658 /*-----------------------------------------------------------------*/
11659 /* genDataPointerSet - remat pointer to data space */
11660 /*-----------------------------------------------------------------*/
11661 static void genDataPointerSet(operand *right,
11665 int size, offset = 0, resoffset=0 ;
11667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11668 pic16_aopOp(right,ic,FALSE);
11670 size = AOP_SIZE(right);
11672 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11675 if ( AOP_TYPE(result) == AOP_PCODE) {
11676 fprintf(stderr,"genDataPointerSet %s, %d\n",
11677 AOP(result)->aopu.pcop->name,
11678 (AOP(result)->aopu.pcop->type == PO_DIR)?
11679 PCOR(AOP(result)->aopu.pcop)->instance:
11680 PCOI(AOP(result)->aopu.pcop)->offset);
11684 if(AOP(result)->aopu.pcop->type == PO_DIR)
11685 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11688 if (AOP_TYPE(right) == AOP_LIT) {
11691 if(!IS_FLOAT(operandType( right )))
11692 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11695 unsigned long lit_int;
11699 /* take care if literal is a float */
11700 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11701 lit = info.lit_int;
11704 lit = lit >> (8*offset);
11706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11707 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11709 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11712 pic16_mov2w(AOP(right), offset);
11713 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11719 pic16_freeAsmop(right,NULL,ic,TRUE);
11724 /*-----------------------------------------------------------------*/
11725 /* genNearPointerSet - pic16_emitcode for near pointer put */
11726 /*-----------------------------------------------------------------*/
11727 static void genNearPointerSet (operand *right,
11733 sym_link *ptype = operandType(result);
11734 sym_link *resetype;
11736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11737 retype= getSpec(operandType(right));
11738 resetype = getSpec(operandType(result));
11740 pic16_aopOp(result,ic,FALSE);
11742 /* if the result is rematerializable &
11743 * in data space & not a bit variable */
11745 /* and result is not a bit variable */
11746 if (AOP_TYPE(result) == AOP_PCODE
11747 // && AOP_TYPE(result) == AOP_IMMD
11748 && DCL_TYPE(ptype) == POINTER
11749 && !IS_BITFIELD(retype)
11750 && !IS_BITFIELD(resetype)) {
11752 genDataPointerSet (right,result,ic);
11753 pic16_freeAsmop(result,NULL,ic,TRUE);
11757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11758 pic16_aopOp(right,ic,FALSE);
11759 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11761 /* if the value is already in a pointer register
11762 * then don't need anything more */
11763 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11764 /* otherwise get a free pointer register */
11765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11772 /* if bitfield then unpack the bits */
11773 if (IS_BITFIELD(resetype)) {
11774 genPackBits (resetype, result, right, NULL, POINTER);
11776 /* we have can just get the values */
11777 int size = AOP_SIZE(right);
11780 pic16_loadFSR0(result, 0);
11782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11784 if (AOP_TYPE(right) == AOP_LIT) {
11785 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11787 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11789 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11791 } else { // no literal
11793 pic16_emitpcode(POC_MOVFF,
11794 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11795 pic16_popCopyReg(&pic16_pc_postinc0)));
11797 pic16_emitpcode(POC_MOVFF,
11798 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11799 pic16_popCopyReg(&pic16_pc_indf0)));
11806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11807 /* now some housekeeping stuff */
11809 /* we had to allocate for this iCode */
11810 pic16_freeAsmop(NULL,aop,ic,TRUE);
11812 /* we did not allocate which means left
11813 * already in a pointer register, then
11814 * if size > 0 && this could be used again
11815 * we have to point it back to where it
11817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11818 if (AOP_SIZE(right) > 1
11819 && !OP_SYMBOL(result)->remat
11820 && ( OP_SYMBOL(result)->liveTo > ic->seq
11823 int size = AOP_SIZE(right) - 1;
11826 pic16_emitcode("decf","fsr0,f");
11827 //pic16_emitcode("dec","%s",rname);
11831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11834 pic16_freeAsmop(right,NULL,ic,TRUE);
11835 pic16_freeAsmop(result,NULL,ic,TRUE);
11838 /*-----------------------------------------------------------------*/
11839 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11840 /*-----------------------------------------------------------------*/
11841 static void genPagedPointerSet (operand *right,
11846 regs *preg = NULL ;
11850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11852 retype= getSpec(operandType(right));
11854 pic16_aopOp(result,ic,FALSE);
11856 /* if the value is already in a pointer register
11857 then don't need anything more */
11858 if (!AOP_INPREG(AOP(result))) {
11859 /* otherwise get a free pointer register */
11861 preg = getFreePtr(ic,&aop,FALSE);
11862 pic16_emitcode("mov","%s,%s",
11864 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11865 rname = preg->name ;
11867 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11869 pic16_freeAsmop(result,NULL,ic,TRUE);
11870 pic16_aopOp (right,ic,FALSE);
11872 /* if bitfield then unpack the bits */
11873 if (IS_BITFIELD(retype))
11874 genPackBits (retype,result,right,rname,PPOINTER);
11876 /* we have can just get the values */
11877 int size = AOP_SIZE(right);
11881 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11884 pic16_emitcode("movx","@%s,a",rname);
11887 pic16_emitcode("inc","%s",rname);
11893 /* now some housekeeping stuff */
11895 /* we had to allocate for this iCode */
11896 pic16_freeAsmop(NULL,aop,ic,TRUE);
11898 /* we did not allocate which means left
11899 already in a pointer register, then
11900 if size > 0 && this could be used again
11901 we have to point it back to where it
11903 if (AOP_SIZE(right) > 1 &&
11904 !OP_SYMBOL(result)->remat &&
11905 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11907 int size = AOP_SIZE(right) - 1;
11909 pic16_emitcode("dec","%s",rname);
11914 pic16_freeAsmop(right,NULL,ic,TRUE);
11919 /*-----------------------------------------------------------------*/
11920 /* genFarPointerSet - set value from far space */
11921 /*-----------------------------------------------------------------*/
11922 static void genFarPointerSet (operand *right,
11923 operand *result, iCode *ic)
11926 sym_link *retype = getSpec(operandType(right));
11928 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11929 pic16_aopOp(result,ic,FALSE);
11931 /* if the operand is already in dptr
11932 then we do nothing else we move the value to dptr */
11933 if (AOP_TYPE(result) != AOP_STR) {
11934 /* if this is remateriazable */
11935 if (AOP_TYPE(result) == AOP_IMMD)
11936 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11937 else { /* we need to get it byte by byte */
11938 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11939 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11940 if (options.model == MODEL_FLAT24)
11942 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11946 /* so dptr know contains the address */
11947 pic16_freeAsmop(result,NULL,ic,TRUE);
11948 pic16_aopOp(right,ic,FALSE);
11950 /* if bit then unpack */
11951 if (IS_BITFIELD(retype))
11952 genPackBits(retype,result,right,"dptr",FPOINTER);
11954 size = AOP_SIZE(right);
11958 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11960 pic16_emitcode("movx","@dptr,a");
11962 pic16_emitcode("inc","dptr");
11966 pic16_freeAsmop(right,NULL,ic,TRUE);
11969 /*-----------------------------------------------------------------*/
11970 /* genGenPointerSet - set value from generic pointer space */
11971 /*-----------------------------------------------------------------*/
11973 static void genGenPointerSet (operand *right,
11974 operand *result, iCode *ic)
11976 int i, size, offset, lit;
11977 sym_link *retype = getSpec(operandType(right));
11979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11981 pic16_aopOp(result,ic,FALSE);
11982 pic16_aopOp(right,ic,FALSE);
11983 size = AOP_SIZE(right);
11986 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11988 /* if the operand is already in dptr
11989 then we do nothing else we move the value to dptr */
11990 if (AOP_TYPE(result) != AOP_STR) {
11991 /* if this is remateriazable */
11992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11993 // WARNING: anythig until "else" is untested!
11994 if (AOP_TYPE(result) == AOP_IMMD) {
11995 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11996 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11997 // load FSR0 from immediate
11998 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12002 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12004 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12010 else { /* we need to get it byte by byte */
12011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12012 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12014 // set up FSR0 with address of result
12015 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12016 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12018 /* hack hack! see if this the FSR. If so don't load W */
12019 if(AOP_TYPE(right) != AOP_ACC) {
12021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12023 if(AOP_TYPE(right) == AOP_LIT)
12026 // note: pic16_popGet handles sign extension
12027 for(i=0;i<size;i++) {
12028 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12030 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12032 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12037 for(i=0;i<size;i++) {
12039 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12040 pic16_popCopyReg(&pic16_pc_postinc0)));
12042 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12043 pic16_popCopyReg(&pic16_pc_indf0)));
12049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12050 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12052 } // if (AOP_TYPE(result) != AOP_IMMD)
12054 } // if (AOP_TYPE(result) != AOP_STR)
12055 /* so dptr know contains the address */
12058 /* if bit then unpack */
12059 if (IS_BITFIELD(retype))
12060 genPackBits(retype,result,right,"dptr",GPOINTER);
12062 size = AOP_SIZE(right);
12065 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12067 // set up FSR0 with address of result
12068 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12069 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12072 if (AOP_TYPE(right) == AOP_LIT) {
12073 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12075 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12077 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12079 } else { // no literal
12081 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12083 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12091 pic16_freeAsmop(right,NULL,ic,TRUE);
12092 pic16_freeAsmop(result,NULL,ic,TRUE);
12096 static void genGenPointerSet (operand *right,
12097 operand *result, iCode *ic)
12100 sym_link *retype = getSpec(operandType(right));
12102 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12104 pic16_aopOp(result,ic,FALSE);
12105 pic16_aopOp(right,ic,FALSE);
12106 size = AOP_SIZE(right);
12108 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12111 /* if bit then unpack */
12112 if (IS_BITFIELD(retype)) {
12113 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12114 genPackBits(retype,result,right,"dptr",GPOINTER);
12118 size = AOP_SIZE(right);
12120 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12124 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12126 /* value of right+0 is placed on stack, which will be retrieved
12127 * by the support function this restoring the stack. The important
12128 * thing is that there is no need to manually restore stack pointer
12130 pushaop(AOP(right), 0);
12131 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12132 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12133 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12134 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12136 /* load address to write to in WREG:FSR0H:FSR0L */
12137 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12138 pic16_popCopyReg(&pic16_pc_fsr0l)));
12139 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12140 pic16_popCopyReg(&pic16_pc_prodl)));
12141 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12143 pic16_callGenericPointerRW(1, size);
12146 pic16_freeAsmop(right,NULL,ic,TRUE);
12147 pic16_freeAsmop(result,NULL,ic,TRUE);
12150 /*-----------------------------------------------------------------*/
12151 /* genPointerSet - stores the value into a pointer location */
12152 /*-----------------------------------------------------------------*/
12153 static void genPointerSet (iCode *ic)
12155 operand *right, *result ;
12156 sym_link *type, *etype;
12161 right = IC_RIGHT(ic);
12162 result = IC_RESULT(ic) ;
12164 /* depending on the type of pointer we need to
12165 move it to the correct pointer register */
12166 type = operandType(result);
12167 etype = getSpec(type);
12168 /* if left is of type of pointer then it is simple */
12169 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12170 p_type = DCL_TYPE(type);
12173 /* we have to go by the storage class */
12174 p_type = PTR_TYPE(SPEC_OCLS(etype));
12176 /* if (SPEC_OCLS(etype)->codesp ) { */
12177 /* p_type = CPOINTER ; */
12180 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12181 /* p_type = FPOINTER ; */
12183 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12184 /* p_type = PPOINTER ; */
12186 /* if (SPEC_OCLS(etype) == idata ) */
12187 /* p_type = IPOINTER ; */
12189 /* p_type = POINTER ; */
12192 /* now that we have the pointer type we assign
12193 the pointer values */
12197 genNearPointerSet (right,result,ic);
12201 genPagedPointerSet (right,result,ic);
12205 genFarPointerSet (right,result,ic);
12209 genGenPointerSet (right,result,ic);
12213 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12214 "genPointerSet: illegal pointer type");
12218 /*-----------------------------------------------------------------*/
12219 /* genIfx - generate code for Ifx statement */
12220 /*-----------------------------------------------------------------*/
12221 static void genIfx (iCode *ic, iCode *popIc)
12223 operand *cond = IC_COND(ic);
12228 pic16_aopOp(cond,ic,FALSE);
12230 /* get the value into acc */
12231 if (AOP_TYPE(cond) != AOP_CRY)
12232 pic16_toBoolean(cond);
12235 /* the result is now in the accumulator */
12236 pic16_freeAsmop(cond,NULL,ic,TRUE);
12238 /* if there was something to be popped then do it */
12242 /* if the condition is a bit variable */
12243 if (isbit && IS_ITEMP(cond) &&
12245 genIfxJump(ic,"c");
12246 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12248 if (isbit && !IS_ITEMP(cond))
12249 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12251 genIfxJump(ic,"a");
12256 /*-----------------------------------------------------------------*/
12257 /* genAddrOf - generates code for address of */
12258 /*-----------------------------------------------------------------*/
12259 static void genAddrOf (iCode *ic)
12261 operand *result, *left;
12263 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12264 pCodeOp *pcop0, *pcop1, *pcop2;
12268 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12270 sym = OP_SYMBOL( IC_LEFT(ic) );
12273 /* get address of symbol on stack */
12274 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12276 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12277 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12280 // operands on stack are accessible via "FSR2 + index" with index
12281 // starting at 2 for arguments and growing from 0 downwards for
12282 // local variables (index == 0 is not assigned so we add one here)
12284 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12286 assert (soffs < 0);
12289 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12290 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12291 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12292 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12293 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12294 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12295 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12301 // if(pic16_debug_verbose) {
12302 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12303 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12306 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12307 size = AOP_SIZE(IC_RESULT(ic));
12309 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12310 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12311 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12314 pic16_emitpcode(POC_MOVLW, pcop0);
12315 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12316 pic16_emitpcode(POC_MOVLW, pcop1);
12317 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12318 pic16_emitpcode(POC_MOVLW, pcop2);
12319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12322 pic16_emitpcode(POC_MOVLW, pcop0);
12323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12324 pic16_emitpcode(POC_MOVLW, pcop1);
12325 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12327 pic16_emitpcode(POC_MOVLW, pcop0);
12328 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12331 pic16_freeAsmop(left, NULL, ic, FALSE);
12333 pic16_freeAsmop(result,NULL,ic,TRUE);
12338 /*-----------------------------------------------------------------*/
12339 /* genFarFarAssign - assignment when both are in far space */
12340 /*-----------------------------------------------------------------*/
12341 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12343 int size = AOP_SIZE(right);
12346 /* first push the right side on to the stack */
12348 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12350 pic16_emitcode ("push","acc");
12353 pic16_freeAsmop(right,NULL,ic,FALSE);
12354 /* now assign DPTR to result */
12355 pic16_aopOp(result,ic,FALSE);
12356 size = AOP_SIZE(result);
12358 pic16_emitcode ("pop","acc");
12359 pic16_aopPut(AOP(result),"a",--offset);
12361 pic16_freeAsmop(result,NULL,ic,FALSE);
12366 /*-----------------------------------------------------------------*/
12367 /* genAssign - generate code for assignment */
12368 /*-----------------------------------------------------------------*/
12369 static void genAssign (iCode *ic)
12371 operand *result, *right;
12372 int size, offset,know_W;
12373 unsigned long lit = 0L;
12375 result = IC_RESULT(ic);
12376 right = IC_RIGHT(ic) ;
12380 /* if they are the same */
12381 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12384 /* reversed order operands are aopOp'ed so that result operand
12385 * is effective in case right is a stack symbol. This maneauver
12386 * allows to use the _G.resDirect flag later */
12387 pic16_aopOp(result,ic,TRUE);
12388 pic16_aopOp(right,ic,FALSE);
12390 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12392 /* if they are the same registers */
12393 if (pic16_sameRegs(AOP(right),AOP(result)))
12396 /* if the result is a bit */
12397 if (AOP_TYPE(result) == AOP_CRY) {
12398 /* if the right size is a literal then
12399 we know what the value is */
12400 if (AOP_TYPE(right) == AOP_LIT) {
12402 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12403 pic16_popGet(AOP(result),0));
12405 if (((int) operandLitValue(right)))
12406 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12407 AOP(result)->aopu.aop_dir,
12408 AOP(result)->aopu.aop_dir);
12410 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12411 AOP(result)->aopu.aop_dir,
12412 AOP(result)->aopu.aop_dir);
12416 /* the right is also a bit variable */
12417 if (AOP_TYPE(right) == AOP_CRY) {
12418 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12419 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12420 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12422 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12423 AOP(result)->aopu.aop_dir,
12424 AOP(result)->aopu.aop_dir);
12425 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12426 AOP(right)->aopu.aop_dir,
12427 AOP(right)->aopu.aop_dir);
12428 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12429 AOP(result)->aopu.aop_dir,
12430 AOP(result)->aopu.aop_dir);
12434 /* we need to or */
12435 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12436 pic16_toBoolean(right);
12438 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12439 //pic16_aopPut(AOP(result),"a",0);
12443 /* bit variables done */
12445 size = AOP_SIZE(result);
12448 if(AOP_TYPE(right) == AOP_LIT) {
12449 if(!IS_FLOAT(operandType( right )))
12450 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12453 unsigned long lit_int;
12457 /* take care if literal is a float */
12458 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12459 lit = info.lit_int;
12463 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12464 // sizeof(unsigned long int), sizeof(float));
12467 if (AOP_TYPE(right) == AOP_REG) {
12468 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12471 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12476 if(AOP_TYPE(right) != AOP_LIT
12477 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12478 && !IS_FUNC(OP_SYM_TYPE(right))
12480 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12481 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12483 // set up table pointer
12484 if(is_LitOp(right)) {
12485 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12486 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12487 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12488 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12489 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12490 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12491 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12493 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12494 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12495 pic16_popCopyReg(&pic16_pc_tblptrl)));
12496 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12497 pic16_popCopyReg(&pic16_pc_tblptrh)));
12498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12499 pic16_popCopyReg(&pic16_pc_tblptru)));
12502 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12504 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12505 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12506 pic16_popGet(AOP(result),offset)));
12510 size = getSize(OP_SYM_ETYPE(right));
12511 if(AOP_SIZE(result) > size) {
12512 size = AOP_SIZE(result) - size;
12514 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12524 /* VR - What is this?! */
12525 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12526 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12527 if(aopIdx(AOP(result),0) == 4) {
12529 /* this is a workaround to save value of right into wreg too,
12530 * value of wreg is going to be used later */
12531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12532 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12533 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12537 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12543 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12544 if(AOP_TYPE(right) == AOP_LIT) {
12546 if(know_W != (lit&0xff))
12547 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12549 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12551 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12555 } else if (AOP_TYPE(right) == AOP_CRY) {
12556 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12558 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12559 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12560 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12562 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12563 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12564 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12566 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12568 if(!_G.resDirect) /* use this aopForSym feature */
12569 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12576 pic16_freeAsmop (right,NULL,ic,FALSE);
12577 pic16_freeAsmop (result,NULL,ic,TRUE);
12580 /*-----------------------------------------------------------------*/
12581 /* genJumpTab - generates code for jump table */
12582 /*-----------------------------------------------------------------*/
12583 static void genJumpTab (iCode *ic)
12588 pCodeOp *jt_offs_hi;
12593 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12594 /* get the condition into accumulator */
12595 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12597 /* multiply by three */
12598 pic16_emitcode("add","a,acc");
12599 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12601 jtab = newiTempLabel(NULL);
12602 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12603 pic16_emitcode("jmp","@a+dptr");
12604 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12607 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12608 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12610 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12611 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12612 pic16_emitpLabel(jtab->key);
12616 jt_offs = pic16_popGetTempReg(0);
12617 jt_offs_hi = pic16_popGetTempReg(1);
12618 jt_label = pic16_popGetLabel (jtab->key);
12619 //fprintf (stderr, "Creating jump table...\n");
12621 // calculate offset into jump table (idx * sizeof (GOTO))
12622 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12623 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12624 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12625 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12626 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12627 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12628 pic16_emitpcode(POC_MOVWF , jt_offs);
12630 // prepare PCLATx (set to first entry in jump table)
12631 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12632 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12633 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12634 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12635 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12637 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12638 pic16_emitpcode(POC_ADDWF , jt_offs);
12639 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12640 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12642 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12644 // release temporaries and prepare jump into table (new PCL --> WREG)
12645 pic16_emitpcode(POC_MOVFW , jt_offs);
12646 pic16_popReleaseTempReg (jt_offs_hi, 1);
12647 pic16_popReleaseTempReg (jt_offs, 0);
12649 // jump into the table
12650 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12652 pic16_emitpLabelFORCE(jtab->key);
12655 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12656 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12658 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12659 /* now generate the jump labels */
12660 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12661 jtab = setNextItem(IC_JTLABELS(ic))) {
12662 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12666 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12670 /*-----------------------------------------------------------------*/
12671 /* genMixedOperation - gen code for operators between mixed types */
12672 /*-----------------------------------------------------------------*/
12674 TSD - Written for the PIC port - but this unfortunately is buggy.
12675 This routine is good in that it is able to efficiently promote
12676 types to different (larger) sizes. Unfortunately, the temporary
12677 variables that are optimized out by this routine are sometimes
12678 used in other places. So until I know how to really parse the
12679 iCode tree, I'm going to not be using this routine :(.
12681 static int genMixedOperation (iCode *ic)
12684 operand *result = IC_RESULT(ic);
12685 sym_link *ctype = operandType(IC_LEFT(ic));
12686 operand *right = IC_RIGHT(ic);
12692 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12694 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12700 nextright = IC_RIGHT(nextic);
12701 nextleft = IC_LEFT(nextic);
12702 nextresult = IC_RESULT(nextic);
12704 pic16_aopOp(right,ic,FALSE);
12705 pic16_aopOp(result,ic,FALSE);
12706 pic16_aopOp(nextright, nextic, FALSE);
12707 pic16_aopOp(nextleft, nextic, FALSE);
12708 pic16_aopOp(nextresult, nextic, FALSE);
12710 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12712 operand *t = right;
12716 pic16_emitcode(";remove right +","");
12718 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12720 operand *t = right;
12724 pic16_emitcode(";remove left +","");
12728 big = AOP_SIZE(nextleft);
12729 small = AOP_SIZE(nextright);
12731 switch(nextic->op) {
12734 pic16_emitcode(";optimize a +","");
12735 /* if unsigned or not an integral type */
12736 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12737 pic16_emitcode(";add a bit to something","");
12740 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12742 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12743 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12744 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12746 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12754 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12755 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12756 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12759 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12761 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12762 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12763 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12764 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12768 pic16_emitcode("rlf","known_zero,w");
12775 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12776 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12777 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12779 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12789 pic16_freeAsmop(right,NULL,ic,TRUE);
12790 pic16_freeAsmop(result,NULL,ic,TRUE);
12791 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12792 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12794 nextic->generated = 1;
12801 /*-----------------------------------------------------------------*/
12802 /* genCast - gen code for casting */
12803 /*-----------------------------------------------------------------*/
12804 static void genCast (iCode *ic)
12806 operand *result = IC_RESULT(ic);
12807 sym_link *ctype = operandType(IC_LEFT(ic));
12808 sym_link *rtype = operandType(IC_RIGHT(ic));
12809 sym_link *restype = operandType(IC_RESULT(ic));
12810 operand *right = IC_RIGHT(ic);
12816 /* if they are equivalent then do nothing */
12817 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12820 pic16_aopOp(result,ic,FALSE);
12821 pic16_aopOp(right,ic,FALSE) ;
12823 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12826 /* if the result is a bit */
12827 if (AOP_TYPE(result) == AOP_CRY) {
12829 /* if the right size is a literal then
12830 * we know what the value is */
12831 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12833 if (AOP_TYPE(right) == AOP_LIT) {
12834 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12835 pic16_popGet(AOP(result),0));
12837 if (((int) operandLitValue(right)))
12838 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12839 AOP(result)->aopu.aop_dir,
12840 AOP(result)->aopu.aop_dir);
12842 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12843 AOP(result)->aopu.aop_dir,
12844 AOP(result)->aopu.aop_dir);
12848 /* the right is also a bit variable */
12849 if (AOP_TYPE(right) == AOP_CRY) {
12851 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12853 pic16_emitcode("clrc","");
12854 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12855 AOP(right)->aopu.aop_dir,
12856 AOP(right)->aopu.aop_dir);
12857 pic16_aopPut(AOP(result),"c",0);
12861 /* we need to or */
12862 if (AOP_TYPE(right) == AOP_REG) {
12863 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12864 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12865 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12867 pic16_toBoolean(right);
12868 pic16_aopPut(AOP(result),"a",0);
12872 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12875 size = AOP_SIZE(result);
12877 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12880 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12881 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12884 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12889 if(IS_BITFIELD(getSpec(restype))
12890 && IS_BITFIELD(getSpec(rtype))) {
12891 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12894 /* if they are the same size : or less */
12895 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12897 /* if they are in the same place */
12898 if (pic16_sameRegs(AOP(right),AOP(result)))
12901 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12903 if (IS_PTR_CONST(rtype))
12905 if (IS_CODEPTR(rtype))
12907 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12910 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12912 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12914 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12917 if(AOP_TYPE(right) == AOP_IMMD) {
12918 pCodeOp *pcop0, *pcop1, *pcop2;
12919 symbol *sym = OP_SYMBOL( right );
12921 size = AOP_SIZE(result);
12923 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12925 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12927 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12930 pic16_emitpcode(POC_MOVLW, pcop0);
12931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12932 pic16_emitpcode(POC_MOVLW, pcop1);
12933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12934 pic16_emitpcode(POC_MOVLW, pcop2);
12935 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12938 pic16_emitpcode(POC_MOVLW, pcop0);
12939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12940 pic16_emitpcode(POC_MOVLW, pcop1);
12941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12943 pic16_emitpcode(POC_MOVLW, pcop0);
12944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12948 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12949 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12951 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12953 if(AOP_SIZE(result) <2)
12954 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12956 /* if they in different places then copy */
12957 size = AOP_SIZE(result);
12960 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12968 /* if the result is of type pointer */
12969 if (IS_PTR(ctype)) {
12971 sym_link *type = operandType(right);
12972 sym_link *etype = getSpec(type);
12974 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12976 /* pointer to generic pointer */
12977 if (IS_GENPTR(ctype)) {
12981 p_type = DCL_TYPE(type);
12983 /* we have to go by the storage class */
12984 p_type = PTR_TYPE(SPEC_OCLS(etype));
12986 /* if (SPEC_OCLS(etype)->codesp ) */
12987 /* p_type = CPOINTER ; */
12989 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12990 /* p_type = FPOINTER ; */
12992 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12993 /* p_type = PPOINTER; */
12995 /* if (SPEC_OCLS(etype) == idata ) */
12996 /* p_type = IPOINTER ; */
12998 /* p_type = POINTER ; */
13001 /* the first two bytes are known */
13002 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13003 size = GPTRSIZE - 1;
13006 if(offset < AOP_SIZE(right)) {
13007 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13008 mov2f(AOP(result), AOP(right), offset);
13010 if ((AOP_TYPE(right) == AOP_PCODE) &&
13011 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13012 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13016 pic16_aopPut(AOP(result),
13017 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13022 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13025 /* the last byte depending on type */
13029 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13031 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13035 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13039 pic16_emitcode(";BUG!? ","%d",__LINE__);
13043 pic16_emitcode(";BUG!? ","%d",__LINE__);
13048 if (GPTRSIZE > AOP_SIZE(right)) {
13049 // assume data pointer... THIS MIGHT BE WRONG!
13050 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13051 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13053 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13058 /* this should never happen */
13059 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13060 "got unknown pointer type");
13063 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13069 /* just copy the pointers */
13070 size = AOP_SIZE(result);
13073 pic16_aopPut(AOP(result),
13074 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13083 /* so we now know that the size of destination is greater
13084 than the size of the source.
13085 Now, if the next iCode is an operator then we might be
13086 able to optimize the operation without performing a cast.
13088 if(genMixedOperation(ic))
13091 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13093 /* we move to result for the size of source */
13094 size = AOP_SIZE(right);
13099 mov2f(AOP(result), AOP(right), offset);
13103 /* now depending on the sign of the destination */
13104 size = AOP_SIZE(result) - AOP_SIZE(right);
13105 /* if unsigned or not an integral type */
13106 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13108 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13110 /* we need to extend the sign :( */
13113 /* Save one instruction of casting char to int */
13114 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13115 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13116 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13118 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13121 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13123 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13125 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13128 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13133 pic16_freeAsmop(right,NULL,ic,TRUE);
13134 pic16_freeAsmop(result,NULL,ic,TRUE);
13138 /*-----------------------------------------------------------------*/
13139 /* genDjnz - generate decrement & jump if not zero instrucion */
13140 /*-----------------------------------------------------------------*/
13141 static int genDjnz (iCode *ic, iCode *ifx)
13143 symbol *lbl, *lbl1;
13144 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13149 /* if the if condition has a false label
13150 then we cannot save */
13154 /* if the minus is not of the form
13156 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13157 !IS_OP_LITERAL(IC_RIGHT(ic)))
13160 if (operandLitValue(IC_RIGHT(ic)) != 1)
13163 /* if the size of this greater than one then no
13165 if (getSize(operandType(IC_RESULT(ic))) > 1)
13168 /* otherwise we can save BIG */
13169 lbl = newiTempLabel(NULL);
13170 lbl1= newiTempLabel(NULL);
13172 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13174 if (IS_AOP_PREG(IC_RESULT(ic))) {
13175 pic16_emitcode("dec","%s",
13176 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13177 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13178 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13182 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13183 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13185 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13186 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13190 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13191 ifx->generated = 1;
13195 /*-----------------------------------------------------------------*/
13196 /* genReceive - generate code for a receive iCode */
13197 /*-----------------------------------------------------------------*/
13198 static void genReceive (iCode *ic)
13204 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13205 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13207 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13209 if (isOperandInFarSpace(IC_RESULT(ic))
13210 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13211 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13213 int size = getSize(operandType(IC_RESULT(ic)));
13214 int offset = pic16_fReturnSizePic - size;
13218 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13219 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13223 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13225 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13226 size = AOP_SIZE(IC_RESULT(ic));
13229 pic16_emitcode ("pop","acc");
13230 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13233 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13235 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13238 /* set pseudo stack pointer to where it should be - dw*/
13239 GpsuedoStkPtr = ic->parmBytes;
13241 /* setting GpsuedoStkPtr has side effects here: */
13242 assignResultValue(IC_RESULT(ic), 0);
13245 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13248 /*-----------------------------------------------------------------*/
13249 /* genDummyRead - generate code for dummy read of volatiles */
13250 /*-----------------------------------------------------------------*/
13252 genDummyRead (iCode * ic)
13258 if (op && IS_SYMOP(op)) {
13259 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13260 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13263 pic16_aopOp (op, ic, FALSE);
13264 for (i=0; i < AOP_SIZE(op); i++) {
13265 // may need to protect this from the peepholer -- this is not nice but works...
13266 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13267 pic16_mov2w (AOP(op),i);
13268 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13270 pic16_freeAsmop (op, NULL, ic, TRUE);
13272 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13276 /*-----------------------------------------------------------------*/
13277 /* genpic16Code - generate code for pic16 based controllers */
13278 /*-----------------------------------------------------------------*/
13280 * At this point, ralloc.c has gone through the iCode and attempted
13281 * to optimize in a way suitable for a PIC. Now we've got to generate
13282 * PIC instructions that correspond to the iCode.
13284 * Once the instructions are generated, we'll pass through both the
13285 * peep hole optimizer and the pCode optimizer.
13286 *-----------------------------------------------------------------*/
13288 void genpic16Code (iCode *lic)
13293 lineHead = lineCurr = NULL;
13295 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13296 pic16_addpBlock(pb);
13299 /* if debug information required */
13300 if (options.debug && currFunc) {
13302 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13307 for (ic = lic ; ic ; ic = ic->next ) {
13309 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13310 if ( cln != ic->lineno ) {
13311 if ( options.debug ) {
13312 debugFile->writeCLine (ic);
13315 if(!options.noCcodeInAsm) {
13316 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13317 printCLine(ic->filename, ic->lineno)));
13323 if(options.iCodeInAsm) {
13326 /* insert here code to print iCode as comment */
13327 l = Safe_strdup(printILine(ic));
13328 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13331 /* if the result is marked as
13332 * spilt and rematerializable or code for
13333 * this has already been generated then
13335 if (resultRemat(ic) || ic->generated )
13338 /* depending on the operation */
13357 /* IPOP happens only when trying to restore a
13358 * spilt live range, if there is an ifx statement
13359 * following this pop then the if statement might
13360 * be using some of the registers being popped which
13361 * would destroy the contents of the register so
13362 * we need to check for this condition and handle it */
13364 && ic->next->op == IFX
13365 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13366 genIfx (ic->next,ic);
13384 genEndFunction (ic);
13400 pic16_genPlus (ic) ;
13404 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13405 pic16_genMinus (ic);
13421 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13425 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13431 /* note these two are xlated by algebraic equivalence
13432 * during parsing SDCC.y */
13433 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13434 "got '>=' or '<=' shouldn't have come here");
13438 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13450 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13454 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13458 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13482 genRightShift (ic);
13485 case GET_VALUE_AT_ADDRESS:
13490 if (POINTER_SET(ic))
13517 addSet(&_G.sendSet,ic);
13520 case DUMMY_READ_VOLATILE:
13530 /* now we are ready to call the
13531 peep hole optimizer */
13532 if (!options.nopeep)
13533 peepHole (&lineHead);
13535 /* now do the actual printing */
13536 printLine (lineHead, codeOutFile);
13539 DFPRINTF((stderr,"printing pBlock\n\n"));
13540 pic16_printpBlock(stdout,pb);