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 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
141 static char *accUse[] = {"WREG"};
143 //static short rbank = -1;
158 int stack_lat; /* stack offset latency */
160 int useWreg; /* flag when WREG is used to pass function parameter */
163 /* Resolved ifx structure. This structure stores information
164 about an iCode ifx that makes it easier to generate code.
166 typedef struct resolvedIfx {
167 symbol *lbl; /* pointer to a label */
168 int condition; /* true or false ifx */
169 int generated; /* set true when the code associated with the ifx
173 extern int pic16_ptrRegReq ;
174 extern int pic16_nRegs;
175 extern FILE *codeOutFile;
176 //static void saverbank (int, iCode *,bool);
178 static lineNode *lineHead = NULL;
179 static lineNode *lineCurr = NULL;
181 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
182 0xE0, 0xC0, 0x80, 0x00};
183 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
188 /*-----------------------------------------------------------------*/
189 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
190 /* exponent of 2 is returned, otherwise -1 is */
192 /* note that this is similar to the function `powof2' in SDCCsymt */
196 /*-----------------------------------------------------------------*/
197 int pic16_my_powof2 (unsigned long num)
200 if( (num & (num-1)) == 0) {
213 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
215 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
217 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
218 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
219 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
220 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
221 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
222 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
223 ((result) ? AOP_SIZE(result) : 0));
226 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
229 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
231 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
232 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
233 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
234 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
235 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
236 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
240 void pic16_emitpcomment (char *fmt, ...)
243 char lb[INITIAL_INLINEASM];
249 vsprintf(lb+1,fmt,ap);
251 while (isspace(*lbp)) lbp++;
254 lineCurr = (lineCurr ?
255 connectLine(lineCurr,newLineNode(lb)) :
256 (lineHead = newLineNode(lb)));
257 lineCurr->isInline = _G.inLine;
258 lineCurr->isDebug = _G.debugLine;
260 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
263 // fprintf(stderr, "%s\n", lb);
266 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
269 char lb[INITIAL_INLINEASM];
272 if(!pic16_debug_verbose)
279 sprintf(lb,"%s\t",inst);
281 sprintf(lb,"%s",inst);
282 vsprintf(lb+(strlen(lb)),fmt,ap);
286 while (isspace(*lbp)) lbp++;
289 lineCurr = (lineCurr ?
290 connectLine(lineCurr,newLineNode(lb)) :
291 (lineHead = newLineNode(lb)));
292 lineCurr->isInline = _G.inLine;
293 lineCurr->isDebug = _G.debugLine;
295 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
298 // fprintf(stderr, "%s\n", lb);
303 void pic16_emitpLabel(int key)
305 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
308 void pic16_emitpLabelFORCE(int key)
310 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
313 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
317 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
319 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
322 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
325 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
327 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
330 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
333 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
339 #define pic16_emitcode DEBUGpic16_emitcode
341 /*-----------------------------------------------------------------*/
342 /* pic16_emitcode - writes the code into a file : for now it is simple */
343 /*-----------------------------------------------------------------*/
344 void pic16_emitcode (char *inst,char *fmt, ...)
347 char lb[INITIAL_INLINEASM];
354 sprintf(lb,"%s\t",inst);
356 sprintf(lb,"%s",inst);
357 vsprintf(lb+(strlen(lb)),fmt,ap);
361 while (isspace(*lbp)) lbp++;
364 lineCurr = (lineCurr ?
365 connectLine(lineCurr,newLineNode(lb)) :
366 (lineHead = newLineNode(lb)));
367 lineCurr->isInline = _G.inLine;
368 lineCurr->isDebug = _G.debugLine;
370 // VR fprintf(stderr, "lb = <%s>\n", lbp);
372 // if(pic16_debug_verbose)
373 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
380 /*-----------------------------------------------------------------*/
381 /* pic16_emitDebuggerSymbol - associate the current code location */
382 /* with a debugger symbol */
383 /*-----------------------------------------------------------------*/
385 pic16_emitDebuggerSymbol (char * debugSym)
388 pic16_emitcode (";", "%s ==.", debugSym);
393 /*-----------------------------------------------------------------*/
394 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
395 /*-----------------------------------------------------------------*/
396 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
398 // bool r0iu = FALSE , r1iu = FALSE;
399 // bool r0ou = FALSE , r1ou = FALSE;
400 bool fsr0iu = FALSE, fsr0ou;
401 bool fsr2iu = FALSE, fsr2ou;
403 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
406 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
407 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
409 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
410 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
412 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
413 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
414 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
417 if(!fsr0iu && !fsr0ou) {
418 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
419 (*aopp)->type = AOP_FSR0;
421 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
423 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
427 /* no usage of FSR2 */
428 if(!fsr2iu && !fsr2ou) {
429 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
430 (*aopp)->type = AOP_FSR2;
432 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
436 /* now we know they both have usage */
437 /* if fsr0 not used in this instruction */
439 if (!_G.fsr0Pushed) {
440 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
441 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
445 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
446 (*aopp)->type = AOP_FSR0;
448 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
450 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
454 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
459 /* the logic: if r0 & r1 used in the instruction
460 then we are in trouble otherwise */
462 /* first check if r0 & r1 are used by this
463 instruction, in which case we are in trouble */
464 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
465 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
470 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
471 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
473 /* if no usage of r0 then return it */
474 if (!r0iu && !r0ou) {
475 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
476 (*aopp)->type = AOP_R0;
478 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
481 /* if no usage of r1 then return it */
482 if (!r1iu && !r1ou) {
483 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
484 (*aopp)->type = AOP_R1;
486 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
489 /* now we know they both have usage */
490 /* if r0 not used in this instruction */
492 /* push it if not already pushed */
494 //pic16_emitcode ("push","%s",
495 // pic16_regWithIdx(R0_IDX)->dname);
499 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
500 (*aopp)->type = AOP_R0;
502 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
505 /* if r1 not used then */
508 /* push it if not already pushed */
510 //pic16_emitcode ("push","%s",
511 // pic16_regWithIdx(R1_IDX)->dname);
515 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
516 (*aopp)->type = AOP_R1;
517 return pic16_regWithIdx(R1_IDX);
521 /* I said end of world but not quite end of world yet */
522 /* if this is a result then we can push it on the stack*/
524 (*aopp)->type = AOP_STK;
528 /* other wise this is true end of the world */
529 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
530 "getFreePtr should never reach here");
535 /*-----------------------------------------------------------------*/
536 /* newAsmop - creates a new asmOp */
537 /*-----------------------------------------------------------------*/
538 static asmop *newAsmop (short type)
542 aop = Safe_calloc(1,sizeof(asmop));
547 static void genSetDPTR(int n)
551 pic16_emitcode(";", "Select standard DPTR");
552 pic16_emitcode("mov", "dps, #0x00");
556 pic16_emitcode(";", "Select alternate DPTR");
557 pic16_emitcode("mov", "dps, #0x01");
561 /*-----------------------------------------------------------------*/
562 /* resolveIfx - converts an iCode ifx into a form more useful for */
563 /* generating code */
564 /*-----------------------------------------------------------------*/
565 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
569 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
575 resIfx->condition = 1; /* assume that the ifx is true */
576 resIfx->generated = 0; /* indicate that the ifx has not been used */
579 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
582 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
583 __FUNCTION__,__LINE__,resIfx->lbl->key);
588 resIfx->lbl = IC_TRUE(ifx);
590 resIfx->lbl = IC_FALSE(ifx);
591 resIfx->condition = 0;
596 DEBUGpic16_emitcode("; +++","ifx true is non-null");
598 DEBUGpic16_emitcode("; +++","ifx true is null");
600 DEBUGpic16_emitcode("; +++","ifx false is non-null");
602 DEBUGpic16_emitcode("; +++","ifx false is null");
606 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type */
612 /*-----------------------------------------------------------------*/
613 static int pointerCode (sym_link *etype)
616 return PTR_TYPE(SPEC_OCLS(etype));
621 /*-----------------------------------------------------------------*/
622 /* aopForSym - for a true symbol */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForSym (iCode *ic, operand *op, bool result)
626 symbol *sym=OP_SYMBOL(op);
628 memmap *space= SPEC_OCLS(sym->etype);
632 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
634 // sym = OP_SYMBOL(op);
636 /* if already has one */
638 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
643 /* if symbol was initially placed onStack then we must re-place it
644 * to direct memory, since pic16 does not have a specific stack */
646 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
654 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
656 sym->aop = aop = newAsmop (AOP_PAGED);
657 aop->aopu.aop_dir = sym->rname ;
658 aop->size = getSize(sym->type);
659 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660 pic16_allocDirReg( IC_LEFT(ic) );
668 /* assign depending on the storage class */
669 /* if it is on the stack or indirectly addressable */
670 /* space we need to assign either r0 or r1 to it */
671 if (sym->onStack) // || sym->iaccess)
676 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
677 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
679 /* acquire a temporary register -- it is saved in function */
681 sym->aop = aop = newAsmop(AOP_STA);
682 aop->aopu.stk.stk = sym->stack;
683 aop->size = getSize(sym->type);
686 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
687 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
688 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
689 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
691 for(i=0;i<aop->size;i++)
692 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
693 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
695 for(i=0;i<aop->size;i++) {
696 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
697 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
701 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
704 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
707 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
710 for(i=0;i<aop->size;i++) {
712 /* initialise for stack access via frame pointer */
713 // operands on stack are accessible via "FSR2 + index" with index
714 // starting at 2 for arguments and growing from 0 downwards for
715 // local variables (index == 0 is not assigned so we add one here)
717 int soffs = sym->stack;
722 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
723 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
724 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
729 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
736 /* now assign the address of the variable to
737 the pointer register */
738 if (aop->type != AOP_STK) {
742 pic16_emitcode("push","acc");
744 pic16_emitcode("mov","a,_bp");
745 pic16_emitcode("add","a,#0x%02x",
747 ((char)(sym->stack - _G.nRegsSaved )) :
748 ((char)sym->stack)) & 0xff);
749 pic16_emitcode("mov","%s,a",
750 aop->aopu.aop_ptr->name);
753 pic16_emitcode("pop","acc");
755 pic16_emitcode("mov","%s,#%s",
756 aop->aopu.aop_ptr->name,
758 aop->paged = space->paged;
760 aop->aopu.aop_stk = sym->stack;
768 if (sym->onStack && options.stack10bit)
770 /* It's on the 10 bit stack, which is located in
774 //DEBUGpic16_emitcode(";","%d",__LINE__);
777 pic16_emitcode("push","acc");
779 pic16_emitcode("mov","a,_bp");
780 pic16_emitcode("add","a,#0x%02x",
782 ((char)(sym->stack - _G.nRegsSaved )) :
783 ((char)sym->stack)) & 0xff);
786 pic16_emitcode ("mov","dpx1,#0x40");
787 pic16_emitcode ("mov","dph1,#0x00");
788 pic16_emitcode ("mov","dpl1, a");
792 pic16_emitcode("pop","acc");
794 sym->aop = aop = newAsmop(AOP_DPTR2);
795 aop->size = getSize(sym->type);
801 /* special case for a function */
802 if (IS_FUNC(sym->type)) {
803 sym->aop = aop = newAsmop(AOP_PCODE);
804 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
805 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
806 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
807 PCOI(aop->aopu.pcop)->index = 0;
808 aop->size = FPTRSIZE;
809 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
816 //DEBUGpic16_emitcode(";","%d",__LINE__);
817 /* if in bit space */
818 if (IN_BITSPACE(space)) {
819 sym->aop = aop = newAsmop (AOP_CRY);
820 aop->aopu.aop_dir = sym->rname ;
821 aop->size = getSize(sym->type);
822 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
825 /* if it is in direct space */
826 if (IN_DIRSPACE(space)) {
827 sym->aop = aop = newAsmop (AOP_DIR);
828 aop->aopu.aop_dir = sym->rname ;
829 aop->size = getSize(sym->type);
830 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
831 pic16_allocDirReg( IC_LEFT(ic) );
836 if (IN_FARSPACE(space) && !IN_CODESPACE(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 /* only remaining is far space */
847 sym->aop = aop = newAsmop(AOP_PCODE);
849 /* change the next if to 1 to revert to good old immediate code */
850 if(IN_CODESPACE(space)) {
851 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
852 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
853 PCOI(aop->aopu.pcop)->index = 0;
855 /* try to allocate via direct register */
856 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
857 // aop->size = getSize( sym->type );
860 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
861 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
864 if(!pic16_allocDirReg (IC_LEFT(ic)))
868 if(IN_DIRSPACE( space ))
870 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
871 aop->size = FPTRSIZE;
872 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
873 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
874 else if(sym->onStack) {
877 if(SPEC_SCLS(sym->etype) == S_PDATA) {
878 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
879 aop->size = FPTRSIZE;
884 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
886 /* if it is in code space */
887 if (IN_CODESPACE(space))
893 /*-----------------------------------------------------------------*/
894 /* aopForRemat - rematerialzes an object */
895 /*-----------------------------------------------------------------*/
896 static asmop *aopForRemat (operand *op) // x symbol *sym)
898 symbol *sym = OP_SYMBOL(op);
900 iCode *ic = NULL, *oldic;
901 asmop *aop = newAsmop(AOP_PCODE);
908 ic = sym->rematiCode;
910 if(IS_OP_POINTER(op)) {
911 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
917 // pic16_emitpcomment("ic: %s\n", printILine(ic));
920 val += (int) operandLitValue(IC_RIGHT(ic));
921 } else if (ic->op == '-') {
922 val -= (int) operandLitValue(IC_RIGHT(ic));
926 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
929 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
932 if(!op->isaddr)viaimmd++; else viaimmd=0;
934 /* set the following if to 1 to revert to good old immediate code */
935 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
938 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
940 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
943 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
945 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
948 PCOI(aop->aopu.pcop)->index = val;
950 aop->size = getSize( sym->type );
952 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
954 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
955 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
957 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
961 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
962 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
964 val, IS_PTR_CONST(operandType(op)));
966 val, IS_CODEPTR(operandType(op)));
969 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
971 pic16_allocDirReg (IC_LEFT(ic));
973 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
980 static int aopIdx (asmop *aop, int offset)
985 if(aop->type != AOP_REG)
988 return aop->aopu.aop_reg[offset]->rIdx;
993 /*-----------------------------------------------------------------*/
994 /* regsInCommon - two operands have some registers in common */
995 /*-----------------------------------------------------------------*/
996 static bool regsInCommon (operand *op1, operand *op2)
1001 /* if they have registers in common */
1002 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1005 sym1 = OP_SYMBOL(op1);
1006 sym2 = OP_SYMBOL(op2);
1008 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1011 for (i = 0 ; i < sym1->nRegs ; i++) {
1016 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1020 if (sym2->regs[j] == sym1->regs[i])
1028 /*-----------------------------------------------------------------*/
1029 /* operandsEqu - equivalent */
1030 /*-----------------------------------------------------------------*/
1031 static bool operandsEqu ( operand *op1, operand *op2)
1033 symbol *sym1, *sym2;
1035 /* if they not symbols */
1036 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1039 sym1 = OP_SYMBOL(op1);
1040 sym2 = OP_SYMBOL(op2);
1042 /* if both are itemps & one is spilt
1043 and the other is not then false */
1044 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1045 sym1->isspilt != sym2->isspilt )
1048 /* if they are the same */
1052 if (sym1->rname[0] && sym2->rname[0]
1053 && strcmp (sym1->rname, sym2->rname) == 0)
1057 /* if left is a tmp & right is not */
1058 if (IS_ITEMP(op1) &&
1061 (sym1->usl.spillLoc == sym2))
1064 if (IS_ITEMP(op2) &&
1068 (sym2->usl.spillLoc == sym1))
1074 /*-----------------------------------------------------------------*/
1075 /* pic16_sameRegs - two asmops have the same registers */
1076 /*-----------------------------------------------------------------*/
1077 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1084 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1085 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1087 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1089 if (aop1->type != AOP_REG ||
1090 aop2->type != AOP_REG )
1093 /* This is a bit too restrictive if one is a subset of the other...
1094 if (aop1->size != aop2->size )
1098 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1099 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1101 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1102 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1109 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1111 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1112 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1114 if(aop1 == aop2)return TRUE;
1115 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1117 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1123 /*-----------------------------------------------------------------*/
1124 /* pic16_aopOp - allocates an asmop for an operand : */
1125 /*-----------------------------------------------------------------*/
1126 void pic16_aopOp (operand *op, iCode *ic, bool result)
1135 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1137 /* if this a literal */
1138 if (IS_OP_LITERAL(op)) {
1139 op->aop = aop = newAsmop(AOP_LIT);
1140 aop->aopu.aop_lit = op->operand.valOperand;
1141 aop->size = getSize(operandType(op));
1146 sym_link *type = operandType(op);
1148 if(IS_PTR_CONST(type))
1150 if(IS_CODEPTR(type))
1152 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1155 /* if already has a asmop then continue */
1159 /* if the underlying symbol has a aop */
1160 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1161 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1162 op->aop = OP_SYMBOL(op)->aop;
1166 /* if this is a true symbol */
1167 if (IS_TRUE_SYMOP(op)) {
1168 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1169 op->aop = aopForSym(ic, op, result);
1173 /* this is a temporary : this has
1179 e) can be a return use only */
1181 sym = OP_SYMBOL(op);
1183 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1184 /* if the type is a conditional */
1185 if (sym->regType == REG_CND) {
1186 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1191 /* if it is spilt then two situations
1193 b) has a spill location */
1194 if (sym->isspilt || sym->nRegs == 0) {
1196 // debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
1197 DEBUGpic16_emitcode(";","%d",__LINE__);
1198 /* rematerialize it NOW */
1201 sym->aop = op->aop = aop = aopForRemat (op);
1202 // aop->size = getSize(sym->type);
1203 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1210 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1211 aop->size = getSize(sym->type);
1212 for ( i = 0 ; i < 1 ; i++ ) {
1213 aop->aopu.aop_str[i] = accUse[i];
1214 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1216 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1217 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1225 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1226 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1227 //pic16_allocDirReg (IC_LEFT(ic));
1228 aop->size = getSize(sym->type);
1233 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1234 aop->size = getSize(sym->type);
1235 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1236 aop->aopu.aop_str[i] = fReturn[i];
1238 DEBUGpic16_emitcode(";","%d",__LINE__);
1242 /* else spill location */
1243 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1244 /* force a new aop if sizes differ */
1245 sym->usl.spillLoc->aop = NULL;
1249 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1250 __FUNCTION__,__LINE__,
1251 sym->usl.spillLoc->rname,
1252 sym->rname, sym->usl.spillLoc->offset);
1255 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1256 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1257 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1258 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1260 sym->usl.spillLoc->offset, op);
1262 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1263 DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1264 assert (getSize(sym->type) <= 1);
1265 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1267 aop->size = getSize(sym->type);
1273 sym_link *type = operandType(op);
1275 if(IS_PTR_CONST(type))
1277 if(IS_CODEPTR(type))
1279 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1282 /* must be in a register */
1283 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1284 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1285 aop->size = sym->nRegs;
1286 for ( i = 0 ; i < sym->nRegs ;i++)
1287 aop->aopu.aop_reg[i] = sym->regs[i];
1290 /*-----------------------------------------------------------------*/
1291 /* pic16_freeAsmop - free up the asmop given to an operand */
1292 /*----------------------------------------------------------------*/
1293 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1310 /* depending on the asmop type only three cases need work AOP_RO
1311 , AOP_R1 && AOP_STK */
1313 switch (aop->type) {
1315 if (_G.fsr0Pushed ) {
1317 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1318 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1319 // pic16_emitcode ("pop","ar0");
1323 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1327 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1333 pic16_emitcode ("pop","ar0");
1337 bitVectUnSetBit(ic->rUsed,R0_IDX);
1343 pic16_emitcode ("pop","ar1");
1347 bitVectUnSetBit(ic->rUsed,R1_IDX);
1354 /* we must store the result on stack */
1355 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1356 // operands on stack are accessible via "FSR2 + index" with index
1357 // starting at 2 for arguments and growing from 0 downwards for
1358 // local variables (index == 0 is not assigned so we add one here)
1359 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1364 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1365 for(i=0;i<aop->size;i++) {
1366 /* initialise for stack access via frame pointer */
1367 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1368 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1369 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1372 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1376 for(i=0;i<aop->size;i++)
1377 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1386 int stk = aop->aopu.aop_stk + aop->size;
1387 bitVectUnSetBit(ic->rUsed,R0_IDX);
1388 bitVectUnSetBit(ic->rUsed,R1_IDX);
1390 getFreePtr(ic,&aop,FALSE);
1392 if (options.stack10bit)
1394 /* I'm not sure what to do here yet... */
1397 "*** Warning: probably generating bad code for "
1398 "10 bit stack mode.\n");
1402 pic16_emitcode ("mov","a,_bp");
1403 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1404 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1406 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1410 pic16_emitcode("pop","acc");
1411 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1413 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1416 pic16_freeAsmop(op,NULL,ic,TRUE);
1418 pic16_emitcode("pop","ar0");
1423 pic16_emitcode("pop","ar1");
1433 /* all other cases just dealloc */
1437 OP_SYMBOL(op)->aop = NULL;
1438 /* if the symbol has a spill */
1440 SPIL_LOC(op)->aop = NULL;
1445 /*-----------------------------------------------------------------*/
1446 /* pic16_aopGet - for fetching value of the aop */
1447 /*-----------------------------------------------------------------*/
1448 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1453 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1455 /* offset is greater than size then zero */
1456 if (offset > (aop->size - 1) &&
1457 aop->type != AOP_LIT)
1460 /* depending on type */
1461 switch (aop->type) {
1465 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1466 rs = Safe_calloc(1, strlen(s)+1);
1471 /* if we need to increment it */
1472 while (offset > aop->coff)
1474 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478 while (offset < aop->coff)
1480 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1486 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1487 return (dname ? "acc" : "a");
1489 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1490 rs = Safe_calloc (1, strlen (s) + 1);
1498 sprintf (s,"%s",aop->aopu.aop_immd);
1501 sprintf(s,"(%s >> %d)",
1506 aop->aopu.aop_immd);
1507 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1508 rs = Safe_calloc(1,strlen(s)+1);
1514 sprintf(s,"(%s + %d)",
1517 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1519 sprintf(s,"%s",aop->aopu.aop_dir);
1520 rs = Safe_calloc(1,strlen(s)+1);
1526 // return aop->aopu.aop_reg[offset]->dname;
1528 return aop->aopu.aop_reg[offset]->name;
1531 //pic16_emitcode(";","%d",__LINE__);
1532 return aop->aopu.aop_dir;
1535 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1536 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1538 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1539 rs = Safe_strdup("WREG");
1543 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1544 rs = Safe_calloc(1,strlen(s)+1);
1549 aop->coff = offset ;
1550 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1553 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1555 return aop->aopu.aop_str[offset];
1559 pCodeOp *pcop = aop->aopu.pcop;
1560 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1562 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1563 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1565 sprintf(s,"(%s + %d)", pcop->name, offset);
1567 sprintf(s,"%s", pcop->name);
1570 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1573 rs = Safe_calloc(1,strlen(s)+1);
1579 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1581 sprintf(s,"(%s + %d)",
1585 sprintf(s,"%s",aop->aopu.aop_dir);
1586 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1587 rs = Safe_calloc(1,strlen(s)+1);
1593 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1597 // pCodeOp *pcop = aop->aop
1602 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1603 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1604 "aopget got unsupported aop->type");
1610 /* lock has the following meaning: When allocating temporary registers
1611 * for stack variables storage, the value of the temporary register is
1612 * saved on stack. Its value is restored at the end. This procedure is
1613 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1614 * a possibility that before a call to pic16_aopOp, a temporary register
1615 * is allocated for a while and it is freed after some time, this will
1616 * mess the stack and values will not be restored properly. So use lock=1
1617 * to allocate temporary registers used internally by the programmer, and
1618 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1619 * to inform the compiler developer about a possible bug. This is an internal
1620 * feature for developing the compiler -- VR */
1622 int _TempReg_lock = 0;
1623 /*-----------------------------------------------------------------*/
1624 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1625 /*-----------------------------------------------------------------*/
1626 pCodeOp *pic16_popGetTempReg(int lock)
1631 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1633 // werror(W_POSSBUG2, __FILE__, __LINE__);
1636 _TempReg_lock += lock;
1641 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1642 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1643 PCOR(pcop)->r->wasUsed=1;
1644 PCOR(pcop)->r->isFree=0;
1646 /* push value on stack */
1647 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1655 /*-----------------------------------------------------------------*/
1656 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1657 /* don't save if inside v */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1664 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1667 // werror(W_POSSBUG2, __FILE__, __LINE__);
1670 _TempReg_lock += lock;
1675 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1676 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1677 PCOR(pcop)->r->wasUsed=1;
1678 PCOR(pcop)->r->isFree=0;
1680 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1681 /* push value on stack */
1682 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1694 /*-----------------------------------------------------------------*/
1695 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1699 _TempReg_lock -= lock;
1701 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1702 PCOR(pcop)->r->isFree = 1;
1703 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1706 /*-----------------------------------------------------------------*/
1707 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1708 /*-----------------------------------------------------------------*/
1709 pCodeOp *pic16_popGetLabel(unsigned int key)
1712 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1717 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1720 /*-----------------------------------------------------------------*/
1721 /* pic16_popCopyReg - copy a pcode operator */
1722 /*-----------------------------------------------------------------*/
1723 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1727 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1728 pcor->pcop.type = pc->pcop.type;
1730 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1731 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1733 pcor->pcop.name = NULL;
1736 pcor->rIdx = pc->rIdx;
1738 pcor->instance = pc->instance;
1740 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1745 /*-----------------------------------------------------------------*/
1746 /* pic16_popGetLit - asm operator to pcode operator conversion */
1747 /*-----------------------------------------------------------------*/
1748 pCodeOp *pic16_popGetLit(int lit)
1750 return pic16_newpCodeOpLit(lit);
1753 /*-----------------------------------------------------------------*/
1754 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1755 /*-----------------------------------------------------------------*/
1756 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1758 return pic16_newpCodeOpLit2(lit, arg2);
1762 /*-----------------------------------------------------------------*/
1763 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1764 /*-----------------------------------------------------------------*/
1765 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1767 return pic16_newpCodeOpImmd(name, offset,index, 0);
1771 /*-----------------------------------------------------------------*/
1772 /* pic16_popGet - asm operator to pcode operator conversion */
1773 /*-----------------------------------------------------------------*/
1774 pCodeOp *pic16_popGetWithString(char *str)
1780 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1784 pcop = pic16_newpCodeOp(str,PO_STR);
1789 /*-----------------------------------------------------------------*/
1790 /* pic16_popRegFromString - */
1791 /*-----------------------------------------------------------------*/
1792 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1795 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1796 pcop->type = PO_DIR;
1798 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1799 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1804 pcop->name = Safe_calloc(1,strlen(str)+1);
1805 strcpy(pcop->name,str);
1807 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1809 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1811 /* make sure that register doesn't exist,
1812 * and operand isn't NULL
1813 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1814 if((PCOR(pcop)->r == NULL)
1816 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1817 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1818 // __FUNCTION__, __LINE__, str, size, offset);
1820 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1821 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1824 PCOR(pcop)->instance = offset;
1829 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1833 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1835 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1836 PCOR(pcop)->rIdx = rIdx;
1837 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1839 PCOR(pcop)->r->isFree = 0;
1840 PCOR(pcop)->r->wasUsed = 1;
1842 pcop->type = PCOR(pcop)->r->pc_type;
1847 /*---------------------------------------------------------------------------------*/
1848 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1850 /*---------------------------------------------------------------------------------*/
1851 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1856 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1858 /* comment the following check, so errors to throw up */
1859 // if(!pcop2)return NULL;
1861 temp = pic16_popGet(aop_dst, offset);
1862 pcop2->pcop2 = temp;
1869 /*--------------------------------------------------------------------------------.-*/
1870 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1871 /* VR 030601 , adapted by Hans Dorn */
1872 /*--------------------------------------------------------------------------------.-*/
1873 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1877 pcop2 = (pCodeOpReg2 *)src;
1885 /*---------------------------------------------------------------------------------*/
1886 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1887 /* movff instruction */
1888 /*---------------------------------------------------------------------------------*/
1889 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1894 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1895 pcop2->pcop2 = pic16_popCopyReg(dst);
1897 /* the pCodeOp may be already allocated */
1898 pcop2 = (pCodeOpReg2 *)(src);
1899 pcop2->pcop2 = (pCodeOp *)(dst);
1906 /*-----------------------------------------------------------------*/
1907 /* pic16_popGet - asm operator to pcode operator conversion */
1908 /*-----------------------------------------------------------------*/
1909 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1911 //char *s = buffer ;
1916 /* offset is greater than
1919 // if (offset > (aop->size - 1) &&
1920 // aop->type != AOP_LIT)
1921 // return NULL; //zero;
1923 /* depending on type */
1924 switch (aop->type) {
1930 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1931 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1938 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1939 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1940 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1941 PCOR(pcop)->r->wasUsed = 1;
1942 PCOR(pcop)->r->isFree = 0;
1944 PCOR(pcop)->instance = offset;
1945 pcop->type = PCOR(pcop)->r->pc_type;
1949 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1950 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1953 /* pCodeOp is already allocated from aopForSym */
1954 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1955 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1961 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1963 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1965 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1967 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1968 PCOR(pcop)->rIdx = rIdx;
1969 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1970 PCOR(pcop)->r->wasUsed=1;
1971 PCOR(pcop)->r->isFree=0;
1973 PCOR(pcop)->instance = offset;
1974 pcop->type = PCOR(pcop)->r->pc_type;
1975 // rs = aop->aopu.aop_reg[offset]->name;
1976 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1980 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1981 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1987 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1988 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1992 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1993 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1999 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2000 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2002 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2004 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2005 // pcop->type = PO_GPR_REGISTER;
2006 PCOR(pcop)->rIdx = rIdx;
2007 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2008 PCOR(pcop)->r->wasUsed=1;
2009 PCOR(pcop)->r->isFree=0;
2011 PCOR(pcop)->instance = offset;
2012 pcop->type = PCOR(pcop)->r->pc_type;
2014 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2015 rs = aop->aopu.aop_reg[offset]->name;
2016 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2021 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2023 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2024 PCOR(pcop)->instance = offset;
2025 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2026 //if(PCOR(pcop)->r == NULL)
2027 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2031 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2032 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2035 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2036 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2039 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2040 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2041 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2042 pcop->type = PCOR(pcop)->r->pc_type;
2043 pcop->name = PCOR(pcop)->r->name;
2049 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2051 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2052 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2053 switch( aop->aopu.pcop->type ) {
2054 case PO_DIR: PCOR(pcop)->instance += offset; break;
2055 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2056 case PO_WREG: assert (offset==0); break;
2058 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2059 assert( 0 ); /* should never reach here */;
2064 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2065 "pic16_popGet got unsupported aop->type");
2068 /*-----------------------------------------------------------------*/
2069 /* pic16_aopPut - puts a string for a aop */
2070 /*-----------------------------------------------------------------*/
2071 void pic16_aopPut (asmop *aop, char *s, int offset)
2078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2080 if (aop->size && offset > ( aop->size - 1)) {
2081 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2082 "pic16_aopPut got offset > aop->size");
2086 /* will assign value to value */
2087 /* depending on where it is ofcourse */
2088 switch (aop->type) {
2091 sprintf(d,"(%s + %d)",
2092 aop->aopu.aop_dir,offset);
2093 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2096 sprintf(d,"%s",aop->aopu.aop_dir);
2099 DEBUGpic16_emitcode(";","%d",__LINE__);
2101 pic16_emitcode("movf","%s,w",s);
2102 pic16_emitcode("movwf","%s",d);
2105 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2106 if(offset >= aop->size) {
2107 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2110 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2113 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2120 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2121 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2124 strcmp(s,"r0") == 0 ||
2125 strcmp(s,"r1") == 0 ||
2126 strcmp(s,"r2") == 0 ||
2127 strcmp(s,"r3") == 0 ||
2128 strcmp(s,"r4") == 0 ||
2129 strcmp(s,"r5") == 0 ||
2130 strcmp(s,"r6") == 0 ||
2131 strcmp(s,"r7") == 0 )
2132 pic16_emitcode("mov","%s,%s ; %d",
2133 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2137 if(strcmp(s,"W")==0 )
2138 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2140 pic16_emitcode("movwf","%s",
2141 aop->aopu.aop_reg[offset]->name);
2143 if(strcmp(s,zero)==0) {
2144 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2146 } else if(strcmp(s,"W")==0) {
2147 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2148 pcop->type = PO_GPR_REGISTER;
2150 PCOR(pcop)->rIdx = -1;
2151 PCOR(pcop)->r = NULL;
2153 DEBUGpic16_emitcode(";","%d",__LINE__);
2154 pcop->name = Safe_strdup(s);
2155 pic16_emitpcode(POC_MOVFW,pcop);
2156 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2157 } else if(strcmp(s,one)==0) {
2158 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2159 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2161 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2169 if (aop->type == AOP_DPTR2)
2175 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2176 "pic16_aopPut writting to code space");
2180 while (offset > aop->coff) {
2182 pic16_emitcode ("inc","dptr");
2185 while (offset < aop->coff) {
2187 pic16_emitcode("lcall","__decdptr");
2192 /* if not in accumulater */
2195 pic16_emitcode ("movx","@dptr,a");
2197 if (aop->type == AOP_DPTR2)
2205 while (offset > aop->coff) {
2207 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2209 while (offset < aop->coff) {
2211 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2217 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2222 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2224 if (strcmp(s,"r0") == 0 ||
2225 strcmp(s,"r1") == 0 ||
2226 strcmp(s,"r2") == 0 ||
2227 strcmp(s,"r3") == 0 ||
2228 strcmp(s,"r4") == 0 ||
2229 strcmp(s,"r5") == 0 ||
2230 strcmp(s,"r6") == 0 ||
2231 strcmp(s,"r7") == 0 ) {
2233 sprintf(buffer,"a%s",s);
2234 pic16_emitcode("mov","@%s,%s",
2235 aop->aopu.aop_ptr->name,buffer);
2237 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2242 if (strcmp(s,"a") == 0)
2243 pic16_emitcode("push","acc");
2245 pic16_emitcode("push","%s",s);
2250 /* if bit variable */
2251 if (!aop->aopu.aop_dir) {
2252 pic16_emitcode("clr","a");
2253 pic16_emitcode("rlc","a");
2256 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2259 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2262 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2264 lbl = newiTempLabel(NULL);
2266 if (strcmp(s,"a")) {
2269 pic16_emitcode("clr","c");
2270 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2271 pic16_emitcode("cpl","c");
2272 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2273 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2280 if (strcmp(aop->aopu.aop_str[offset],s))
2281 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2286 if (!offset && (strcmp(s,"acc") == 0))
2289 if (strcmp(aop->aopu.aop_str[offset],s))
2290 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2294 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2295 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2296 // "pic16_aopPut got unsupported aop->type");
2302 /*-----------------------------------------------------------------*/
2303 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2304 /*-----------------------------------------------------------------*/
2305 void pic16_mov2w (asmop *aop, int offset)
2307 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2310 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2312 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2315 static void mov2f(asmop *dst, asmop *src, int offset)
2317 if(is_LitAOp(src)) {
2318 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2319 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2321 if(pic16_sameRegsOfs(src, dst, offset))return;
2322 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2323 pic16_popGet(dst, offset)));
2327 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2329 if(is_LitAOp(src)) {
2330 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2331 pic16_emitpcode(POC_MOVWF, dst);
2333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2337 void pic16_testStackOverflow(void)
2339 #define GSTACK_TEST_NAME "__gstack_test"
2341 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2346 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2347 strcpy(sym->rname, GSTACK_TEST_NAME);
2348 checkAddSym(&externs, sym);
2353 /* push pcop into stack */
2354 void pic16_pushpCodeOp(pCodeOp *pcop)
2356 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2357 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2358 if(pic16_options.gstack)
2359 pic16_testStackOverflow();
2363 /* pop pcop from stack */
2364 void pic16_poppCodeOp(pCodeOp *pcop)
2366 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2367 if(pic16_options.gstack)
2368 pic16_testStackOverflow();
2372 /*-----------------------------------------------------------------*/
2373 /* pushw - pushes wreg to stack */
2374 /*-----------------------------------------------------------------*/
2377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2378 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2379 if(pic16_options.gstack)
2380 pic16_testStackOverflow();
2384 /*-----------------------------------------------------------------*/
2385 /* pushaop - pushes aop to stack */
2386 /*-----------------------------------------------------------------*/
2387 void pushaop(asmop *aop, int offset)
2389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2391 if(is_LitAOp(aop)) {
2392 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2393 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2395 pic16_emitpcode(POC_MOVFF,
2396 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2399 if(pic16_options.gstack)
2400 pic16_testStackOverflow();
2403 /*-----------------------------------------------------------------*/
2404 /* popaop - pops aop from stack */
2405 /*-----------------------------------------------------------------*/
2406 void popaop(asmop *aop, int offset)
2408 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2409 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2410 if(pic16_options.gstack)
2411 pic16_testStackOverflow();
2414 void popaopidx(asmop *aop, int offset, int index)
2418 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2420 if(STACK_MODEL_LARGE)ofs++;
2422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2423 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2424 if(pic16_options.gstack)
2425 pic16_testStackOverflow();
2428 #if !(USE_GENERIC_SIGNED_SHIFT)
2429 /*-----------------------------------------------------------------*/
2430 /* reAdjustPreg - points a register back to where it should */
2431 /*-----------------------------------------------------------------*/
2432 static void reAdjustPreg (asmop *aop)
2436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2438 if ((size = aop->size) <= 1)
2441 switch (aop->type) {
2445 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2449 if (aop->type == AOP_DPTR2)
2455 pic16_emitcode("lcall","__decdptr");
2458 if (aop->type == AOP_DPTR2)
2470 /*-----------------------------------------------------------------*/
2471 /* opIsGptr: returns non-zero if the passed operand is */
2472 /* a generic pointer type. */
2473 /*-----------------------------------------------------------------*/
2474 static int opIsGptr(operand *op)
2476 sym_link *type = operandType(op);
2478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2479 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2487 /*-----------------------------------------------------------------*/
2488 /* pic16_getDataSize - get the operand data size */
2489 /*-----------------------------------------------------------------*/
2490 int pic16_getDataSize(operand *op)
2492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2495 return AOP_SIZE(op);
2497 // tsd- in the pic port, the genptr size is 1, so this code here
2498 // fails. ( in the 8051 port, the size was 4).
2501 size = AOP_SIZE(op);
2502 if (size == GPTRSIZE)
2504 sym_link *type = operandType(op);
2505 if (IS_GENPTR(type))
2507 /* generic pointer; arithmetic operations
2508 * should ignore the high byte (pointer type).
2511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2518 /*-----------------------------------------------------------------*/
2519 /* pic16_outAcc - output Acc */
2520 /*-----------------------------------------------------------------*/
2521 void pic16_outAcc(operand *result)
2524 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2525 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2528 size = pic16_getDataSize(result);
2530 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2533 /* unsigned or positive */
2535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2540 /*-----------------------------------------------------------------*/
2541 /* pic16_outBitC - output a bit C */
2542 /* Move to result the value of Carry flag -- VR */
2543 /*-----------------------------------------------------------------*/
2544 void pic16_outBitC(operand *result)
2548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2550 /* if the result is bit */
2551 if (AOP_TYPE(result) == AOP_CRY) {
2552 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2553 pic16_aopPut(AOP(result),"c",0);
2556 i = AOP_SIZE(result);
2558 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2560 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2564 /*-----------------------------------------------------------------*/
2565 /* pic16_outBitOp - output a bit from Op */
2566 /* Move to result the value of set/clr op -- VR */
2567 /*-----------------------------------------------------------------*/
2568 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2574 /* if the result is bit */
2575 if (AOP_TYPE(result) == AOP_CRY) {
2576 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2577 pic16_aopPut(AOP(result),"c",0);
2580 i = AOP_SIZE(result);
2582 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2584 pic16_emitpcode(POC_RRCF, pcop);
2585 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2591 /*-----------------------------------------------------------------*/
2592 void pic16_toBoolean(operand *oper)
2594 int size = AOP_SIZE(oper) - 1;
2597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2599 if ( AOP_TYPE(oper) != AOP_ACC) {
2600 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2603 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2608 #if !defined(GEN_Not)
2609 /*-----------------------------------------------------------------*/
2610 /* genNot - generate code for ! operation */
2611 /*-----------------------------------------------------------------*/
2612 static void pic16_genNot (iCode *ic)
2618 /* assign asmOps to operand & result */
2619 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2620 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2622 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2623 /* if in bit space then a special case */
2624 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2625 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2626 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2627 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2629 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2630 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2631 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2636 size = AOP_SIZE(IC_LEFT(ic));
2638 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2639 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2640 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2643 pic16_toBoolean(IC_LEFT(ic));
2645 tlbl = newiTempLabel(NULL);
2646 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2647 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2648 pic16_outBitC(IC_RESULT(ic));
2651 /* release the aops */
2652 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2653 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2658 #if !defined(GEN_Cpl)
2659 /*-----------------------------------------------------------------*/
2660 /* genCpl - generate code for complement */
2661 /*-----------------------------------------------------------------*/
2662 static void pic16_genCpl (iCode *ic)
2668 /* assign asmOps to operand & result */
2669 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2670 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2672 /* if both are in bit space then
2674 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2675 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2677 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2678 pic16_emitcode("cpl","c");
2679 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2683 size = AOP_SIZE(IC_RESULT(ic));
2686 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2688 pic16_emitcode("cpl","a");
2689 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2691 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2692 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2694 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2703 /* release the aops */
2704 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2705 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2709 /*-----------------------------------------------------------------*/
2710 /* genUminusFloat - unary minus for floating points */
2711 /*-----------------------------------------------------------------*/
2712 static void genUminusFloat(operand *op,operand *result)
2714 int size ,offset =0 ;
2717 /* for this we just need to flip the
2718 first it then copy the rest in place */
2719 size = AOP_SIZE(op);
2722 mov2f(AOP(result), AOP(op), offset);
2726 /* toggle the MSB's highest bit */
2727 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2730 /*-----------------------------------------------------------------*/
2731 /* genUminus - unary minus code generation */
2732 /*-----------------------------------------------------------------*/
2733 static void genUminus (iCode *ic)
2736 sym_link *optype, *rtype;
2743 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2744 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2746 /* if both in bit space then special case */
2747 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2748 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2750 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2751 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2752 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2756 optype = operandType(IC_LEFT(ic));
2757 rtype = operandType(IC_RESULT(ic));
2759 /* if float then do float stuff */
2760 if (IS_FLOAT(optype)) {
2761 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2765 /* otherwise subtract from zero by taking the 2's complement */
2766 size = AOP_SIZE(IC_LEFT(ic));
2767 label = newiTempLabel ( NULL );
2769 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2770 for (i=size-1; i > 0; i--) {
2771 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2773 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2774 for (i=1; i < size; i++) {
2775 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2776 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2779 for (i=size-1; i >= 0; i--) {
2780 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2781 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2784 for (i=0; i < size-2; i++) {
2785 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2786 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2788 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2790 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2793 pic16_emitpLabel (label->key);
2796 /* release the aops */
2797 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2798 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2802 /*-----------------------------------------------------------------*/
2803 /* saveRegisters - will look for a call and save the registers */
2804 /*-----------------------------------------------------------------*/
2805 static void saveRegisters(iCode *lic)
2812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2814 for (ic = lic ; ic ; ic = ic->next)
2815 if (ic->op == CALL || ic->op == PCALL)
2819 fprintf(stderr,"found parameter push with no function call\n");
2823 /* if the registers have been saved already then
2825 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2828 /* find the registers in use at this time
2829 and push them away to safety */
2830 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2834 if (options.useXstack) {
2835 if (bitVectBitValue(rsave,R0_IDX))
2836 pic16_emitcode("mov","b,r0");
2837 pic16_emitcode("mov","r0,%s",spname);
2838 for (i = 0 ; i < pic16_nRegs ; i++) {
2839 if (bitVectBitValue(rsave,i)) {
2841 pic16_emitcode("mov","a,b");
2843 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2844 pic16_emitcode("movx","@r0,a");
2845 pic16_emitcode("inc","r0");
2848 pic16_emitcode("mov","%s,r0",spname);
2849 if (bitVectBitValue(rsave,R0_IDX))
2850 pic16_emitcode("mov","r0,b");
2852 //for (i = 0 ; i < pic16_nRegs ; i++) {
2853 // if (bitVectBitValue(rsave,i))
2854 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2857 dtype = operandType(IC_LEFT(ic));
2858 if (currFunc && dtype &&
2859 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2860 IFFUNC_ISISR(currFunc->type) &&
2863 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2866 /*-----------------------------------------------------------------*/
2867 /* unsaveRegisters - pop the pushed registers */
2868 /*-----------------------------------------------------------------*/
2869 static void unsaveRegisters (iCode *ic)
2874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2875 /* find the registers in use at this time
2876 and push them away to safety */
2877 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2880 if (options.useXstack) {
2881 pic16_emitcode("mov","r0,%s",spname);
2882 for (i = pic16_nRegs ; i >= 0 ; i--) {
2883 if (bitVectBitValue(rsave,i)) {
2884 pic16_emitcode("dec","r0");
2885 pic16_emitcode("movx","a,@r0");
2887 pic16_emitcode("mov","b,a");
2889 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2893 pic16_emitcode("mov","%s,r0",spname);
2894 if (bitVectBitValue(rsave,R0_IDX))
2895 pic16_emitcode("mov","r0,b");
2897 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2898 // if (bitVectBitValue(rsave,i))
2899 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2906 /*-----------------------------------------------------------------*/
2908 /*-----------------------------------------------------------------*/
2909 static void pushSide(operand * oper, int size)
2912 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2914 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2915 if (AOP_TYPE(oper) != AOP_REG &&
2916 AOP_TYPE(oper) != AOP_DIR &&
2918 pic16_emitcode("mov","a,%s",l);
2919 pic16_emitcode("push","acc");
2921 pic16_emitcode("push","%s",l);
2926 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2928 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2929 pic16_emitpcode(POC_MOVFW, src);
2930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2932 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2933 src, pic16_popGet(AOP(op), offset)));
2938 /*-----------------------------------------------------------------*/
2939 /* assignResultValue - assign results to oper, rescall==1 is */
2940 /* called from genCall() or genPcall() */
2941 /*-----------------------------------------------------------------*/
2942 static void assignResultValue(operand * oper, int rescall)
2944 int size = AOP_SIZE(oper);
2948 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2949 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2952 /* assign result from a call/pcall function() */
2954 /* function results are stored in a special order,
2955 * see top of file with Function return policy, or manual */
2958 /* 8-bits, result in WREG */
2959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2962 /* 16-bits, result in PRODL:WREG */
2963 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2967 /* 24-bits, result in PRODH:PRODL:WREG */
2968 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2972 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2973 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2977 /* >32-bits, result on stack, and FSR0 points to beginning.
2978 * Fix stack when done */
2980 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2982 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2983 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2985 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2990 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2991 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2992 if(STACK_MODEL_LARGE) {
2994 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2998 int areg = 0; /* matching argument register */
3000 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3001 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3004 /* its called from genReceive (probably) -- VR */
3005 /* I hope this code will not be called from somewhere else in the future!
3006 * We manually set the pseudo stack pointer in genReceive. - dw
3008 if(!GpsuedoStkPtr && _G.useWreg) {
3009 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3011 /* The last byte in the assignment is in W */
3012 if(areg <= GpsuedoStkPtr) {
3014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3016 // debugf("receive from WREG\n", 0);
3018 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3021 _G.stack_lat = AOP_SIZE(oper)-1;
3026 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3027 // debugf("receive from STACK\n", 0);
3034 /*-----------------------------------------------------------------*/
3035 /* genIpush - generate code for pushing this gets a little complex */
3036 /*-----------------------------------------------------------------*/
3037 static void genIpush (iCode *ic)
3039 // int size, offset=0;
3042 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3045 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3047 /* send to stack as normal */
3048 addSet(&_G.sendSet,ic);
3049 // addSetHead(&_G.sendSet,ic);
3050 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3055 int size, offset = 0 ;
3059 /* if this is not a parm push : ie. it is spill push
3060 and spill push is always done on the local stack */
3061 if (!ic->parmPush) {
3063 /* and the item is spilt then do nothing */
3064 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3067 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3068 size = AOP_SIZE(IC_LEFT(ic));
3069 /* push it on the stack */
3071 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3076 pic16_emitcode("push","%s",l);
3081 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3085 /*-----------------------------------------------------------------*/
3086 /* genIpop - recover the registers: can happen only for spilling */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpop (iCode *ic)
3091 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3096 /* if the temp was not pushed then */
3097 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3100 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3101 size = AOP_SIZE(IC_LEFT(ic));
3104 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3107 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3112 /*-----------------------------------------------------------------*/
3113 /* unsaverbank - restores the resgister bank from stack */
3114 /*-----------------------------------------------------------------*/
3115 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3117 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3125 if (options.useXstack) {
3127 r = getFreePtr(ic,&aop,FALSE);
3130 pic16_emitcode("mov","%s,_spx",r->name);
3131 pic16_emitcode("movx","a,@%s",r->name);
3132 pic16_emitcode("mov","psw,a");
3133 pic16_emitcode("dec","%s",r->name);
3136 pic16_emitcode ("pop","psw");
3139 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3140 if (options.useXstack) {
3141 pic16_emitcode("movx","a,@%s",r->name);
3142 //pic16_emitcode("mov","(%s+%d),a",
3143 // regspic16[i].base,8*bank+regspic16[i].offset);
3144 pic16_emitcode("dec","%s",r->name);
3147 pic16_emitcode("pop",""); //"(%s+%d)",
3148 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3151 if (options.useXstack) {
3153 pic16_emitcode("mov","_spx,%s",r->name);
3154 pic16_freeAsmop(NULL,aop,ic,TRUE);
3160 /*-----------------------------------------------------------------*/
3161 /* saverbank - saves an entire register bank on the stack */
3162 /*-----------------------------------------------------------------*/
3163 static void saverbank (int bank, iCode *ic, bool pushPsw)
3165 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3172 if (options.useXstack) {
3175 r = getFreePtr(ic,&aop,FALSE);
3176 pic16_emitcode("mov","%s,_spx",r->name);
3180 for (i = 0 ; i < pic16_nRegs ;i++) {
3181 if (options.useXstack) {
3182 pic16_emitcode("inc","%s",r->name);
3183 //pic16_emitcode("mov","a,(%s+%d)",
3184 // regspic16[i].base,8*bank+regspic16[i].offset);
3185 pic16_emitcode("movx","@%s,a",r->name);
3187 pic16_emitcode("push","");// "(%s+%d)",
3188 //regspic16[i].base,8*bank+regspic16[i].offset);
3192 if (options.useXstack) {
3193 pic16_emitcode("mov","a,psw");
3194 pic16_emitcode("movx","@%s,a",r->name);
3195 pic16_emitcode("inc","%s",r->name);
3196 pic16_emitcode("mov","_spx,%s",r->name);
3197 pic16_freeAsmop (NULL,aop,ic,TRUE);
3200 pic16_emitcode("push","psw");
3202 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3210 static int wparamCmp(void *p1, void *p2)
3212 return (!strcmp((char *)p1, (char *)p2));
3215 int inWparamList(char *s)
3217 return isinSetWith(wparamList, s, wparamCmp);
3221 /*-----------------------------------------------------------------*/
3222 /* genCall - generates a call statement */
3223 /*-----------------------------------------------------------------*/
3224 static void genCall (iCode *ic)
3234 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3235 /* if caller saves & we have not saved then */
3236 // if (!ic->regsSaved)
3237 // saveRegisters(ic);
3239 /* initialise stackParms for IPUSH pushes */
3240 // stackParms = psuedoStkPtr;
3241 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3242 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3243 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3246 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3249 /* if send set is not empty the assign */
3252 int psuedoStkPtr=-1;
3253 int firstTimeThruLoop = 1;
3256 /* reverse sendSet if function is not reentrant */
3257 if(!IFFUNC_ISREENT(ftype))
3258 _G.sendSet = reverseSet(_G.sendSet);
3260 /* First figure how many parameters are getting passed */
3264 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3268 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3269 size = AOP_SIZE(IC_LEFT(sic));
3273 /* pass the last byte through WREG */
3277 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3278 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3279 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3281 if(!firstTimeThruLoop) {
3282 /* If this is not the first time we've been through the loop
3283 * then we need to save the parameter in a temporary
3284 * register. The last byte of the last parameter is
3288 // --psuedoStkPtr; // sanity check
3292 firstTimeThruLoop=0;
3294 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3299 /* all arguments are passed via stack */
3303 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3304 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3305 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3307 // pushaop(AOP(IC_LEFT(sic)), size);
3308 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3313 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3317 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3318 pushw(); /* save last parameter to stack if functions has varargs */
3322 } else use_wreg = 0;
3324 _G.stackRegSet = _G.sendSet;
3329 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3333 /* if we need to assign a result value */
3334 if ((IS_ITEMP(IC_RESULT(ic))
3335 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3336 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3337 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3340 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3343 assignResultValue(IC_RESULT(ic), 1);
3345 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3348 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3351 if(!stackParms && ic->parmBytes) {
3352 stackParms = ic->parmBytes;
3355 stackParms -= use_wreg;
3358 if(stackParms == 1) {
3359 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3361 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3362 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3364 if(STACK_MODEL_LARGE) {
3366 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3371 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3374 /* adjust the stack for parameters if required */
3375 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3378 /* if register bank was saved then pop them */
3380 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3382 /* if we hade saved some registers then unsave them */
3383 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3384 unsaveRegisters (ic);
3390 /*-----------------------------------------------------------------*/
3391 /* genPcall - generates a call by pointer statement */
3392 /* new version, created from genCall - HJD */
3393 /*-----------------------------------------------------------------*/
3394 static void genPcall (iCode *ic)
3396 sym_link *ftype, *fntype;
3398 symbol *retlbl = newiTempLabel(NULL);
3399 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3403 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3404 fntype = operandType( IC_LEFT(ic) )->next;
3406 /* if send set is not empty the assign */
3409 int psuedoStkPtr=-1;
3411 /* reverse sendSet if function is not reentrant */
3412 if(!IFFUNC_ISREENT(fntype))
3413 _G.sendSet = reverseSet(_G.sendSet);
3417 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3420 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3421 size = AOP_SIZE(IC_LEFT(sic));
3424 /* all parameters are passed via stack, since WREG is clobbered
3425 * by the calling sequence */
3427 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3428 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3429 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3431 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3435 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3438 _G.stackRegSet = _G.sendSet;
3442 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3444 // push return address
3445 // push $ on return stack, then replace with retlbl
3447 /* Thanks to Thorsten Klose for pointing out that the following
3448 * snippet should be interrupt safe */
3449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3450 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3452 pic16_emitpcodeNULLop(POC_PUSH);
3454 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3455 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3456 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3457 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3458 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3459 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3462 /* restore interrupt control register */
3463 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3464 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3466 /* make the call by writing the pointer into pc */
3467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3470 // note: MOVFF to PCL not allowed
3471 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3472 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3475 /* return address is here: (X) */
3476 pic16_emitpLabelFORCE(retlbl->key);
3478 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3481 /* if we need assign a result value */
3482 if ((IS_ITEMP(IC_RESULT(ic))
3483 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3484 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3485 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3488 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3491 assignResultValue(IC_RESULT(ic), 1);
3493 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3494 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3496 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3499 // stackParms -= use_wreg;
3502 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3503 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3504 if(STACK_MODEL_LARGE) {
3506 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3511 /*-----------------------------------------------------------------*/
3512 /* resultRemat - result is rematerializable */
3513 /*-----------------------------------------------------------------*/
3514 static int resultRemat (iCode *ic)
3516 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3517 if (SKIP_IC(ic) || ic->op == IFX)
3520 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3521 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3522 if (sym->remat && !POINTER_SET(ic))
3529 #if defined(__BORLANDC__) || defined(_MSC_VER)
3530 #define STRCASECMP stricmp
3532 #define STRCASECMP strcasecmp
3536 /*-----------------------------------------------------------------*/
3537 /* inExcludeList - return 1 if the string is in exclude Reg list */
3538 /*-----------------------------------------------------------------*/
3539 static bool inExcludeList(char *s)
3541 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3545 if (options.excludeRegs[i] &&
3546 STRCASECMP(options.excludeRegs[i],"none") == 0)
3549 for ( i = 0 ; options.excludeRegs[i]; i++) {
3550 if (options.excludeRegs[i] &&
3551 STRCASECMP(s,options.excludeRegs[i]) == 0)
3558 /*-----------------------------------------------------------------*/
3559 /* genFunction - generated code for function entry */
3560 /*-----------------------------------------------------------------*/
3561 static void genFunction (iCode *ic)
3567 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3569 pic16_labelOffset += (max_key+4);
3574 ftype = operandType(IC_LEFT(ic));
3575 sym = OP_SYMBOL(IC_LEFT(ic));
3577 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3578 /* create an absolute section at the interrupt vector:
3579 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3585 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3591 sym = OP_SYMBOL( IC_LEFT(ic));
3593 if(interrupts[i]->name
3594 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3601 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3602 __FILE__, __LINE__, sym->name);
3605 _G.interruptvector = found;
3609 if(FUNC_INTNO(sym->type) == 256)
3610 sprintf(asymname, "ivec_%s", sym->name);
3612 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3613 asym = newSymbol(asymname, 0);
3615 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3616 pic16_addpBlock( apb );
3618 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3619 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3620 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3622 /* mark the end of this tiny function */
3623 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3628 abSym = Safe_calloc(1, sizeof(absSym));
3629 strcpy(abSym->name, asymname);
3631 switch( FUNC_INTNO(sym->type) ) {
3632 case 0: abSym->address = 0x000000; break;
3633 case 1: abSym->address = 0x000008; break;
3634 case 2: abSym->address = 0x000018; break;
3637 abSym->address = -1; break;
3640 /* relocate interrupt vectors if needed */
3641 if(abSym->address != -1)
3642 abSym->address += pic16_options.ivt_loc;
3644 addSet(&absSymSet, abSym);
3648 /* create the function header */
3649 pic16_emitcode(";","-----------------------------------------");
3650 pic16_emitcode(";"," function %s",sym->name);
3651 pic16_emitcode(";","-----------------------------------------");
3653 pic16_emitcode("","%s:",sym->rname);
3654 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3660 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3661 if(!strcmp(ab->name, sym->rname)) {
3662 pic16_pBlockConvert2Absolute(pb);
3669 if(IFFUNC_ISNAKED(ftype)) {
3670 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3674 /* if critical function then turn interrupts off */
3675 if (IFFUNC_ISCRITICAL(ftype)) {
3676 //pic16_emitcode("clr","ea");
3679 _G.fregsUsed = sym->regsUsed;
3681 /* if this is an interrupt service routine then
3682 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3683 if (IFFUNC_ISISR(sym->type)) {
3684 _G.usefastretfie = 1; /* use shadow registers by default */
3686 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3687 if(!FUNC_ISSHADOWREGS(sym->type)) {
3688 /* do not save WREG,STATUS,BSR for high priority interrupts
3689 * because they are stored in the hardware shadow registers already */
3690 _G.usefastretfie = 0;
3691 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3692 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3693 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3696 /* these should really be optimized somehow, because not all
3697 * interrupt handlers modify them */
3698 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3699 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3700 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3701 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3703 // pic16_pBlockConvert2ISR(pb);
3707 /* emit code to setup stack frame if user enabled,
3708 * and function is not main() */
3710 //fprintf(stderr, "function name: %s\n", sym->name);
3711 if(strcmp(sym->name, "main")) {
3712 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3713 /* setup the stack frame */
3714 if(STACK_MODEL_LARGE)
3715 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3716 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3718 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3719 if(STACK_MODEL_LARGE)
3720 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3724 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3727 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3729 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3730 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3732 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3735 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3736 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3743 /* if callee-save to be used for this function
3744 * then save the registers being used in this function */
3745 // if (IFFUNC_CALLEESAVES(sym->type))
3749 /* if any registers used */
3750 if (sym->regsUsed) {
3751 /* save the registers used */
3752 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3753 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3754 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3755 if (bitVectBitValue(sym->regsUsed,i)) {
3756 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3759 if(!pic16_regWithIdx(i)->wasUsed) {
3760 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3761 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3762 pic16_regWithIdx(i)->wasUsed = 1;
3766 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3770 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3771 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3774 /*-----------------------------------------------------------------*/
3775 /* genEndFunction - generates epilogue for functions */
3776 /*-----------------------------------------------------------------*/
3777 static void genEndFunction (iCode *ic)
3779 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3783 if(IFFUNC_ISNAKED(sym->type)) {
3784 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3790 /* add code for ISCRITICAL */
3791 if(IFFUNC_ISCRITICAL(sym->type)) {
3792 /* if critical function, turn on interrupts */
3794 /* TODO: add code here -- VR */
3797 // sym->regsUsed = _G.fregsUsed;
3799 /* now we need to restore the registers */
3800 /* if any registers used */
3801 if (sym->regsUsed) {
3804 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3805 /* restore registers used */
3806 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3807 for ( i = sym->regsUsed->size; i >= 0; i--) {
3808 if (bitVectBitValue(sym->regsUsed,i)) {
3809 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3813 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3817 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3819 if (sym->stack == 1) {
3820 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3821 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3823 // we have to add more than one...
3824 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3825 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3826 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3828 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3829 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3830 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3834 if(strcmp(sym->name, "main")) {
3835 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3836 /* restore stack frame */
3837 if(STACK_MODEL_LARGE)
3838 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3839 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3845 if (IFFUNC_ISISR(sym->type)) {
3846 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3847 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3848 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3849 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3851 if(!FUNC_ISSHADOWREGS(sym->type)) {
3852 /* do not restore interrupt vector for WREG,STATUS,BSR
3853 * for high priority interrupt, see genFunction */
3854 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3855 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3856 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3858 // _G.interruptvector = 0; /* sanity check */
3861 /* if debug then send end of function */
3862 /* if (options.debug && currFunc) */
3864 debugFile->writeEndFunction (currFunc, ic, 1);
3867 if(_G.usefastretfie)
3868 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3870 pic16_emitpcodeNULLop(POC_RETFIE);
3872 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3874 _G.usefastretfie = 0;
3878 if (IFFUNC_ISCRITICAL(sym->type)) {
3879 pic16_emitcode("setb","ea");
3882 /* if debug then send end of function */
3884 debugFile->writeEndFunction (currFunc, ic, 1);
3887 /* insert code to restore stack frame, if user enabled it
3888 * and function is not main() */
3891 pic16_emitpcodeNULLop(POC_RETURN);
3893 /* Mark the end of a function */
3894 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3898 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3900 unsigned long lit=1;
3902 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3903 if(AOP_TYPE(op) == AOP_LIT) {
3904 if(!IS_FLOAT(operandType( op ))) {
3905 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3908 unsigned long lit_int;
3912 /* take care if literal is a float */
3913 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3920 pic16_emitpcode(POC_CLRF, dest);
3922 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3923 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3926 if(dest->type == PO_WREG && (offset == 0)) {
3927 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3930 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3934 /*-----------------------------------------------------------------*/
3935 /* genRet - generate code for return statement */
3936 /*-----------------------------------------------------------------*/
3937 static void genRet (iCode *ic)
3943 /* if we have no return value then
3944 * just generate the "ret" */
3949 /* we have something to return then
3950 * move the return value into place */
3951 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3952 size = AOP_SIZE(IC_LEFT(ic));
3956 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3957 // pic16_emitpcode(POC_MOVFF,
3958 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3961 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3962 // pic16_emitpcode(POC_MOVFF,
3963 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3966 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3967 // pic16_emitpcode(POC_MOVFF,
3968 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3971 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3973 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3974 // pic16_emitpcode(POC_MOVFF,
3975 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3978 /* >32-bits, setup stack and FSR0 */
3980 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3981 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3983 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3985 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3990 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3991 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3993 if(STACK_MODEL_LARGE) {
3994 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3997 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4002 /* old code, left here for reference -- VR */
4006 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4008 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4009 pic16_emitpcomment("push %s",l);
4012 DEBUGpic16_emitcode(";", "%d", __LINE__);
4013 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4014 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4016 if (strcmp(fReturn[offset],l)) {
4017 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4018 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4019 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4021 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4025 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4035 if (strcmp(fReturn[pushed],"a"))
4036 pic16_emitcode("pop",fReturn[pushed]);
4038 pic16_emitcode("pop","acc");
4044 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4047 /* generate a jump to the return label
4048 * if the next is not the return statement */
4049 if (!(ic->next && ic->next->op == LABEL
4050 && IC_LABEL(ic->next) == returnLabel)) {
4052 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4053 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4057 /*-----------------------------------------------------------------*/
4058 /* genLabel - generates a label */
4059 /*-----------------------------------------------------------------*/
4060 static void genLabel (iCode *ic)
4064 /* special case never generate */
4065 if (IC_LABEL(ic) == entryLabel)
4068 pic16_emitpLabel(IC_LABEL(ic)->key);
4069 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4072 /*-----------------------------------------------------------------*/
4073 /* genGoto - generates a goto */
4074 /*-----------------------------------------------------------------*/
4076 static void genGoto (iCode *ic)
4079 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4080 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4084 /*-----------------------------------------------------------------*/
4085 /* genMultbits :- multiplication of bits */
4086 /*-----------------------------------------------------------------*/
4087 static void genMultbits (operand *left,
4093 if(!pic16_sameRegs(AOP(result),AOP(right)))
4094 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4096 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4097 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4098 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4103 /*-----------------------------------------------------------------*/
4104 /* genMultOneByte : 8 bit multiplication & division */
4105 /*-----------------------------------------------------------------*/
4106 static void genMultOneByte (operand *left,
4112 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4113 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4115 /* (if two literals, the value is computed before) */
4116 /* if one literal, literal on the right */
4117 if (AOP_TYPE(left) == AOP_LIT){
4123 /* size is already checked in genMult == 1 */
4124 // size = AOP_SIZE(result);
4126 if (AOP_TYPE(right) == AOP_LIT){
4127 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4128 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4129 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4130 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4132 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4133 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4134 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4135 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4138 pic16_genMult8X8_8 (left, right,result);
4141 /*-----------------------------------------------------------------*/
4142 /* genMultOneWord : 16 bit multiplication */
4143 /*-----------------------------------------------------------------*/
4144 static void genMultOneWord (operand *left,
4149 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4150 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4152 /* (if two literals, the value is computed before)
4153 * if one literal, literal on the right */
4154 if (AOP_TYPE(left) == AOP_LIT){
4160 /* size is checked already == 2 */
4161 // size = AOP_SIZE(result);
4163 if (AOP_TYPE(right) == AOP_LIT) {
4164 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4165 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4166 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4167 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4169 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4170 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4171 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4172 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4175 pic16_genMult16X16_16(left, right,result);
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneLong : 32 bit multiplication */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneLong (operand *left,
4186 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4187 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4189 /* (if two literals, the value is computed before)
4190 * if one literal, literal on the right */
4191 if (AOP_TYPE(left) == AOP_LIT){
4197 /* size is checked already == 4 */
4198 // size = AOP_SIZE(result);
4200 if (AOP_TYPE(right) == AOP_LIT) {
4201 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4202 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4203 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4204 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4206 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4207 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212 pic16_genMult32X32_32(left, right,result);
4217 /*-----------------------------------------------------------------*/
4218 /* genMult - generates code for multiplication */
4219 /*-----------------------------------------------------------------*/
4220 static void genMult (iCode *ic)
4222 operand *left = IC_LEFT(ic);
4223 operand *right = IC_RIGHT(ic);
4224 operand *result= IC_RESULT(ic);
4227 /* assign the amsops */
4228 pic16_aopOp (left,ic,FALSE);
4229 pic16_aopOp (right,ic,FALSE);
4230 pic16_aopOp (result,ic,TRUE);
4232 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4234 /* special cases first *
4236 if (AOP_TYPE(left) == AOP_CRY
4237 && AOP_TYPE(right)== AOP_CRY) {
4238 genMultbits(left,right,result);
4242 /* if both are of size == 1 */
4243 if(AOP_SIZE(left) == 1
4244 && AOP_SIZE(right) == 1) {
4245 genMultOneByte(left,right,result);
4249 /* if both are of size == 2 */
4250 if(AOP_SIZE(left) == 2
4251 && AOP_SIZE(right) == 2) {
4252 genMultOneWord(left, right, result);
4256 /* if both are of size == 4 */
4257 if(AOP_SIZE(left) == 4
4258 && AOP_SIZE(right) == 4) {
4259 genMultOneLong(left, right, result);
4263 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4266 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4267 /* should have been converted to function call */
4271 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273 pic16_freeAsmop(result,NULL,ic,TRUE);
4276 /*-----------------------------------------------------------------*/
4277 /* genDivbits :- division of bits */
4278 /*-----------------------------------------------------------------*/
4279 static void genDivbits (operand *left,
4286 /* the result must be bit */
4287 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4288 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4292 pic16_emitcode("div","ab");
4293 pic16_emitcode("rrc","a");
4294 pic16_aopPut(AOP(result),"c",0);
4297 /*-----------------------------------------------------------------*/
4298 /* genDivOneByte : 8 bit division */
4299 /*-----------------------------------------------------------------*/
4300 static void genDivOneByte (operand *left,
4304 sym_link *opetype = operandType(result);
4309 /* result = divident / divisor
4310 * - divident may be a register or a literal,
4311 * - divisor may be a register or a literal,
4312 * so there are 3 cases (literal / literal is optimized
4313 * by the front-end) to handle.
4314 * In addition we must handle signed and unsigned, which
4315 * result in 6 final different cases -- VR */
4319 size = AOP_SIZE(result) - 1;
4321 /* signed or unsigned */
4322 if (SPEC_USIGN(opetype)) {
4323 pCodeOp *pct1, /* count */
4326 symbol *label1, *label2, *label3;;
4329 /* unsigned is easy */
4331 pct1 = pic16_popGetTempReg(1);
4332 pct2 = pic16_popGetTempReg(1);
4333 pct3 = pic16_popGetTempReg(1);
4335 label1 = newiTempLabel(NULL);
4336 label2 = newiTempLabel(NULL);
4337 label3 = newiTempLabel(NULL);
4339 /* the following algorithm is extracted from divuint.c */
4341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4342 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4344 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4346 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4348 pic16_emitpLabel(label1->key);
4351 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4355 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4359 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4361 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4362 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4364 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4365 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4366 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4368 pic16_emitpLabel( label3->key );
4369 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4370 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4374 pic16_emitpLabel(label2->key);
4375 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4376 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4377 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4379 /* result is in wreg */
4380 if(AOP_TYPE(result) != AOP_ACC)
4381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4383 pic16_popReleaseTempReg( pct3, 1);
4384 pic16_popReleaseTempReg( pct2, 1);
4385 pic16_popReleaseTempReg( pct1, 1);
4390 /* signed is a little bit more difficult */
4392 /* save the signs of the operands */
4393 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4395 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4396 pic16_emitcode("push","acc"); /* save it on the stack */
4398 /* now sign adjust for both left & right */
4399 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4401 lbl = newiTempLabel(NULL);
4402 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4403 pic16_emitcode("cpl","a");
4404 pic16_emitcode("inc","a");
4405 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4406 pic16_emitcode("mov","b,a");
4408 /* sign adjust left side */
4409 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4412 lbl = newiTempLabel(NULL);
4413 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4414 pic16_emitcode("cpl","a");
4415 pic16_emitcode("inc","a");
4416 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4418 /* now the division */
4419 pic16_emitcode("div","ab");
4420 /* we are interested in the lower order
4422 pic16_emitcode("mov","b,a");
4423 lbl = newiTempLabel(NULL);
4424 pic16_emitcode("pop","acc");
4425 /* if there was an over flow we don't
4426 adjust the sign of the result */
4427 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4428 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4430 pic16_emitcode("clr","a");
4431 pic16_emitcode("subb","a,b");
4432 pic16_emitcode("mov","b,a");
4433 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4435 /* now we are done */
4436 pic16_aopPut(AOP(result),"b",0);
4438 pic16_emitcode("mov","c,b.7");
4439 pic16_emitcode("subb","a,acc");
4442 pic16_aopPut(AOP(result),"a",offset++);
4446 /*-----------------------------------------------------------------*/
4447 /* genDiv - generates code for division */
4448 /*-----------------------------------------------------------------*/
4449 static void genDiv (iCode *ic)
4451 operand *left = IC_LEFT(ic);
4452 operand *right = IC_RIGHT(ic);
4453 operand *result= IC_RESULT(ic);
4456 /* Division is a very lengthy algorithm, so it is better
4457 * to call support routines than inlining algorithm.
4458 * Division functions written here just in case someone
4459 * wants to inline and not use the support libraries -- VR */
4463 /* assign the amsops */
4464 pic16_aopOp (left,ic,FALSE);
4465 pic16_aopOp (right,ic,FALSE);
4466 pic16_aopOp (result,ic,TRUE);
4468 /* special cases first */
4470 if (AOP_TYPE(left) == AOP_CRY &&
4471 AOP_TYPE(right)== AOP_CRY) {
4472 genDivbits(left,right,result);
4476 /* if both are of size == 1 */
4477 if (AOP_SIZE(left) == 1 &&
4478 AOP_SIZE(right) == 1 ) {
4479 genDivOneByte(left,right,result);
4483 /* should have been converted to function call */
4486 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488 pic16_freeAsmop(result,NULL,ic,TRUE);
4491 /*-----------------------------------------------------------------*/
4492 /* genModbits :- modulus of bits */
4493 /*-----------------------------------------------------------------*/
4494 static void genModbits (operand *left,
4502 werror(W_POSSBUG2, __FILE__, __LINE__);
4503 /* the result must be bit */
4504 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4505 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4509 pic16_emitcode("div","ab");
4510 pic16_emitcode("mov","a,b");
4511 pic16_emitcode("rrc","a");
4512 pic16_aopPut(AOP(result),"c",0);
4515 /*-----------------------------------------------------------------*/
4516 /* genModOneByte : 8 bit modulus */
4517 /*-----------------------------------------------------------------*/
4518 static void genModOneByte (operand *left,
4522 sym_link *opetype = operandType(result);
4527 werror(W_POSSBUG2, __FILE__, __LINE__);
4529 /* signed or unsigned */
4530 if (SPEC_USIGN(opetype)) {
4531 /* unsigned is easy */
4532 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4533 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4535 pic16_emitcode("div","ab");
4536 pic16_aopPut(AOP(result),"b",0);
4540 /* signed is a little bit more difficult */
4542 /* save the signs of the operands */
4543 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4546 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4547 pic16_emitcode("push","acc"); /* save it on the stack */
4549 /* now sign adjust for both left & right */
4550 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4553 lbl = newiTempLabel(NULL);
4554 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4555 pic16_emitcode("cpl","a");
4556 pic16_emitcode("inc","a");
4557 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4558 pic16_emitcode("mov","b,a");
4560 /* sign adjust left side */
4561 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4564 lbl = newiTempLabel(NULL);
4565 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4566 pic16_emitcode("cpl","a");
4567 pic16_emitcode("inc","a");
4568 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4570 /* now the multiplication */
4571 pic16_emitcode("div","ab");
4572 /* we are interested in the lower order
4574 lbl = newiTempLabel(NULL);
4575 pic16_emitcode("pop","acc");
4576 /* if there was an over flow we don't
4577 adjust the sign of the result */
4578 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4579 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4581 pic16_emitcode("clr","a");
4582 pic16_emitcode("subb","a,b");
4583 pic16_emitcode("mov","b,a");
4584 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4586 /* now we are done */
4587 pic16_aopPut(AOP(result),"b",0);
4591 /*-----------------------------------------------------------------*/
4592 /* genMod - generates code for division */
4593 /*-----------------------------------------------------------------*/
4594 static void genMod (iCode *ic)
4596 operand *left = IC_LEFT(ic);
4597 operand *right = IC_RIGHT(ic);
4598 operand *result= IC_RESULT(ic);
4602 /* assign the amsops */
4603 pic16_aopOp (left,ic,FALSE);
4604 pic16_aopOp (right,ic,FALSE);
4605 pic16_aopOp (result,ic,TRUE);
4607 /* special cases first */
4609 if (AOP_TYPE(left) == AOP_CRY &&
4610 AOP_TYPE(right)== AOP_CRY) {
4611 genModbits(left,right,result);
4615 /* if both are of size == 1 */
4616 if (AOP_SIZE(left) == 1 &&
4617 AOP_SIZE(right) == 1 ) {
4618 genModOneByte(left,right,result);
4622 /* should have been converted to function call */
4626 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4627 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628 pic16_freeAsmop(result,NULL,ic,TRUE);
4631 /*-----------------------------------------------------------------*/
4632 /* genIfxJump :- will create a jump depending on the ifx */
4633 /*-----------------------------------------------------------------*/
4635 note: May need to add parameter to indicate when a variable is in bit space.
4637 static void genIfxJump (iCode *ic, char *jval)
4641 /* if true label then we jump if condition
4643 if ( IC_TRUE(ic) ) {
4645 if(strcmp(jval,"a") == 0)
4647 else if (strcmp(jval,"c") == 0)
4650 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4651 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4654 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4655 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4659 /* false label is present */
4660 if(strcmp(jval,"a") == 0)
4662 else if (strcmp(jval,"c") == 0)
4665 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4666 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4669 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4670 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4675 /* mark the icode as generated */
4679 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4683 /* if true label then we jump if condition
4685 if ( IC_TRUE(ic) ) {
4686 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4687 pic16_emitpcode(POC_BTFSC, jop);
4689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4690 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4693 /* false label is present */
4694 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4695 pic16_emitpcode(POC_BTFSS, jop);
4697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4698 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4702 /* mark the icode as generated */
4709 /*-----------------------------------------------------------------*/
4711 /*-----------------------------------------------------------------*/
4712 static void genSkip(iCode *ifx,int status_bit)
4714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4718 if ( IC_TRUE(ifx) ) {
4719 switch(status_bit) {
4734 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4735 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4739 switch(status_bit) {
4753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4754 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4761 /*-----------------------------------------------------------------*/
4763 /*-----------------------------------------------------------------*/
4764 static void genSkipc(resolvedIfx *rifx)
4766 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4776 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4777 rifx->generated = 1;
4780 #if !(USE_SIMPLE_GENCMP)
4781 /*-----------------------------------------------------------------*/
4783 /*-----------------------------------------------------------------*/
4784 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4786 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4791 if( (rifx->condition ^ invert_condition) & 1)
4796 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4797 rifx->generated = 1;
4802 /*-----------------------------------------------------------------*/
4804 /*-----------------------------------------------------------------*/
4805 static void genSkipz(iCode *ifx, int condition)
4816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4818 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4821 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4823 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4828 #if !(USE_SIMPLE_GENCMP)
4829 /*-----------------------------------------------------------------*/
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4838 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4840 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4843 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4844 rifx->generated = 1;
4849 /*-----------------------------------------------------------------*/
4850 /* genChkZeroes :- greater or less than comparison */
4851 /* For each byte in a literal that is zero, inclusive or the */
4852 /* the corresponding byte in the operand with W */
4853 /* returns true if any of the bytes are zero */
4854 /*-----------------------------------------------------------------*/
4855 static int genChkZeroes(operand *op, int lit, int size)
4862 i = (lit >> (size*8)) & 0xff;
4866 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4868 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4877 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4878 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4880 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4881 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4883 /*-----------------------------------------------------------------*/
4884 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4885 /* aop (if it's NOT a literal) or from lit (if */
4886 /* aop is a literal) */
4887 /*-----------------------------------------------------------------*/
4888 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4889 if (aop->type == AOP_LIT) {
4890 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4892 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4896 /*-----------------------------------------------------------------*/
4897 /* genCmp :- greater or less than comparison */
4898 /*-----------------------------------------------------------------*/
4900 #if USE_SIMPLE_GENCMP
4902 /* genCmp performs a left < right comparison, stores
4903 * the outcome in result (if != NULL) and generates
4904 * control flow code for the ifx (if != NULL).
4906 * This version leaves in sequences like
4907 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4908 * which should be optmized by the peephole
4909 * optimizer - RN 2005-01-01 */
4910 static void genCmp (operand *left,operand *right,
4911 operand *result, iCode *ifx, int sign)
4924 assert (AOP_SIZE(left) == AOP_SIZE(right));
4925 assert (left && right);
4927 size = AOP_SIZE(right) - 1;
4928 mask = (0x100UL << (size*8)) - 1;
4929 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4934 resolveIfx (&rIfx, ifx);
4936 /**********************************************************************
4937 * handle bits - bit compares are promoted to int compares seemingly! *
4938 **********************************************************************/
4940 // THIS IS COMPLETELY UNTESTED!
4941 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4942 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4943 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4944 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4947 // 1 < {0,1} is false --> clear C by skipping the next instruction
4948 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4949 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4950 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4951 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4952 emitCLRC; // only skipped for left=0 && right=1
4954 goto correct_result_in_carry;
4958 /*************************************************
4959 * make sure that left is register (or the like) *
4960 *************************************************/
4961 if (!isAOP_REGlike(left)) {
4962 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4963 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4965 assert (isAOP_LIT(left));
4966 assert (isAOP_REGlike(right));
4967 // swap left and right
4968 // left < right <==> right > left <==> (right >= left + 1)
4969 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4971 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4972 // MAXVALUE < right? always false
4973 if (performedLt) emitCLRC; else emitSETC;
4974 goto correct_result_in_carry;
4977 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4978 // that's we handled it above.
4985 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4986 } else if (isAOP_LIT(right)) {
4987 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4990 assert (isAOP_REGlike(left)); // left must be register or the like
4991 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4993 /*************************************************
4994 * special cases go here *
4995 *************************************************/
4997 if (isAOP_LIT(right)) {
4999 // unsigned comparison to a literal
5000 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5001 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5004 // unsigned left < 0? always false
5005 if (performedLt) emitCLRC; else emitSETC;
5006 goto correct_result_in_carry;
5009 // signed comparison to a literal
5010 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5011 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5013 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5014 // signed left < 0x80000000? always false
5015 if (performedLt) emitCLRC; else emitSETC;
5016 goto correct_result_in_carry;
5017 } else if (lit == 0) {
5018 // compare left < 0; set CARRY if SIGNBIT(left) is set
5019 if (performedLt) emitSETC; else emitCLRC;
5020 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5021 if (performedLt) emitCLRC; else emitSETC;
5022 goto correct_result_in_carry;
5025 } // right is literal
5027 /*************************************************
5028 * perform a general case comparison *
5029 * make sure we get CARRY==1 <==> left >= right *
5030 *************************************************/
5031 // compare most significant bytes
5032 //DEBUGpc ("comparing bytes at offset %d", size);
5034 // unsigned comparison
5035 mov2w_regOrLit (AOP(right), lit, size);
5036 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5038 // signed comparison
5039 // (add 2^n to both operands then perform an unsigned comparison)
5040 if (isAOP_LIT(right)) {
5041 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5042 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5044 if (litbyte == 0x80) {
5045 // left >= 0x80 -- always true, but more bytes to come
5046 pic16_mov2w (AOP(left), size);
5047 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5050 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5051 pic16_mov2w (AOP(left), size);
5052 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5053 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5056 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5057 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5058 pic16_mov2w (AOP(left), size);
5059 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5060 pic16_emitpcode (POC_MOVWF, pctemp);
5061 pic16_mov2w (AOP(right), size);
5062 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5063 pic16_emitpcode (POC_SUBFW, pctemp);
5064 //pic16_popReleaseTempReg(pctemp, 1);
5068 // compare remaining bytes (treat as unsigned case from above)
5069 templbl = newiTempLabel ( NULL );
5072 //DEBUGpc ("comparing bytes at offset %d", offs);
5073 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5074 mov2w_regOrLit (AOP(right), lit, offs);
5075 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5077 pic16_emitpLabel (templbl->key);
5078 goto result_in_carry;
5082 /****************************************************
5083 * now CARRY contains the result of the comparison: *
5084 * SUBWF sets CARRY iff *
5085 * F-W >= 0 <==> F >= W <==> !(F < W) *
5087 ****************************************************/
5090 if (result && AOP_TYPE(result) != AOP_CRY) {
5091 // value will be stored
5094 // value wil only be used in the following genSkipc()
5095 rIfx.condition ^= 1;
5099 correct_result_in_carry:
5101 // assign result to variable (if neccessary)
5102 if (result && AOP_TYPE(result) != AOP_CRY) {
5103 //DEBUGpc ("assign result");
5104 size = AOP_SIZE(result);
5106 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5108 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5111 // perform conditional jump
5112 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5114 //DEBUGpc ("generate control flow");
5115 rIfx.condition ^= 1;
5124 static void genCmp (operand *left,operand *right,
5125 operand *result, iCode *ifx, int sign)
5127 int size; //, offset = 0 ;
5128 unsigned long lit = 0L,i = 0;
5129 resolvedIfx rFalseIfx;
5130 // resolvedIfx rTrueIfx;
5132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5135 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5136 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5142 resolveIfx(&rFalseIfx,ifx);
5143 truelbl = newiTempLabel(NULL);
5144 size = max(AOP_SIZE(left),AOP_SIZE(right));
5146 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5150 /* if literal is on the right then swap with left */
5151 if ((AOP_TYPE(right) == AOP_LIT)) {
5152 operand *tmp = right ;
5153 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5154 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5157 lit = (lit - 1) & mask;
5160 rFalseIfx.condition ^= 1;
5163 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5164 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5168 //if(IC_TRUE(ifx) == NULL)
5169 /* if left & right are bit variables */
5170 if (AOP_TYPE(left) == AOP_CRY &&
5171 AOP_TYPE(right) == AOP_CRY ) {
5172 assert (0 && "bit variables used in genCmp");
5173 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5174 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5176 /* subtract right from left if at the
5177 end the carry flag is set then we know that
5178 left is greater than right */
5180 symbol *lbl = newiTempLabel(NULL);
5183 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5184 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5188 if(AOP_TYPE(right) == AOP_LIT) {
5190 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5192 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5199 genSkipCond(&rFalseIfx,left,size-1,7);
5201 /* no need to compare to 0...*/
5202 /* NOTE: this is a de-generate compare that most certainly
5203 * creates some dead code. */
5204 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5206 if(ifx) ifx->generated = 1;
5213 //i = (lit >> (size*8)) & 0xff;
5214 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5216 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5218 i = ((0-lit) & 0xff);
5221 /* lit is 0x7f, all signed chars are less than
5222 * this except for 0x7f itself */
5223 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5224 genSkipz2(&rFalseIfx,0);
5226 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5228 genSkipc(&rFalseIfx);
5233 genSkipz2(&rFalseIfx,1);
5235 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5236 genSkipc(&rFalseIfx);
5240 if(ifx) ifx->generated = 1;
5244 /* chars are out of the way. now do ints and longs */
5247 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5254 genSkipCond(&rFalseIfx,left,size,7);
5255 if(ifx) ifx->generated = 1;
5260 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5262 //rFalseIfx.condition ^= 1;
5263 //genSkipCond(&rFalseIfx,left,size,7);
5264 //rFalseIfx.condition ^= 1;
5266 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5267 if(rFalseIfx.condition)
5268 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5270 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5272 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5273 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5274 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5277 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5279 if(rFalseIfx.condition) {
5281 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5287 genSkipc(&rFalseIfx);
5288 pic16_emitpLabel(truelbl->key);
5289 if(ifx) ifx->generated = 1;
5296 if( (lit & 0xff) == 0) {
5297 /* lower byte is zero */
5298 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5299 i = ((lit >> 8) & 0xff) ^0x80;
5300 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5301 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5302 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5303 genSkipc(&rFalseIfx);
5306 if(ifx) ifx->generated = 1;
5311 /* Special cases for signed longs */
5312 if( (lit & 0xffffff) == 0) {
5313 /* lower byte is zero */
5314 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5315 i = ((lit >> 8*3) & 0xff) ^0x80;
5316 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5317 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5318 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5319 genSkipc(&rFalseIfx);
5322 if(ifx) ifx->generated = 1;
5330 if(lit & (0x80 << (size*8))) {
5331 /* lit is negative */
5332 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334 //genSkipCond(&rFalseIfx,left,size,7);
5336 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5338 if(rFalseIfx.condition)
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5341 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5345 /* lit is positive */
5346 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5347 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5348 if(rFalseIfx.condition)
5349 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5351 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5356 This works, but is only good for ints.
5357 It also requires a "known zero" register.
5358 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5359 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5360 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5361 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5362 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5363 genSkipc(&rFalseIfx);
5365 pic16_emitpLabel(truelbl->key);
5366 if(ifx) ifx->generated = 1;
5370 /* There are no more special cases, so perform a general compare */
5372 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5373 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5377 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5379 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5381 //rFalseIfx.condition ^= 1;
5382 genSkipc(&rFalseIfx);
5384 pic16_emitpLabel(truelbl->key);
5386 if(ifx) ifx->generated = 1;
5393 /* sign is out of the way. So now do an unsigned compare */
5394 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5397 /* General case - compare to an unsigned literal on the right.*/
5399 i = (lit >> (size*8)) & 0xff;
5400 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5401 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5403 i = (lit >> (size*8)) & 0xff;
5406 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5408 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5410 /* this byte of the lit is zero,
5411 *if it's not the last then OR in the variable */
5413 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5418 pic16_emitpLabel(lbl->key);
5419 // pic16_emitpLabel(truelbl->key);
5420 //if(emitFinalCheck)
5421 genSkipc(&rFalseIfx);
5423 pic16_emitpLabel(truelbl->key);
5425 if(ifx) ifx->generated = 1;
5432 if(AOP_TYPE(left) == AOP_LIT) {
5433 //symbol *lbl = newiTempLabel(NULL);
5435 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5438 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5441 if((lit == 0) && (sign == 0)){
5444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5446 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5448 genSkipz2(&rFalseIfx,0);
5449 if(ifx) ifx->generated = 1;
5456 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5457 /* degenerate compare can never be true */
5458 if(rFalseIfx.condition == 0)
5459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5461 if(ifx) ifx->generated = 1;
5466 /* signed comparisons to a literal byte */
5468 int lp1 = (lit+1) & 0xff;
5470 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5473 rFalseIfx.condition ^= 1;
5474 genSkipCond(&rFalseIfx,right,0,7);
5477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5478 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5479 genSkipz2(&rFalseIfx,1);
5482 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5483 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5484 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5485 rFalseIfx.condition ^= 1;
5486 genSkipc(&rFalseIfx);
5490 /* unsigned comparisons to a literal byte */
5492 switch(lit & 0xff ) {
5494 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5495 genSkipz2(&rFalseIfx,0);
5498 rFalseIfx.condition ^= 1;
5499 genSkipCond(&rFalseIfx,right,0,7);
5503 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5504 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5506 rFalseIfx.condition ^= 1;
5507 if (AOP_TYPE(result) == AOP_CRY)
5508 genSkipc(&rFalseIfx);
5510 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5511 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5517 if(ifx) ifx->generated = 1;
5518 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5524 /* Size is greater than 1 */
5532 /* this means lit = 0xffffffff, or -1 */
5535 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5536 rFalseIfx.condition ^= 1;
5537 genSkipCond(&rFalseIfx,right,size,7);
5538 if(ifx) ifx->generated = 1;
5540 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5549 if(rFalseIfx.condition) {
5550 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5551 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5556 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5560 if(rFalseIfx.condition) {
5561 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5562 pic16_emitpLabel(truelbl->key);
5564 rFalseIfx.condition ^= 1;
5565 genSkipCond(&rFalseIfx,right,s,7);
5568 if(ifx) ifx->generated = 1;
5570 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5576 if((size == 1) && (0 == (lp1&0xff))) {
5577 /* lower byte of signed word is zero */
5578 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5579 i = ((lp1 >> 8) & 0xff) ^0x80;
5580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5581 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5582 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5584 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5586 if(ifx) ifx->generated = 1;
5589 rFalseIfx.condition ^= 1;
5590 genSkipc(&rFalseIfx);
5591 if(ifx) ifx->generated = 1;
5597 if(lit & (0x80 << (size*8))) {
5598 /* Lit is less than zero */
5599 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5600 //rFalseIfx.condition ^= 1;
5601 //genSkipCond(&rFalseIfx,left,size,7);
5602 //rFalseIfx.condition ^= 1;
5603 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5604 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5606 if(rFalseIfx.condition)
5607 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5609 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5613 /* Lit is greater than or equal to zero */
5614 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5615 //rFalseIfx.condition ^= 1;
5616 //genSkipCond(&rFalseIfx,right,size,7);
5617 //rFalseIfx.condition ^= 1;
5619 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5620 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5622 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5623 if(rFalseIfx.condition)
5624 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5626 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5630 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5631 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5635 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5637 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5639 rFalseIfx.condition ^= 1;
5640 //rFalseIfx.condition = 1;
5641 genSkipc(&rFalseIfx);
5643 pic16_emitpLabel(truelbl->key);
5645 if(ifx) ifx->generated = 1;
5648 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5655 /* compare word or long to an unsigned literal on the right.*/
5660 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5663 break; /* handled above */
5666 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5668 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5669 genSkipz2(&rFalseIfx,0);
5673 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5675 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5678 if(rFalseIfx.condition)
5679 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5681 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5684 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5685 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5687 rFalseIfx.condition ^= 1;
5688 genSkipc(&rFalseIfx);
5691 pic16_emitpLabel(truelbl->key);
5693 if(ifx) ifx->generated = 1;
5695 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5703 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5704 i = (lit >> (size*8)) & 0xff;
5706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5707 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5710 i = (lit >> (size*8)) & 0xff;
5713 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5715 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5717 /* this byte of the lit is zero,
5718 * if it's not the last then OR in the variable */
5720 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5725 pic16_emitpLabel(lbl->key);
5727 rFalseIfx.condition ^= 1;
5729 genSkipc(&rFalseIfx);
5733 pic16_emitpLabel(truelbl->key);
5734 if(ifx) ifx->generated = 1;
5736 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5742 /* Compare two variables */
5744 DEBUGpic16_emitcode(";sign","%d",sign);
5748 /* Sigh. thus sucks... */
5752 pctemp = pic16_popGetTempReg(1);
5753 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5754 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5755 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5756 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5757 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5758 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759 pic16_popReleaseTempReg(pctemp, 1);
5761 /* Signed char comparison */
5762 /* Special thanks to Nikolai Golovchenko for this snippet */
5763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5764 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5765 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5766 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5767 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5768 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5771 genSkipc(&rFalseIfx);
5773 if(ifx) ifx->generated = 1;
5775 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5783 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5784 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5788 /* The rest of the bytes of a multi-byte compare */
5792 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5795 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5796 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5801 pic16_emitpLabel(lbl->key);
5803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5804 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5805 (AOP_TYPE(result) == AOP_REG)) {
5806 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5807 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5809 genSkipc(&rFalseIfx);
5811 //genSkipc(&rFalseIfx);
5812 if(ifx) ifx->generated = 1;
5815 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5823 if ((AOP_TYPE(result) != AOP_CRY)
5824 && AOP_SIZE(result)) {
5825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5827 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5829 pic16_outBitC(result);
5831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5832 /* if the result is used in the next
5833 ifx conditional branch then generate
5834 code a little differently */
5836 genIfxJump (ifx,"c");
5838 pic16_outBitC(result);
5839 /* leave the result in acc */
5844 #else /* old version of genCmp() */ /* } else { */
5846 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5847 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5848 operand *result, int offset, int invert_op)
5852 /* check condition, > or < ?? */
5853 if(rIfx->condition != 0)invert_op ^= 1;
5855 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5857 if(!ifx)invert_op ^= 1;
5859 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5860 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5863 if(!invert_op)return POC_CPFSGT;
5864 else return POC_CPFSLT;
5867 static int compareAopfirstpass=1;
5869 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5870 operand *oper, int offset, operand *result,
5871 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5877 /* invert if there is a result to be loaded, in order to fit,
5878 * SETC/CLRC sequence */
5879 if(AOP_SIZE(result))invert_op ^= 1;
5881 // if(sign && !offset)invert_op ^= 1;
5883 // if(sign)invert_op ^= 1;
5885 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5887 if(AOP_SIZE(result) && compareAopfirstpass) {
5890 pic16_emitpcode(POC_SETF, pcop2);
5895 pic16_emitpcode(POC_CLRF, pcop2);
5901 compareAopfirstpass = 0;
5903 /* there is a bug when comparing operands with size > 1,
5904 * because higher bytes can be equal and test should be performed
5905 * to the next lower byte, current algorithm, considers operands
5906 * inequal in these cases! -- VR 20041107 */
5910 pic16_emitpcode(op, pcop);
5912 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5915 if((!sign || !offset) && AOP_SIZE(result)) {
5918 pic16_emitpcode(POC_CLRF, pcop2);
5923 pic16_emitpcode(POC_SETF, pcop2);
5928 /* don't emit final branch (offset == 0) */
5932 pic16_emitpcode(POC_RRCF, pcop2);
5934 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5937 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5938 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5939 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5941 truelbl = newiTempLabel( NULL );
5942 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5943 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5946 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5947 pic16_emitpLabel(truelbl->key);
5949 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5958 static void genCmp (operand *left, operand *right,
5959 operand *result, iCode *ifx, int sign)
5963 resolvedIfx rFalseIfx;
5964 symbol *falselbl, *tlbl;
5968 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5970 resolveIfx(&rFalseIfx, ifx);
5971 size = max(AOP_SIZE(left), AOP_SIZE(right));
5973 /* if left & right are bit variables */
5974 if(AOP_TYPE(left) == AOP_CRY
5975 && AOP_TYPE(right) == AOP_CRY ) {
5977 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5978 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5980 werror(W_POSSBUG2, __FILE__, __LINE__);
5984 /* if literal is on the right then swap with left */
5985 if((AOP_TYPE(right) == AOP_LIT)) {
5986 operand *tmp = right ;
5987 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5989 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5991 // lit = (lit - 1) & mask;
5994 rFalseIfx.condition ^= 1; /* reverse compare */
5996 if ((AOP_TYPE(left) == AOP_LIT)) {
5997 /* float compares are handled by support functions */
5998 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6001 /* actual comparing algorithm */
6002 // size = AOP_SIZE( right );
6004 falselbl = newiTempLabel( NULL );
6005 if(AOP_TYPE(left) == AOP_LIT) {
6006 /* compare to literal */
6007 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6010 pCodeOp *pct, *pct2;
6013 /* signed compare */
6014 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6016 pct = pic16_popCopyReg(&pic16_pc_prodl);
6017 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6018 tlbl = newiTempLabel( NULL );
6020 /* first compare signs:
6021 * a. if both are positive, compare just like unsigned
6022 * b. if both are negative, invert cmpop, compare just like unsigned
6023 * c. if different signs, determine the result directly */
6029 tlbl1 = newiTempLabel( NULL );
6030 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6034 /* literal is zero or positive:
6035 * a. if carry is zero, too, continue compare,
6036 * b. if carry is set, then continue depending on cmpop ^ condition:
6037 * 1. '<' return false (literal < variable),
6038 * 2. '>' return true (literal > variable) */
6039 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6040 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6043 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6044 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6048 /* literal is negative:
6049 * a. if carry is set, too, continue compare,
6050 * b. if carry is zero, then continue depending on cmpop ^ condition:
6051 * 1. '<' return true (literal < variable),
6052 * 2. '>' return false (literal > variable) */
6053 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6054 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6056 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6057 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6062 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6064 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6065 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6070 pic16_emitpLabel( tlbl1->key );
6073 compareAopfirstpass=1;
6074 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6075 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6076 // pic16_emitpcode(POC_MOVWF, pct);
6078 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6079 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6080 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6081 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6085 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6086 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6087 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6088 // pic16_emitpcode(POC_MOVWF, pct);
6090 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6091 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6092 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6093 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6094 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6098 if(ifx)ifx->generated = 1;
6100 if(AOP_SIZE(result)) {
6101 pic16_emitpLabel(tlbl->key);
6102 pic16_emitpLabel(falselbl->key);
6103 pic16_outBitOp( result, pct2 );
6105 pic16_emitpLabel(tlbl->key);
6110 /* unsigned compare */
6111 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6113 compareAopfirstpass=1;
6116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6117 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6121 if(ifx)ifx->generated = 1;
6124 if(AOP_SIZE(result)) {
6125 pic16_emitpLabel(falselbl->key);
6126 pic16_outBitC( result );
6131 /* compare registers */
6132 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6136 pCodeOp *pct, *pct2;
6138 /* signed compare */
6139 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6141 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6142 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6143 tlbl = newiTempLabel( NULL );
6145 compareAopfirstpass=1;
6148 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6149 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6150 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6151 pic16_emitpcode(POC_MOVWF, pct);
6153 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6154 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6155 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6157 /* WREG already holds left + 0x80 */
6158 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6161 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6162 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6163 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6164 pic16_emitpcode(POC_MOVWF, pct);
6166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6167 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6168 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6170 /* WREG already holds left + 0x80 */
6171 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6172 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6175 if(ifx)ifx->generated = 1;
6177 if(AOP_SIZE(result)) {
6178 pic16_emitpLabel(tlbl->key);
6179 pic16_emitpLabel(falselbl->key);
6180 pic16_outBitOp( result, pct2 );
6182 pic16_emitpLabel(tlbl->key);
6186 /* unsigned compare */
6187 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6189 compareAopfirstpass=1;
6192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6193 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6197 if(ifx)ifx->generated = 1;
6198 if(AOP_SIZE(result)) {
6200 pic16_emitpLabel(falselbl->key);
6201 pic16_outBitC( result );
6208 #else /* } else { */
6210 /* new version of genCmp -- VR 20041012 */
6211 static void genCmp (operand *left,operand *right,
6212 operand *result, iCode *ifx, int sign)
6214 int size; //, offset = 0 ;
6215 unsigned long lit = 0L,i = 0;
6216 resolvedIfx rFalseIfx;
6217 int willCheckCarry=0;
6218 // resolvedIfx rTrueIfx;
6224 * subtract right from left if at the end the carry flag is set then we
6225 * know that left is greater than right */
6227 resolveIfx(&rFalseIfx,ifx);
6228 truelbl = newiTempLabel(NULL);
6229 size = max(AOP_SIZE(left),AOP_SIZE(right));
6231 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6233 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6234 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6237 /* if literal is on the right then swap with left */
6238 if ((AOP_TYPE(right) == AOP_LIT)) {
6239 operand *tmp = right ;
6240 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6242 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6244 // lit = (lit - 1) & mask;
6247 rFalseIfx.condition ^= 1; /* reverse compare */
6249 if ((AOP_TYPE(left) == AOP_LIT)) {
6250 /* float compares are handled by support functions */
6251 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6255 //if(IC_TRUE(ifx) == NULL)
6256 /* if left & right are bit variables */
6257 if (AOP_TYPE(left) == AOP_CRY &&
6258 AOP_TYPE(right) == AOP_CRY ) {
6260 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6261 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6264 symbol *lbl = newiTempLabel(NULL);
6266 if(AOP_TYPE(left) == AOP_LIT) {
6267 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6269 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6271 else willCheckCarry = 0;
6274 if((lit == 0) && (sign == 0)) {
6275 /* unsigned compare to 0 */
6276 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6279 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6281 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6283 genSkipz2(&rFalseIfx,0);
6284 if(ifx)ifx->generated = 1;
6291 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6292 /* degenerate compare can never be true */
6293 if(rFalseIfx.condition == 0)
6294 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6296 if(ifx) ifx->generated = 1;
6301 /* signed comparisons to a literal byte */
6302 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6304 int lp1 = (lit+1) & 0xff;
6306 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6309 rFalseIfx.condition ^= 1;
6310 genSkipCond(&rFalseIfx,right,0,7);
6313 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6314 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6315 genSkipz2(&rFalseIfx,1);
6318 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6320 if(rFalseIfx.condition)
6321 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6323 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6325 if(willCheckCarry) {
6326 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6327 else { emitSETC; emitCLRC; }
6330 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6333 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6334 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6336 rFalseIfx.condition ^= 1;
6337 genSkipc(&rFalseIfx);
6342 /* unsigned comparisons to a literal byte */
6343 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6345 switch(lit & 0xff ) {
6348 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6349 genSkipz2(&rFalseIfx,0);
6352 rFalseIfx.condition ^= 1;
6353 genSkipCond(&rFalseIfx,right,0,7);
6356 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6357 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6358 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6359 rFalseIfx.condition ^= 1;
6360 if (AOP_TYPE(result) == AOP_CRY)
6361 genSkipc(&rFalseIfx);
6363 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6364 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6370 if(ifx) ifx->generated = 1;
6371 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6377 /* Size is greater than 1 */
6385 /* this means lit = 0xffffffff, or -1 */
6388 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6389 rFalseIfx.condition ^= 1;
6390 genSkipCond(&rFalseIfx,right,size,7);
6391 if(ifx) ifx->generated = 1;
6398 if(rFalseIfx.condition) {
6399 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6400 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6403 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6405 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6409 if(rFalseIfx.condition) {
6410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6411 pic16_emitpLabel(truelbl->key);
6413 rFalseIfx.condition ^= 1;
6414 genSkipCond(&rFalseIfx,right,s,7);
6417 if(ifx) ifx->generated = 1;
6421 if((size == 1) && (0 == (lp1&0xff))) {
6422 /* lower byte of signed word is zero */
6423 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6424 i = ((lp1 >> 8) & 0xff) ^0x80;
6425 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6426 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6427 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6428 rFalseIfx.condition ^= 1;
6429 genSkipc(&rFalseIfx);
6432 if(ifx) ifx->generated = 1;
6436 if(lit & (0x80 << (size*8))) {
6437 /* Lit is less than zero */
6438 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6439 //rFalseIfx.condition ^= 1;
6440 //genSkipCond(&rFalseIfx,left,size,7);
6441 //rFalseIfx.condition ^= 1;
6442 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6443 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6445 if(rFalseIfx.condition)
6446 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6448 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6452 /* Lit is greater than or equal to zero */
6453 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6454 //rFalseIfx.condition ^= 1;
6455 //genSkipCond(&rFalseIfx,right,size,7);
6456 //rFalseIfx.condition ^= 1;
6458 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6459 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6461 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6462 if(rFalseIfx.condition)
6463 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6465 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6470 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6471 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6479 rFalseIfx.condition ^= 1;
6480 //rFalseIfx.condition = 1;
6481 genSkipc(&rFalseIfx);
6483 pic16_emitpLabel(truelbl->key);
6485 if(ifx) ifx->generated = 1;
6490 /* compare word or long to an unsigned literal on the right.*/
6495 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6498 break; /* handled above */
6501 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6503 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6504 genSkipz2(&rFalseIfx,0);
6508 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6510 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6513 if(rFalseIfx.condition)
6514 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6516 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6519 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6520 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6522 rFalseIfx.condition ^= 1;
6523 genSkipc(&rFalseIfx);
6526 pic16_emitpLabel(truelbl->key);
6528 if(ifx) ifx->generated = 1;
6534 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6535 i = (lit >> (size*8)) & 0xff;
6537 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6538 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6541 i = (lit >> (size*8)) & 0xff;
6544 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6546 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6548 /* this byte of the lit is zero,
6549 * if it's not the last then OR in the variable */
6551 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6556 pic16_emitpLabel(lbl->key);
6558 rFalseIfx.condition ^= 1;
6560 genSkipc(&rFalseIfx);
6564 pic16_emitpLabel(truelbl->key);
6565 if(ifx) ifx->generated = 1;
6569 /* Compare two variables */
6571 DEBUGpic16_emitcode(";sign","%d",sign);
6575 /* Sigh. thus sucks... */
6579 pctemp = pic16_popGetTempReg(1);
6580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6581 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6583 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6584 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6585 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586 pic16_popReleaseTempReg(pctemp, 1);
6588 /* Signed char comparison */
6589 /* Special thanks to Nikolai Golovchenko for this snippet */
6590 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6591 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6592 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6593 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6594 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6598 genSkipc(&rFalseIfx);
6600 if(ifx) ifx->generated = 1;
6606 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6607 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6611 /* The rest of the bytes of a multi-byte compare */
6615 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6618 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6619 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6624 pic16_emitpLabel(lbl->key);
6626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6627 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6628 (AOP_TYPE(result) == AOP_REG)) {
6629 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6630 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6632 genSkipc(&rFalseIfx);
6634 //genSkipc(&rFalseIfx);
6635 if(ifx) ifx->generated = 1;
6642 if ((AOP_TYPE(result) != AOP_CRY)
6643 && AOP_SIZE(result)) {
6644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6646 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6648 pic16_outBitC(result);
6650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6651 /* if the result is used in the next
6652 ifx conditional branch then generate
6653 code a little differently */
6655 genIfxJump (ifx,"c");
6657 pic16_outBitC(result);
6658 /* leave the result in acc */
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpGt :- greater than comparison */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpGt (iCode *ic, iCode *ifx)
6674 operand *left, *right, *result;
6675 sym_link *letype , *retype;
6681 right= IC_RIGHT(ic);
6682 result = IC_RESULT(ic);
6684 letype = getSpec(operandType(left));
6685 retype =getSpec(operandType(right));
6686 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6687 /* assign the amsops */
6688 pic16_aopOp (left,ic,FALSE);
6689 pic16_aopOp (right,ic,FALSE);
6690 pic16_aopOp (result,ic,TRUE);
6692 genCmp(right, left, result, ifx, sign);
6694 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6695 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6696 pic16_freeAsmop(result,NULL,ic,TRUE);
6699 /*-----------------------------------------------------------------*/
6700 /* genCmpLt - less than comparisons */
6701 /*-----------------------------------------------------------------*/
6702 static void genCmpLt (iCode *ic, iCode *ifx)
6704 operand *left, *right, *result;
6705 sym_link *letype , *retype;
6711 right= IC_RIGHT(ic);
6712 result = IC_RESULT(ic);
6714 letype = getSpec(operandType(left));
6715 retype =getSpec(operandType(right));
6716 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6718 /* assign the amsops */
6719 pic16_aopOp (left,ic,FALSE);
6720 pic16_aopOp (right,ic,FALSE);
6721 pic16_aopOp (result,ic,TRUE);
6723 genCmp(left, right, result, ifx, sign);
6725 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6726 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6727 pic16_freeAsmop(result,NULL,ic,TRUE);
6732 // FIXME reenable literal optimisation when the pic16 port is stable
6734 /*-----------------------------------------------------------------*/
6735 /* genc16bit2lit - compare a 16 bit value to a literal */
6736 /*-----------------------------------------------------------------*/
6737 static void genc16bit2lit(operand *op, int lit, int offset)
6741 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6742 if( (lit&0xff) == 0)
6747 switch( BYTEofLONG(lit,i)) {
6749 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6752 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6755 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6758 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6759 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6764 switch( BYTEofLONG(lit,i)) {
6766 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6770 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6774 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6777 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6779 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6788 /*-----------------------------------------------------------------*/
6789 /* gencjneshort - compare and jump if not equal */
6790 /*-----------------------------------------------------------------*/
6791 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6793 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6795 int res_offset = 0; /* the result may be a different size then left or right */
6796 int res_size = AOP_SIZE(result);
6798 symbol *lbl, *lbl_done;
6800 unsigned long lit = 0L;
6801 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6804 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6806 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6807 resolveIfx(&rIfx,ifx);
6808 lbl = newiTempLabel(NULL);
6809 lbl_done = newiTempLabel(NULL);
6812 /* if the left side is a literal or
6813 if the right is in a pointer register and left
6815 if ((AOP_TYPE(left) == AOP_LIT) ||
6816 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821 if(AOP_TYPE(right) == AOP_LIT)
6822 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6824 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6825 preserve_result = 1;
6827 if(result && !preserve_result)
6830 for(i = 0; i < AOP_SIZE(result); i++)
6831 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6835 /* if the right side is a literal then anything goes */
6836 if (AOP_TYPE(right) == AOP_LIT &&
6837 AOP_TYPE(left) != AOP_DIR ) {
6840 genc16bit2lit(left, lit, 0);
6842 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6848 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6849 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6851 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6857 if(res_offset < res_size-1)
6865 /* if the right side is in a register or in direct space or
6866 if the left is a pointer register & right is not */
6867 else if (AOP_TYPE(right) == AOP_REG ||
6868 AOP_TYPE(right) == AOP_DIR ||
6869 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6870 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6871 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6872 int lbl_key = lbl->key;
6875 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6876 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6878 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6879 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6880 __FUNCTION__,__LINE__);
6884 /* switch(size) { */
6886 /* genc16bit2lit(left, lit, 0); */
6888 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6893 if((AOP_TYPE(left) == AOP_DIR) &&
6894 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6896 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6897 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6899 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6901 switch (lit & 0xff) {
6903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6906 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6907 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6912 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6913 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6914 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6915 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6919 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6920 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6925 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6928 if(AOP_TYPE(result) == AOP_CRY) {
6929 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6934 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6936 /* fix me. probably need to check result size too */
6937 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6942 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6943 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6950 if(res_offset < res_size-1)
6955 } else if(AOP_TYPE(right) == AOP_REG &&
6956 AOP_TYPE(left) != AOP_DIR){
6959 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6960 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6961 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6966 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6968 if(res_offset < res_size-1)
6973 /* right is a pointer reg need both a & b */
6975 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6977 pic16_emitcode("mov","b,%s",l);
6978 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6979 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6984 if(result && preserve_result)
6987 for(i = 0; i < AOP_SIZE(result); i++)
6988 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6991 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6993 if(result && preserve_result)
6994 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6997 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6999 pic16_emitpLabel(lbl->key);
7001 if(result && preserve_result)
7004 for(i = 0; i < AOP_SIZE(result); i++)
7005 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7007 pic16_emitpLabel(lbl_done->key);
7010 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7018 /*-----------------------------------------------------------------*/
7019 /* gencjne - compare and jump if not equal */
7020 /*-----------------------------------------------------------------*/
7021 static void gencjne(operand *left, operand *right, iCode *ifx)
7023 symbol *tlbl = newiTempLabel(NULL);
7025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7026 gencjneshort(left, right, lbl);
7028 pic16_emitcode("mov","a,%s",one);
7029 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7030 pic16_emitcode("","%05d_DS_:",lbl->key+100);
7031 pic16_emitcode("clr","a");
7032 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7034 pic16_emitpLabel(lbl->key);
7035 pic16_emitpLabel(tlbl->key);
7041 /*-----------------------------------------------------------------*/
7042 /* is_LitOp - check if operand has to be treated as literal */
7043 /*-----------------------------------------------------------------*/
7044 static bool is_LitOp(operand *op)
7046 return ((AOP_TYPE(op) == AOP_LIT)
7047 || ( (AOP_TYPE(op) == AOP_PCODE)
7048 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7049 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7052 /*-----------------------------------------------------------------*/
7053 /* is_LitAOp - check if operand has to be treated as literal */
7054 /*-----------------------------------------------------------------*/
7055 static bool is_LitAOp(asmop *aop)
7057 return ((aop->type == AOP_LIT)
7058 || ( (aop->type == AOP_PCODE)
7059 && ( (aop->aopu.pcop->type == PO_LITERAL)
7060 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7065 /*-----------------------------------------------------------------*/
7066 /* genCmpEq - generates code for equal to */
7067 /*-----------------------------------------------------------------*/
7068 static void genCmpEq (iCode *ic, iCode *ifx)
7070 operand *left, *right, *result;
7071 symbol *falselbl = newiTempLabel(NULL);
7072 symbol *donelbl = newiTempLabel(NULL);
7074 int preserve_result = 0;
7075 int generate_result = 0;
7080 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7081 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7082 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7084 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7086 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7088 werror(W_POSSBUG2, __FILE__, __LINE__);
7089 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7090 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7094 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7096 operand *tmp = right ;
7101 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7102 preserve_result = 1;
7104 if(result && AOP_SIZE(result))
7105 generate_result = 1;
7107 if(generate_result && !preserve_result)
7109 for(i = 0; i < AOP_SIZE(result); i++)
7110 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7113 for(i=0; i < AOP_SIZE(left); i++)
7115 if(AOP_TYPE(left) != AOP_ACC)
7118 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7120 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7123 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7125 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7127 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7132 if(generate_result && preserve_result)
7134 for(i = 0; i < AOP_SIZE(result); i++)
7135 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7139 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7141 if(generate_result && preserve_result)
7142 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7144 if(ifx && IC_TRUE(ifx))
7145 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7147 if(ifx && IC_FALSE(ifx))
7148 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7150 pic16_emitpLabel(falselbl->key);
7154 if(ifx && IC_FALSE(ifx))
7155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7157 if(generate_result && preserve_result)
7159 for(i = 0; i < AOP_SIZE(result); i++)
7160 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7163 pic16_emitpLabel(donelbl->key);
7169 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7170 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7171 pic16_freeAsmop(result,NULL,ic,TRUE);
7177 // old version kept for reference
7179 /*-----------------------------------------------------------------*/
7180 /* genCmpEq - generates code for equal to */
7181 /*-----------------------------------------------------------------*/
7182 static void genCmpEq (iCode *ic, iCode *ifx)
7184 operand *left, *right, *result;
7185 unsigned long lit = 0L;
7187 symbol *falselbl = newiTempLabel(NULL);
7190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7193 DEBUGpic16_emitcode ("; ifx is non-null","");
7195 DEBUGpic16_emitcode ("; ifx is null","");
7197 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7198 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7199 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7201 size = max(AOP_SIZE(left),AOP_SIZE(right));
7203 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7205 /* if literal, literal on the right or
7206 if the right is in a pointer register and left
7208 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7209 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7210 operand *tmp = right ;
7216 if(ifx && !AOP_SIZE(result)){
7218 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7219 /* if they are both bit variables */
7220 if (AOP_TYPE(left) == AOP_CRY &&
7221 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7222 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7223 if(AOP_TYPE(right) == AOP_LIT){
7224 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7226 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7227 pic16_emitcode("cpl","c");
7228 } else if(lit == 1L) {
7229 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7231 pic16_emitcode("clr","c");
7233 /* AOP_TYPE(right) == AOP_CRY */
7235 symbol *lbl = newiTempLabel(NULL);
7236 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7237 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7238 pic16_emitcode("cpl","c");
7239 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7241 /* if true label then we jump if condition
7243 tlbl = newiTempLabel(NULL);
7244 if ( IC_TRUE(ifx) ) {
7245 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7246 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7248 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7249 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7251 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7254 /* left and right are both bit variables, result is carry */
7257 resolveIfx(&rIfx,ifx);
7259 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7260 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7261 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7262 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7267 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7269 /* They're not both bit variables. Is the right a literal? */
7270 if(AOP_TYPE(right) == AOP_LIT) {
7271 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7276 switch(lit & 0xff) {
7278 if ( IC_TRUE(ifx) ) {
7279 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7281 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7283 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7284 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7288 if ( IC_TRUE(ifx) ) {
7289 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7291 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7293 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7294 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7298 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7300 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7305 /* end of size == 1 */
7309 genc16bit2lit(left,lit,offset);
7312 /* end of size == 2 */
7317 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7318 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7319 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7320 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7323 /* search for patterns that can be optimized */
7325 genc16bit2lit(left,lit,0);
7329 emitSKPZ; // if hi word unequal
7331 emitSKPNZ; // if hi word equal
7333 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7334 genc16bit2lit(left,lit,2);
7337 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7338 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7342 pic16_emitpLabel(falselbl->key);
7351 } else if(AOP_TYPE(right) == AOP_CRY ) {
7352 /* we know the left is not a bit, but that the right is */
7353 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7354 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7355 pic16_popGet(AOP(right),offset));
7356 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7358 /* if the two are equal, then W will be 0 and the Z bit is set
7359 * we could test Z now, or go ahead and check the high order bytes if
7360 * the variable we're comparing is larger than a byte. */
7363 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7365 if ( IC_TRUE(ifx) ) {
7367 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7368 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7371 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7372 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7376 /* They're both variables that are larger than bits */
7379 tlbl = newiTempLabel(NULL);
7382 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7383 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7385 if ( IC_TRUE(ifx) ) {
7389 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7391 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7392 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7396 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7399 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7400 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7405 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7407 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7408 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7412 if(s>1 && IC_TRUE(ifx)) {
7413 pic16_emitpLabel(tlbl->key);
7414 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7418 /* mark the icode as generated */
7423 /* if they are both bit variables */
7424 if (AOP_TYPE(left) == AOP_CRY &&
7425 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7426 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7427 if(AOP_TYPE(right) == AOP_LIT){
7428 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7430 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7431 pic16_emitcode("cpl","c");
7432 } else if(lit == 1L) {
7433 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7435 pic16_emitcode("clr","c");
7437 /* AOP_TYPE(right) == AOP_CRY */
7439 symbol *lbl = newiTempLabel(NULL);
7440 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7441 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7442 pic16_emitcode("cpl","c");
7443 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7446 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7447 pic16_outBitC(result);
7451 genIfxJump (ifx,"c");
7454 /* if the result is used in an arithmetic operation
7455 then put the result in place */
7456 pic16_outBitC(result);
7459 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7460 gencjne(left,right,result,ifx);
7463 gencjne(left,right,newiTempLabel(NULL));
7465 if(IC_TRUE(ifx)->key)
7466 gencjne(left,right,IC_TRUE(ifx)->key);
7468 gencjne(left,right,IC_FALSE(ifx)->key);
7472 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7473 pic16_aopPut(AOP(result),"a",0);
7478 genIfxJump (ifx,"a");
7482 /* if the result is used in an arithmetic operation
7483 then put the result in place */
7485 if (AOP_TYPE(result) != AOP_CRY)
7486 pic16_outAcc(result);
7488 /* leave the result in acc */
7492 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7493 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7494 pic16_freeAsmop(result,NULL,ic,TRUE);
7498 /*-----------------------------------------------------------------*/
7499 /* ifxForOp - returns the icode containing the ifx for operand */
7500 /*-----------------------------------------------------------------*/
7501 static iCode *ifxForOp ( operand *op, iCode *ic )
7505 /* if true symbol then needs to be assigned */
7506 if (IS_TRUE_SYMOP(op))
7509 /* if this has register type condition and
7510 the next instruction is ifx with the same operand
7511 and live to of the operand is upto the ifx only then */
7513 && ic->next->op == IFX
7514 && IC_COND(ic->next)->key == op->key
7515 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7517 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7523 ic->next->op == IFX &&
7524 IC_COND(ic->next)->key == op->key) {
7525 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7530 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7532 ic->next->op == IFX)
7533 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7536 ic->next->op == IFX &&
7537 IC_COND(ic->next)->key == op->key) {
7538 DEBUGpic16_emitcode ("; "," key is okay");
7539 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7540 OP_SYMBOL(op)->liveTo,
7545 /* the code below is completely untested
7546 * it just allows ulong2fs.c compile -- VR */
7549 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7550 __FILE__, __FUNCTION__, __LINE__);
7552 /* if this has register type condition and
7553 the next instruction is ifx with the same operand
7554 and live to of the operand is upto the ifx only then */
7556 ic->next->op == IFX &&
7557 IC_COND(ic->next)->key == op->key &&
7558 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7562 ic->next->op == IFX &&
7563 IC_COND(ic->next)->key == op->key) {
7564 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7568 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7569 __FILE__, __FUNCTION__, __LINE__);
7571 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7576 /*-----------------------------------------------------------------*/
7577 /* genAndOp - for && operation */
7578 /*-----------------------------------------------------------------*/
7579 static void genAndOp (iCode *ic)
7581 operand *left,*right, *result;
7586 /* note here that && operations that are in an
7587 if statement are taken away by backPatchLabels
7588 only those used in arthmetic operations remain */
7589 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7590 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7591 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7593 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7595 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7596 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7597 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7599 /* if both are bit variables */
7600 /* if (AOP_TYPE(left) == AOP_CRY && */
7601 /* AOP_TYPE(right) == AOP_CRY ) { */
7602 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7603 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7604 /* pic16_outBitC(result); */
7606 /* tlbl = newiTempLabel(NULL); */
7607 /* pic16_toBoolean(left); */
7608 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7609 /* pic16_toBoolean(right); */
7610 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7611 /* pic16_outBitAcc(result); */
7614 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7615 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7616 pic16_freeAsmop(result,NULL,ic,TRUE);
7620 /*-----------------------------------------------------------------*/
7621 /* genOrOp - for || operation */
7622 /*-----------------------------------------------------------------*/
7625 modified this code, but it doesn't appear to ever get called
7628 static void genOrOp (iCode *ic)
7630 operand *left,*right, *result;
7635 /* note here that || operations that are in an
7636 if statement are taken away by backPatchLabels
7637 only those used in arthmetic operations remain */
7638 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7639 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7640 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7642 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7644 /* if both are bit variables */
7645 if (AOP_TYPE(left) == AOP_CRY &&
7646 AOP_TYPE(right) == AOP_CRY ) {
7647 pic16_emitcode("clrc","");
7648 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7649 AOP(left)->aopu.aop_dir,
7650 AOP(left)->aopu.aop_dir);
7651 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7652 AOP(right)->aopu.aop_dir,
7653 AOP(right)->aopu.aop_dir);
7654 pic16_emitcode("setc","");
7657 tlbl = newiTempLabel(NULL);
7658 pic16_toBoolean(left);
7660 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7661 pic16_toBoolean(right);
7662 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7664 pic16_outBitAcc(result);
7667 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7668 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7669 pic16_freeAsmop(result,NULL,ic,TRUE);
7672 /*-----------------------------------------------------------------*/
7673 /* isLiteralBit - test if lit == 2^n */
7674 /*-----------------------------------------------------------------*/
7675 static int isLiteralBit(unsigned long lit)
7677 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7678 0x100L,0x200L,0x400L,0x800L,
7679 0x1000L,0x2000L,0x4000L,0x8000L,
7680 0x10000L,0x20000L,0x40000L,0x80000L,
7681 0x100000L,0x200000L,0x400000L,0x800000L,
7682 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7683 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7687 for(idx = 0; idx < 32; idx++)
7693 /*-----------------------------------------------------------------*/
7694 /* continueIfTrue - */
7695 /*-----------------------------------------------------------------*/
7696 static void continueIfTrue (iCode *ic)
7700 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7704 /*-----------------------------------------------------------------*/
7706 /*-----------------------------------------------------------------*/
7707 static void jumpIfTrue (iCode *ic)
7711 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7715 /*-----------------------------------------------------------------*/
7716 /* jmpTrueOrFalse - */
7717 /*-----------------------------------------------------------------*/
7718 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7720 // ugly but optimized by peephole
7723 symbol *nlbl = newiTempLabel(NULL);
7724 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7725 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7726 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7727 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7729 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7730 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7735 /*-----------------------------------------------------------------*/
7736 /* genAnd - code for and */
7737 /*-----------------------------------------------------------------*/
7738 static void genAnd (iCode *ic, iCode *ifx)
7740 operand *left, *right, *result;
7742 unsigned long lit = 0L;
7748 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7749 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7750 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7752 resolveIfx(&rIfx,ifx);
7754 /* if left is a literal & right is not then exchange them */
7755 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7756 AOP_NEEDSACC(left)) {
7757 operand *tmp = right ;
7762 /* if result = right then exchange them */
7763 if(pic16_sameRegs(AOP(result),AOP(right))){
7764 operand *tmp = right ;
7769 /* if right is bit then exchange them */
7770 if (AOP_TYPE(right) == AOP_CRY &&
7771 AOP_TYPE(left) != AOP_CRY){
7772 operand *tmp = right ;
7776 if(AOP_TYPE(right) == AOP_LIT)
7777 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7779 size = AOP_SIZE(result);
7781 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7784 // result = bit & yy;
7785 if (AOP_TYPE(left) == AOP_CRY){
7786 // c = bit & literal;
7787 if(AOP_TYPE(right) == AOP_LIT){
7789 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7792 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7795 if(size && (AOP_TYPE(result) == AOP_CRY)){
7796 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7799 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7803 pic16_emitcode("clr","c");
7806 if (AOP_TYPE(right) == AOP_CRY){
7808 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7809 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7812 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7814 pic16_emitcode("rrc","a");
7815 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7821 pic16_outBitC(result);
7823 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7824 genIfxJump(ifx, "c");
7828 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7829 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7830 if((AOP_TYPE(right) == AOP_LIT) &&
7831 (AOP_TYPE(result) == AOP_CRY) &&
7832 (AOP_TYPE(left) != AOP_CRY)){
7833 int posbit = isLiteralBit(lit);
7837 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7840 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7846 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7847 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7849 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7850 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7853 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7854 size = AOP_SIZE(left);
7857 int bp = posbit, ofs=0;
7864 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7865 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7869 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7870 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7879 symbol *tlbl = newiTempLabel(NULL);
7880 int sizel = AOP_SIZE(left);
7886 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7888 /* patch provided by Aaron Colwell */
7889 if((posbit = isLiteralBit(bytelit)) != 0) {
7890 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7891 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7892 (posbit-1),0, PO_GPR_REGISTER));
7894 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7895 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7897 if (bytelit == 0xff) {
7898 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7899 * a peephole could optimize it out -- VR */
7900 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7902 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7903 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7906 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7907 pic16_popGetLabel(tlbl->key));
7911 /* old code, left here for reference -- VR 09/2004 */
7912 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7914 if((posbit = isLiteralBit(bytelit)) != 0)
7915 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7917 if(bytelit != 0x0FFL)
7918 pic16_emitcode("anl","a,%s",
7919 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7920 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7926 // bit = left & literal
7929 pic16_emitpLabel(tlbl->key);
7931 // if(left & literal)
7934 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7937 pic16_emitpLabel(tlbl->key);
7942 pic16_outBitC(result);
7946 /* if left is same as result */
7947 if(pic16_sameRegs(AOP(result),AOP(left))){
7949 for(;size--; offset++,lit>>=8) {
7950 if(AOP_TYPE(right) == AOP_LIT){
7951 switch(lit & 0xff) {
7953 /* and'ing with 0 has clears the result */
7954 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7955 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7958 /* and'ing with 0xff is a nop when the result and left are the same */
7963 int p = pic16_my_powof2( (~lit) & 0xff );
7965 /* only one bit is set in the literal, so use a bcf instruction */
7966 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7967 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7970 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7971 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7972 if(know_W != (lit&0xff))
7973 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7975 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7980 if (AOP_TYPE(left) == AOP_ACC) {
7981 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7983 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7984 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7991 // left & result in different registers
7992 if(AOP_TYPE(result) == AOP_CRY){
7994 // if(size), result in bit
7995 // if(!size && ifx), conditional oper: if(left & right)
7996 symbol *tlbl = newiTempLabel(NULL);
7997 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7999 pic16_emitcode("setb","c");
8001 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8002 pic16_emitcode("anl","a,%s",
8003 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8004 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8009 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8010 pic16_outBitC(result);
8012 jmpTrueOrFalse(ifx, tlbl);
8014 for(;(size--);offset++) {
8016 // result = left & right
8017 if(AOP_TYPE(right) == AOP_LIT){
8018 int t = (lit >> (offset*8)) & 0x0FFL;
8021 pic16_emitcode("clrf","%s",
8022 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8023 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8026 pic16_emitcode("movf","%s,w",
8027 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8028 pic16_emitcode("movwf","%s",
8029 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8030 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8031 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8034 pic16_emitcode("movlw","0x%x",t);
8035 pic16_emitcode("andwf","%s,w",
8036 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8037 pic16_emitcode("movwf","%s",
8038 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8040 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8041 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8042 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8047 if (AOP_TYPE(left) == AOP_ACC) {
8048 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8049 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8051 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8052 pic16_emitcode("andwf","%s,w",
8053 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8054 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8055 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8057 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8058 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8064 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8065 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8066 pic16_freeAsmop(result,NULL,ic,TRUE);
8069 /*-----------------------------------------------------------------*/
8070 /* genOr - code for or */
8071 /*-----------------------------------------------------------------*/
8072 static void genOr (iCode *ic, iCode *ifx)
8074 operand *left, *right, *result;
8076 unsigned long lit = 0L;
8078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8080 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8081 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8082 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8084 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8086 /* if left is a literal & right is not then exchange them */
8087 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8088 AOP_NEEDSACC(left)) {
8089 operand *tmp = right ;
8094 /* if result = right then exchange them */
8095 if(pic16_sameRegs(AOP(result),AOP(right))){
8096 operand *tmp = right ;
8101 /* if right is bit then exchange them */
8102 if (AOP_TYPE(right) == AOP_CRY &&
8103 AOP_TYPE(left) != AOP_CRY){
8104 operand *tmp = right ;
8109 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8111 if(AOP_TYPE(right) == AOP_LIT)
8112 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8114 size = AOP_SIZE(result);
8118 if (AOP_TYPE(left) == AOP_CRY){
8119 if(AOP_TYPE(right) == AOP_LIT){
8120 // c = bit & literal;
8122 // lit != 0 => result = 1
8123 if(AOP_TYPE(result) == AOP_CRY){
8125 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8126 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8127 // AOP(result)->aopu.aop_dir,
8128 // AOP(result)->aopu.aop_dir);
8130 continueIfTrue(ifx);
8134 // lit == 0 => result = left
8135 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8137 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8140 if (AOP_TYPE(right) == AOP_CRY){
8141 if(pic16_sameRegs(AOP(result),AOP(left))){
8143 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8144 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8145 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8147 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8148 AOP(result)->aopu.aop_dir,
8149 AOP(result)->aopu.aop_dir);
8150 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8151 AOP(right)->aopu.aop_dir,
8152 AOP(right)->aopu.aop_dir);
8153 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8154 AOP(result)->aopu.aop_dir,
8155 AOP(result)->aopu.aop_dir);
8157 if( AOP_TYPE(result) == AOP_ACC) {
8158 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8159 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8160 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8161 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8165 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8166 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8167 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8168 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8170 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8171 AOP(result)->aopu.aop_dir,
8172 AOP(result)->aopu.aop_dir);
8173 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8174 AOP(right)->aopu.aop_dir,
8175 AOP(right)->aopu.aop_dir);
8176 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8177 AOP(left)->aopu.aop_dir,
8178 AOP(left)->aopu.aop_dir);
8179 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8180 AOP(result)->aopu.aop_dir,
8181 AOP(result)->aopu.aop_dir);
8186 symbol *tlbl = newiTempLabel(NULL);
8187 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8190 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8191 if( AOP_TYPE(right) == AOP_ACC) {
8192 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8194 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8195 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8200 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8201 pic16_emitcode(";XXX setb","c");
8202 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8203 AOP(left)->aopu.aop_dir,tlbl->key+100);
8204 pic16_toBoolean(right);
8205 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8206 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8207 jmpTrueOrFalse(ifx, tlbl);
8211 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8218 pic16_outBitC(result);
8220 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8221 genIfxJump(ifx, "c");
8225 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8226 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8227 if((AOP_TYPE(right) == AOP_LIT) &&
8228 (AOP_TYPE(result) == AOP_CRY) &&
8229 (AOP_TYPE(left) != AOP_CRY)){
8231 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8234 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8236 continueIfTrue(ifx);
8239 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8240 // lit = 0, result = boolean(left)
8242 pic16_emitcode(";XXX setb","c");
8243 pic16_toBoolean(right);
8245 symbol *tlbl = newiTempLabel(NULL);
8246 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8248 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8250 genIfxJump (ifx,"a");
8254 pic16_outBitC(result);
8258 /* if left is same as result */
8259 if(pic16_sameRegs(AOP(result),AOP(left))){
8261 for(;size--; offset++,lit>>=8) {
8262 if(AOP_TYPE(right) == AOP_LIT){
8263 if((lit & 0xff) == 0)
8264 /* or'ing with 0 has no effect */
8267 int p = pic16_my_powof2(lit & 0xff);
8269 /* only one bit is set in the literal, so use a bsf instruction */
8270 pic16_emitpcode(POC_BSF,
8271 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8273 if(know_W != (lit & 0xff))
8274 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8275 know_W = lit & 0xff;
8276 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8281 if (AOP_TYPE(left) == AOP_ACC) {
8282 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8283 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8285 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8286 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8288 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8289 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8295 // left & result in different registers
8296 if(AOP_TYPE(result) == AOP_CRY){
8298 // if(size), result in bit
8299 // if(!size && ifx), conditional oper: if(left | right)
8300 symbol *tlbl = newiTempLabel(NULL);
8301 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8302 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8306 pic16_emitcode(";XXX setb","c");
8308 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8309 pic16_emitcode(";XXX orl","a,%s",
8310 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8311 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8316 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8317 pic16_outBitC(result);
8319 jmpTrueOrFalse(ifx, tlbl);
8320 } else for(;(size--);offset++){
8322 // result = left & right
8323 if(AOP_TYPE(right) == AOP_LIT){
8324 int t = (lit >> (offset*8)) & 0x0FFL;
8327 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8328 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8330 pic16_emitcode("movf","%s,w",
8331 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8332 pic16_emitcode("movwf","%s",
8333 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8336 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8337 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8338 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8340 pic16_emitcode("movlw","0x%x",t);
8341 pic16_emitcode("iorwf","%s,w",
8342 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8343 pic16_emitcode("movwf","%s",
8344 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8350 // faster than result <- left, anl result,right
8351 // and better if result is SFR
8352 if (AOP_TYPE(left) == AOP_ACC) {
8353 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8354 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8356 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8357 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8359 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8360 pic16_emitcode("iorwf","%s,w",
8361 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8364 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8369 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8370 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8371 pic16_freeAsmop(result,NULL,ic,TRUE);
8374 /*-----------------------------------------------------------------*/
8375 /* genXor - code for xclusive or */
8376 /*-----------------------------------------------------------------*/
8377 static void genXor (iCode *ic, iCode *ifx)
8379 operand *left, *right, *result;
8381 unsigned long lit = 0L;
8383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8385 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8386 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8387 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8389 /* if left is a literal & right is not ||
8390 if left needs acc & right does not */
8391 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8392 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8393 operand *tmp = right ;
8398 /* if result = right then exchange them */
8399 if(pic16_sameRegs(AOP(result),AOP(right))){
8400 operand *tmp = right ;
8405 /* if right is bit then exchange them */
8406 if (AOP_TYPE(right) == AOP_CRY &&
8407 AOP_TYPE(left) != AOP_CRY){
8408 operand *tmp = right ;
8412 if(AOP_TYPE(right) == AOP_LIT)
8413 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8415 size = AOP_SIZE(result);
8419 if (AOP_TYPE(left) == AOP_CRY){
8420 if(AOP_TYPE(right) == AOP_LIT){
8421 // c = bit & literal;
8423 // lit>>1 != 0 => result = 1
8424 if(AOP_TYPE(result) == AOP_CRY){
8426 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8427 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8429 continueIfTrue(ifx);
8432 pic16_emitcode("setb","c");
8436 // lit == 0, result = left
8437 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8439 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8441 // lit == 1, result = not(left)
8442 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8443 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8444 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8445 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8448 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8449 pic16_emitcode("cpl","c");
8456 symbol *tlbl = newiTempLabel(NULL);
8457 if (AOP_TYPE(right) == AOP_CRY){
8459 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8462 int sizer = AOP_SIZE(right);
8464 // if val>>1 != 0, result = 1
8465 pic16_emitcode("setb","c");
8467 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8469 // test the msb of the lsb
8470 pic16_emitcode("anl","a,#0xfe");
8471 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8475 pic16_emitcode("rrc","a");
8477 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8478 pic16_emitcode("cpl","c");
8479 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8484 pic16_outBitC(result);
8486 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8487 genIfxJump(ifx, "c");
8491 if(pic16_sameRegs(AOP(result),AOP(left))){
8492 /* if left is same as result */
8493 for(;size--; offset++) {
8494 if(AOP_TYPE(right) == AOP_LIT){
8495 int t = (lit >> (offset*8)) & 0x0FFL;
8499 if (IS_AOP_PREG(left)) {
8500 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8501 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8502 pic16_aopPut(AOP(result),"a",offset);
8504 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8505 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8506 pic16_emitcode("xrl","%s,%s",
8507 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8508 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8511 if (AOP_TYPE(left) == AOP_ACC)
8512 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8514 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8515 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8517 if (IS_AOP_PREG(left)) {
8518 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8519 pic16_aopPut(AOP(result),"a",offset);
8521 pic16_emitcode("xrl","%s,a",
8522 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8528 // left & result in different registers
8529 if(AOP_TYPE(result) == AOP_CRY){
8531 // if(size), result in bit
8532 // if(!size && ifx), conditional oper: if(left ^ right)
8533 symbol *tlbl = newiTempLabel(NULL);
8534 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8536 pic16_emitcode("setb","c");
8538 if((AOP_TYPE(right) == AOP_LIT) &&
8539 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8540 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8542 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8543 pic16_emitcode("xrl","a,%s",
8544 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8546 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8551 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8552 pic16_outBitC(result);
8554 jmpTrueOrFalse(ifx, tlbl);
8555 } else for(;(size--);offset++){
8557 // result = left & right
8558 if(AOP_TYPE(right) == AOP_LIT){
8559 int t = (lit >> (offset*8)) & 0x0FFL;
8562 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8563 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8564 pic16_emitcode("movf","%s,w",
8565 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8566 pic16_emitcode("movwf","%s",
8567 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8570 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8571 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8572 pic16_emitcode("comf","%s,w",
8573 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8574 pic16_emitcode("movwf","%s",
8575 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8579 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8580 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8581 pic16_emitcode("movlw","0x%x",t);
8582 pic16_emitcode("xorwf","%s,w",
8583 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8584 pic16_emitcode("movwf","%s",
8585 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8591 // faster than result <- left, anl result,right
8592 // and better if result is SFR
8593 if (AOP_TYPE(left) == AOP_ACC) {
8594 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8595 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8597 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8598 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8599 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8600 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8602 if ( AOP_TYPE(result) != AOP_ACC){
8603 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8604 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8610 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8611 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8612 pic16_freeAsmop(result,NULL,ic,TRUE);
8615 /*-----------------------------------------------------------------*/
8616 /* genInline - write the inline code out */
8617 /*-----------------------------------------------------------------*/
8618 static void genInline (iCode *ic)
8620 char *buffer, *bp, *bp1;
8622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8624 _G.inLine += (!options.asmpeep);
8626 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8627 strcpy(buffer,IC_INLINE(ic));
8629 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8631 /* emit each line as a code */
8637 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8645 /* print label, use this special format with NULL directive
8646 * to denote that the argument should not be indented with tab */
8647 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8654 if ((bp1 != bp) && *bp1)
8655 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8660 _G.inLine -= (!options.asmpeep);
8663 /*-----------------------------------------------------------------*/
8664 /* genRRC - rotate right with carry */
8665 /*-----------------------------------------------------------------*/
8666 static void genRRC (iCode *ic)
8668 operand *left , *result ;
8669 int size, offset = 0, same;
8671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8673 /* rotate right with carry */
8675 result=IC_RESULT(ic);
8676 pic16_aopOp (left,ic,FALSE);
8677 pic16_aopOp (result,ic,FALSE);
8679 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8681 same = pic16_sameRegs(AOP(result),AOP(left));
8683 size = AOP_SIZE(result);
8685 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8687 /* get the lsb and put it into the carry */
8688 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8695 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8697 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8698 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8704 pic16_freeAsmop(left,NULL,ic,TRUE);
8705 pic16_freeAsmop(result,NULL,ic,TRUE);
8708 /*-----------------------------------------------------------------*/
8709 /* genRLC - generate code for rotate left with carry */
8710 /*-----------------------------------------------------------------*/
8711 static void genRLC (iCode *ic)
8713 operand *left , *result ;
8714 int size, offset = 0;
8717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8718 /* rotate right with carry */
8720 result=IC_RESULT(ic);
8721 pic16_aopOp (left,ic,FALSE);
8722 pic16_aopOp (result,ic,FALSE);
8724 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8726 same = pic16_sameRegs(AOP(result),AOP(left));
8728 /* move it to the result */
8729 size = AOP_SIZE(result);
8731 /* get the msb and put it into the carry */
8732 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8739 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8741 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8749 pic16_freeAsmop(left,NULL,ic,TRUE);
8750 pic16_freeAsmop(result,NULL,ic,TRUE);
8754 /* gpasm can get the highest order bit with HIGH/UPPER
8755 * so the following probably is not needed -- VR */
8757 /*-----------------------------------------------------------------*/
8758 /* genGetHbit - generates code get highest order bit */
8759 /*-----------------------------------------------------------------*/
8760 static void genGetHbit (iCode *ic)
8762 operand *left, *result;
8764 result=IC_RESULT(ic);
8765 pic16_aopOp (left,ic,FALSE);
8766 pic16_aopOp (result,ic,FALSE);
8768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8769 /* get the highest order byte into a */
8770 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8771 if(AOP_TYPE(result) == AOP_CRY){
8772 pic16_emitcode("rlc","a");
8773 pic16_outBitC(result);
8776 pic16_emitcode("rl","a");
8777 pic16_emitcode("anl","a,#0x01");
8778 pic16_outAcc(result);
8782 pic16_freeAsmop(left,NULL,ic,TRUE);
8783 pic16_freeAsmop(result,NULL,ic,TRUE);
8787 /*-----------------------------------------------------------------*/
8788 /* AccRol - rotate left accumulator by known count */
8789 /*-----------------------------------------------------------------*/
8790 static void AccRol (int shCount)
8792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8793 shCount &= 0x0007; // shCount : 0..7
8798 pic16_emitcode("rl","a");
8801 pic16_emitcode("rl","a");
8802 pic16_emitcode("rl","a");
8805 pic16_emitcode("swap","a");
8806 pic16_emitcode("rr","a");
8809 pic16_emitcode("swap","a");
8812 pic16_emitcode("swap","a");
8813 pic16_emitcode("rl","a");
8816 pic16_emitcode("rr","a");
8817 pic16_emitcode("rr","a");
8820 pic16_emitcode("rr","a");
8826 /*-----------------------------------------------------------------*/
8827 /* AccLsh - left shift accumulator by known count */
8828 /*-----------------------------------------------------------------*/
8829 static void AccLsh (int shCount)
8831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8837 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8840 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8841 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8844 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8845 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8848 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8851 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8852 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8855 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8856 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8859 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8863 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8866 /*-----------------------------------------------------------------*/
8867 /* AccRsh - right shift accumulator by known count */
8868 /*-----------------------------------------------------------------*/
8869 static void AccRsh (int shCount, int andmask)
8871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8876 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8879 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8880 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8883 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8884 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8887 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8890 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8891 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8894 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8895 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8898 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8903 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8905 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8909 /*-----------------------------------------------------------------*/
8910 /* AccSRsh - signed right shift accumulator by known count */
8911 /*-----------------------------------------------------------------*/
8912 static void AccSRsh (int shCount)
8915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8918 pic16_emitcode("mov","c,acc.7");
8919 pic16_emitcode("rrc","a");
8920 } else if(shCount == 2){
8921 pic16_emitcode("mov","c,acc.7");
8922 pic16_emitcode("rrc","a");
8923 pic16_emitcode("mov","c,acc.7");
8924 pic16_emitcode("rrc","a");
8926 tlbl = newiTempLabel(NULL);
8927 /* rotate right accumulator */
8928 AccRol(8 - shCount);
8929 /* and kill the higher order bits */
8930 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8931 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8932 pic16_emitcode("orl","a,#0x%02x",
8933 (unsigned char)~SRMask[shCount]);
8934 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8940 /*-----------------------------------------------------------------*/
8941 /* shiftR1Left2Result - shift right one byte from left to result */
8942 /*-----------------------------------------------------------------*/
8943 static void shiftR1Left2ResultSigned (operand *left, int offl,
8944 operand *result, int offr,
8949 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8951 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8955 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8957 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8960 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8983 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8987 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8990 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8991 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8997 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8998 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8999 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9000 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
9001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9005 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9011 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9012 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9013 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
9014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9020 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9021 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9022 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9023 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9027 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9028 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9030 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9036 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9037 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9038 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9039 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9043 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9051 /*-----------------------------------------------------------------*/
9052 /* shiftR1Left2Result - shift right one byte from left to result */
9053 /*-----------------------------------------------------------------*/
9054 static void shiftR1Left2Result (operand *left, int offl,
9055 operand *result, int offr,
9056 int shCount, int sign)
9060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9062 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9064 /* Copy the msb into the carry if signed. */
9066 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9076 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9078 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9085 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9087 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9091 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9096 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9099 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9102 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9103 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9104 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9105 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9110 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9111 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9116 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9117 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9119 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9124 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9125 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9126 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9127 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9133 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9134 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9144 /*-----------------------------------------------------------------*/
9145 /* shiftL1Left2Result - shift left one byte from left to result */
9146 /*-----------------------------------------------------------------*/
9147 static void shiftL1Left2Result (operand *left, int offl,
9148 operand *result, int offr, int shCount)
9153 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9155 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9156 DEBUGpic16_emitcode ("; ***","same = %d",same);
9157 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9159 /* shift left accumulator */
9160 //AccLsh(shCount); // don't comment out just yet...
9161 // pic16_aopPut(AOP(result),"a",offr);
9165 /* Shift left 1 bit position */
9166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9168 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9170 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9171 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9175 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9176 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9178 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9181 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9182 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9183 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9184 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9185 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9188 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9189 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9190 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9193 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9194 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9195 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9196 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9199 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9200 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9201 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9202 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9203 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9206 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9207 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9208 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9212 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9217 /*-----------------------------------------------------------------*/
9218 /* movLeft2Result - move byte from left to result */
9219 /*-----------------------------------------------------------------*/
9220 static void movLeft2Result (operand *left, int offl,
9221 operand *result, int offr)
9224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9225 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9226 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9228 if (*l == '@' && (IS_AOP_PREG(result))) {
9229 pic16_emitcode("mov","a,%s",l);
9230 pic16_aopPut(AOP(result),"a",offr);
9232 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9238 /*-----------------------------------------------------------------*/
9239 /* shiftL2Left2Result - shift left two bytes from left to result */
9240 /*-----------------------------------------------------------------*/
9241 static void shiftL2Left2Result (operand *left, int offl,
9242 operand *result, int offr, int shCount)
9244 int same = pic16_sameRegs(AOP(result), AOP(left));
9247 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9249 if (same && (offl != offr)) { // shift bytes
9252 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9253 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9255 } else { // just treat as different later on
9268 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9269 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9270 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9274 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9275 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9281 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9282 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9283 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9284 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9285 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9286 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9287 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9289 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9290 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9294 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9295 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9296 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9297 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9298 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9300 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9301 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9302 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9306 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9307 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9308 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9309 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9310 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9320 /* note, use a mov/add for the shift since the mov has a
9321 chance of getting optimized out */
9322 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9324 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9325 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9326 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9330 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9331 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9337 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9338 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9339 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9340 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9341 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9342 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9343 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9344 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9348 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9349 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9353 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9354 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9355 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9358 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9359 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9360 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9361 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9362 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9363 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9364 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9365 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9368 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9370 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9372 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9377 /*-----------------------------------------------------------------*/
9378 /* shiftR2Left2Result - shift right two bytes from left to result */
9379 /*-----------------------------------------------------------------*/
9380 static void shiftR2Left2Result (operand *left, int offl,
9381 operand *result, int offr,
9382 int shCount, int sign)
9384 int same = pic16_sameRegs(AOP(result), AOP(left));
9386 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9388 if (same && (offl != offr)) { // shift right bytes
9391 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9392 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9394 } else { // just treat as different later on
9406 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9411 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9412 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9414 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9415 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9416 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9417 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9422 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9425 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9426 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9433 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9434 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9435 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9437 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9438 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9439 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9440 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9442 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9443 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9444 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9446 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9447 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9448 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9449 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9450 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9454 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9455 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9459 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9460 pic16_emitpcode(POC_BTFSC,
9461 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9462 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9470 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9471 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9473 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9474 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9475 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9476 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9478 pic16_emitpcode(POC_BTFSC,
9479 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9480 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9482 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9483 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9484 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9485 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9487 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9488 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9489 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9490 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9491 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9492 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9493 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9494 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9496 pic16_emitpcode(POC_BTFSC,
9497 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9498 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9500 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9501 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9508 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9509 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9510 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9511 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9514 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9516 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9521 /*-----------------------------------------------------------------*/
9522 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9523 /*-----------------------------------------------------------------*/
9524 static void shiftLLeftOrResult (operand *left, int offl,
9525 operand *result, int offr, int shCount)
9527 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9529 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9530 /* shift left accumulator */
9532 /* or with result */
9533 /* back to result */
9534 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9537 /*-----------------------------------------------------------------*/
9538 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9539 /*-----------------------------------------------------------------*/
9540 static void shiftRLeftOrResult (operand *left, int offl,
9541 operand *result, int offr, int shCount)
9543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9546 /* shift right accumulator */
9548 /* or with result */
9549 /* back to result */
9550 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9553 /*-----------------------------------------------------------------*/
9554 /* genlshOne - left shift a one byte quantity by known count */
9555 /*-----------------------------------------------------------------*/
9556 static void genlshOne (operand *result, operand *left, int shCount)
9558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9559 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9562 /*-----------------------------------------------------------------*/
9563 /* genlshTwo - left shift two bytes by known amount != 0 */
9564 /*-----------------------------------------------------------------*/
9565 static void genlshTwo (operand *result,operand *left, int shCount)
9569 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9570 size = pic16_getDataSize(result);
9572 /* if shCount >= 8 */
9578 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9580 movLeft2Result(left, LSB, result, MSB16);
9582 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9585 /* 1 <= shCount <= 7 */
9588 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9590 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9594 /*-----------------------------------------------------------------*/
9595 /* shiftLLong - shift left one long from left to result */
9596 /* offr = LSB or MSB16 */
9597 /*-----------------------------------------------------------------*/
9598 static void shiftLLong (operand *left, operand *result, int offr )
9600 int size = AOP_SIZE(result);
9601 int same = pic16_sameRegs(AOP(left),AOP(result));
9604 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9606 if (same && (offr == MSB16)) { //shift one byte
9607 for(i=size-1;i>=MSB16;i--) {
9608 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9609 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9612 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9615 if (size > LSB+offr ){
9617 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9619 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9620 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9624 if(size > MSB16+offr){
9626 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9628 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9629 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9633 if(size > MSB24+offr){
9635 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9637 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9638 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9642 if(size > MSB32+offr){
9644 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9646 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9647 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9651 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9655 /*-----------------------------------------------------------------*/
9656 /* genlshFour - shift four byte by a known amount != 0 */
9657 /*-----------------------------------------------------------------*/
9658 static void genlshFour (operand *result, operand *left, int shCount)
9662 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9663 size = AOP_SIZE(result);
9665 /* if shifting more that 3 bytes */
9666 if (shCount >= 24 ) {
9669 /* lowest order of left goes to the highest
9670 order of the destination */
9671 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9673 movLeft2Result(left, LSB, result, MSB32);
9675 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9676 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9677 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9682 /* more than two bytes */
9683 else if ( shCount >= 16 ) {
9684 /* lower order two bytes goes to higher order two bytes */
9686 /* if some more remaining */
9688 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9690 movLeft2Result(left, MSB16, result, MSB32);
9691 movLeft2Result(left, LSB, result, MSB24);
9693 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9694 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9698 /* if more than 1 byte */
9699 else if ( shCount >= 8 ) {
9700 /* lower order three bytes goes to higher order three bytes */
9704 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9706 movLeft2Result(left, LSB, result, MSB16);
9708 else{ /* size = 4 */
9710 movLeft2Result(left, MSB24, result, MSB32);
9711 movLeft2Result(left, MSB16, result, MSB24);
9712 movLeft2Result(left, LSB, result, MSB16);
9713 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9715 else if(shCount == 1)
9716 shiftLLong(left, result, MSB16);
9718 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9719 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9720 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9721 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9726 /* 1 <= shCount <= 7 */
9727 else if(shCount <= 3)
9729 shiftLLong(left, result, LSB);
9730 while(--shCount >= 1)
9731 shiftLLong(result, result, LSB);
9733 /* 3 <= shCount <= 7, optimize */
9735 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9736 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9737 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9741 /*-----------------------------------------------------------------*/
9742 /* genLeftShiftLiteral - left shifting by known count */
9743 /*-----------------------------------------------------------------*/
9744 void pic16_genLeftShiftLiteral (operand *left,
9749 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9753 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9754 pic16_freeAsmop(right,NULL,ic,TRUE);
9756 pic16_aopOp(left,ic,FALSE);
9757 pic16_aopOp(result,ic,FALSE);
9759 size = getSize(operandType(result));
9762 pic16_emitcode("; shift left ","result %d, left %d",size,
9766 /* I suppose that the left size >= result size */
9769 movLeft2Result(left, size, result, size);
9773 else if(shCount >= (size * 8))
9775 pic16_aopPut(AOP(result),zero,size);
9779 genlshOne (result,left,shCount);
9784 genlshTwo (result,left,shCount);
9788 genlshFour (result,left,shCount);
9792 pic16_freeAsmop(left,NULL,ic,TRUE);
9793 pic16_freeAsmop(result,NULL,ic,TRUE);
9796 /*-----------------------------------------------------------------*
9797 * genMultiAsm - repeat assembly instruction for size of register.
9798 * if endian == 1, then the high byte (i.e base address + size of
9799 * register) is used first else the low byte is used first;
9800 *-----------------------------------------------------------------*/
9801 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9819 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9825 #if !(USE_GENERIC_SIGNED_SHIFT)
9826 /*-----------------------------------------------------------------*/
9827 /* genLeftShift - generates code for left shifting */
9828 /*-----------------------------------------------------------------*/
9829 static void genLeftShift (iCode *ic)
9831 operand *left,*right, *result;
9834 symbol *tlbl , *tlbl1;
9837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9839 right = IC_RIGHT(ic);
9841 result = IC_RESULT(ic);
9843 pic16_aopOp(right,ic,FALSE);
9845 /* if the shift count is known then do it
9846 as efficiently as possible */
9847 if (AOP_TYPE(right) == AOP_LIT) {
9848 pic16_genLeftShiftLiteral (left,right,result,ic);
9852 /* shift count is unknown then we have to form
9853 * a loop. Get the loop count in WREG : Note: we take
9854 * only the lower order byte since shifting
9855 * more than 32 bits make no sense anyway, ( the
9856 * largest size of an object can be only 32 bits ) */
9858 pic16_aopOp(left,ic,FALSE);
9859 pic16_aopOp(result,ic,FALSE);
9861 /* now move the left to the result if they are not the
9862 * same, and if size > 1,
9863 * and if right is not same to result (!!!) -- VR */
9864 if (!pic16_sameRegs(AOP(left),AOP(result))
9865 && (AOP_SIZE(result) > 1)) {
9867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9869 size = AOP_SIZE(result);
9874 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9875 if (*l == '@' && (IS_AOP_PREG(result))) {
9877 pic16_emitcode("mov","a,%s",l);
9878 pic16_aopPut(AOP(result),"a",offset);
9882 /* we don't know if left is a literal or a register, take care -- VR */
9883 mov2f(AOP(result), AOP(left), offset);
9889 size = AOP_SIZE(result);
9891 /* if it is only one byte then */
9893 if(optimized_for_speed) {
9894 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9895 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9896 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9897 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9898 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9899 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9900 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9901 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9902 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9903 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9904 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9905 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9908 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9910 tlbl = newiTempLabel(NULL);
9913 /* this is already done, why change it? */
9914 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9915 mov2f(AOP(result), AOP(left), 0);
9919 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9920 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9921 pic16_emitpLabel(tlbl->key);
9922 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9923 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9925 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9930 if (pic16_sameRegs(AOP(left),AOP(result))) {
9932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9934 tlbl = newiTempLabel(NULL);
9935 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9936 genMultiAsm(POC_RRCF, result, size,1);
9937 pic16_emitpLabel(tlbl->key);
9938 genMultiAsm(POC_RLCF, result, size,0);
9939 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9945 //tlbl = newiTempLabel(NULL);
9947 //tlbl1 = newiTempLabel(NULL);
9949 //reAdjustPreg(AOP(result));
9951 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9952 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9953 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9955 //pic16_emitcode("add","a,acc");
9956 //pic16_aopPut(AOP(result),"a",offset++);
9958 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9960 // pic16_emitcode("rlc","a");
9961 // pic16_aopPut(AOP(result),"a",offset++);
9963 //reAdjustPreg(AOP(result));
9965 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9966 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9969 tlbl = newiTempLabel(NULL);
9970 tlbl1= newiTempLabel(NULL);
9972 size = AOP_SIZE(result);
9975 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9977 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9979 /* offset should be 0, 1 or 3 */
9981 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9983 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9985 pic16_emitpcode(POC_MOVWF, pctemp);
9988 pic16_emitpLabel(tlbl->key);
9991 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9993 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9995 pic16_emitpcode(POC_DECFSZ, pctemp);
9996 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9997 pic16_emitpLabel(tlbl1->key);
9999 pic16_popReleaseTempReg(pctemp,1);
10003 pic16_freeAsmop (right,NULL,ic,TRUE);
10004 pic16_freeAsmop(left,NULL,ic,TRUE);
10005 pic16_freeAsmop(result,NULL,ic,TRUE);
10011 #error old code (left here for reference)
10012 /*-----------------------------------------------------------------*/
10013 /* genLeftShift - generates code for left shifting */
10014 /*-----------------------------------------------------------------*/
10015 static void genLeftShift (iCode *ic)
10017 operand *left,*right, *result;
10020 symbol *tlbl , *tlbl1;
10023 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10025 right = IC_RIGHT(ic);
10026 left = IC_LEFT(ic);
10027 result = IC_RESULT(ic);
10029 pic16_aopOp(right,ic,FALSE);
10031 /* if the shift count is known then do it
10032 as efficiently as possible */
10033 if (AOP_TYPE(right) == AOP_LIT) {
10034 pic16_genLeftShiftLiteral (left,right,result,ic);
10038 /* shift count is unknown then we have to form
10039 a loop get the loop count in B : Note: we take
10040 only the lower order byte since shifting
10041 more that 32 bits make no sense anyway, ( the
10042 largest size of an object can be only 32 bits ) */
10045 pic16_aopOp(left,ic,FALSE);
10046 pic16_aopOp(result,ic,FALSE);
10048 /* now move the left to the result if they are not the
10050 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10051 AOP_SIZE(result) > 1) {
10053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10055 size = AOP_SIZE(result);
10058 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10059 if (*l == '@' && (IS_AOP_PREG(result))) {
10061 pic16_emitcode("mov","a,%s",l);
10062 pic16_aopPut(AOP(result),"a",offset);
10065 /* we don't know if left is a literal or a register, take care -- VR */
10066 mov2f(AOP(result), AOP(left), offset);
10072 size = AOP_SIZE(result);
10074 /* if it is only one byte then */
10076 if(optimized_for_speed) {
10077 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10078 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10079 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10080 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10081 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10082 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10083 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10084 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10085 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10086 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10087 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10088 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10091 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10093 tlbl = newiTempLabel(NULL);
10094 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10095 mov2f(AOP(result), AOP(left), 0);
10097 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10098 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10101 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10102 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10103 pic16_emitpLabel(tlbl->key);
10104 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10105 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10107 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10112 if (pic16_sameRegs(AOP(left),AOP(result))) {
10114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10116 tlbl = newiTempLabel(NULL);
10117 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10118 genMultiAsm(POC_RRCF, result, size,1);
10119 pic16_emitpLabel(tlbl->key);
10120 genMultiAsm(POC_RLCF, result, size,0);
10121 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10123 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10127 //tlbl = newiTempLabel(NULL);
10129 //tlbl1 = newiTempLabel(NULL);
10131 //reAdjustPreg(AOP(result));
10133 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10134 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10135 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10137 //pic16_emitcode("add","a,acc");
10138 //pic16_aopPut(AOP(result),"a",offset++);
10140 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10142 // pic16_emitcode("rlc","a");
10143 // pic16_aopPut(AOP(result),"a",offset++);
10145 //reAdjustPreg(AOP(result));
10147 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10148 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10151 tlbl = newiTempLabel(NULL);
10152 tlbl1= newiTempLabel(NULL);
10154 size = AOP_SIZE(result);
10157 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10161 /* offset should be 0, 1 or 3 */
10163 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10165 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10167 pic16_emitpcode(POC_MOVWF, pctemp);
10170 pic16_emitpLabel(tlbl->key);
10173 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10175 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10177 pic16_emitpcode(POC_DECFSZ, pctemp);
10178 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10179 pic16_emitpLabel(tlbl1->key);
10181 pic16_popReleaseTempReg(pctemp,1);
10185 pic16_freeAsmop (right,NULL,ic,TRUE);
10186 pic16_freeAsmop(left,NULL,ic,TRUE);
10187 pic16_freeAsmop(result,NULL,ic,TRUE);
10191 /*-----------------------------------------------------------------*/
10192 /* genrshOne - right shift a one byte quantity by known count */
10193 /*-----------------------------------------------------------------*/
10194 static void genrshOne (operand *result, operand *left,
10195 int shCount, int sign)
10197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10198 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10201 /*-----------------------------------------------------------------*/
10202 /* genrshTwo - right shift two bytes by known amount != 0 */
10203 /*-----------------------------------------------------------------*/
10204 static void genrshTwo (operand *result,operand *left,
10205 int shCount, int sign)
10207 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10208 /* if shCount >= 8 */
10209 if (shCount >= 8) {
10212 shiftR1Left2Result(left, MSB16, result, LSB,
10215 movLeft2Result(left, MSB16, result, LSB);
10217 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10220 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10221 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10225 /* 1 <= shCount <= 7 */
10227 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10230 /*-----------------------------------------------------------------*/
10231 /* shiftRLong - shift right one long from left to result */
10232 /* offl = LSB or MSB16 */
10233 /*-----------------------------------------------------------------*/
10234 static void shiftRLong (operand *left, int offl,
10235 operand *result, int sign)
10237 int size = AOP_SIZE(result);
10238 int same = pic16_sameRegs(AOP(left),AOP(result));
10240 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10242 if (same && (offl == MSB16)) { //shift one byte right
10243 for(i=MSB16;i<size;i++) {
10244 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10245 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10250 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10256 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10258 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10262 if(offl == MSB16) {
10263 /* add sign of "a" */
10264 pic16_addSign(result, MSB32, sign);
10268 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10270 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10271 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10275 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10277 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10282 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10285 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10286 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10291 /*-----------------------------------------------------------------*/
10292 /* genrshFour - shift four byte by a known amount != 0 */
10293 /*-----------------------------------------------------------------*/
10294 static void genrshFour (operand *result, operand *left,
10295 int shCount, int sign)
10297 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10298 /* if shifting more that 3 bytes */
10299 if(shCount >= 24 ) {
10302 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10304 movLeft2Result(left, MSB32, result, LSB);
10306 pic16_addSign(result, MSB16, sign);
10308 else if(shCount >= 16){
10311 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10313 movLeft2Result(left, MSB24, result, LSB);
10314 movLeft2Result(left, MSB32, result, MSB16);
10316 pic16_addSign(result, MSB24, sign);
10318 else if(shCount >= 8){
10321 shiftRLong(left, MSB16, result, sign);
10322 else if(shCount == 0){
10323 movLeft2Result(left, MSB16, result, LSB);
10324 movLeft2Result(left, MSB24, result, MSB16);
10325 movLeft2Result(left, MSB32, result, MSB24);
10326 pic16_addSign(result, MSB32, sign);
10328 else{ //shcount >= 2
10329 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10330 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10331 /* the last shift is signed */
10332 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10333 pic16_addSign(result, MSB32, sign);
10336 else{ /* 1 <= shCount <= 7 */
10338 shiftRLong(left, LSB, result, sign);
10340 shiftRLong(result, LSB, result, sign);
10343 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10344 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10345 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10350 /*-----------------------------------------------------------------*/
10351 /* genRightShiftLiteral - right shifting by known count */
10352 /*-----------------------------------------------------------------*/
10353 static void genRightShiftLiteral (operand *left,
10359 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10360 int lsize,res_size;
10362 pic16_freeAsmop(right,NULL,ic,TRUE);
10364 pic16_aopOp(left,ic,FALSE);
10365 pic16_aopOp(result,ic,FALSE);
10367 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10370 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10374 lsize = pic16_getDataSize(left);
10375 res_size = pic16_getDataSize(result);
10376 /* test the LEFT size !!! */
10378 /* I suppose that the left size >= result size */
10381 movLeft2Result(left, lsize, result, res_size);
10384 else if(shCount >= (lsize * 8)){
10386 if(res_size == 1) {
10387 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10389 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10390 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10395 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10396 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10397 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10399 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10404 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10409 switch (res_size) {
10411 genrshOne (result,left,shCount,sign);
10415 genrshTwo (result,left,shCount,sign);
10419 genrshFour (result,left,shCount,sign);
10427 pic16_freeAsmop(left,NULL,ic,TRUE);
10428 pic16_freeAsmop(result,NULL,ic,TRUE);
10431 #if !(USE_GENERIC_SIGNED_SHIFT)
10432 /*-----------------------------------------------------------------*/
10433 /* genSignedRightShift - right shift of signed number */
10434 /*-----------------------------------------------------------------*/
10435 static void genSignedRightShift (iCode *ic)
10437 operand *right, *left, *result;
10440 symbol *tlbl, *tlbl1 ;
10443 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10445 /* we do it the hard way put the shift count in b
10446 and loop thru preserving the sign */
10447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10449 right = IC_RIGHT(ic);
10450 left = IC_LEFT(ic);
10451 result = IC_RESULT(ic);
10453 pic16_aopOp(right,ic,FALSE);
10454 pic16_aopOp(left,ic,FALSE);
10455 pic16_aopOp(result,ic,FALSE);
10458 if ( AOP_TYPE(right) == AOP_LIT) {
10459 genRightShiftLiteral (left,right,result,ic,1);
10462 /* shift count is unknown then we have to form
10463 a loop get the loop count in B : Note: we take
10464 only the lower order byte since shifting
10465 more that 32 bits make no sense anyway, ( the
10466 largest size of an object can be only 32 bits ) */
10468 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10469 //pic16_emitcode("inc","b");
10470 //pic16_freeAsmop (right,NULL,ic,TRUE);
10471 //pic16_aopOp(left,ic,FALSE);
10472 //pic16_aopOp(result,ic,FALSE);
10474 /* now move the left to the result if they are not the
10476 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10477 AOP_SIZE(result) > 1) {
10479 size = AOP_SIZE(result);
10483 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10484 if (*l == '@' && IS_AOP_PREG(result)) {
10486 pic16_emitcode("mov","a,%s",l);
10487 pic16_aopPut(AOP(result),"a",offset);
10489 pic16_aopPut(AOP(result),l,offset);
10491 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10492 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10498 /* mov the highest order bit to OVR */
10499 tlbl = newiTempLabel(NULL);
10500 tlbl1= newiTempLabel(NULL);
10502 size = AOP_SIZE(result);
10505 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10509 /* offset should be 0, 1 or 3 */
10510 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10512 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10514 pic16_emitpcode(POC_MOVWF, pctemp);
10517 pic16_emitpLabel(tlbl->key);
10519 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10520 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10523 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10526 pic16_emitpcode(POC_DECFSZ, pctemp);
10527 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10528 pic16_emitpLabel(tlbl1->key);
10530 pic16_popReleaseTempReg(pctemp,1);
10532 size = AOP_SIZE(result);
10534 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10535 pic16_emitcode("rlc","a");
10536 pic16_emitcode("mov","ov,c");
10537 /* if it is only one byte then */
10539 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10541 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10542 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10543 pic16_emitcode("mov","c,ov");
10544 pic16_emitcode("rrc","a");
10545 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10546 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10547 pic16_aopPut(AOP(result),"a",0);
10551 reAdjustPreg(AOP(result));
10552 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10553 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10554 pic16_emitcode("mov","c,ov");
10556 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10558 pic16_emitcode("rrc","a");
10559 pic16_aopPut(AOP(result),"a",offset--);
10561 reAdjustPreg(AOP(result));
10562 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10563 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10568 pic16_freeAsmop(left,NULL,ic,TRUE);
10569 pic16_freeAsmop(result,NULL,ic,TRUE);
10570 pic16_freeAsmop(right,NULL,ic,TRUE);
10574 #if !(USE_GENERIC_SIGNED_SHIFT)
10575 #warning This implementation of genRightShift() is incomplete!
10576 /*-----------------------------------------------------------------*/
10577 /* genRightShift - generate code for right shifting */
10578 /*-----------------------------------------------------------------*/
10579 static void genRightShift (iCode *ic)
10581 operand *right, *left, *result;
10585 symbol *tlbl, *tlbl1 ;
10587 /* if signed then we do it the hard way preserve the
10588 sign bit moving it inwards */
10589 letype = getSpec(operandType(IC_LEFT(ic)));
10590 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10592 if (!SPEC_USIGN(letype)) {
10593 genSignedRightShift (ic);
10597 /* signed & unsigned types are treated the same : i.e. the
10598 signed is NOT propagated inwards : quoting from the
10599 ANSI - standard : "for E1 >> E2, is equivalent to division
10600 by 2**E2 if unsigned or if it has a non-negative value,
10601 otherwise the result is implementation defined ", MY definition
10602 is that the sign does not get propagated */
10604 right = IC_RIGHT(ic);
10605 left = IC_LEFT(ic);
10606 result = IC_RESULT(ic);
10608 pic16_aopOp(right,ic,FALSE);
10610 /* if the shift count is known then do it
10611 as efficiently as possible */
10612 if (AOP_TYPE(right) == AOP_LIT) {
10613 genRightShiftLiteral (left,right,result,ic, 0);
10617 /* shift count is unknown then we have to form
10618 a loop get the loop count in B : Note: we take
10619 only the lower order byte since shifting
10620 more that 32 bits make no sense anyway, ( the
10621 largest size of an object can be only 32 bits ) */
10623 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10624 pic16_emitcode("inc","b");
10625 pic16_aopOp(left,ic,FALSE);
10626 pic16_aopOp(result,ic,FALSE);
10628 /* now move the left to the result if they are not the
10630 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10631 AOP_SIZE(result) > 1) {
10633 size = AOP_SIZE(result);
10636 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10637 if (*l == '@' && IS_AOP_PREG(result)) {
10639 pic16_emitcode("mov","a,%s",l);
10640 pic16_aopPut(AOP(result),"a",offset);
10642 pic16_aopPut(AOP(result),l,offset);
10647 tlbl = newiTempLabel(NULL);
10648 tlbl1= newiTempLabel(NULL);
10649 size = AOP_SIZE(result);
10652 /* if it is only one byte then */
10655 tlbl = newiTempLabel(NULL);
10656 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10657 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10658 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10661 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10662 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10663 pic16_emitpLabel(tlbl->key);
10664 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10665 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10667 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10672 reAdjustPreg(AOP(result));
10673 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10674 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10677 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10679 pic16_emitcode("rrc","a");
10680 pic16_aopPut(AOP(result),"a",offset--);
10682 reAdjustPreg(AOP(result));
10684 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10685 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10688 pic16_freeAsmop(left,NULL,ic,TRUE);
10689 pic16_freeAsmop (right,NULL,ic,TRUE);
10690 pic16_freeAsmop(result,NULL,ic,TRUE);
10694 #if (USE_GENERIC_SIGNED_SHIFT)
10695 /*-----------------------------------------------------------------*/
10696 /* genGenericShift - generates code for left or right shifting */
10697 /*-----------------------------------------------------------------*/
10698 static void genGenericShift (iCode *ic, int isShiftLeft) {
10699 operand *left,*right, *result;
10701 int sign, signedCount;
10702 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10703 PIC_OPCODE pos_shift, neg_shift;
10707 right = IC_RIGHT(ic);
10708 left = IC_LEFT(ic);
10709 result = IC_RESULT(ic);
10711 pic16_aopOp(right,ic,FALSE);
10712 pic16_aopOp(left,ic,FALSE);
10713 pic16_aopOp(result,ic,FALSE);
10715 sign = !SPEC_USIGN(operandType (left));
10716 signedCount = !SPEC_USIGN(operandType (right));
10718 /* if the shift count is known then do it
10719 as efficiently as possible */
10720 if (AOP_TYPE(right) == AOP_LIT) {
10721 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10722 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10723 // we should modify right->aopu.aop_lit here!
10724 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10725 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10727 pic16_genLeftShiftLiteral (left,right,result,ic);
10729 genRightShiftLiteral (left,right,result,ic, sign);
10732 } // if (right is literal)
10734 /* shift count is unknown then we have to form a loop.
10735 * Note: we take only the lower order byte since shifting
10736 * more than 32 bits make no sense anyway, ( the
10737 * largest size of an object can be only 32 bits )
10738 * Note: we perform arithmetic shifts if the left operand is
10739 * signed and we do an (effective) right shift, i. e. we
10740 * shift in the sign bit from the left. */
10742 label_complete = newiTempLabel ( NULL );
10743 label_loop_pos = newiTempLabel ( NULL );
10744 label_loop_neg = NULL;
10745 label_negative = NULL;
10746 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10747 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10750 // additional labels needed
10751 label_loop_neg = newiTempLabel ( NULL );
10752 label_negative = newiTempLabel ( NULL );
10755 // copy source to result -- this will effectively truncate the left operand to the size of result!
10756 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10757 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10758 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10759 mov2f (AOP(result),AOP(left), offset);
10762 // if result is longer than left, fill with zeros (or sign)
10763 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10764 if (sign && AOP_SIZE(left) > 0) {
10765 // shift signed operand -- fill with sign
10766 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10767 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10768 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10769 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10770 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10773 // shift unsigned operand -- fill result with zeros
10774 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10775 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10778 } // if (size mismatch)
10780 pic16_mov2w (AOP(right), 0);
10781 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10782 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10785 // perform a shift by one (shift count is positive)
10786 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10787 // 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])
10788 pic16_emitpLabel (label_loop_pos->key);
10790 if (sign && (pos_shift == POC_RRCF)) {
10791 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10794 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10795 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10796 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10798 // perform a shift by one (shift count is positive)
10799 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10800 // 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])
10801 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10802 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10804 pic16_emitpLabel (label_loop_pos->key);
10805 if (sign && (pos_shift == POC_RRCF)) {
10806 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10809 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10810 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10811 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10812 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10816 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10818 pic16_emitpLabel (label_negative->key);
10819 // perform a shift by -1 (shift count is negative)
10820 // 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)
10822 pic16_emitpLabel (label_loop_neg->key);
10823 if (sign && (neg_shift == POC_RRCF)) {
10824 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10827 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10828 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10829 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10830 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10831 } // if (signedCount)
10833 pic16_emitpLabel (label_complete->key);
10836 pic16_freeAsmop (right,NULL,ic,TRUE);
10837 pic16_freeAsmop(left,NULL,ic,TRUE);
10838 pic16_freeAsmop(result,NULL,ic,TRUE);
10841 static void genLeftShift (iCode *ic) {
10842 genGenericShift (ic, 1);
10845 static void genRightShift (iCode *ic) {
10846 genGenericShift (ic, 0);
10851 void pic16_loadFSR0(operand *op)
10853 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10856 /*-----------------------------------------------------------------*/
10857 /* genUnpackBits - generates code for unpacking bits */
10858 /*-----------------------------------------------------------------*/
10859 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10863 sym_link *etype, *letype;
10864 int blen=0, bstr=0;
10868 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10869 etype = getSpec(operandType(result));
10870 letype = getSpec(operandType(left));
10872 // if(IS_BITFIELD(etype)) {
10873 blen = SPEC_BLEN(etype);
10874 bstr = SPEC_BSTR(etype);
10877 lbstr = SPEC_BSTR( letype );
10880 if((blen == 1) && (bstr < 8)) {
10881 /* it is a single bit, so use the appropriate bit instructions */
10882 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10884 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10886 if((ptype == POINTER) && (result)) {
10887 /* workaround to reduce the extra lfsr instruction */
10888 pic16_emitpcode(POC_BTFSC,
10889 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10891 pic16_emitpcode(POC_BTFSC,
10892 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10895 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10897 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10903 /* the following call to pic16_loadFSR0 is temporary until
10904 * optimization to handle single bit assignments is added
10905 * to the function. Until then use the old safe way! -- VR */
10906 pic16_loadFSR0( left );
10908 /* read the first byte */
10915 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10918 pic16_emitcode("clr","a");
10919 pic16_emitcode("movc","a","@a+dptr");
10924 /* if we have bitdisplacement then it fits */
10925 /* into this byte completely or if length is */
10926 /* less than a byte */
10927 if ((shCnt = SPEC_BSTR(etype)) ||
10928 (SPEC_BLEN(etype) <= 8)) {
10930 /* shift right acc */
10933 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10934 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10936 /* VR -- normally I would use the following, but since we use the hack,
10937 * to avoid the masking from AccRsh, why not mask it right now? */
10940 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10949 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10950 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10953 /* bit field did not fit in a byte */
10954 rlen = SPEC_BLEN(etype) - 8;
10955 pic16_aopPut(AOP(result),"a",offset++);
10962 pic16_emitcode("inc","%s",rname);
10963 pic16_emitcode("mov","a,@%s",rname);
10967 pic16_emitcode("inc","%s",rname);
10968 pic16_emitcode("movx","a,@%s",rname);
10972 pic16_emitcode("inc","dptr");
10973 pic16_emitcode("movx","a,@dptr");
10977 pic16_emitcode("clr","a");
10978 pic16_emitcode("inc","dptr");
10979 pic16_emitcode("movc","a","@a+dptr");
10983 pic16_emitcode("inc","dptr");
10984 pic16_emitcode("lcall","__gptrget");
10989 /* if we are done */
10993 pic16_aopPut(AOP(result),"a",offset++);
10998 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10999 pic16_aopPut(AOP(result),"a",offset);
11006 static void genDataPointerGet(operand *left,
11010 int size, offset = 0, leoffset=0 ;
11012 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11013 pic16_aopOp(result, ic, FALSE);
11015 size = AOP_SIZE(result);
11016 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11020 /* The following tests may save a redudant movff instruction when
11021 * accessing unions */
11023 /* if they are the same */
11024 if (operandsEqu (left, result)) {
11025 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11031 /* if they are the same registers */
11032 if (pic16_sameRegs(AOP(left),AOP(result))) {
11033 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11039 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11040 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11041 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11048 if ( AOP_TYPE(left) == AOP_PCODE) {
11049 fprintf(stderr,"genDataPointerGet %s, %d\n",
11050 AOP(left)->aopu.pcop->name,
11051 (AOP(left)->aopu.pcop->type == PO_DIR)?
11052 PCOR(AOP(left)->aopu.pcop)->instance:
11053 PCOI(AOP(left)->aopu.pcop)->offset);
11057 if(AOP(left)->aopu.pcop->type == PO_DIR)
11058 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11060 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11063 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11065 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11066 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11067 pic16_mov2w(AOP(left), offset); // patch 8
11068 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11070 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11071 pic16_popGet(AOP(left), offset), //patch 8
11072 pic16_popGet(AOP(result), offset)));
11080 pic16_freeAsmop(result,NULL,ic,TRUE);
11085 /*-----------------------------------------------------------------*/
11086 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11087 /*-----------------------------------------------------------------*/
11088 static void genNearPointerGet (operand *left,
11093 //regs *preg = NULL ;
11094 sym_link *rtype, *retype;
11095 sym_link *ltype = operandType(left);
11099 rtype = operandType(result);
11100 retype= getSpec(rtype);
11102 pic16_aopOp(left,ic,FALSE);
11104 // pic16_DumpOp("(left)",left);
11105 // pic16_DumpOp("(result)",result);
11107 /* if left is rematerialisable and
11108 * result is not bit variable type and
11109 * the left is pointer to data space i.e
11110 * lower 128 bytes of space */
11112 if (AOP_TYPE(left) == AOP_PCODE
11113 && !IS_BITFIELD(retype)
11114 && DCL_TYPE(ltype) == POINTER) {
11116 genDataPointerGet (left,result,ic);
11117 pic16_freeAsmop(left, NULL, ic, TRUE);
11121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11122 pic16_aopOp (result,ic,FALSE);
11124 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11127 if(IS_BITFIELD( retype )
11128 && (SPEC_BLEN(operandType(result))==1)
11132 int bitstrt, bytestrt;
11134 /* if this is bitfield of size 1, see if we are checking the value
11135 * of a single bit in an if-statement,
11136 * if yes, then don't generate usual code, but execute the
11137 * genIfx directly -- VR */
11141 /* CHECK: if next iCode is IFX
11142 * and current result operand is nextic's conditional operand
11143 * and current result operand live ranges ends at nextic's key number
11145 if((nextic->op == IFX)
11146 && (result == IC_COND(nextic))
11147 && (OP_LIVETO(result) == nextic->seq)
11149 /* everything is ok then */
11150 /* find a way to optimize the genIfx iCode */
11152 bytestrt = SPEC_BSTR(operandType(result))/8;
11153 bitstrt = SPEC_BSTR(operandType(result))%8;
11155 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11157 genIfxpCOpJump(nextic, jop);
11159 pic16_freeAsmop(left, NULL, ic, TRUE);
11160 pic16_freeAsmop(result, NULL, ic, TRUE);
11167 /* if the value is already in a pointer register
11168 * then don't need anything more */
11169 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11170 /* otherwise get a free pointer register */
11171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11173 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11174 /* bitfields will be handled by genUnpackBits */
11175 if(!IS_BITFIELD(retype)) {
11177 if(is_LitAOp( AOP(left) )) {
11178 pic16_loadFSR0( left );
11180 // set up FSR0 with address from left
11181 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11182 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11187 /* if bitfield then unpack the bits */
11188 if (IS_BITFIELD(retype))
11189 genUnpackBits (result, left, NULL, POINTER);
11191 /* we have can just get the values */
11192 int size = AOP_SIZE(result);
11195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11197 /* fsr0 is loaded already -- VR */
11198 // pic16_loadFSR0( left );
11200 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11201 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11204 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11205 pic16_popGet(AOP(result), offset++)));
11207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11208 pic16_popGet(AOP(result), offset++)));
11212 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11213 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11215 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11219 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11221 pic16_emitcode("mov","a,@%s",rname);
11222 pic16_aopPut(AOP(result),"a",offset);
11224 sprintf(buffer,"@%s",rname);
11225 pic16_aopPut(AOP(result),buffer,offset);
11229 pic16_emitcode("inc","%s",rname);
11234 /* now some housekeeping stuff */
11236 /* we had to allocate for this iCode */
11237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11238 pic16_freeAsmop(NULL,aop,ic,TRUE);
11240 /* we did not allocate which means left
11241 * already in a pointer register, then
11242 * if size > 0 && this could be used again
11243 * we have to point it back to where it
11245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11246 if (AOP_SIZE(result) > 1
11247 && !OP_SYMBOL(left)->remat
11248 && ( OP_SYMBOL(left)->liveTo > ic->seq
11250 // int size = AOP_SIZE(result) - 1;
11252 // pic16_emitcode("dec","%s",rname);
11257 pic16_freeAsmop(left,NULL,ic,TRUE);
11258 pic16_freeAsmop(result,NULL,ic,TRUE);
11261 /*-----------------------------------------------------------------*/
11262 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11263 /*-----------------------------------------------------------------*/
11264 static void genPagedPointerGet (operand *left,
11269 regs *preg = NULL ;
11271 sym_link *rtype, *retype;
11273 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11275 rtype = operandType(result);
11276 retype= getSpec(rtype);
11278 pic16_aopOp(left,ic,FALSE);
11280 /* if the value is already in a pointer register
11281 then don't need anything more */
11282 if (!AOP_INPREG(AOP(left))) {
11283 /* otherwise get a free pointer register */
11285 preg = getFreePtr(ic,&aop,FALSE);
11286 pic16_emitcode("mov","%s,%s",
11288 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11289 rname = preg->name ;
11291 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11293 pic16_freeAsmop(left,NULL,ic,TRUE);
11294 pic16_aopOp (result,ic,FALSE);
11296 /* if bitfield then unpack the bits */
11297 if (IS_BITFIELD(retype))
11298 genUnpackBits (result,left,rname,PPOINTER);
11300 /* we have can just get the values */
11301 int size = AOP_SIZE(result);
11306 pic16_emitcode("movx","a,@%s",rname);
11307 pic16_aopPut(AOP(result),"a",offset);
11312 pic16_emitcode("inc","%s",rname);
11316 /* now some housekeeping stuff */
11318 /* we had to allocate for this iCode */
11319 pic16_freeAsmop(NULL,aop,ic,TRUE);
11321 /* we did not allocate which means left
11322 already in a pointer register, then
11323 if size > 0 && this could be used again
11324 we have to point it back to where it
11326 if (AOP_SIZE(result) > 1 &&
11327 !OP_SYMBOL(left)->remat &&
11328 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11330 int size = AOP_SIZE(result) - 1;
11332 pic16_emitcode("dec","%s",rname);
11337 pic16_freeAsmop(result,NULL,ic,TRUE);
11342 /*-----------------------------------------------------------------*/
11343 /* genFarPointerGet - gget value from far space */
11344 /*-----------------------------------------------------------------*/
11345 static void genFarPointerGet (operand *left,
11346 operand *result, iCode *ic)
11349 sym_link *retype = getSpec(operandType(result));
11351 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11353 pic16_aopOp(left,ic,FALSE);
11355 /* if the operand is already in dptr
11356 then we do nothing else we move the value to dptr */
11357 if (AOP_TYPE(left) != AOP_STR) {
11358 /* if this is remateriazable */
11359 if (AOP_TYPE(left) == AOP_IMMD)
11360 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11361 else { /* we need to get it byte by byte */
11362 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11363 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11364 if (options.model == MODEL_FLAT24)
11366 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11370 /* so dptr know contains the address */
11371 pic16_freeAsmop(left,NULL,ic,TRUE);
11372 pic16_aopOp(result,ic,FALSE);
11374 /* if bit then unpack */
11375 if (IS_BITFIELD(retype))
11376 genUnpackBits(result,left,"dptr",FPOINTER);
11378 size = AOP_SIZE(result);
11382 pic16_emitcode("movx","a,@dptr");
11383 pic16_aopPut(AOP(result),"a",offset++);
11385 pic16_emitcode("inc","dptr");
11389 pic16_freeAsmop(result,NULL,ic,TRUE);
11393 /*-----------------------------------------------------------------*/
11394 /* genCodePointerGet - get value from code space */
11395 /*-----------------------------------------------------------------*/
11396 static void genCodePointerGet (operand *left,
11397 operand *result, iCode *ic)
11400 sym_link *retype = getSpec(operandType(result));
11402 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11404 pic16_aopOp(left,ic,FALSE);
11406 /* if the operand is already in dptr
11407 then we do nothing else we move the value to dptr */
11408 if (AOP_TYPE(left) != AOP_STR) {
11409 /* if this is remateriazable */
11410 if (AOP_TYPE(left) == AOP_IMMD)
11411 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11412 else { /* we need to get it byte by byte */
11413 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11414 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11415 if (options.model == MODEL_FLAT24)
11417 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11421 /* so dptr know contains the address */
11422 pic16_freeAsmop(left,NULL,ic,TRUE);
11423 pic16_aopOp(result,ic,FALSE);
11425 /* if bit then unpack */
11426 if (IS_BITFIELD(retype))
11427 genUnpackBits(result,left,"dptr",CPOINTER);
11429 size = AOP_SIZE(result);
11433 pic16_emitcode("clr","a");
11434 pic16_emitcode("movc","a,@a+dptr");
11435 pic16_aopPut(AOP(result),"a",offset++);
11437 pic16_emitcode("inc","dptr");
11441 pic16_freeAsmop(result,NULL,ic,TRUE);
11446 /*-----------------------------------------------------------------*/
11447 /* genGenPointerGet - gget value from generic pointer space */
11448 /*-----------------------------------------------------------------*/
11449 static void genGenPointerGet (operand *left,
11450 operand *result, iCode *ic)
11452 int size, offset, lit;
11453 sym_link *retype = getSpec(operandType(result));
11455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11456 pic16_aopOp(left,ic,FALSE);
11457 pic16_aopOp(result,ic,FALSE);
11458 size = AOP_SIZE(result);
11460 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11462 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11464 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11465 // load FSR0 from immediate
11466 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11468 // pic16_loadFSR0( left );
11473 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11475 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11482 else { /* we need to get it byte by byte */
11483 // set up FSR0 with address from left
11484 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11485 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11491 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11500 /* if bit then unpack */
11501 if (IS_BITFIELD(retype))
11502 genUnpackBits(result,left,"BAD",GPOINTER);
11505 pic16_freeAsmop(left,NULL,ic,TRUE);
11506 pic16_freeAsmop(result,NULL,ic,TRUE);
11512 /*-----------------------------------------------------------------*/
11513 /* genGenPointerGet - gget value from generic pointer space */
11514 /*-----------------------------------------------------------------*/
11515 static void genGenPointerGet (operand *left,
11516 operand *result, iCode *ic)
11518 int size, offset, lit;
11519 sym_link *retype = getSpec(operandType(result));
11522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11523 pic16_aopOp(left,ic,FALSE);
11524 pic16_aopOp(result,ic,FALSE);
11525 size = AOP_SIZE(result);
11527 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11529 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11531 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11532 // load FSR0 from immediate
11533 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11535 werror(W_POSSBUG2, __FILE__, __LINE__);
11540 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11542 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11549 } else { /* we need to get it byte by byte */
11551 /* set up WREG:PRODL:FSR0L with address from left */
11552 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11553 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11557 case 1: strcpy(fgptrget, "__gptrget1"); break;
11558 case 2: strcpy(fgptrget, "__gptrget2"); break;
11559 case 3: strcpy(fgptrget, "__gptrget3"); break;
11560 case 4: strcpy(fgptrget, "__gptrget4"); break;
11562 werror(W_POSSBUG2, __FILE__, __LINE__);
11566 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11568 assignResultValue(result, 1);
11573 sym = newSymbol( fgptrget, 0 );
11574 strcpy(sym->rname, fgptrget);
11575 checkAddSym(&externs, sym);
11577 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11583 /* if bit then unpack */
11584 if (IS_BITFIELD(retype))
11585 genUnpackBits(result,left,"BAD",GPOINTER);
11588 pic16_freeAsmop(left,NULL,ic,TRUE);
11589 pic16_freeAsmop(result,NULL,ic,TRUE);
11592 /*-----------------------------------------------------------------*/
11593 /* genConstPointerGet - get value from const generic pointer space */
11594 /*-----------------------------------------------------------------*/
11595 static void genConstPointerGet (operand *left,
11596 operand *result, iCode *ic)
11598 //sym_link *retype = getSpec(operandType(result));
11599 // symbol *albl = newiTempLabel(NULL); // patch 15
11600 // symbol *blbl = newiTempLabel(NULL); //
11601 // PIC_OPCODE poc; // patch 15
11605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11606 pic16_aopOp(left,ic,FALSE);
11607 pic16_aopOp(result,ic,TRUE);
11608 size = AOP_SIZE(result);
11610 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11612 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11614 // set up table pointer
11615 if( (AOP_TYPE(left) == AOP_PCODE)
11616 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11617 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11619 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11620 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11621 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11622 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11623 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11624 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11626 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11627 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11628 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11632 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11633 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11637 pic16_freeAsmop(left,NULL,ic,TRUE);
11638 pic16_freeAsmop(result,NULL,ic,TRUE);
11642 /*-----------------------------------------------------------------*/
11643 /* genPointerGet - generate code for pointer get */
11644 /*-----------------------------------------------------------------*/
11645 static void genPointerGet (iCode *ic)
11647 operand *left, *result ;
11648 sym_link *type, *etype;
11653 left = IC_LEFT(ic);
11654 result = IC_RESULT(ic) ;
11656 /* depending on the type of pointer we need to
11657 move it to the correct pointer register */
11658 type = operandType(left);
11659 etype = getSpec(type);
11662 if (IS_PTR_CONST(type))
11664 if (IS_CODEPTR(type))
11666 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11668 /* if left is of type of pointer then it is simple */
11669 if (IS_PTR(type) && !IS_FUNC(type->next))
11670 p_type = DCL_TYPE(type);
11672 /* we have to go by the storage class */
11673 p_type = PTR_TYPE(SPEC_OCLS(etype));
11675 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11677 if (SPEC_OCLS(etype)->codesp ) {
11678 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11679 //p_type = CPOINTER ;
11681 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11682 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11683 /*p_type = FPOINTER ;*/
11685 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11686 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11687 /* p_type = PPOINTER; */
11689 if (SPEC_OCLS(etype) == idata ) {
11690 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11691 /* p_type = IPOINTER; */
11693 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11694 /* p_type = POINTER ; */
11698 /* now that we have the pointer type we assign
11699 the pointer values */
11703 genNearPointerGet (left,result,ic);
11707 genPagedPointerGet(left,result,ic);
11711 genFarPointerGet (left,result,ic);
11715 genConstPointerGet (left,result,ic);
11716 //pic16_emitcodePointerGet (left,result,ic);
11721 if (IS_PTR_CONST(type))
11722 genConstPointerGet (left,result,ic);
11725 genGenPointerGet (left,result,ic);
11729 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11730 "genPointerGet: illegal pointer type");
11735 /*-----------------------------------------------------------------*/
11736 /* genPackBits - generates code for packed bit storage */
11737 /*-----------------------------------------------------------------*/
11738 static void genPackBits (sym_link *etype , operand *result,
11740 char *rname, int p_type)
11749 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11750 blen = SPEC_BLEN(etype);
11751 bstr = SPEC_BSTR(etype);
11753 retype = getSpec(operandType(right));
11755 if(AOP_TYPE(right) == AOP_LIT) {
11756 if((blen == 1) && (bstr < 8)) {
11758 /* it is a single bit, so use the appropriate bit instructions */
11760 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11762 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11763 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11764 if((p_type == POINTER) && (result)) {
11765 /* workaround to reduce the extra lfsr instruction */
11767 pic16_emitpcode(POC_BSF,
11768 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11770 pic16_emitpcode(POC_BCF,
11771 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11774 pic16_loadFSR0( result );
11776 pic16_emitpcode(POC_BSF,
11777 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11779 pic16_emitpcode(POC_BCF,
11780 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11787 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11790 if(IS_BITFIELD(retype)
11791 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11795 rblen = SPEC_BLEN( retype );
11796 rbstr = SPEC_BSTR( retype );
11799 if(IS_BITFIELD(etype)) {
11800 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11801 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11803 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11806 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11808 if(IS_BITFIELD(etype)) {
11809 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11811 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11814 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11818 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11820 /* if the bit length is less than or */
11821 /* it exactly fits a byte then */
11822 if((shCnt=SPEC_BSTR(etype))
11823 || SPEC_BLEN(etype) <= 8 ) {
11824 int fsr0_setup = 0;
11826 if (blen != 8 || bstr != 0) {
11827 // we need to combine the value with the old value
11828 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11830 /* shift left acc */
11833 /* using PRODH as a temporary register here */
11834 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11836 /* get old value */
11840 pic16_loadFSR0( result );
11842 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11843 // pic16_emitcode ("mov","b,a");
11844 // pic16_emitcode("mov","a,@%s",rname);
11848 if (AOP(result)->aopu.aop_reg[2]) {
11849 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11850 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11851 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11852 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11853 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11856 sym = newSymbol( "__gptrget1", 0 );
11857 strcpy(sym->rname, "__gptrget1");
11858 checkAddSym(&externs, sym);
11861 // data pointer (just 2 byte given)
11862 pic16_loadFSR0( result );
11864 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11867 // warnings will be emitted below
11868 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11869 //werror(W_POSSBUG2, __FILE__, __LINE__);
11873 assert (0 && "invalid pointer type specified");
11877 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11878 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11879 (unsigned char)(0xff >> (8-bstr))) ));
11880 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11881 } // if (blen != 8 || bstr != 0)
11883 /* write new value back */
11887 if (!fsr0_setup) pic16_loadFSR0( result );
11888 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11892 if (AOP(result)->aopu.aop_reg[2]) {
11893 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11894 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11895 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11896 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11897 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11898 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11901 sym = newSymbol( "__gptrput1", 0 );
11902 strcpy(sym->rname, "__gptrput1");
11903 checkAddSym(&externs, sym);
11906 // data pointer (just 2 byte given)
11907 if (!fsr0_setup) pic16_loadFSR0( result );
11908 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11911 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11912 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11913 werror(W_POSSBUG2, __FILE__, __LINE__);
11917 assert (0 && "invalid pointer type specified");
11926 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11927 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11932 if ( SPEC_BLEN(etype) <= 8 )
11935 pic16_emitcode("inc","%s",rname);
11936 rLen = SPEC_BLEN(etype) ;
11940 /* now generate for lengths greater than one byte */
11943 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11953 pic16_emitcode("mov","@%s,a",rname);
11955 pic16_emitcode("mov","@%s,%s",rname,l);
11960 pic16_emitcode("movx","@dptr,a");
11965 DEBUGpic16_emitcode(";lcall","__gptrput");
11968 pic16_emitcode ("inc","%s",rname);
11973 /* last last was not complete */
11975 /* save the byte & read byte */
11978 pic16_emitcode ("mov","b,a");
11979 pic16_emitcode("mov","a,@%s",rname);
11983 pic16_emitcode ("mov","b,a");
11984 pic16_emitcode("movx","a,@dptr");
11988 pic16_emitcode ("push","b");
11989 pic16_emitcode ("push","acc");
11990 pic16_emitcode ("lcall","__gptrget");
11991 pic16_emitcode ("pop","b");
11995 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11996 pic16_emitcode ("orl","a,b");
11999 if (p_type == GPOINTER)
12000 pic16_emitcode("pop","b");
12005 pic16_emitcode("mov","@%s,a",rname);
12009 pic16_emitcode("movx","@dptr,a");
12013 DEBUGpic16_emitcode(";lcall","__gptrput");
12017 /*-----------------------------------------------------------------*/
12018 /* genDataPointerSet - remat pointer to data space */
12019 /*-----------------------------------------------------------------*/
12020 static void genDataPointerSet(operand *right,
12024 int size, offset = 0, resoffset=0 ;
12026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12027 pic16_aopOp(right,ic,FALSE);
12029 size = AOP_SIZE(right);
12031 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12034 if ( AOP_TYPE(result) == AOP_PCODE) {
12035 fprintf(stderr,"genDataPointerSet %s, %d\n",
12036 AOP(result)->aopu.pcop->name,
12037 (AOP(result)->aopu.pcop->type == PO_DIR)?
12038 PCOR(AOP(result)->aopu.pcop)->instance:
12039 PCOI(AOP(result)->aopu.pcop)->offset);
12043 if(AOP(result)->aopu.pcop->type == PO_DIR)
12044 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12047 if (AOP_TYPE(right) == AOP_LIT) {
12050 if(!IS_FLOAT(operandType( right )))
12051 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12054 unsigned long lit_int;
12058 /* take care if literal is a float */
12059 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12060 lit = info.lit_int;
12063 lit = lit >> (8*offset);
12065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12068 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12071 pic16_mov2w(AOP(right), offset);
12072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12078 pic16_freeAsmop(right,NULL,ic,TRUE);
12083 /*-----------------------------------------------------------------*/
12084 /* genNearPointerSet - pic16_emitcode for near pointer put */
12085 /*-----------------------------------------------------------------*/
12086 static void genNearPointerSet (operand *right,
12093 sym_link *ptype = operandType(result);
12094 sym_link *resetype;
12096 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12097 retype= getSpec(operandType(right));
12098 resetype = getSpec(operandType(result));
12100 pic16_aopOp(result,ic,FALSE);
12102 /* if the result is rematerializable &
12103 * in data space & not a bit variable */
12105 /* and result is not a bit variable */
12106 if (AOP_TYPE(result) == AOP_PCODE
12107 // && AOP_TYPE(result) == AOP_IMMD
12108 && DCL_TYPE(ptype) == POINTER
12109 && !IS_BITFIELD(retype)
12110 && !IS_BITFIELD(resetype)) {
12112 genDataPointerSet (right,result,ic);
12113 pic16_freeAsmop(result,NULL,ic,TRUE);
12117 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12118 pic16_aopOp(right,ic,FALSE);
12119 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12121 /* if the value is already in a pointer register
12122 * then don't need anything more */
12123 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12124 /* otherwise get a free pointer register */
12125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12127 // if( (AOP_TYPE(result) == AOP_PCODE)
12128 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12129 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12130 if(is_LitAOp( AOP(result) ))
12132 if(!IS_BITFIELD(resetype))
12133 pic16_loadFSR0( result ); // patch 10
12135 if(!IS_BITFIELD(resetype)) {
12136 // set up FSR0 with address of result
12137 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12138 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12144 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12146 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12148 // pic16_loadFSR0( result );
12150 /* if bitfield then unpack the bits */
12151 if (IS_BITFIELD(resetype)) {
12152 genPackBits (resetype, result, right, NULL, POINTER);
12154 /* we have can just get the values */
12155 int size = AOP_SIZE(right);
12158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12160 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12163 //pic16_emitcode("mov","@%s,a",rname);
12164 pic16_emitcode("movf","indf0,w ;1");
12167 if (AOP_TYPE(right) == AOP_LIT) {
12168 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12170 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12172 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12174 } else { // no literal
12176 pic16_emitpcode(POC_MOVFF,
12177 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12178 pic16_popCopyReg(&pic16_pc_postinc0)));
12180 pic16_emitpcode(POC_MOVFF,
12181 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12182 pic16_popCopyReg(&pic16_pc_indf0)));
12190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12191 /* now some housekeeping stuff */
12193 /* we had to allocate for this iCode */
12194 pic16_freeAsmop(NULL,aop,ic,TRUE);
12196 /* we did not allocate which means left
12197 * already in a pointer register, then
12198 * if size > 0 && this could be used again
12199 * we have to point it back to where it
12201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12202 if (AOP_SIZE(right) > 1
12203 && !OP_SYMBOL(result)->remat
12204 && ( OP_SYMBOL(result)->liveTo > ic->seq
12207 int size = AOP_SIZE(right) - 1;
12210 pic16_emitcode("decf","fsr0,f");
12211 //pic16_emitcode("dec","%s",rname);
12215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12218 pic16_freeAsmop(right,NULL,ic,TRUE);
12219 pic16_freeAsmop(result,NULL,ic,TRUE);
12222 /*-----------------------------------------------------------------*/
12223 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12224 /*-----------------------------------------------------------------*/
12225 static void genPagedPointerSet (operand *right,
12230 regs *preg = NULL ;
12234 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12236 retype= getSpec(operandType(right));
12238 pic16_aopOp(result,ic,FALSE);
12240 /* if the value is already in a pointer register
12241 then don't need anything more */
12242 if (!AOP_INPREG(AOP(result))) {
12243 /* otherwise get a free pointer register */
12245 preg = getFreePtr(ic,&aop,FALSE);
12246 pic16_emitcode("mov","%s,%s",
12248 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12249 rname = preg->name ;
12251 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12253 pic16_freeAsmop(result,NULL,ic,TRUE);
12254 pic16_aopOp (right,ic,FALSE);
12256 /* if bitfield then unpack the bits */
12257 if (IS_BITFIELD(retype))
12258 genPackBits (retype,result,right,rname,PPOINTER);
12260 /* we have can just get the values */
12261 int size = AOP_SIZE(right);
12265 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12268 pic16_emitcode("movx","@%s,a",rname);
12271 pic16_emitcode("inc","%s",rname);
12277 /* now some housekeeping stuff */
12279 /* we had to allocate for this iCode */
12280 pic16_freeAsmop(NULL,aop,ic,TRUE);
12282 /* we did not allocate which means left
12283 already in a pointer register, then
12284 if size > 0 && this could be used again
12285 we have to point it back to where it
12287 if (AOP_SIZE(right) > 1 &&
12288 !OP_SYMBOL(result)->remat &&
12289 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12291 int size = AOP_SIZE(right) - 1;
12293 pic16_emitcode("dec","%s",rname);
12298 pic16_freeAsmop(right,NULL,ic,TRUE);
12303 /*-----------------------------------------------------------------*/
12304 /* genFarPointerSet - set value from far space */
12305 /*-----------------------------------------------------------------*/
12306 static void genFarPointerSet (operand *right,
12307 operand *result, iCode *ic)
12310 sym_link *retype = getSpec(operandType(right));
12312 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12313 pic16_aopOp(result,ic,FALSE);
12315 /* if the operand is already in dptr
12316 then we do nothing else we move the value to dptr */
12317 if (AOP_TYPE(result) != AOP_STR) {
12318 /* if this is remateriazable */
12319 if (AOP_TYPE(result) == AOP_IMMD)
12320 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12321 else { /* we need to get it byte by byte */
12322 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12323 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12324 if (options.model == MODEL_FLAT24)
12326 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12330 /* so dptr know contains the address */
12331 pic16_freeAsmop(result,NULL,ic,TRUE);
12332 pic16_aopOp(right,ic,FALSE);
12334 /* if bit then unpack */
12335 if (IS_BITFIELD(retype))
12336 genPackBits(retype,result,right,"dptr",FPOINTER);
12338 size = AOP_SIZE(right);
12342 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12344 pic16_emitcode("movx","@dptr,a");
12346 pic16_emitcode("inc","dptr");
12350 pic16_freeAsmop(right,NULL,ic,TRUE);
12353 /*-----------------------------------------------------------------*/
12354 /* genGenPointerSet - set value from generic pointer space */
12355 /*-----------------------------------------------------------------*/
12357 static void genGenPointerSet (operand *right,
12358 operand *result, iCode *ic)
12360 int i, size, offset, lit;
12361 sym_link *retype = getSpec(operandType(right));
12363 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12365 pic16_aopOp(result,ic,FALSE);
12366 pic16_aopOp(right,ic,FALSE);
12367 size = AOP_SIZE(right);
12370 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12372 /* if the operand is already in dptr
12373 then we do nothing else we move the value to dptr */
12374 if (AOP_TYPE(result) != AOP_STR) {
12375 /* if this is remateriazable */
12376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12377 // WARNING: anythig until "else" is untested!
12378 if (AOP_TYPE(result) == AOP_IMMD) {
12379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12380 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12381 // load FSR0 from immediate
12382 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12386 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12388 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12394 else { /* we need to get it byte by byte */
12395 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12396 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12398 // set up FSR0 with address of result
12399 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12400 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12402 /* hack hack! see if this the FSR. If so don't load W */
12403 if(AOP_TYPE(right) != AOP_ACC) {
12405 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12407 if(AOP_TYPE(right) == AOP_LIT)
12410 // note: pic16_popGet handles sign extension
12411 for(i=0;i<size;i++) {
12412 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12414 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12416 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12421 for(i=0;i<size;i++) {
12423 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12424 pic16_popCopyReg(&pic16_pc_postinc0)));
12426 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12427 pic16_popCopyReg(&pic16_pc_indf0)));
12433 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12434 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12436 } // if (AOP_TYPE(result) != AOP_IMMD)
12438 } // if (AOP_TYPE(result) != AOP_STR)
12439 /* so dptr know contains the address */
12442 /* if bit then unpack */
12443 if (IS_BITFIELD(retype))
12444 genPackBits(retype,result,right,"dptr",GPOINTER);
12446 size = AOP_SIZE(right);
12449 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12451 // set up FSR0 with address of result
12452 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12453 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12456 if (AOP_TYPE(right) == AOP_LIT) {
12457 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12459 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12461 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12463 } else { // no literal
12465 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12475 pic16_freeAsmop(right,NULL,ic,TRUE);
12476 pic16_freeAsmop(result,NULL,ic,TRUE);
12480 static void genGenPointerSet (operand *right,
12481 operand *result, iCode *ic)
12484 sym_link *retype = getSpec(operandType(right));
12487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12489 pic16_aopOp(result,ic,FALSE);
12490 pic16_aopOp(right,ic,FALSE);
12491 size = AOP_SIZE(right);
12493 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12496 /* if bit then unpack */
12497 if (IS_BITFIELD(retype)) {
12498 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12499 genPackBits(retype,result,right,"dptr",GPOINTER);
12503 size = AOP_SIZE(right);
12505 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12509 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12511 /* value of right+0 is placed on stack, which will be retrieved
12512 * by the support function this restoring the stack. The important
12513 * thing is that there is no need to manually restore stack pointer
12515 pushaop(AOP(right), 0);
12516 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12517 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12518 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12519 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12521 /* load address to write to in WREG:FSR0H:FSR0L */
12522 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12523 pic16_popCopyReg(&pic16_pc_fsr0l)));
12524 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12525 pic16_popCopyReg(&pic16_pc_prodl)));
12526 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12529 /* put code here */
12531 case 1: strcpy(fgptrput, "__gptrput1"); break;
12532 case 2: strcpy(fgptrput, "__gptrput2"); break;
12533 case 3: strcpy(fgptrput, "__gptrput3"); break;
12534 case 4: strcpy(fgptrput, "__gptrput4"); break;
12536 werror(W_POSSBUG2, __FILE__, __LINE__);
12540 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12545 sym = newSymbol( fgptrput, 0 );
12546 strcpy(sym->rname, fgptrput);
12547 checkAddSym(&externs, sym);
12551 pic16_freeAsmop(right,NULL,ic,TRUE);
12552 pic16_freeAsmop(result,NULL,ic,TRUE);
12555 /*-----------------------------------------------------------------*/
12556 /* genPointerSet - stores the value into a pointer location */
12557 /*-----------------------------------------------------------------*/
12558 static void genPointerSet (iCode *ic)
12560 operand *right, *result ;
12561 sym_link *type, *etype;
12566 right = IC_RIGHT(ic);
12567 result = IC_RESULT(ic) ;
12569 /* depending on the type of pointer we need to
12570 move it to the correct pointer register */
12571 type = operandType(result);
12572 etype = getSpec(type);
12573 /* if left is of type of pointer then it is simple */
12574 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12575 p_type = DCL_TYPE(type);
12578 /* we have to go by the storage class */
12579 p_type = PTR_TYPE(SPEC_OCLS(etype));
12581 /* if (SPEC_OCLS(etype)->codesp ) { */
12582 /* p_type = CPOINTER ; */
12585 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12586 /* p_type = FPOINTER ; */
12588 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12589 /* p_type = PPOINTER ; */
12591 /* if (SPEC_OCLS(etype) == idata ) */
12592 /* p_type = IPOINTER ; */
12594 /* p_type = POINTER ; */
12597 /* now that we have the pointer type we assign
12598 the pointer values */
12602 genNearPointerSet (right,result,ic);
12606 genPagedPointerSet (right,result,ic);
12610 genFarPointerSet (right,result,ic);
12614 genGenPointerSet (right,result,ic);
12618 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12619 "genPointerSet: illegal pointer type");
12623 /*-----------------------------------------------------------------*/
12624 /* genIfx - generate code for Ifx statement */
12625 /*-----------------------------------------------------------------*/
12626 static void genIfx (iCode *ic, iCode *popIc)
12628 operand *cond = IC_COND(ic);
12633 pic16_aopOp(cond,ic,FALSE);
12635 /* get the value into acc */
12636 if (AOP_TYPE(cond) != AOP_CRY)
12637 pic16_toBoolean(cond);
12640 /* the result is now in the accumulator */
12641 pic16_freeAsmop(cond,NULL,ic,TRUE);
12643 /* if there was something to be popped then do it */
12647 /* if the condition is a bit variable */
12648 if (isbit && IS_ITEMP(cond) &&
12650 genIfxJump(ic,"c");
12651 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12653 if (isbit && !IS_ITEMP(cond))
12654 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12656 genIfxJump(ic,"a");
12661 /*-----------------------------------------------------------------*/
12662 /* genAddrOf - generates code for address of */
12663 /*-----------------------------------------------------------------*/
12664 static void genAddrOf (iCode *ic)
12666 operand *result, *left;
12668 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12669 pCodeOp *pcop0, *pcop1, *pcop2;
12673 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12675 sym = OP_SYMBOL( IC_LEFT(ic) );
12678 /* get address of symbol on stack */
12679 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12681 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12682 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12685 // operands on stack are accessible via "FSR2 + index" with index
12686 // starting at 2 for arguments and growing from 0 downwards for
12687 // local variables (index == 0 is not assigned so we add one here)
12689 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12691 assert (soffs < 0);
12694 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12695 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12696 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12697 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12698 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12699 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12700 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12706 // if(pic16_debug_verbose) {
12707 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12708 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12711 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12712 size = AOP_SIZE(IC_RESULT(ic));
12714 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12715 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12716 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12719 pic16_emitpcode(POC_MOVLW, pcop0);
12720 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12721 pic16_emitpcode(POC_MOVLW, pcop1);
12722 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12723 pic16_emitpcode(POC_MOVLW, pcop2);
12724 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12727 pic16_emitpcode(POC_MOVLW, pcop0);
12728 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12729 pic16_emitpcode(POC_MOVLW, pcop1);
12730 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12732 pic16_emitpcode(POC_MOVLW, pcop0);
12733 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12736 pic16_freeAsmop(left, NULL, ic, FALSE);
12738 pic16_freeAsmop(result,NULL,ic,TRUE);
12743 /*-----------------------------------------------------------------*/
12744 /* genFarFarAssign - assignment when both are in far space */
12745 /*-----------------------------------------------------------------*/
12746 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12748 int size = AOP_SIZE(right);
12751 /* first push the right side on to the stack */
12753 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12755 pic16_emitcode ("push","acc");
12758 pic16_freeAsmop(right,NULL,ic,FALSE);
12759 /* now assign DPTR to result */
12760 pic16_aopOp(result,ic,FALSE);
12761 size = AOP_SIZE(result);
12763 pic16_emitcode ("pop","acc");
12764 pic16_aopPut(AOP(result),"a",--offset);
12766 pic16_freeAsmop(result,NULL,ic,FALSE);
12771 /*-----------------------------------------------------------------*/
12772 /* genAssign - generate code for assignment */
12773 /*-----------------------------------------------------------------*/
12774 static void genAssign (iCode *ic)
12776 operand *result, *right;
12777 int size, offset,know_W;
12778 unsigned long lit = 0L;
12780 result = IC_RESULT(ic);
12781 right = IC_RIGHT(ic) ;
12785 /* if they are the same */
12786 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12789 /* reversed order operands are aopOp'ed so that result operand
12790 * is effective in case right is a stack symbol. This maneauver
12791 * allows to use the _G.resDirect flag later */
12792 pic16_aopOp(result,ic,TRUE);
12793 pic16_aopOp(right,ic,FALSE);
12795 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12797 /* if they are the same registers */
12798 if (pic16_sameRegs(AOP(right),AOP(result)))
12801 /* if the result is a bit */
12802 if (AOP_TYPE(result) == AOP_CRY) {
12803 /* if the right size is a literal then
12804 we know what the value is */
12805 if (AOP_TYPE(right) == AOP_LIT) {
12807 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12808 pic16_popGet(AOP(result),0));
12810 if (((int) operandLitValue(right)))
12811 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12812 AOP(result)->aopu.aop_dir,
12813 AOP(result)->aopu.aop_dir);
12815 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12816 AOP(result)->aopu.aop_dir,
12817 AOP(result)->aopu.aop_dir);
12821 /* the right is also a bit variable */
12822 if (AOP_TYPE(right) == AOP_CRY) {
12823 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12824 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12825 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12827 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12828 AOP(result)->aopu.aop_dir,
12829 AOP(result)->aopu.aop_dir);
12830 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12831 AOP(right)->aopu.aop_dir,
12832 AOP(right)->aopu.aop_dir);
12833 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12834 AOP(result)->aopu.aop_dir,
12835 AOP(result)->aopu.aop_dir);
12839 /* we need to or */
12840 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12841 pic16_toBoolean(right);
12843 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12844 //pic16_aopPut(AOP(result),"a",0);
12848 /* bit variables done */
12850 size = AOP_SIZE(result);
12853 if(AOP_TYPE(right) == AOP_LIT) {
12854 if(!IS_FLOAT(operandType( right )))
12855 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12858 unsigned long lit_int;
12862 /* take care if literal is a float */
12863 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12864 lit = info.lit_int;
12868 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12869 // sizeof(unsigned long int), sizeof(float));
12872 if (AOP_TYPE(right) == AOP_REG) {
12873 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12876 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12881 if(AOP_TYPE(right) != AOP_LIT
12882 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12883 && !IS_FUNC(OP_SYM_TYPE(right))
12885 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12886 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12888 // set up table pointer
12889 if(is_LitOp(right)) {
12890 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12891 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12892 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12893 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12894 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12895 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12896 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12898 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12899 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12900 pic16_popCopyReg(&pic16_pc_tblptrl)));
12901 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12902 pic16_popCopyReg(&pic16_pc_tblptrh)));
12903 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12904 pic16_popCopyReg(&pic16_pc_tblptru)));
12907 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12909 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12910 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12911 pic16_popGet(AOP(result),offset)));
12915 size = getSize(OP_SYM_ETYPE(right));
12916 if(AOP_SIZE(result) > size) {
12917 size = AOP_SIZE(result) - size;
12919 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12929 /* VR - What is this?! */
12930 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12932 if(aopIdx(AOP(result),0) == 4) {
12934 /* this is a workaround to save value of right into wreg too,
12935 * value of wreg is going to be used later */
12936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12937 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12942 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12948 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12949 if(AOP_TYPE(right) == AOP_LIT) {
12951 if(know_W != (lit&0xff))
12952 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12956 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12960 } else if (AOP_TYPE(right) == AOP_CRY) {
12961 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12963 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12964 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12965 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12967 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12968 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12969 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12971 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12973 if(!_G.resDirect) /* use this aopForSym feature */
12974 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12981 pic16_freeAsmop (right,NULL,ic,FALSE);
12982 pic16_freeAsmop (result,NULL,ic,TRUE);
12985 /*-----------------------------------------------------------------*/
12986 /* genJumpTab - generates code for jump table */
12987 /*-----------------------------------------------------------------*/
12988 static void genJumpTab (iCode *ic)
12993 pCodeOp *jt_offs_hi;
12998 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12999 /* get the condition into accumulator */
13000 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
13002 /* multiply by three */
13003 pic16_emitcode("add","a,acc");
13004 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
13006 jtab = newiTempLabel(NULL);
13007 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
13008 pic16_emitcode("jmp","@a+dptr");
13009 pic16_emitcode("","%05d_DS_:",jtab->key+100);
13012 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
13013 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
13015 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
13016 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
13017 pic16_emitpLabel(jtab->key);
13021 jt_offs = pic16_popGetTempReg(0);
13022 jt_offs_hi = pic16_popGetTempReg(1);
13023 jt_label = pic16_popGetLabel (jtab->key);
13024 //fprintf (stderr, "Creating jump table...\n");
13026 // calculate offset into jump table (idx * sizeof (GOTO))
13027 pic16_emitpcode(POC_CLRF , jt_offs_hi);
13028 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13029 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13030 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13031 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13032 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13033 pic16_emitpcode(POC_MOVWF , jt_offs);
13035 // prepare PCLATx (set to first entry in jump table)
13036 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13037 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13038 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13039 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13040 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13042 // set PCLATx to selected entry (new PCL is stored in jt_offs)
13043 pic16_emitpcode(POC_ADDWF , jt_offs);
13044 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13045 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13047 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
13049 // release temporaries and prepare jump into table (new PCL --> WREG)
13050 pic16_emitpcode(POC_MOVFW , jt_offs);
13051 pic16_popReleaseTempReg (jt_offs_hi, 1);
13052 pic16_popReleaseTempReg (jt_offs, 0);
13054 // jump into the table
13055 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13057 pic16_emitpLabelFORCE(jtab->key);
13060 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13062 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13063 /* now generate the jump labels */
13064 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13065 jtab = setNextItem(IC_JTLABELS(ic))) {
13066 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13067 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13070 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13074 /*-----------------------------------------------------------------*/
13075 /* genMixedOperation - gen code for operators between mixed types */
13076 /*-----------------------------------------------------------------*/
13078 TSD - Written for the PIC port - but this unfortunately is buggy.
13079 This routine is good in that it is able to efficiently promote
13080 types to different (larger) sizes. Unfortunately, the temporary
13081 variables that are optimized out by this routine are sometimes
13082 used in other places. So until I know how to really parse the
13083 iCode tree, I'm going to not be using this routine :(.
13085 static int genMixedOperation (iCode *ic)
13088 operand *result = IC_RESULT(ic);
13089 sym_link *ctype = operandType(IC_LEFT(ic));
13090 operand *right = IC_RIGHT(ic);
13096 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13098 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13104 nextright = IC_RIGHT(nextic);
13105 nextleft = IC_LEFT(nextic);
13106 nextresult = IC_RESULT(nextic);
13108 pic16_aopOp(right,ic,FALSE);
13109 pic16_aopOp(result,ic,FALSE);
13110 pic16_aopOp(nextright, nextic, FALSE);
13111 pic16_aopOp(nextleft, nextic, FALSE);
13112 pic16_aopOp(nextresult, nextic, FALSE);
13114 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13116 operand *t = right;
13120 pic16_emitcode(";remove right +","");
13122 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13124 operand *t = right;
13128 pic16_emitcode(";remove left +","");
13132 big = AOP_SIZE(nextleft);
13133 small = AOP_SIZE(nextright);
13135 switch(nextic->op) {
13138 pic16_emitcode(";optimize a +","");
13139 /* if unsigned or not an integral type */
13140 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13141 pic16_emitcode(";add a bit to something","");
13144 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13146 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13147 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13148 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13150 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13158 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13159 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13160 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13163 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13165 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13166 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13167 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13168 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13169 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13172 pic16_emitcode("rlf","known_zero,w");
13179 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13180 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13181 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13183 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13193 pic16_freeAsmop(right,NULL,ic,TRUE);
13194 pic16_freeAsmop(result,NULL,ic,TRUE);
13195 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13196 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13198 nextic->generated = 1;
13205 /*-----------------------------------------------------------------*/
13206 /* genCast - gen code for casting */
13207 /*-----------------------------------------------------------------*/
13208 static void genCast (iCode *ic)
13210 operand *result = IC_RESULT(ic);
13211 sym_link *ctype = operandType(IC_LEFT(ic));
13212 sym_link *rtype = operandType(IC_RIGHT(ic));
13213 sym_link *restype = operandType(IC_RESULT(ic));
13214 operand *right = IC_RIGHT(ic);
13220 /* if they are equivalent then do nothing */
13221 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13224 pic16_aopOp(right,ic,FALSE) ;
13225 pic16_aopOp(result,ic,FALSE);
13227 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13230 /* if the result is a bit */
13231 if (AOP_TYPE(result) == AOP_CRY) {
13233 /* if the right size is a literal then
13234 * we know what the value is */
13235 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13237 if (AOP_TYPE(right) == AOP_LIT) {
13238 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13239 pic16_popGet(AOP(result),0));
13241 if (((int) operandLitValue(right)))
13242 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13243 AOP(result)->aopu.aop_dir,
13244 AOP(result)->aopu.aop_dir);
13246 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13247 AOP(result)->aopu.aop_dir,
13248 AOP(result)->aopu.aop_dir);
13252 /* the right is also a bit variable */
13253 if (AOP_TYPE(right) == AOP_CRY) {
13255 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13257 pic16_emitcode("clrc","");
13258 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13259 AOP(right)->aopu.aop_dir,
13260 AOP(right)->aopu.aop_dir);
13261 pic16_aopPut(AOP(result),"c",0);
13265 /* we need to or */
13266 if (AOP_TYPE(right) == AOP_REG) {
13267 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13268 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13269 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13271 pic16_toBoolean(right);
13272 pic16_aopPut(AOP(result),"a",0);
13276 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13279 size = AOP_SIZE(result);
13281 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13283 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13284 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13285 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13288 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13293 if(IS_BITFIELD(getSpec(restype))
13294 && IS_BITFIELD(getSpec(rtype))) {
13295 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13298 /* if they are the same size : or less */
13299 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13301 /* if they are in the same place */
13302 if (pic16_sameRegs(AOP(right),AOP(result)))
13305 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13307 if (IS_PTR_CONST(rtype))
13309 if (IS_CODEPTR(rtype))
13311 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13314 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13316 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13318 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13321 if(AOP_TYPE(right) == AOP_IMMD) {
13322 pCodeOp *pcop0, *pcop1, *pcop2;
13323 symbol *sym = OP_SYMBOL( right );
13325 size = AOP_SIZE(result);
13327 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13329 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13331 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13334 pic16_emitpcode(POC_MOVLW, pcop0);
13335 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13336 pic16_emitpcode(POC_MOVLW, pcop1);
13337 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13338 pic16_emitpcode(POC_MOVLW, pcop2);
13339 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13342 pic16_emitpcode(POC_MOVLW, pcop0);
13343 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13344 pic16_emitpcode(POC_MOVLW, pcop1);
13345 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13347 pic16_emitpcode(POC_MOVLW, pcop0);
13348 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13352 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13353 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13354 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13355 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13357 if(AOP_SIZE(result) <2)
13358 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13360 /* if they in different places then copy */
13361 size = AOP_SIZE(result);
13364 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13365 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13372 /* if the result is of type pointer */
13373 if (IS_PTR(ctype)) {
13375 sym_link *type = operandType(right);
13376 sym_link *etype = getSpec(type);
13378 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13380 /* pointer to generic pointer */
13381 if (IS_GENPTR(ctype)) {
13385 p_type = DCL_TYPE(type);
13387 /* we have to go by the storage class */
13388 p_type = PTR_TYPE(SPEC_OCLS(etype));
13390 /* if (SPEC_OCLS(etype)->codesp ) */
13391 /* p_type = CPOINTER ; */
13393 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13394 /* p_type = FPOINTER ; */
13396 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13397 /* p_type = PPOINTER; */
13399 /* if (SPEC_OCLS(etype) == idata ) */
13400 /* p_type = IPOINTER ; */
13402 /* p_type = POINTER ; */
13405 /* the first two bytes are known */
13406 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13407 size = GPTRSIZE - 1;
13410 if(offset < AOP_SIZE(right)) {
13411 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13412 mov2f(AOP(result), AOP(right), offset);
13414 if ((AOP_TYPE(right) == AOP_PCODE) &&
13415 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13416 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13417 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13420 pic16_aopPut(AOP(result),
13421 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13426 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13429 /* the last byte depending on type */
13433 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13434 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13435 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13439 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13443 pic16_emitcode(";BUG!? ","%d",__LINE__);
13447 pic16_emitcode(";BUG!? ","%d",__LINE__);
13452 if (GPTRSIZE > AOP_SIZE(right)) {
13453 // assume data pointer... THIS MIGHT BE WRONG!
13454 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13455 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13457 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13462 /* this should never happen */
13463 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13464 "got unknown pointer type");
13467 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13471 /* just copy the pointers */
13472 size = AOP_SIZE(result);
13475 pic16_aopPut(AOP(result),
13476 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13485 /* so we now know that the size of destination is greater
13486 than the size of the source.
13487 Now, if the next iCode is an operator then we might be
13488 able to optimize the operation without performing a cast.
13490 if(genMixedOperation(ic))
13493 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13495 /* we move to result for the size of source */
13496 size = AOP_SIZE(right);
13499 mov2f(AOP(result), AOP(right), offset);
13503 /* now depending on the sign of the destination */
13504 size = AOP_SIZE(result) - AOP_SIZE(right);
13505 /* if unsigned or not an integral type */
13506 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13508 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13510 /* we need to extend the sign :( */
13513 /* Save one instruction of casting char to int */
13514 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13515 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13516 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13518 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13521 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13523 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13525 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13528 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13533 pic16_freeAsmop(right,NULL,ic,TRUE);
13534 pic16_freeAsmop(result,NULL,ic,TRUE);
13538 /*-----------------------------------------------------------------*/
13539 /* genDjnz - generate decrement & jump if not zero instrucion */
13540 /*-----------------------------------------------------------------*/
13541 static int genDjnz (iCode *ic, iCode *ifx)
13543 symbol *lbl, *lbl1;
13544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13549 /* if the if condition has a false label
13550 then we cannot save */
13554 /* if the minus is not of the form
13556 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13557 !IS_OP_LITERAL(IC_RIGHT(ic)))
13560 if (operandLitValue(IC_RIGHT(ic)) != 1)
13563 /* if the size of this greater than one then no
13565 if (getSize(operandType(IC_RESULT(ic))) > 1)
13568 /* otherwise we can save BIG */
13569 lbl = newiTempLabel(NULL);
13570 lbl1= newiTempLabel(NULL);
13572 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13574 if (IS_AOP_PREG(IC_RESULT(ic))) {
13575 pic16_emitcode("dec","%s",
13576 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13577 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13578 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13582 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13583 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13585 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13586 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13590 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13591 ifx->generated = 1;
13595 /*-----------------------------------------------------------------*/
13596 /* genReceive - generate code for a receive iCode */
13597 /*-----------------------------------------------------------------*/
13598 static void genReceive (iCode *ic)
13604 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13605 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13607 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13609 if (isOperandInFarSpace(IC_RESULT(ic))
13610 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13611 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13613 int size = getSize(operandType(IC_RESULT(ic)));
13614 int offset = pic16_fReturnSizePic - size;
13618 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13619 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13623 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13625 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13626 size = AOP_SIZE(IC_RESULT(ic));
13629 pic16_emitcode ("pop","acc");
13630 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13633 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13635 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13638 /* set pseudo stack pointer to where it should be - dw*/
13639 GpsuedoStkPtr = ic->parmBytes;
13641 /* setting GpsuedoStkPtr has side effects here: */
13642 assignResultValue(IC_RESULT(ic), 0);
13645 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13648 /*-----------------------------------------------------------------*/
13649 /* genDummyRead - generate code for dummy read of volatiles */
13650 /*-----------------------------------------------------------------*/
13652 genDummyRead (iCode * ic)
13658 if (op && IS_SYMOP(op)) {
13659 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13660 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13663 pic16_aopOp (op, ic, FALSE);
13664 for (i=0; i < AOP_SIZE(op); i++) {
13665 // may need to protect this from the peepholer -- this is not nice but works...
13666 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13667 pic16_mov2w (AOP(op),i);
13668 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13670 pic16_freeAsmop (op, NULL, ic, TRUE);
13672 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13676 /*-----------------------------------------------------------------*/
13677 /* genpic16Code - generate code for pic16 based controllers */
13678 /*-----------------------------------------------------------------*/
13680 * At this point, ralloc.c has gone through the iCode and attempted
13681 * to optimize in a way suitable for a PIC. Now we've got to generate
13682 * PIC instructions that correspond to the iCode.
13684 * Once the instructions are generated, we'll pass through both the
13685 * peep hole optimizer and the pCode optimizer.
13686 *-----------------------------------------------------------------*/
13688 void genpic16Code (iCode *lic)
13693 lineHead = lineCurr = NULL;
13695 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13696 pic16_addpBlock(pb);
13699 /* if debug information required */
13700 if (options.debug && currFunc) {
13702 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13707 for (ic = lic ; ic ; ic = ic->next ) {
13709 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13710 if ( cln != ic->lineno ) {
13711 if ( options.debug ) {
13712 debugFile->writeCLine (ic);
13715 if(!options.noCcodeInAsm) {
13716 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13717 printCLine(ic->filename, ic->lineno)));
13723 if(options.iCodeInAsm) {
13726 /* insert here code to print iCode as comment */
13727 l = Safe_strdup(printILine(ic));
13728 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13731 /* if the result is marked as
13732 * spilt and rematerializable or code for
13733 * this has already been generated then
13735 if (resultRemat(ic) || ic->generated )
13738 /* depending on the operation */
13757 /* IPOP happens only when trying to restore a
13758 * spilt live range, if there is an ifx statement
13759 * following this pop then the if statement might
13760 * be using some of the registers being popped which
13761 * would destroy the contents of the register so
13762 * we need to check for this condition and handle it */
13764 && ic->next->op == IFX
13765 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13766 genIfx (ic->next,ic);
13784 genEndFunction (ic);
13800 pic16_genPlus (ic) ;
13804 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13805 pic16_genMinus (ic);
13821 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13825 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13831 /* note these two are xlated by algebraic equivalence
13832 * during parsing SDCC.y */
13833 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13834 "got '>=' or '<=' shouldn't have come here");
13838 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13850 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13854 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13858 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13882 genRightShift (ic);
13885 case GET_VALUE_AT_ADDRESS:
13890 if (POINTER_SET(ic))
13917 addSet(&_G.sendSet,ic);
13920 case DUMMY_READ_VOLATILE:
13930 /* now we are ready to call the
13931 peep hole optimizer */
13932 if (!options.nopeep)
13933 peepHole (&lineHead);
13935 /* now do the actual printing */
13936 printLine (lineHead, codeOutFile);
13939 DFPRINTF((stderr,"printing pBlock\n\n"));
13940 pic16_printpBlock(stdout,pb);