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 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, 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", __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;
2060 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2061 assert( 0 ); /* should never reach here */;
2066 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2067 "pic16_popGet got unsupported aop->type");
2070 /*-----------------------------------------------------------------*/
2071 /* pic16_aopPut - puts a string for a aop */
2072 /*-----------------------------------------------------------------*/
2073 void pic16_aopPut (asmop *aop, char *s, int offset)
2080 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2082 if (aop->size && offset > ( aop->size - 1)) {
2083 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2084 "pic16_aopPut got offset > aop->size");
2088 /* will assign value to value */
2089 /* depending on where it is ofcourse */
2090 switch (aop->type) {
2093 sprintf(d,"(%s + %d)",
2094 aop->aopu.aop_dir,offset);
2095 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2098 sprintf(d,"%s",aop->aopu.aop_dir);
2101 DEBUGpic16_emitcode(";","%d",__LINE__);
2103 pic16_emitcode("movf","%s,w",s);
2104 pic16_emitcode("movwf","%s",d);
2107 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2108 if(offset >= aop->size) {
2109 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2112 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2115 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2122 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2123 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2126 strcmp(s,"r0") == 0 ||
2127 strcmp(s,"r1") == 0 ||
2128 strcmp(s,"r2") == 0 ||
2129 strcmp(s,"r3") == 0 ||
2130 strcmp(s,"r4") == 0 ||
2131 strcmp(s,"r5") == 0 ||
2132 strcmp(s,"r6") == 0 ||
2133 strcmp(s,"r7") == 0 )
2134 pic16_emitcode("mov","%s,%s ; %d",
2135 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2139 if(strcmp(s,"W")==0 )
2140 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2142 pic16_emitcode("movwf","%s",
2143 aop->aopu.aop_reg[offset]->name);
2145 if(strcmp(s,zero)==0) {
2146 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2148 } else if(strcmp(s,"W")==0) {
2149 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2150 pcop->type = PO_GPR_REGISTER;
2152 PCOR(pcop)->rIdx = -1;
2153 PCOR(pcop)->r = NULL;
2155 DEBUGpic16_emitcode(";","%d",__LINE__);
2156 pcop->name = Safe_strdup(s);
2157 pic16_emitpcode(POC_MOVFW,pcop);
2158 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2159 } else if(strcmp(s,one)==0) {
2160 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2161 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2163 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2171 if (aop->type == AOP_DPTR2)
2177 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2178 "pic16_aopPut writting to code space");
2182 while (offset > aop->coff) {
2184 pic16_emitcode ("inc","dptr");
2187 while (offset < aop->coff) {
2189 pic16_emitcode("lcall","__decdptr");
2194 /* if not in accumulater */
2197 pic16_emitcode ("movx","@dptr,a");
2199 if (aop->type == AOP_DPTR2)
2207 while (offset > aop->coff) {
2209 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2211 while (offset < aop->coff) {
2213 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2219 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2224 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2226 if (strcmp(s,"r0") == 0 ||
2227 strcmp(s,"r1") == 0 ||
2228 strcmp(s,"r2") == 0 ||
2229 strcmp(s,"r3") == 0 ||
2230 strcmp(s,"r4") == 0 ||
2231 strcmp(s,"r5") == 0 ||
2232 strcmp(s,"r6") == 0 ||
2233 strcmp(s,"r7") == 0 ) {
2235 sprintf(buffer,"a%s",s);
2236 pic16_emitcode("mov","@%s,%s",
2237 aop->aopu.aop_ptr->name,buffer);
2239 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2244 if (strcmp(s,"a") == 0)
2245 pic16_emitcode("push","acc");
2247 pic16_emitcode("push","%s",s);
2252 /* if bit variable */
2253 if (!aop->aopu.aop_dir) {
2254 pic16_emitcode("clr","a");
2255 pic16_emitcode("rlc","a");
2258 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2261 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2264 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2266 lbl = newiTempLabel(NULL);
2268 if (strcmp(s,"a")) {
2271 pic16_emitcode("clr","c");
2272 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2273 pic16_emitcode("cpl","c");
2274 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2275 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2282 if (strcmp(aop->aopu.aop_str[offset],s))
2283 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2288 if (!offset && (strcmp(s,"acc") == 0))
2291 if (strcmp(aop->aopu.aop_str[offset],s))
2292 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2296 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2297 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2298 // "pic16_aopPut got unsupported aop->type");
2304 /*-----------------------------------------------------------------*/
2305 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2306 /*-----------------------------------------------------------------*/
2307 void pic16_mov2w (asmop *aop, int offset)
2309 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2312 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2314 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2317 static void mov2f(asmop *dst, asmop *src, int offset)
2319 if(is_LitAOp(src)) {
2320 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2321 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2323 if(pic16_sameRegsOfs(src, dst, offset))return;
2324 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2325 pic16_popGet(dst, offset)));
2329 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2331 if(is_LitAOp(src)) {
2332 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2333 pic16_emitpcode(POC_MOVWF, dst);
2335 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2339 void pic16_testStackOverflow(void)
2341 #define GSTACK_TEST_NAME "__gstack_test"
2343 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2348 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2349 strcpy(sym->rname, GSTACK_TEST_NAME);
2350 checkAddSym(&externs, sym);
2355 /* push pcop into stack */
2356 void pic16_pushpCodeOp(pCodeOp *pcop)
2358 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2359 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2360 if(pic16_options.gstack)
2361 pic16_testStackOverflow();
2365 /* pop pcop from stack */
2366 void pic16_poppCodeOp(pCodeOp *pcop)
2368 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2369 if(pic16_options.gstack)
2370 pic16_testStackOverflow();
2374 /*-----------------------------------------------------------------*/
2375 /* pushw - pushes wreg to stack */
2376 /*-----------------------------------------------------------------*/
2379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2380 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2381 if(pic16_options.gstack)
2382 pic16_testStackOverflow();
2386 /*-----------------------------------------------------------------*/
2387 /* pushaop - pushes aop to stack */
2388 /*-----------------------------------------------------------------*/
2389 void pushaop(asmop *aop, int offset)
2391 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2393 if(is_LitAOp(aop)) {
2394 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2395 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2397 pic16_emitpcode(POC_MOVFF,
2398 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2401 if(pic16_options.gstack)
2402 pic16_testStackOverflow();
2405 /*-----------------------------------------------------------------*/
2406 /* popaop - pops aop from stack */
2407 /*-----------------------------------------------------------------*/
2408 void popaop(asmop *aop, int offset)
2410 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2411 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2412 if(pic16_options.gstack)
2413 pic16_testStackOverflow();
2416 void popaopidx(asmop *aop, int offset, int index)
2420 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2422 if(STACK_MODEL_LARGE)ofs++;
2424 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2425 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2426 if(pic16_options.gstack)
2427 pic16_testStackOverflow();
2430 #if !(USE_GENERIC_SIGNED_SHIFT)
2431 /*-----------------------------------------------------------------*/
2432 /* reAdjustPreg - points a register back to where it should */
2433 /*-----------------------------------------------------------------*/
2434 static void reAdjustPreg (asmop *aop)
2438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2440 if ((size = aop->size) <= 1)
2443 switch (aop->type) {
2447 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2451 if (aop->type == AOP_DPTR2)
2457 pic16_emitcode("lcall","__decdptr");
2460 if (aop->type == AOP_DPTR2)
2472 /*-----------------------------------------------------------------*/
2473 /* opIsGptr: returns non-zero if the passed operand is */
2474 /* a generic pointer type. */
2475 /*-----------------------------------------------------------------*/
2476 static int opIsGptr(operand *op)
2478 sym_link *type = operandType(op);
2480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2481 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2489 /*-----------------------------------------------------------------*/
2490 /* pic16_getDataSize - get the operand data size */
2491 /*-----------------------------------------------------------------*/
2492 int pic16_getDataSize(operand *op)
2494 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2497 return AOP_SIZE(op);
2499 // tsd- in the pic port, the genptr size is 1, so this code here
2500 // fails. ( in the 8051 port, the size was 4).
2503 size = AOP_SIZE(op);
2504 if (size == GPTRSIZE)
2506 sym_link *type = operandType(op);
2507 if (IS_GENPTR(type))
2509 /* generic pointer; arithmetic operations
2510 * should ignore the high byte (pointer type).
2513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2520 /*-----------------------------------------------------------------*/
2521 /* pic16_outAcc - output Acc */
2522 /*-----------------------------------------------------------------*/
2523 void pic16_outAcc(operand *result)
2526 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2527 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2530 size = pic16_getDataSize(result);
2532 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2535 /* unsigned or positive */
2537 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2542 /*-----------------------------------------------------------------*/
2543 /* pic16_outBitC - output a bit C */
2544 /* Move to result the value of Carry flag -- VR */
2545 /*-----------------------------------------------------------------*/
2546 void pic16_outBitC(operand *result)
2550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2552 /* if the result is bit */
2553 if (AOP_TYPE(result) == AOP_CRY) {
2554 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2555 pic16_aopPut(AOP(result),"c",0);
2558 i = AOP_SIZE(result);
2560 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2562 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2566 /*-----------------------------------------------------------------*/
2567 /* pic16_outBitOp - output a bit from Op */
2568 /* Move to result the value of set/clr op -- VR */
2569 /*-----------------------------------------------------------------*/
2570 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2576 /* if the result is bit */
2577 if (AOP_TYPE(result) == AOP_CRY) {
2578 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2579 pic16_aopPut(AOP(result),"c",0);
2582 i = AOP_SIZE(result);
2584 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2586 pic16_emitpcode(POC_RRCF, pcop);
2587 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2591 /*-----------------------------------------------------------------*/
2592 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2593 /*-----------------------------------------------------------------*/
2594 void pic16_toBoolean(operand *oper)
2596 int size = AOP_SIZE(oper) - 1;
2599 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2601 if ( AOP_TYPE(oper) != AOP_ACC) {
2602 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2605 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2610 #if !defined(GEN_Not)
2611 /*-----------------------------------------------------------------*/
2612 /* genNot - generate code for ! operation */
2613 /*-----------------------------------------------------------------*/
2614 static void pic16_genNot (iCode *ic)
2620 /* assign asmOps to operand & result */
2621 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2622 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2624 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2625 /* if in bit space then a special case */
2626 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2627 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2628 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2629 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2631 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2632 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2633 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2638 size = AOP_SIZE(IC_LEFT(ic));
2640 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2641 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2642 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2645 pic16_toBoolean(IC_LEFT(ic));
2647 tlbl = newiTempLabel(NULL);
2648 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2649 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2650 pic16_outBitC(IC_RESULT(ic));
2653 /* release the aops */
2654 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2655 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2660 #if !defined(GEN_Cpl)
2661 /*-----------------------------------------------------------------*/
2662 /* genCpl - generate code for complement */
2663 /*-----------------------------------------------------------------*/
2664 static void pic16_genCpl (iCode *ic)
2670 /* assign asmOps to operand & result */
2671 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2672 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2674 /* if both are in bit space then
2676 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2677 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2679 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2680 pic16_emitcode("cpl","c");
2681 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2685 size = AOP_SIZE(IC_RESULT(ic));
2688 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2690 pic16_emitcode("cpl","a");
2691 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2693 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2694 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2696 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2705 /* release the aops */
2706 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2707 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2711 /*-----------------------------------------------------------------*/
2712 /* genUminusFloat - unary minus for floating points */
2713 /*-----------------------------------------------------------------*/
2714 static void genUminusFloat(operand *op,operand *result)
2716 int size ,offset =0 ;
2719 /* for this we just need to flip the
2720 first it then copy the rest in place */
2721 size = AOP_SIZE(op);
2724 mov2f(AOP(result), AOP(op), offset);
2728 /* toggle the MSB's highest bit */
2729 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2732 /*-----------------------------------------------------------------*/
2733 /* genUminus - unary minus code generation */
2734 /*-----------------------------------------------------------------*/
2735 static void genUminus (iCode *ic)
2738 sym_link *optype, *rtype;
2745 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2746 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2748 /* if both in bit space then special case */
2749 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2750 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2752 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2753 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2754 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2758 optype = operandType(IC_LEFT(ic));
2759 rtype = operandType(IC_RESULT(ic));
2761 /* if float then do float stuff */
2762 if (IS_FLOAT(optype)) {
2763 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2767 /* otherwise subtract from zero by taking the 2's complement */
2768 size = AOP_SIZE(IC_LEFT(ic));
2769 label = newiTempLabel ( NULL );
2771 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2772 for (i=size-1; i > 0; i--) {
2773 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2775 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2776 for (i=1; i < size; i++) {
2777 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2778 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2781 for (i=size-1; i >= 0; i--) {
2782 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2783 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2786 for (i=0; i < size-2; i++) {
2787 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2788 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2790 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2792 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2795 pic16_emitpLabel (label->key);
2798 /* release the aops */
2799 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2800 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2804 /*-----------------------------------------------------------------*/
2805 /* saveRegisters - will look for a call and save the registers */
2806 /*-----------------------------------------------------------------*/
2807 static void saveRegisters(iCode *lic)
2814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2816 for (ic = lic ; ic ; ic = ic->next)
2817 if (ic->op == CALL || ic->op == PCALL)
2821 fprintf(stderr,"found parameter push with no function call\n");
2825 /* if the registers have been saved already then
2827 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2830 /* find the registers in use at this time
2831 and push them away to safety */
2832 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2836 if (options.useXstack) {
2837 if (bitVectBitValue(rsave,R0_IDX))
2838 pic16_emitcode("mov","b,r0");
2839 pic16_emitcode("mov","r0,%s",spname);
2840 for (i = 0 ; i < pic16_nRegs ; i++) {
2841 if (bitVectBitValue(rsave,i)) {
2843 pic16_emitcode("mov","a,b");
2845 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2846 pic16_emitcode("movx","@r0,a");
2847 pic16_emitcode("inc","r0");
2850 pic16_emitcode("mov","%s,r0",spname);
2851 if (bitVectBitValue(rsave,R0_IDX))
2852 pic16_emitcode("mov","r0,b");
2854 //for (i = 0 ; i < pic16_nRegs ; i++) {
2855 // if (bitVectBitValue(rsave,i))
2856 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2859 dtype = operandType(IC_LEFT(ic));
2860 if (currFunc && dtype &&
2861 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2862 IFFUNC_ISISR(currFunc->type) &&
2865 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2868 /*-----------------------------------------------------------------*/
2869 /* unsaveRegisters - pop the pushed registers */
2870 /*-----------------------------------------------------------------*/
2871 static void unsaveRegisters (iCode *ic)
2876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2877 /* find the registers in use at this time
2878 and push them away to safety */
2879 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2882 if (options.useXstack) {
2883 pic16_emitcode("mov","r0,%s",spname);
2884 for (i = pic16_nRegs ; i >= 0 ; i--) {
2885 if (bitVectBitValue(rsave,i)) {
2886 pic16_emitcode("dec","r0");
2887 pic16_emitcode("movx","a,@r0");
2889 pic16_emitcode("mov","b,a");
2891 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2895 pic16_emitcode("mov","%s,r0",spname);
2896 if (bitVectBitValue(rsave,R0_IDX))
2897 pic16_emitcode("mov","r0,b");
2899 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2900 // if (bitVectBitValue(rsave,i))
2901 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2908 /*-----------------------------------------------------------------*/
2910 /*-----------------------------------------------------------------*/
2911 static void pushSide(operand * oper, int size)
2914 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2916 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2917 if (AOP_TYPE(oper) != AOP_REG &&
2918 AOP_TYPE(oper) != AOP_DIR &&
2920 pic16_emitcode("mov","a,%s",l);
2921 pic16_emitcode("push","acc");
2923 pic16_emitcode("push","%s",l);
2928 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2930 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2931 pic16_emitpcode(POC_MOVFW, src);
2932 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2935 src, pic16_popGet(AOP(op), offset)));
2940 /*-----------------------------------------------------------------*/
2941 /* assignResultValue - assign results to oper, rescall==1 is */
2942 /* called from genCall() or genPcall() */
2943 /*-----------------------------------------------------------------*/
2944 static void assignResultValue(operand * oper, int rescall)
2946 int size = AOP_SIZE(oper);
2950 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2951 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2954 /* assign result from a call/pcall function() */
2956 /* function results are stored in a special order,
2957 * see top of file with Function return policy, or manual */
2960 /* 8-bits, result in WREG */
2961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2964 /* 16-bits, result in PRODL:WREG */
2965 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2969 /* 24-bits, result in PRODH:PRODL:WREG */
2970 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2974 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2975 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2979 /* >32-bits, result on stack, and FSR0 points to beginning.
2980 * Fix stack when done */
2982 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2984 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2985 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2987 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2992 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2993 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2994 if(STACK_MODEL_LARGE) {
2996 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3000 int areg = 0; /* matching argument register */
3002 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3003 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3006 /* its called from genReceive (probably) -- VR */
3007 /* I hope this code will not be called from somewhere else in the future!
3008 * We manually set the pseudo stack pointer in genReceive. - dw
3010 if(!GpsuedoStkPtr && _G.useWreg) {
3011 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3013 /* The last byte in the assignment is in W */
3014 if(areg <= GpsuedoStkPtr) {
3016 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3018 // debugf("receive from WREG\n", 0);
3020 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3023 _G.stack_lat = AOP_SIZE(oper)-1;
3028 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3029 // debugf("receive from STACK\n", 0);
3036 /*-----------------------------------------------------------------*/
3037 /* genIpush - generate code for pushing this gets a little complex */
3038 /*-----------------------------------------------------------------*/
3039 static void genIpush (iCode *ic)
3041 // int size, offset=0;
3044 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3047 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3049 /* send to stack as normal */
3050 addSet(&_G.sendSet,ic);
3051 // addSetHead(&_G.sendSet,ic);
3052 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3057 int size, offset = 0 ;
3061 /* if this is not a parm push : ie. it is spill push
3062 and spill push is always done on the local stack */
3063 if (!ic->parmPush) {
3065 /* and the item is spilt then do nothing */
3066 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3069 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3070 size = AOP_SIZE(IC_LEFT(ic));
3071 /* push it on the stack */
3073 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3078 pic16_emitcode("push","%s",l);
3083 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3087 /*-----------------------------------------------------------------*/
3088 /* genIpop - recover the registers: can happen only for spilling */
3089 /*-----------------------------------------------------------------*/
3090 static void genIpop (iCode *ic)
3093 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3098 /* if the temp was not pushed then */
3099 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3102 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3103 size = AOP_SIZE(IC_LEFT(ic));
3106 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3109 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3114 /*-----------------------------------------------------------------*/
3115 /* unsaverbank - restores the resgister bank from stack */
3116 /*-----------------------------------------------------------------*/
3117 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3119 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3127 if (options.useXstack) {
3129 r = getFreePtr(ic,&aop,FALSE);
3132 pic16_emitcode("mov","%s,_spx",r->name);
3133 pic16_emitcode("movx","a,@%s",r->name);
3134 pic16_emitcode("mov","psw,a");
3135 pic16_emitcode("dec","%s",r->name);
3138 pic16_emitcode ("pop","psw");
3141 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3142 if (options.useXstack) {
3143 pic16_emitcode("movx","a,@%s",r->name);
3144 //pic16_emitcode("mov","(%s+%d),a",
3145 // regspic16[i].base,8*bank+regspic16[i].offset);
3146 pic16_emitcode("dec","%s",r->name);
3149 pic16_emitcode("pop",""); //"(%s+%d)",
3150 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3153 if (options.useXstack) {
3155 pic16_emitcode("mov","_spx,%s",r->name);
3156 pic16_freeAsmop(NULL,aop,ic,TRUE);
3162 /*-----------------------------------------------------------------*/
3163 /* saverbank - saves an entire register bank on the stack */
3164 /*-----------------------------------------------------------------*/
3165 static void saverbank (int bank, iCode *ic, bool pushPsw)
3167 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3174 if (options.useXstack) {
3177 r = getFreePtr(ic,&aop,FALSE);
3178 pic16_emitcode("mov","%s,_spx",r->name);
3182 for (i = 0 ; i < pic16_nRegs ;i++) {
3183 if (options.useXstack) {
3184 pic16_emitcode("inc","%s",r->name);
3185 //pic16_emitcode("mov","a,(%s+%d)",
3186 // regspic16[i].base,8*bank+regspic16[i].offset);
3187 pic16_emitcode("movx","@%s,a",r->name);
3189 pic16_emitcode("push","");// "(%s+%d)",
3190 //regspic16[i].base,8*bank+regspic16[i].offset);
3194 if (options.useXstack) {
3195 pic16_emitcode("mov","a,psw");
3196 pic16_emitcode("movx","@%s,a",r->name);
3197 pic16_emitcode("inc","%s",r->name);
3198 pic16_emitcode("mov","_spx,%s",r->name);
3199 pic16_freeAsmop (NULL,aop,ic,TRUE);
3202 pic16_emitcode("push","psw");
3204 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3212 static int wparamCmp(void *p1, void *p2)
3214 return (!strcmp((char *)p1, (char *)p2));
3217 int inWparamList(char *s)
3219 return isinSetWith(wparamList, s, wparamCmp);
3223 /*-----------------------------------------------------------------*/
3224 /* genCall - generates a call statement */
3225 /*-----------------------------------------------------------------*/
3226 static void genCall (iCode *ic)
3236 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3237 /* if caller saves & we have not saved then */
3238 // if (!ic->regsSaved)
3239 // saveRegisters(ic);
3241 /* initialise stackParms for IPUSH pushes */
3242 // stackParms = psuedoStkPtr;
3243 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3244 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3245 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3248 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3251 /* if send set is not empty the assign */
3254 int psuedoStkPtr=-1;
3255 int firstTimeThruLoop = 1;
3258 /* reverse sendSet if function is not reentrant */
3259 if(!IFFUNC_ISREENT(ftype))
3260 _G.sendSet = reverseSet(_G.sendSet);
3262 /* First figure how many parameters are getting passed */
3266 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3270 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3271 size = AOP_SIZE(IC_LEFT(sic));
3275 /* pass the last byte through WREG */
3279 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3280 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3281 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3283 if(!firstTimeThruLoop) {
3284 /* If this is not the first time we've been through the loop
3285 * then we need to save the parameter in a temporary
3286 * register. The last byte of the last parameter is
3290 // --psuedoStkPtr; // sanity check
3294 firstTimeThruLoop=0;
3296 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3301 /* all arguments are passed via stack */
3305 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3306 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3307 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3309 // pushaop(AOP(IC_LEFT(sic)), size);
3310 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3315 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3319 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3320 pushw(); /* save last parameter to stack if functions has varargs */
3324 } else use_wreg = 0;
3326 _G.stackRegSet = _G.sendSet;
3331 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3335 /* if we need to assign a result value */
3336 if ((IS_ITEMP(IC_RESULT(ic))
3337 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3338 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3339 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3342 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3345 assignResultValue(IC_RESULT(ic), 1);
3347 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3348 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3350 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3353 if(!stackParms && ic->parmBytes) {
3354 stackParms = ic->parmBytes;
3357 stackParms -= use_wreg;
3360 if(stackParms == 1) {
3361 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3363 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3364 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3366 if(STACK_MODEL_LARGE) {
3368 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3373 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3376 /* adjust the stack for parameters if required */
3377 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3380 /* if register bank was saved then pop them */
3382 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3384 /* if we hade saved some registers then unsave them */
3385 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3386 unsaveRegisters (ic);
3392 /*-----------------------------------------------------------------*/
3393 /* genPcall - generates a call by pointer statement */
3394 /* new version, created from genCall - HJD */
3395 /*-----------------------------------------------------------------*/
3396 static void genPcall (iCode *ic)
3398 sym_link *ftype, *fntype;
3400 symbol *retlbl = newiTempLabel(NULL);
3401 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3405 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3406 fntype = operandType( IC_LEFT(ic) )->next;
3408 /* if send set is not empty the assign */
3411 int psuedoStkPtr=-1;
3413 /* reverse sendSet if function is not reentrant */
3414 if(!IFFUNC_ISREENT(fntype))
3415 _G.sendSet = reverseSet(_G.sendSet);
3419 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3422 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3423 size = AOP_SIZE(IC_LEFT(sic));
3426 /* all parameters are passed via stack, since WREG is clobbered
3427 * by the calling sequence */
3429 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3430 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3431 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3433 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3437 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3440 _G.stackRegSet = _G.sendSet;
3444 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3446 // push return address
3447 // push $ on return stack, then replace with retlbl
3449 /* Thanks to Thorsten Klose for pointing out that the following
3450 * snippet should be interrupt safe */
3451 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3452 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3454 pic16_emitpcodeNULLop(POC_PUSH);
3456 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3457 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3458 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3459 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3460 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3461 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3464 /* restore interrupt control register */
3465 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3466 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3468 /* make the call by writing the pointer into pc */
3469 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3470 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3472 // note: MOVFF to PCL not allowed
3473 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3474 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3477 /* return address is here: (X) */
3478 pic16_emitpLabelFORCE(retlbl->key);
3480 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3483 /* if we need assign a result value */
3484 if ((IS_ITEMP(IC_RESULT(ic))
3485 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3486 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3487 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3490 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3493 assignResultValue(IC_RESULT(ic), 1);
3495 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3496 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3498 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3501 // stackParms -= use_wreg;
3504 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3505 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3506 if(STACK_MODEL_LARGE) {
3508 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3513 /*-----------------------------------------------------------------*/
3514 /* resultRemat - result is rematerializable */
3515 /*-----------------------------------------------------------------*/
3516 static int resultRemat (iCode *ic)
3518 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3519 if (SKIP_IC(ic) || ic->op == IFX)
3522 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3523 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3524 if (sym->remat && !POINTER_SET(ic))
3531 #if defined(__BORLANDC__) || defined(_MSC_VER)
3532 #define STRCASECMP stricmp
3534 #define STRCASECMP strcasecmp
3538 /*-----------------------------------------------------------------*/
3539 /* inExcludeList - return 1 if the string is in exclude Reg list */
3540 /*-----------------------------------------------------------------*/
3541 static bool inExcludeList(char *s)
3543 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3547 if (options.excludeRegs[i] &&
3548 STRCASECMP(options.excludeRegs[i],"none") == 0)
3551 for ( i = 0 ; options.excludeRegs[i]; i++) {
3552 if (options.excludeRegs[i] &&
3553 STRCASECMP(s,options.excludeRegs[i]) == 0)
3560 /*-----------------------------------------------------------------*/
3561 /* genFunction - generated code for function entry */
3562 /*-----------------------------------------------------------------*/
3563 static void genFunction (iCode *ic)
3569 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3571 pic16_labelOffset += (max_key+4);
3576 ftype = operandType(IC_LEFT(ic));
3577 sym = OP_SYMBOL(IC_LEFT(ic));
3579 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3580 /* create an absolute section at the interrupt vector:
3581 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3586 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3592 sym = OP_SYMBOL( IC_LEFT(ic));
3594 if(interrupts[i]->name
3595 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3602 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3603 __FILE__, __LINE__, sym->name);
3606 _G.interruptvector = found;
3610 if(FUNC_INTNO(sym->type) == 256)
3611 sprintf(asymname, "ivec_%s", sym->name);
3613 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3614 asym = newSymbol(asymname, 0);
3616 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3617 pic16_addpBlock( apb );
3619 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3620 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3621 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3623 /* mark the end of this tiny function */
3624 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3629 abSym = Safe_calloc(1, sizeof(absSym));
3630 strcpy(abSym->name, asymname);
3632 switch( FUNC_INTNO(sym->type) ) {
3633 case 0: abSym->address = 0x000000; break;
3634 case 1: abSym->address = 0x000008; break;
3635 case 2: abSym->address = 0x000018; break;
3638 abSym->address = -1; break;
3641 /* relocate interrupt vectors if needed */
3642 if(abSym->address != -1)
3643 abSym->address += pic16_options.ivt_loc;
3645 addSet(&absSymSet, abSym);
3649 /* create the function header */
3650 pic16_emitcode(";","-----------------------------------------");
3651 pic16_emitcode(";"," function %s",sym->name);
3652 pic16_emitcode(";","-----------------------------------------");
3654 pic16_emitcode("","%s:",sym->rname);
3655 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3661 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3662 if(!strcmp(ab->name, sym->rname)) {
3663 pic16_pBlockConvert2Absolute(pb);
3670 if(IFFUNC_ISNAKED(ftype)) {
3671 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3675 /* if critical function then turn interrupts off */
3676 if (IFFUNC_ISCRITICAL(ftype)) {
3677 //pic16_emitcode("clr","ea");
3680 _G.fregsUsed = sym->regsUsed;
3682 /* if this is an interrupt service routine then
3683 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3684 if (IFFUNC_ISISR(sym->type)) {
3685 _G.usefastretfie = 1; /* use shadow registers by default */
3687 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3688 if(!FUNC_ISSHADOWREGS(sym->type)) {
3689 /* do not save WREG,STATUS,BSR for high priority interrupts
3690 * because they are stored in the hardware shadow registers already */
3691 _G.usefastretfie = 0;
3692 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3693 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3694 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3697 /* these should really be optimized somehow, because not all
3698 * interrupt handlers modify them */
3699 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3700 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3701 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3702 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3704 // pic16_pBlockConvert2ISR(pb);
3708 /* emit code to setup stack frame if user enabled,
3709 * and function is not main() */
3711 //fprintf(stderr, "function name: %s\n", sym->name);
3712 if(strcmp(sym->name, "main")) {
3713 if(0 || !options.ommitFramePtr || sym->regsUsed) {
3714 /* setup the stack frame */
3715 if(STACK_MODEL_LARGE)
3716 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3717 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3719 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3720 if(STACK_MODEL_LARGE)
3721 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3725 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3728 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3730 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3731 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3733 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3736 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3737 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3744 /* if callee-save to be used for this function
3745 * then save the registers being used in this function */
3746 // if (IFFUNC_CALLEESAVES(sym->type))
3750 /* if any registers used */
3751 if (sym->regsUsed) {
3752 /* save the registers used */
3753 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3754 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3755 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3756 if (bitVectBitValue(sym->regsUsed,i)) {
3757 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3760 if(!pic16_regWithIdx(i)->wasUsed) {
3761 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3762 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3763 pic16_regWithIdx(i)->wasUsed = 1;
3767 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3771 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3772 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3775 /*-----------------------------------------------------------------*/
3776 /* genEndFunction - generates epilogue for functions */
3777 /*-----------------------------------------------------------------*/
3778 static void genEndFunction (iCode *ic)
3780 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3784 if(IFFUNC_ISNAKED(sym->type)) {
3785 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3791 /* add code for ISCRITICAL */
3792 if(IFFUNC_ISCRITICAL(sym->type)) {
3793 /* if critical function, turn on interrupts */
3795 /* TODO: add code here -- VR */
3798 // sym->regsUsed = _G.fregsUsed;
3800 /* now we need to restore the registers */
3801 /* if any registers used */
3802 if (sym->regsUsed) {
3805 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3806 /* restore registers used */
3807 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3808 for ( i = sym->regsUsed->size; i >= 0; i--) {
3809 if (bitVectBitValue(sym->regsUsed,i)) {
3810 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3814 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3818 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3820 if (sym->stack == 1) {
3821 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3822 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3824 // we have to add more than one...
3825 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3826 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3827 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3829 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3830 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3831 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3835 if(strcmp(sym->name, "main")) {
3836 if(0 || !options.ommitFramePtr || sym->regsUsed) {
3837 /* restore stack frame */
3838 if(STACK_MODEL_LARGE)
3839 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3840 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3846 if (IFFUNC_ISISR(sym->type)) {
3847 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3848 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3849 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3850 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3852 if(!FUNC_ISSHADOWREGS(sym->type)) {
3853 /* do not restore interrupt vector for WREG,STATUS,BSR
3854 * for high priority interrupt, see genFunction */
3855 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3856 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3857 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3859 // _G.interruptvector = 0; /* sanity check */
3862 /* if debug then send end of function */
3863 /* if (options.debug && currFunc) */
3865 debugFile->writeEndFunction (currFunc, ic, 1);
3868 if(_G.usefastretfie)
3869 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3871 pic16_emitpcodeNULLop(POC_RETFIE);
3873 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3875 _G.usefastretfie = 0;
3879 if (IFFUNC_ISCRITICAL(sym->type)) {
3880 pic16_emitcode("setb","ea");
3883 /* if debug then send end of function */
3885 debugFile->writeEndFunction (currFunc, ic, 1);
3888 /* insert code to restore stack frame, if user enabled it
3889 * and function is not main() */
3892 pic16_emitpcodeNULLop(POC_RETURN);
3894 /* Mark the end of a function */
3895 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3899 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3901 unsigned long lit=1;
3903 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3904 if(AOP_TYPE(op) == AOP_LIT) {
3905 if(!IS_FLOAT(operandType( op ))) {
3906 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3909 unsigned long lit_int;
3913 /* take care if literal is a float */
3914 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3921 pic16_emitpcode(POC_CLRF, dest);
3923 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3924 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3927 if(dest->type == PO_WREG && (offset == 0)) {
3928 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3931 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3935 /*-----------------------------------------------------------------*/
3936 /* genRet - generate code for return statement */
3937 /*-----------------------------------------------------------------*/
3938 static void genRet (iCode *ic)
3944 /* if we have no return value then
3945 * just generate the "ret" */
3950 /* we have something to return then
3951 * move the return value into place */
3952 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3953 size = AOP_SIZE(IC_LEFT(ic));
3957 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3958 // pic16_emitpcode(POC_MOVFF,
3959 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3962 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3963 // pic16_emitpcode(POC_MOVFF,
3964 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3967 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3968 // pic16_emitpcode(POC_MOVFF,
3969 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3972 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3974 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3975 // pic16_emitpcode(POC_MOVFF,
3976 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3979 /* >32-bits, setup stack and FSR0 */
3981 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3982 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3984 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3986 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3991 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3992 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3994 if(STACK_MODEL_LARGE) {
3995 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3996 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3998 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4003 /* old code, left here for reference -- VR */
4007 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4009 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4010 pic16_emitpcomment("push %s",l);
4013 DEBUGpic16_emitcode(";", "%d", __LINE__);
4014 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4015 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4017 if (strcmp(fReturn[offset],l)) {
4018 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4019 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4020 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4022 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4026 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4036 if (strcmp(fReturn[pushed],"a"))
4037 pic16_emitcode("pop",fReturn[pushed]);
4039 pic16_emitcode("pop","acc");
4045 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4048 /* generate a jump to the return label
4049 * if the next is not the return statement */
4050 if (!(ic->next && ic->next->op == LABEL
4051 && IC_LABEL(ic->next) == returnLabel)) {
4053 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4054 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4058 /*-----------------------------------------------------------------*/
4059 /* genLabel - generates a label */
4060 /*-----------------------------------------------------------------*/
4061 static void genLabel (iCode *ic)
4065 /* special case never generate */
4066 if (IC_LABEL(ic) == entryLabel)
4069 pic16_emitpLabel(IC_LABEL(ic)->key);
4070 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4073 /*-----------------------------------------------------------------*/
4074 /* genGoto - generates a goto */
4075 /*-----------------------------------------------------------------*/
4077 static void genGoto (iCode *ic)
4080 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4081 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4085 /*-----------------------------------------------------------------*/
4086 /* genMultbits :- multiplication of bits */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultbits (operand *left,
4094 if(!pic16_sameRegs(AOP(result),AOP(right)))
4095 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4097 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4098 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4099 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4104 /*-----------------------------------------------------------------*/
4105 /* genMultOneByte : 8 bit multiplication & division */
4106 /*-----------------------------------------------------------------*/
4107 static void genMultOneByte (operand *left,
4113 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4114 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4116 /* (if two literals, the value is computed before) */
4117 /* if one literal, literal on the right */
4118 if (AOP_TYPE(left) == AOP_LIT){
4124 /* size is already checked in genMult == 1 */
4125 // size = AOP_SIZE(result);
4127 if (AOP_TYPE(right) == AOP_LIT){
4128 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4129 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4130 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4131 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4133 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4134 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4135 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4136 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4139 pic16_genMult8X8_8 (left, right,result);
4142 /*-----------------------------------------------------------------*/
4143 /* genMultOneWord : 16 bit multiplication */
4144 /*-----------------------------------------------------------------*/
4145 static void genMultOneWord (operand *left,
4150 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4151 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4153 /* (if two literals, the value is computed before)
4154 * if one literal, literal on the right */
4155 if (AOP_TYPE(left) == AOP_LIT){
4161 /* size is checked already == 2 */
4162 // size = AOP_SIZE(result);
4164 if (AOP_TYPE(right) == AOP_LIT) {
4165 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4166 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4167 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4168 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4170 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4171 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4172 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4173 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4176 pic16_genMult16X16_16(left, right,result);
4179 /*-----------------------------------------------------------------*/
4180 /* genMultOneLong : 32 bit multiplication */
4181 /*-----------------------------------------------------------------*/
4182 static void genMultOneLong (operand *left,
4187 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4190 /* (if two literals, the value is computed before)
4191 * if one literal, literal on the right */
4192 if (AOP_TYPE(left) == AOP_LIT){
4198 /* size is checked already == 4 */
4199 // size = AOP_SIZE(result);
4201 if (AOP_TYPE(right) == AOP_LIT) {
4202 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4203 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4204 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4208 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213 pic16_genMult32X32_32(left, right,result);
4218 /*-----------------------------------------------------------------*/
4219 /* genMult - generates code for multiplication */
4220 /*-----------------------------------------------------------------*/
4221 static void genMult (iCode *ic)
4223 operand *left = IC_LEFT(ic);
4224 operand *right = IC_RIGHT(ic);
4225 operand *result= IC_RESULT(ic);
4228 /* assign the amsops */
4229 pic16_aopOp (left,ic,FALSE);
4230 pic16_aopOp (right,ic,FALSE);
4231 pic16_aopOp (result,ic,TRUE);
4233 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4235 /* special cases first *
4237 if (AOP_TYPE(left) == AOP_CRY
4238 && AOP_TYPE(right)== AOP_CRY) {
4239 genMultbits(left,right,result);
4243 /* if both are of size == 1 */
4244 if(AOP_SIZE(left) == 1
4245 && AOP_SIZE(right) == 1) {
4246 genMultOneByte(left,right,result);
4250 /* if both are of size == 2 */
4251 if(AOP_SIZE(left) == 2
4252 && AOP_SIZE(right) == 2) {
4253 genMultOneWord(left, right, result);
4257 /* if both are of size == 4 */
4258 if(AOP_SIZE(left) == 4
4259 && AOP_SIZE(right) == 4) {
4260 genMultOneLong(left, right, result);
4264 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4267 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4268 /* should have been converted to function call */
4272 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4274 pic16_freeAsmop(result,NULL,ic,TRUE);
4277 /*-----------------------------------------------------------------*/
4278 /* genDivbits :- division of bits */
4279 /*-----------------------------------------------------------------*/
4280 static void genDivbits (operand *left,
4287 /* the result must be bit */
4288 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4289 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4293 pic16_emitcode("div","ab");
4294 pic16_emitcode("rrc","a");
4295 pic16_aopPut(AOP(result),"c",0);
4298 /*-----------------------------------------------------------------*/
4299 /* genDivOneByte : 8 bit division */
4300 /*-----------------------------------------------------------------*/
4301 static void genDivOneByte (operand *left,
4305 sym_link *opetype = operandType(result);
4310 /* result = divident / divisor
4311 * - divident may be a register or a literal,
4312 * - divisor may be a register or a literal,
4313 * so there are 3 cases (literal / literal is optimized
4314 * by the front-end) to handle.
4315 * In addition we must handle signed and unsigned, which
4316 * result in 6 final different cases -- VR */
4320 size = AOP_SIZE(result) - 1;
4322 /* signed or unsigned */
4323 if (SPEC_USIGN(opetype)) {
4324 pCodeOp *pct1, /* count */
4327 symbol *label1, *label2, *label3;;
4330 /* unsigned is easy */
4332 pct1 = pic16_popGetTempReg(1);
4333 pct2 = pic16_popGetTempReg(1);
4334 pct3 = pic16_popGetTempReg(1);
4336 label1 = newiTempLabel(NULL);
4337 label2 = newiTempLabel(NULL);
4338 label3 = newiTempLabel(NULL);
4340 /* the following algorithm is extracted from divuint.c */
4342 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4343 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4345 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4349 pic16_emitpLabel(label1->key);
4352 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4356 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4360 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4362 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4365 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4366 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4367 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4369 pic16_emitpLabel( label3->key );
4370 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4371 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4375 pic16_emitpLabel(label2->key);
4376 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4377 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4378 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4380 /* result is in wreg */
4381 if(AOP_TYPE(result) != AOP_ACC)
4382 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4384 pic16_popReleaseTempReg( pct3, 1);
4385 pic16_popReleaseTempReg( pct2, 1);
4386 pic16_popReleaseTempReg( pct1, 1);
4391 /* signed is a little bit more difficult */
4393 /* save the signs of the operands */
4394 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4396 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4397 pic16_emitcode("push","acc"); /* save it on the stack */
4399 /* now sign adjust for both left & right */
4400 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4402 lbl = newiTempLabel(NULL);
4403 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4404 pic16_emitcode("cpl","a");
4405 pic16_emitcode("inc","a");
4406 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4407 pic16_emitcode("mov","b,a");
4409 /* sign adjust left side */
4410 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4413 lbl = newiTempLabel(NULL);
4414 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4415 pic16_emitcode("cpl","a");
4416 pic16_emitcode("inc","a");
4417 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4419 /* now the division */
4420 pic16_emitcode("div","ab");
4421 /* we are interested in the lower order
4423 pic16_emitcode("mov","b,a");
4424 lbl = newiTempLabel(NULL);
4425 pic16_emitcode("pop","acc");
4426 /* if there was an over flow we don't
4427 adjust the sign of the result */
4428 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4429 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4431 pic16_emitcode("clr","a");
4432 pic16_emitcode("subb","a,b");
4433 pic16_emitcode("mov","b,a");
4434 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4436 /* now we are done */
4437 pic16_aopPut(AOP(result),"b",0);
4439 pic16_emitcode("mov","c,b.7");
4440 pic16_emitcode("subb","a,acc");
4443 pic16_aopPut(AOP(result),"a",offset++);
4447 /*-----------------------------------------------------------------*/
4448 /* genDiv - generates code for division */
4449 /*-----------------------------------------------------------------*/
4450 static void genDiv (iCode *ic)
4452 operand *left = IC_LEFT(ic);
4453 operand *right = IC_RIGHT(ic);
4454 operand *result= IC_RESULT(ic);
4457 /* Division is a very lengthy algorithm, so it is better
4458 * to call support routines than inlining algorithm.
4459 * Division functions written here just in case someone
4460 * wants to inline and not use the support libraries -- VR */
4464 /* assign the amsops */
4465 pic16_aopOp (left,ic,FALSE);
4466 pic16_aopOp (right,ic,FALSE);
4467 pic16_aopOp (result,ic,TRUE);
4469 /* special cases first */
4471 if (AOP_TYPE(left) == AOP_CRY &&
4472 AOP_TYPE(right)== AOP_CRY) {
4473 genDivbits(left,right,result);
4477 /* if both are of size == 1 */
4478 if (AOP_SIZE(left) == 1 &&
4479 AOP_SIZE(right) == 1 ) {
4480 genDivOneByte(left,right,result);
4484 /* should have been converted to function call */
4487 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489 pic16_freeAsmop(result,NULL,ic,TRUE);
4492 /*-----------------------------------------------------------------*/
4493 /* genModbits :- modulus of bits */
4494 /*-----------------------------------------------------------------*/
4495 static void genModbits (operand *left,
4503 werror(W_POSSBUG2, __FILE__, __LINE__);
4504 /* the result must be bit */
4505 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4506 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4510 pic16_emitcode("div","ab");
4511 pic16_emitcode("mov","a,b");
4512 pic16_emitcode("rrc","a");
4513 pic16_aopPut(AOP(result),"c",0);
4516 /*-----------------------------------------------------------------*/
4517 /* genModOneByte : 8 bit modulus */
4518 /*-----------------------------------------------------------------*/
4519 static void genModOneByte (operand *left,
4523 sym_link *opetype = operandType(result);
4528 werror(W_POSSBUG2, __FILE__, __LINE__);
4530 /* signed or unsigned */
4531 if (SPEC_USIGN(opetype)) {
4532 /* unsigned is easy */
4533 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4534 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4536 pic16_emitcode("div","ab");
4537 pic16_aopPut(AOP(result),"b",0);
4541 /* signed is a little bit more difficult */
4543 /* save the signs of the operands */
4544 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4547 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4548 pic16_emitcode("push","acc"); /* save it on the stack */
4550 /* now sign adjust for both left & right */
4551 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4554 lbl = newiTempLabel(NULL);
4555 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4556 pic16_emitcode("cpl","a");
4557 pic16_emitcode("inc","a");
4558 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4559 pic16_emitcode("mov","b,a");
4561 /* sign adjust left side */
4562 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4565 lbl = newiTempLabel(NULL);
4566 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4567 pic16_emitcode("cpl","a");
4568 pic16_emitcode("inc","a");
4569 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4571 /* now the multiplication */
4572 pic16_emitcode("div","ab");
4573 /* we are interested in the lower order
4575 lbl = newiTempLabel(NULL);
4576 pic16_emitcode("pop","acc");
4577 /* if there was an over flow we don't
4578 adjust the sign of the result */
4579 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4580 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4582 pic16_emitcode("clr","a");
4583 pic16_emitcode("subb","a,b");
4584 pic16_emitcode("mov","b,a");
4585 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4587 /* now we are done */
4588 pic16_aopPut(AOP(result),"b",0);
4592 /*-----------------------------------------------------------------*/
4593 /* genMod - generates code for division */
4594 /*-----------------------------------------------------------------*/
4595 static void genMod (iCode *ic)
4597 operand *left = IC_LEFT(ic);
4598 operand *right = IC_RIGHT(ic);
4599 operand *result= IC_RESULT(ic);
4603 /* assign the amsops */
4604 pic16_aopOp (left,ic,FALSE);
4605 pic16_aopOp (right,ic,FALSE);
4606 pic16_aopOp (result,ic,TRUE);
4608 /* special cases first */
4610 if (AOP_TYPE(left) == AOP_CRY &&
4611 AOP_TYPE(right)== AOP_CRY) {
4612 genModbits(left,right,result);
4616 /* if both are of size == 1 */
4617 if (AOP_SIZE(left) == 1 &&
4618 AOP_SIZE(right) == 1 ) {
4619 genModOneByte(left,right,result);
4623 /* should have been converted to function call */
4627 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629 pic16_freeAsmop(result,NULL,ic,TRUE);
4632 /*-----------------------------------------------------------------*/
4633 /* genIfxJump :- will create a jump depending on the ifx */
4634 /*-----------------------------------------------------------------*/
4636 note: May need to add parameter to indicate when a variable is in bit space.
4638 static void genIfxJump (iCode *ic, char *jval)
4642 /* if true label then we jump if condition
4644 if ( IC_TRUE(ic) ) {
4646 if(strcmp(jval,"a") == 0)
4648 else if (strcmp(jval,"c") == 0)
4651 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4652 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4655 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4656 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4660 /* false label is present */
4661 if(strcmp(jval,"a") == 0)
4663 else if (strcmp(jval,"c") == 0)
4666 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4667 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4670 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4671 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4676 /* mark the icode as generated */
4680 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4684 /* if true label then we jump if condition
4686 if ( IC_TRUE(ic) ) {
4687 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4688 pic16_emitpcode(POC_BTFSC, jop);
4690 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4691 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4694 /* false label is present */
4695 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4696 pic16_emitpcode(POC_BTFSS, jop);
4698 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4699 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4703 /* mark the icode as generated */
4710 /*-----------------------------------------------------------------*/
4712 /*-----------------------------------------------------------------*/
4713 static void genSkip(iCode *ifx,int status_bit)
4715 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4719 if ( IC_TRUE(ifx) ) {
4720 switch(status_bit) {
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4736 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4740 switch(status_bit) {
4754 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4755 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4762 /*-----------------------------------------------------------------*/
4764 /*-----------------------------------------------------------------*/
4765 static void genSkipc(resolvedIfx *rifx)
4767 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4777 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4778 rifx->generated = 1;
4781 #if !(USE_SIMPLE_GENCMP)
4782 /*-----------------------------------------------------------------*/
4784 /*-----------------------------------------------------------------*/
4785 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4787 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4792 if( (rifx->condition ^ invert_condition) & 1)
4797 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4798 rifx->generated = 1;
4803 /*-----------------------------------------------------------------*/
4805 /*-----------------------------------------------------------------*/
4806 static void genSkipz(iCode *ifx, int condition)
4817 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4819 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4822 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4824 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4829 #if !(USE_SIMPLE_GENCMP)
4830 /*-----------------------------------------------------------------*/
4832 /*-----------------------------------------------------------------*/
4833 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4839 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4841 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4845 rifx->generated = 1;
4850 /*-----------------------------------------------------------------*/
4851 /* genChkZeroes :- greater or less than comparison */
4852 /* For each byte in a literal that is zero, inclusive or the */
4853 /* the corresponding byte in the operand with W */
4854 /* returns true if any of the bytes are zero */
4855 /*-----------------------------------------------------------------*/
4856 static int genChkZeroes(operand *op, int lit, int size)
4863 i = (lit >> (size*8)) & 0xff;
4867 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4869 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4878 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4879 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4881 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4882 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4884 /*-----------------------------------------------------------------*/
4885 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4886 /* aop (if it's NOT a literal) or from lit (if */
4887 /* aop is a literal) */
4888 /*-----------------------------------------------------------------*/
4889 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4890 if (aop->type == AOP_LIT) {
4891 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4893 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4897 /*-----------------------------------------------------------------*/
4898 /* genCmp :- greater or less than comparison */
4899 /*-----------------------------------------------------------------*/
4901 #if USE_SIMPLE_GENCMP
4903 /* genCmp performs a left < right comparison, stores
4904 * the outcome in result (if != NULL) and generates
4905 * control flow code for the ifx (if != NULL).
4907 * This version leaves in sequences like
4908 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4909 * which should be optmized by the peephole
4910 * optimizer - RN 2005-01-01 */
4911 static void genCmp (operand *left,operand *right,
4912 operand *result, iCode *ifx, int sign)
4925 assert (AOP_SIZE(left) == AOP_SIZE(right));
4926 assert (left && right);
4928 size = AOP_SIZE(right) - 1;
4929 mask = (0x100UL << (size*8)) - 1;
4930 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4935 resolveIfx (&rIfx, ifx);
4937 /**********************************************************************
4938 * handle bits - bit compares are promoted to int compares seemingly! *
4939 **********************************************************************/
4941 // THIS IS COMPLETELY UNTESTED!
4942 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4943 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4944 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4945 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4948 // 1 < {0,1} is false --> clear C by skipping the next instruction
4949 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4950 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4951 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4952 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4953 emitCLRC; // only skipped for left=0 && right=1
4955 goto correct_result_in_carry;
4959 /*************************************************
4960 * make sure that left is register (or the like) *
4961 *************************************************/
4962 if (!isAOP_REGlike(left)) {
4963 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4964 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4966 assert (isAOP_LIT(left));
4967 assert (isAOP_REGlike(right));
4968 // swap left and right
4969 // left < right <==> right > left <==> (right >= left + 1)
4970 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4972 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4973 // MAXVALUE < right? always false
4974 if (performedLt) emitCLRC; else emitSETC;
4975 goto correct_result_in_carry;
4978 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4979 // that's we handled it above.
4986 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4987 } else if (isAOP_LIT(right)) {
4988 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4991 assert (isAOP_REGlike(left)); // left must be register or the like
4992 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4994 /*************************************************
4995 * special cases go here *
4996 *************************************************/
4998 if (isAOP_LIT(right)) {
5000 // unsigned comparison to a literal
5001 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5002 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5005 // unsigned left < 0? always false
5006 if (performedLt) emitCLRC; else emitSETC;
5007 goto correct_result_in_carry;
5010 // signed comparison to a literal
5011 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5012 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5014 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5015 // signed left < 0x80000000? always false
5016 if (performedLt) emitCLRC; else emitSETC;
5017 goto correct_result_in_carry;
5018 } else if (lit == 0) {
5019 // compare left < 0; set CARRY if SIGNBIT(left) is set
5020 if (performedLt) emitSETC; else emitCLRC;
5021 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5022 if (performedLt) emitCLRC; else emitSETC;
5023 goto correct_result_in_carry;
5026 } // right is literal
5028 /*************************************************
5029 * perform a general case comparison *
5030 * make sure we get CARRY==1 <==> left >= right *
5031 *************************************************/
5032 // compare most significant bytes
5033 //DEBUGpc ("comparing bytes at offset %d", size);
5035 // unsigned comparison
5036 mov2w_regOrLit (AOP(right), lit, size);
5037 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5039 // signed comparison
5040 // (add 2^n to both operands then perform an unsigned comparison)
5041 if (isAOP_LIT(right)) {
5042 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5043 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5045 if (litbyte == 0x80) {
5046 // left >= 0x80 -- always true, but more bytes to come
5047 pic16_mov2w (AOP(left), size);
5048 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5051 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5052 pic16_mov2w (AOP(left), size);
5053 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5054 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5057 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5058 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5059 pic16_mov2w (AOP(left), size);
5060 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5061 pic16_emitpcode (POC_MOVWF, pctemp);
5062 pic16_mov2w (AOP(right), size);
5063 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5064 pic16_emitpcode (POC_SUBFW, pctemp);
5065 //pic16_popReleaseTempReg(pctemp, 1);
5069 // compare remaining bytes (treat as unsigned case from above)
5070 templbl = newiTempLabel ( NULL );
5073 //DEBUGpc ("comparing bytes at offset %d", offs);
5074 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5075 mov2w_regOrLit (AOP(right), lit, offs);
5076 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5078 pic16_emitpLabel (templbl->key);
5079 goto result_in_carry;
5083 /****************************************************
5084 * now CARRY contains the result of the comparison: *
5085 * SUBWF sets CARRY iff *
5086 * F-W >= 0 <==> F >= W <==> !(F < W) *
5088 ****************************************************/
5091 if (result && AOP_TYPE(result) != AOP_CRY) {
5092 // value will be stored
5095 // value wil only be used in the following genSkipc()
5096 rIfx.condition ^= 1;
5100 correct_result_in_carry:
5102 // assign result to variable (if neccessary)
5103 if (result && AOP_TYPE(result) != AOP_CRY) {
5104 //DEBUGpc ("assign result");
5105 size = AOP_SIZE(result);
5107 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5109 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5112 // perform conditional jump
5113 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5115 //DEBUGpc ("generate control flow");
5116 rIfx.condition ^= 1;
5125 static void genCmp (operand *left,operand *right,
5126 operand *result, iCode *ifx, int sign)
5128 int size; //, offset = 0 ;
5129 unsigned long lit = 0L,i = 0;
5130 resolvedIfx rFalseIfx;
5131 // resolvedIfx rTrueIfx;
5133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5136 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5137 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5143 resolveIfx(&rFalseIfx,ifx);
5144 truelbl = newiTempLabel(NULL);
5145 size = max(AOP_SIZE(left),AOP_SIZE(right));
5147 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5151 /* if literal is on the right then swap with left */
5152 if ((AOP_TYPE(right) == AOP_LIT)) {
5153 operand *tmp = right ;
5154 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5155 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5158 lit = (lit - 1) & mask;
5161 rFalseIfx.condition ^= 1;
5164 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5165 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5169 //if(IC_TRUE(ifx) == NULL)
5170 /* if left & right are bit variables */
5171 if (AOP_TYPE(left) == AOP_CRY &&
5172 AOP_TYPE(right) == AOP_CRY ) {
5173 assert (0 && "bit variables used in genCmp");
5174 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5175 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5177 /* subtract right from left if at the
5178 end the carry flag is set then we know that
5179 left is greater than right */
5181 symbol *lbl = newiTempLabel(NULL);
5184 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5185 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5189 if(AOP_TYPE(right) == AOP_LIT) {
5191 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5193 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5200 genSkipCond(&rFalseIfx,left,size-1,7);
5202 /* no need to compare to 0...*/
5203 /* NOTE: this is a de-generate compare that most certainly
5204 * creates some dead code. */
5205 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5207 if(ifx) ifx->generated = 1;
5214 //i = (lit >> (size*8)) & 0xff;
5215 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5217 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5219 i = ((0-lit) & 0xff);
5222 /* lit is 0x7f, all signed chars are less than
5223 * this except for 0x7f itself */
5224 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5225 genSkipz2(&rFalseIfx,0);
5227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5228 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5229 genSkipc(&rFalseIfx);
5234 genSkipz2(&rFalseIfx,1);
5236 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5237 genSkipc(&rFalseIfx);
5241 if(ifx) ifx->generated = 1;
5245 /* chars are out of the way. now do ints and longs */
5248 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5255 genSkipCond(&rFalseIfx,left,size,7);
5256 if(ifx) ifx->generated = 1;
5261 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5263 //rFalseIfx.condition ^= 1;
5264 //genSkipCond(&rFalseIfx,left,size,7);
5265 //rFalseIfx.condition ^= 1;
5267 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5268 if(rFalseIfx.condition)
5269 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5271 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5273 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5274 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5275 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5278 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5280 if(rFalseIfx.condition) {
5282 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5288 genSkipc(&rFalseIfx);
5289 pic16_emitpLabel(truelbl->key);
5290 if(ifx) ifx->generated = 1;
5297 if( (lit & 0xff) == 0) {
5298 /* lower byte is zero */
5299 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5300 i = ((lit >> 8) & 0xff) ^0x80;
5301 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5302 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5303 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5304 genSkipc(&rFalseIfx);
5307 if(ifx) ifx->generated = 1;
5312 /* Special cases for signed longs */
5313 if( (lit & 0xffffff) == 0) {
5314 /* lower byte is zero */
5315 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5316 i = ((lit >> 8*3) & 0xff) ^0x80;
5317 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5318 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5319 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5320 genSkipc(&rFalseIfx);
5323 if(ifx) ifx->generated = 1;
5331 if(lit & (0x80 << (size*8))) {
5332 /* lit is negative */
5333 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5335 //genSkipCond(&rFalseIfx,left,size,7);
5337 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5339 if(rFalseIfx.condition)
5340 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5342 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5346 /* lit is positive */
5347 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5348 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5349 if(rFalseIfx.condition)
5350 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5352 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5357 This works, but is only good for ints.
5358 It also requires a "known zero" register.
5359 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5360 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5361 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5362 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5363 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5364 genSkipc(&rFalseIfx);
5366 pic16_emitpLabel(truelbl->key);
5367 if(ifx) ifx->generated = 1;
5371 /* There are no more special cases, so perform a general compare */
5373 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5374 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5378 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5380 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5382 //rFalseIfx.condition ^= 1;
5383 genSkipc(&rFalseIfx);
5385 pic16_emitpLabel(truelbl->key);
5387 if(ifx) ifx->generated = 1;
5394 /* sign is out of the way. So now do an unsigned compare */
5395 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5398 /* General case - compare to an unsigned literal on the right.*/
5400 i = (lit >> (size*8)) & 0xff;
5401 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5402 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5404 i = (lit >> (size*8)) & 0xff;
5407 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5409 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5411 /* this byte of the lit is zero,
5412 *if it's not the last then OR in the variable */
5414 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5419 pic16_emitpLabel(lbl->key);
5420 // pic16_emitpLabel(truelbl->key);
5421 //if(emitFinalCheck)
5422 genSkipc(&rFalseIfx);
5424 pic16_emitpLabel(truelbl->key);
5426 if(ifx) ifx->generated = 1;
5433 if(AOP_TYPE(left) == AOP_LIT) {
5434 //symbol *lbl = newiTempLabel(NULL);
5436 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5439 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5442 if((lit == 0) && (sign == 0)){
5445 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5447 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5449 genSkipz2(&rFalseIfx,0);
5450 if(ifx) ifx->generated = 1;
5457 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5458 /* degenerate compare can never be true */
5459 if(rFalseIfx.condition == 0)
5460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5462 if(ifx) ifx->generated = 1;
5467 /* signed comparisons to a literal byte */
5469 int lp1 = (lit+1) & 0xff;
5471 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5474 rFalseIfx.condition ^= 1;
5475 genSkipCond(&rFalseIfx,right,0,7);
5478 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5479 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5480 genSkipz2(&rFalseIfx,1);
5483 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5484 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5485 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5486 rFalseIfx.condition ^= 1;
5487 genSkipc(&rFalseIfx);
5491 /* unsigned comparisons to a literal byte */
5493 switch(lit & 0xff ) {
5495 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5496 genSkipz2(&rFalseIfx,0);
5499 rFalseIfx.condition ^= 1;
5500 genSkipCond(&rFalseIfx,right,0,7);
5504 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5505 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5506 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5507 rFalseIfx.condition ^= 1;
5508 if (AOP_TYPE(result) == AOP_CRY)
5509 genSkipc(&rFalseIfx);
5511 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5512 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5518 if(ifx) ifx->generated = 1;
5519 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5525 /* Size is greater than 1 */
5533 /* this means lit = 0xffffffff, or -1 */
5536 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5537 rFalseIfx.condition ^= 1;
5538 genSkipCond(&rFalseIfx,right,size,7);
5539 if(ifx) ifx->generated = 1;
5541 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5550 if(rFalseIfx.condition) {
5551 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5552 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5555 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5557 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5561 if(rFalseIfx.condition) {
5562 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5563 pic16_emitpLabel(truelbl->key);
5565 rFalseIfx.condition ^= 1;
5566 genSkipCond(&rFalseIfx,right,s,7);
5569 if(ifx) ifx->generated = 1;
5571 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5577 if((size == 1) && (0 == (lp1&0xff))) {
5578 /* lower byte of signed word is zero */
5579 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5580 i = ((lp1 >> 8) & 0xff) ^0x80;
5581 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5582 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5583 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5585 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5587 if(ifx) ifx->generated = 1;
5590 rFalseIfx.condition ^= 1;
5591 genSkipc(&rFalseIfx);
5592 if(ifx) ifx->generated = 1;
5598 if(lit & (0x80 << (size*8))) {
5599 /* Lit is less than zero */
5600 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5601 //rFalseIfx.condition ^= 1;
5602 //genSkipCond(&rFalseIfx,left,size,7);
5603 //rFalseIfx.condition ^= 1;
5604 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5605 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5607 if(rFalseIfx.condition)
5608 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5610 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5614 /* Lit is greater than or equal to zero */
5615 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5616 //rFalseIfx.condition ^= 1;
5617 //genSkipCond(&rFalseIfx,right,size,7);
5618 //rFalseIfx.condition ^= 1;
5620 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5621 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5623 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624 if(rFalseIfx.condition)
5625 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5627 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5631 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5632 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5636 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5638 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5640 rFalseIfx.condition ^= 1;
5641 //rFalseIfx.condition = 1;
5642 genSkipc(&rFalseIfx);
5644 pic16_emitpLabel(truelbl->key);
5646 if(ifx) ifx->generated = 1;
5649 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5656 /* compare word or long to an unsigned literal on the right.*/
5661 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5664 break; /* handled above */
5667 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5669 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5670 genSkipz2(&rFalseIfx,0);
5674 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5676 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5679 if(rFalseIfx.condition)
5680 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5682 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5685 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5686 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5688 rFalseIfx.condition ^= 1;
5689 genSkipc(&rFalseIfx);
5692 pic16_emitpLabel(truelbl->key);
5694 if(ifx) ifx->generated = 1;
5696 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5704 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5705 i = (lit >> (size*8)) & 0xff;
5707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5708 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5711 i = (lit >> (size*8)) & 0xff;
5714 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5716 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5718 /* this byte of the lit is zero,
5719 * if it's not the last then OR in the variable */
5721 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5726 pic16_emitpLabel(lbl->key);
5728 rFalseIfx.condition ^= 1;
5730 genSkipc(&rFalseIfx);
5734 pic16_emitpLabel(truelbl->key);
5735 if(ifx) ifx->generated = 1;
5737 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5743 /* Compare two variables */
5745 DEBUGpic16_emitcode(";sign","%d",sign);
5749 /* Sigh. thus sucks... */
5753 pctemp = pic16_popGetTempReg(1);
5754 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5755 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5756 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5757 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5758 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5759 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5760 pic16_popReleaseTempReg(pctemp, 1);
5762 /* Signed char comparison */
5763 /* Special thanks to Nikolai Golovchenko for this snippet */
5764 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5765 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5766 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5767 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5768 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5769 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5771 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5772 genSkipc(&rFalseIfx);
5774 if(ifx) ifx->generated = 1;
5776 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5784 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5785 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5789 /* The rest of the bytes of a multi-byte compare */
5793 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5796 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5797 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5802 pic16_emitpLabel(lbl->key);
5804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5805 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5806 (AOP_TYPE(result) == AOP_REG)) {
5807 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5808 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5810 genSkipc(&rFalseIfx);
5812 //genSkipc(&rFalseIfx);
5813 if(ifx) ifx->generated = 1;
5816 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5824 if ((AOP_TYPE(result) != AOP_CRY)
5825 && AOP_SIZE(result)) {
5826 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5828 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5830 pic16_outBitC(result);
5832 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5833 /* if the result is used in the next
5834 ifx conditional branch then generate
5835 code a little differently */
5837 genIfxJump (ifx,"c");
5839 pic16_outBitC(result);
5840 /* leave the result in acc */
5845 #else /* old version of genCmp() */ /* } else { */
5847 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5848 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5849 operand *result, int offset, int invert_op)
5853 /* check condition, > or < ?? */
5854 if(rIfx->condition != 0)invert_op ^= 1;
5856 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5858 if(!ifx)invert_op ^= 1;
5860 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5861 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5864 if(!invert_op)return POC_CPFSGT;
5865 else return POC_CPFSLT;
5868 static int compareAopfirstpass=1;
5870 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5871 operand *oper, int offset, operand *result,
5872 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5878 /* invert if there is a result to be loaded, in order to fit,
5879 * SETC/CLRC sequence */
5880 if(AOP_SIZE(result))invert_op ^= 1;
5882 // if(sign && !offset)invert_op ^= 1;
5884 // if(sign)invert_op ^= 1;
5886 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5888 if(AOP_SIZE(result) && compareAopfirstpass) {
5891 pic16_emitpcode(POC_SETF, pcop2);
5896 pic16_emitpcode(POC_CLRF, pcop2);
5902 compareAopfirstpass = 0;
5904 /* there is a bug when comparing operands with size > 1,
5905 * because higher bytes can be equal and test should be performed
5906 * to the next lower byte, current algorithm, considers operands
5907 * inequal in these cases! -- VR 20041107 */
5911 pic16_emitpcode(op, pcop);
5913 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5916 if((!sign || !offset) && AOP_SIZE(result)) {
5919 pic16_emitpcode(POC_CLRF, pcop2);
5924 pic16_emitpcode(POC_SETF, pcop2);
5929 /* don't emit final branch (offset == 0) */
5933 pic16_emitpcode(POC_RRCF, pcop2);
5935 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5938 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5939 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5940 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5942 truelbl = newiTempLabel( NULL );
5943 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5944 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5945 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5947 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5948 pic16_emitpLabel(truelbl->key);
5950 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5959 static void genCmp (operand *left, operand *right,
5960 operand *result, iCode *ifx, int sign)
5964 resolvedIfx rFalseIfx;
5965 symbol *falselbl, *tlbl;
5969 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5971 resolveIfx(&rFalseIfx, ifx);
5972 size = max(AOP_SIZE(left), AOP_SIZE(right));
5974 /* if left & right are bit variables */
5975 if(AOP_TYPE(left) == AOP_CRY
5976 && AOP_TYPE(right) == AOP_CRY ) {
5978 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5979 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5981 werror(W_POSSBUG2, __FILE__, __LINE__);
5985 /* if literal is on the right then swap with left */
5986 if((AOP_TYPE(right) == AOP_LIT)) {
5987 operand *tmp = right ;
5988 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5990 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5992 // lit = (lit - 1) & mask;
5995 rFalseIfx.condition ^= 1; /* reverse compare */
5997 if ((AOP_TYPE(left) == AOP_LIT)) {
5998 /* float compares are handled by support functions */
5999 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6002 /* actual comparing algorithm */
6003 // size = AOP_SIZE( right );
6005 falselbl = newiTempLabel( NULL );
6006 if(AOP_TYPE(left) == AOP_LIT) {
6007 /* compare to literal */
6008 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6011 pCodeOp *pct, *pct2;
6014 /* signed compare */
6015 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6017 pct = pic16_popCopyReg(&pic16_pc_prodl);
6018 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6019 tlbl = newiTempLabel( NULL );
6021 /* first compare signs:
6022 * a. if both are positive, compare just like unsigned
6023 * b. if both are negative, invert cmpop, compare just like unsigned
6024 * c. if different signs, determine the result directly */
6030 tlbl1 = newiTempLabel( NULL );
6031 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6035 /* literal is zero or positive:
6036 * a. if carry is zero, too, continue compare,
6037 * b. if carry is set, then continue depending on cmpop ^ condition:
6038 * 1. '<' return false (literal < variable),
6039 * 2. '>' return true (literal > variable) */
6040 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6041 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6044 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6045 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6049 /* literal is negative:
6050 * a. if carry is set, too, continue compare,
6051 * b. if carry is zero, then continue depending on cmpop ^ condition:
6052 * 1. '<' return true (literal < variable),
6053 * 2. '>' return false (literal > variable) */
6054 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6055 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6057 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6058 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6063 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6065 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6066 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6071 pic16_emitpLabel( tlbl1->key );
6074 compareAopfirstpass=1;
6075 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6076 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6077 // pic16_emitpcode(POC_MOVWF, pct);
6079 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6080 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6081 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6082 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6086 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6087 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6088 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6089 // pic16_emitpcode(POC_MOVWF, pct);
6091 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6092 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6093 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6094 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6095 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6099 if(ifx)ifx->generated = 1;
6101 if(AOP_SIZE(result)) {
6102 pic16_emitpLabel(tlbl->key);
6103 pic16_emitpLabel(falselbl->key);
6104 pic16_outBitOp( result, pct2 );
6106 pic16_emitpLabel(tlbl->key);
6111 /* unsigned compare */
6112 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6114 compareAopfirstpass=1;
6117 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6118 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6122 if(ifx)ifx->generated = 1;
6125 if(AOP_SIZE(result)) {
6126 pic16_emitpLabel(falselbl->key);
6127 pic16_outBitC( result );
6132 /* compare registers */
6133 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6137 pCodeOp *pct, *pct2;
6139 /* signed compare */
6140 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6142 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6143 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6144 tlbl = newiTempLabel( NULL );
6146 compareAopfirstpass=1;
6149 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6150 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6151 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6152 pic16_emitpcode(POC_MOVWF, pct);
6154 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6155 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6156 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6158 /* WREG already holds left + 0x80 */
6159 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6162 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6163 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6164 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6165 pic16_emitpcode(POC_MOVWF, pct);
6167 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6168 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6169 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6171 /* WREG already holds left + 0x80 */
6172 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6173 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6176 if(ifx)ifx->generated = 1;
6178 if(AOP_SIZE(result)) {
6179 pic16_emitpLabel(tlbl->key);
6180 pic16_emitpLabel(falselbl->key);
6181 pic16_outBitOp( result, pct2 );
6183 pic16_emitpLabel(tlbl->key);
6187 /* unsigned compare */
6188 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6190 compareAopfirstpass=1;
6193 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6194 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6198 if(ifx)ifx->generated = 1;
6199 if(AOP_SIZE(result)) {
6201 pic16_emitpLabel(falselbl->key);
6202 pic16_outBitC( result );
6209 #else /* } else { */
6211 /* new version of genCmp -- VR 20041012 */
6212 static void genCmp (operand *left,operand *right,
6213 operand *result, iCode *ifx, int sign)
6215 int size; //, offset = 0 ;
6216 unsigned long lit = 0L,i = 0;
6217 resolvedIfx rFalseIfx;
6218 int willCheckCarry=0;
6219 // resolvedIfx rTrueIfx;
6225 * subtract right from left if at the end the carry flag is set then we
6226 * know that left is greater than right */
6228 resolveIfx(&rFalseIfx,ifx);
6229 truelbl = newiTempLabel(NULL);
6230 size = max(AOP_SIZE(left),AOP_SIZE(right));
6232 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6234 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6235 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6238 /* if literal is on the right then swap with left */
6239 if ((AOP_TYPE(right) == AOP_LIT)) {
6240 operand *tmp = right ;
6241 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6243 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6245 // lit = (lit - 1) & mask;
6248 rFalseIfx.condition ^= 1; /* reverse compare */
6250 if ((AOP_TYPE(left) == AOP_LIT)) {
6251 /* float compares are handled by support functions */
6252 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6256 //if(IC_TRUE(ifx) == NULL)
6257 /* if left & right are bit variables */
6258 if (AOP_TYPE(left) == AOP_CRY &&
6259 AOP_TYPE(right) == AOP_CRY ) {
6261 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6262 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6265 symbol *lbl = newiTempLabel(NULL);
6267 if(AOP_TYPE(left) == AOP_LIT) {
6268 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6270 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6272 else willCheckCarry = 0;
6275 if((lit == 0) && (sign == 0)) {
6276 /* unsigned compare to 0 */
6277 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6280 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6282 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6284 genSkipz2(&rFalseIfx,0);
6285 if(ifx)ifx->generated = 1;
6292 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6293 /* degenerate compare can never be true */
6294 if(rFalseIfx.condition == 0)
6295 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6297 if(ifx) ifx->generated = 1;
6302 /* signed comparisons to a literal byte */
6303 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6305 int lp1 = (lit+1) & 0xff;
6307 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6310 rFalseIfx.condition ^= 1;
6311 genSkipCond(&rFalseIfx,right,0,7);
6314 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6315 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6316 genSkipz2(&rFalseIfx,1);
6319 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6321 if(rFalseIfx.condition)
6322 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6324 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6326 if(willCheckCarry) {
6327 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6328 else { emitSETC; emitCLRC; }
6331 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6334 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6336 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6337 rFalseIfx.condition ^= 1;
6338 genSkipc(&rFalseIfx);
6343 /* unsigned comparisons to a literal byte */
6344 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6346 switch(lit & 0xff ) {
6349 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6350 genSkipz2(&rFalseIfx,0);
6353 rFalseIfx.condition ^= 1;
6354 genSkipCond(&rFalseIfx,right,0,7);
6357 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6358 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6359 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6360 rFalseIfx.condition ^= 1;
6361 if (AOP_TYPE(result) == AOP_CRY)
6362 genSkipc(&rFalseIfx);
6364 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6365 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6371 if(ifx) ifx->generated = 1;
6372 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6378 /* Size is greater than 1 */
6386 /* this means lit = 0xffffffff, or -1 */
6389 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6390 rFalseIfx.condition ^= 1;
6391 genSkipCond(&rFalseIfx,right,size,7);
6392 if(ifx) ifx->generated = 1;
6399 if(rFalseIfx.condition) {
6400 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6401 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6404 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6406 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6410 if(rFalseIfx.condition) {
6411 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6412 pic16_emitpLabel(truelbl->key);
6414 rFalseIfx.condition ^= 1;
6415 genSkipCond(&rFalseIfx,right,s,7);
6418 if(ifx) ifx->generated = 1;
6422 if((size == 1) && (0 == (lp1&0xff))) {
6423 /* lower byte of signed word is zero */
6424 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6425 i = ((lp1 >> 8) & 0xff) ^0x80;
6426 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6427 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6428 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6429 rFalseIfx.condition ^= 1;
6430 genSkipc(&rFalseIfx);
6433 if(ifx) ifx->generated = 1;
6437 if(lit & (0x80 << (size*8))) {
6438 /* Lit is less than zero */
6439 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6440 //rFalseIfx.condition ^= 1;
6441 //genSkipCond(&rFalseIfx,left,size,7);
6442 //rFalseIfx.condition ^= 1;
6443 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6444 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6446 if(rFalseIfx.condition)
6447 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6449 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6453 /* Lit is greater than or equal to zero */
6454 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6455 //rFalseIfx.condition ^= 1;
6456 //genSkipCond(&rFalseIfx,right,size,7);
6457 //rFalseIfx.condition ^= 1;
6459 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6460 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6462 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6463 if(rFalseIfx.condition)
6464 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6466 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6471 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6472 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6476 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6478 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6480 rFalseIfx.condition ^= 1;
6481 //rFalseIfx.condition = 1;
6482 genSkipc(&rFalseIfx);
6484 pic16_emitpLabel(truelbl->key);
6486 if(ifx) ifx->generated = 1;
6491 /* compare word or long to an unsigned literal on the right.*/
6496 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6499 break; /* handled above */
6502 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6504 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6505 genSkipz2(&rFalseIfx,0);
6509 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6511 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6514 if(rFalseIfx.condition)
6515 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6517 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6520 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6521 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6523 rFalseIfx.condition ^= 1;
6524 genSkipc(&rFalseIfx);
6527 pic16_emitpLabel(truelbl->key);
6529 if(ifx) ifx->generated = 1;
6535 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6536 i = (lit >> (size*8)) & 0xff;
6538 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6539 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6542 i = (lit >> (size*8)) & 0xff;
6545 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6547 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6549 /* this byte of the lit is zero,
6550 * if it's not the last then OR in the variable */
6552 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6557 pic16_emitpLabel(lbl->key);
6559 rFalseIfx.condition ^= 1;
6561 genSkipc(&rFalseIfx);
6565 pic16_emitpLabel(truelbl->key);
6566 if(ifx) ifx->generated = 1;
6570 /* Compare two variables */
6572 DEBUGpic16_emitcode(";sign","%d",sign);
6576 /* Sigh. thus sucks... */
6580 pctemp = pic16_popGetTempReg(1);
6581 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6582 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6583 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6584 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6585 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6586 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6587 pic16_popReleaseTempReg(pctemp, 1);
6589 /* Signed char comparison */
6590 /* Special thanks to Nikolai Golovchenko for this snippet */
6591 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6592 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6593 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6594 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6595 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6596 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6598 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6599 genSkipc(&rFalseIfx);
6601 if(ifx) ifx->generated = 1;
6607 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6608 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6612 /* The rest of the bytes of a multi-byte compare */
6616 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6619 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6620 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6625 pic16_emitpLabel(lbl->key);
6627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6628 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6629 (AOP_TYPE(result) == AOP_REG)) {
6630 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6631 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6633 genSkipc(&rFalseIfx);
6635 //genSkipc(&rFalseIfx);
6636 if(ifx) ifx->generated = 1;
6643 if ((AOP_TYPE(result) != AOP_CRY)
6644 && AOP_SIZE(result)) {
6645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6647 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6649 pic16_outBitC(result);
6651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6652 /* if the result is used in the next
6653 ifx conditional branch then generate
6654 code a little differently */
6656 genIfxJump (ifx,"c");
6658 pic16_outBitC(result);
6659 /* leave the result in acc */
6670 /*-----------------------------------------------------------------*/
6671 /* genCmpGt :- greater than comparison */
6672 /*-----------------------------------------------------------------*/
6673 static void genCmpGt (iCode *ic, iCode *ifx)
6675 operand *left, *right, *result;
6676 sym_link *letype , *retype;
6682 right= IC_RIGHT(ic);
6683 result = IC_RESULT(ic);
6685 letype = getSpec(operandType(left));
6686 retype =getSpec(operandType(right));
6687 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6688 /* assign the amsops */
6689 pic16_aopOp (left,ic,FALSE);
6690 pic16_aopOp (right,ic,FALSE);
6691 pic16_aopOp (result,ic,TRUE);
6693 genCmp(right, left, result, ifx, sign);
6695 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6696 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6697 pic16_freeAsmop(result,NULL,ic,TRUE);
6700 /*-----------------------------------------------------------------*/
6701 /* genCmpLt - less than comparisons */
6702 /*-----------------------------------------------------------------*/
6703 static void genCmpLt (iCode *ic, iCode *ifx)
6705 operand *left, *right, *result;
6706 sym_link *letype , *retype;
6712 right= IC_RIGHT(ic);
6713 result = IC_RESULT(ic);
6715 letype = getSpec(operandType(left));
6716 retype =getSpec(operandType(right));
6717 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6719 /* assign the amsops */
6720 pic16_aopOp (left,ic,FALSE);
6721 pic16_aopOp (right,ic,FALSE);
6722 pic16_aopOp (result,ic,TRUE);
6724 genCmp(left, right, result, ifx, sign);
6726 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6727 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6728 pic16_freeAsmop(result,NULL,ic,TRUE);
6733 // FIXME reenable literal optimisation when the pic16 port is stable
6735 /*-----------------------------------------------------------------*/
6736 /* genc16bit2lit - compare a 16 bit value to a literal */
6737 /*-----------------------------------------------------------------*/
6738 static void genc16bit2lit(operand *op, int lit, int offset)
6742 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6743 if( (lit&0xff) == 0)
6748 switch( BYTEofLONG(lit,i)) {
6750 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6753 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6756 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6759 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6760 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6765 switch( BYTEofLONG(lit,i)) {
6767 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6771 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6775 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6778 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6780 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6789 /*-----------------------------------------------------------------*/
6790 /* gencjneshort - compare and jump if not equal */
6791 /*-----------------------------------------------------------------*/
6792 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6794 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6796 int res_offset = 0; /* the result may be a different size then left or right */
6797 int res_size = AOP_SIZE(result);
6799 symbol *lbl, *lbl_done;
6801 unsigned long lit = 0L;
6802 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6805 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6807 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6808 resolveIfx(&rIfx,ifx);
6809 lbl = newiTempLabel(NULL);
6810 lbl_done = newiTempLabel(NULL);
6813 /* if the left side is a literal or
6814 if the right is in a pointer register and left
6816 if ((AOP_TYPE(left) == AOP_LIT) ||
6817 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6822 if(AOP_TYPE(right) == AOP_LIT)
6823 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6825 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6826 preserve_result = 1;
6828 if(result && !preserve_result)
6831 for(i = 0; i < AOP_SIZE(result); i++)
6832 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6836 /* if the right side is a literal then anything goes */
6837 if (AOP_TYPE(right) == AOP_LIT &&
6838 AOP_TYPE(left) != AOP_DIR ) {
6841 genc16bit2lit(left, lit, 0);
6843 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6849 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6850 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6852 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6856 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6858 if(res_offset < res_size-1)
6866 /* if the right side is in a register or in direct space or
6867 if the left is a pointer register & right is not */
6868 else if (AOP_TYPE(right) == AOP_REG ||
6869 AOP_TYPE(right) == AOP_DIR ||
6870 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6871 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6872 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6873 int lbl_key = lbl->key;
6876 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6877 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6879 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6880 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6881 __FUNCTION__,__LINE__);
6885 /* switch(size) { */
6887 /* genc16bit2lit(left, lit, 0); */
6889 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6894 if((AOP_TYPE(left) == AOP_DIR) &&
6895 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6897 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6898 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6900 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6902 switch (lit & 0xff) {
6904 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6907 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6908 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6913 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6914 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6915 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6916 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6920 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6921 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6926 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6929 if(AOP_TYPE(result) == AOP_CRY) {
6930 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6935 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6937 /* fix me. probably need to check result size too */
6938 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6943 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6944 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6951 if(res_offset < res_size-1)
6956 } else if(AOP_TYPE(right) == AOP_REG &&
6957 AOP_TYPE(left) != AOP_DIR){
6960 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6961 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6962 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6967 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6969 if(res_offset < res_size-1)
6974 /* right is a pointer reg need both a & b */
6976 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6978 pic16_emitcode("mov","b,%s",l);
6979 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6980 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6985 if(result && preserve_result)
6988 for(i = 0; i < AOP_SIZE(result); i++)
6989 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6992 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6994 if(result && preserve_result)
6995 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7000 pic16_emitpLabel(lbl->key);
7002 if(result && preserve_result)
7005 for(i = 0; i < AOP_SIZE(result); i++)
7006 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7008 pic16_emitpLabel(lbl_done->key);
7011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7019 /*-----------------------------------------------------------------*/
7020 /* gencjne - compare and jump if not equal */
7021 /*-----------------------------------------------------------------*/
7022 static void gencjne(operand *left, operand *right, iCode *ifx)
7024 symbol *tlbl = newiTempLabel(NULL);
7026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7027 gencjneshort(left, right, lbl);
7029 pic16_emitcode("mov","a,%s",one);
7030 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7031 pic16_emitcode("","%05d_DS_:",lbl->key+100);
7032 pic16_emitcode("clr","a");
7033 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7035 pic16_emitpLabel(lbl->key);
7036 pic16_emitpLabel(tlbl->key);
7042 /*-----------------------------------------------------------------*/
7043 /* is_LitOp - check if operand has to be treated as literal */
7044 /*-----------------------------------------------------------------*/
7045 static bool is_LitOp(operand *op)
7047 return ((AOP_TYPE(op) == AOP_LIT)
7048 || ( (AOP_TYPE(op) == AOP_PCODE)
7049 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7050 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7053 /*-----------------------------------------------------------------*/
7054 /* is_LitAOp - check if operand has to be treated as literal */
7055 /*-----------------------------------------------------------------*/
7056 static bool is_LitAOp(asmop *aop)
7058 return ((aop->type == AOP_LIT)
7059 || ( (aop->type == AOP_PCODE)
7060 && ( (aop->aopu.pcop->type == PO_LITERAL)
7061 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7066 /*-----------------------------------------------------------------*/
7067 /* genCmpEq - generates code for equal to */
7068 /*-----------------------------------------------------------------*/
7069 static void genCmpEq (iCode *ic, iCode *ifx)
7071 operand *left, *right, *result;
7072 symbol *falselbl = newiTempLabel(NULL);
7073 symbol *donelbl = newiTempLabel(NULL);
7075 int preserve_result = 0;
7076 int generate_result = 0;
7078 unsigned long lit = -1;
7082 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7083 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7084 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7086 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7088 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7090 werror(W_POSSBUG2, __FILE__, __LINE__);
7091 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7092 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7096 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7098 operand *tmp = right ;
7103 if (AOP_TYPE(right) == AOP_LIT) {
7104 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7107 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7108 preserve_result = 1;
7110 if(result && AOP_SIZE(result))
7111 generate_result = 1;
7113 if(generate_result && !preserve_result)
7115 for(i = 0; i < AOP_SIZE(result); i++)
7116 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7119 for(i=0; i < AOP_SIZE(left); i++)
7121 if(AOP_TYPE(left) != AOP_ACC)
7124 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7126 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7128 if(is_LitOp(right)) {
7129 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7130 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7133 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7135 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7140 if(generate_result && preserve_result)
7142 for(i = 0; i < AOP_SIZE(result); i++)
7143 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7147 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7149 if(generate_result && preserve_result)
7150 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7152 if(ifx && IC_TRUE(ifx))
7153 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7155 if(ifx && IC_FALSE(ifx))
7156 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7158 pic16_emitpLabel(falselbl->key);
7162 if(ifx && IC_FALSE(ifx))
7163 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7165 if(generate_result && preserve_result)
7167 for(i = 0; i < AOP_SIZE(result); i++)
7168 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7171 pic16_emitpLabel(donelbl->key);
7177 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7178 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7179 pic16_freeAsmop(result,NULL,ic,TRUE);
7185 // old version kept for reference
7187 /*-----------------------------------------------------------------*/
7188 /* genCmpEq - generates code for equal to */
7189 /*-----------------------------------------------------------------*/
7190 static void genCmpEq (iCode *ic, iCode *ifx)
7192 operand *left, *right, *result;
7193 unsigned long lit = 0L;
7195 symbol *falselbl = newiTempLabel(NULL);
7198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7201 DEBUGpic16_emitcode ("; ifx is non-null","");
7203 DEBUGpic16_emitcode ("; ifx is null","");
7205 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7206 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7207 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7209 size = max(AOP_SIZE(left),AOP_SIZE(right));
7211 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7213 /* if literal, literal on the right or
7214 if the right is in a pointer register and left
7216 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7217 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7218 operand *tmp = right ;
7224 if(ifx && !AOP_SIZE(result)){
7226 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7227 /* if they are both bit variables */
7228 if (AOP_TYPE(left) == AOP_CRY &&
7229 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7230 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7231 if(AOP_TYPE(right) == AOP_LIT){
7232 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7234 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7235 pic16_emitcode("cpl","c");
7236 } else if(lit == 1L) {
7237 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7239 pic16_emitcode("clr","c");
7241 /* AOP_TYPE(right) == AOP_CRY */
7243 symbol *lbl = newiTempLabel(NULL);
7244 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7245 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7246 pic16_emitcode("cpl","c");
7247 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7249 /* if true label then we jump if condition
7251 tlbl = newiTempLabel(NULL);
7252 if ( IC_TRUE(ifx) ) {
7253 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7254 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7256 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7257 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7259 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7262 /* left and right are both bit variables, result is carry */
7265 resolveIfx(&rIfx,ifx);
7267 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7268 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7269 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7270 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7275 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7277 /* They're not both bit variables. Is the right a literal? */
7278 if(AOP_TYPE(right) == AOP_LIT) {
7279 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7284 switch(lit & 0xff) {
7286 if ( IC_TRUE(ifx) ) {
7287 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7289 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7291 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7292 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7296 if ( IC_TRUE(ifx) ) {
7297 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7299 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7301 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7302 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7306 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7308 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7313 /* end of size == 1 */
7317 genc16bit2lit(left,lit,offset);
7320 /* end of size == 2 */
7325 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7326 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7327 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7328 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7331 /* search for patterns that can be optimized */
7333 genc16bit2lit(left,lit,0);
7337 emitSKPZ; // if hi word unequal
7339 emitSKPNZ; // if hi word equal
7341 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7342 genc16bit2lit(left,lit,2);
7345 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7346 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7350 pic16_emitpLabel(falselbl->key);
7359 } else if(AOP_TYPE(right) == AOP_CRY ) {
7360 /* we know the left is not a bit, but that the right is */
7361 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7362 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7363 pic16_popGet(AOP(right),offset));
7364 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7366 /* if the two are equal, then W will be 0 and the Z bit is set
7367 * we could test Z now, or go ahead and check the high order bytes if
7368 * the variable we're comparing is larger than a byte. */
7371 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7373 if ( IC_TRUE(ifx) ) {
7375 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7376 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7379 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7380 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7384 /* They're both variables that are larger than bits */
7387 tlbl = newiTempLabel(NULL);
7390 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7391 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7393 if ( IC_TRUE(ifx) ) {
7397 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7399 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7400 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7404 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7407 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7408 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7413 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7415 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7416 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7420 if(s>1 && IC_TRUE(ifx)) {
7421 pic16_emitpLabel(tlbl->key);
7422 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7426 /* mark the icode as generated */
7431 /* if they are both bit variables */
7432 if (AOP_TYPE(left) == AOP_CRY &&
7433 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7434 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7435 if(AOP_TYPE(right) == AOP_LIT){
7436 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7438 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7439 pic16_emitcode("cpl","c");
7440 } else if(lit == 1L) {
7441 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7443 pic16_emitcode("clr","c");
7445 /* AOP_TYPE(right) == AOP_CRY */
7447 symbol *lbl = newiTempLabel(NULL);
7448 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7449 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7450 pic16_emitcode("cpl","c");
7451 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7454 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7455 pic16_outBitC(result);
7459 genIfxJump (ifx,"c");
7462 /* if the result is used in an arithmetic operation
7463 then put the result in place */
7464 pic16_outBitC(result);
7467 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7468 gencjne(left,right,result,ifx);
7471 gencjne(left,right,newiTempLabel(NULL));
7473 if(IC_TRUE(ifx)->key)
7474 gencjne(left,right,IC_TRUE(ifx)->key);
7476 gencjne(left,right,IC_FALSE(ifx)->key);
7480 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7481 pic16_aopPut(AOP(result),"a",0);
7486 genIfxJump (ifx,"a");
7490 /* if the result is used in an arithmetic operation
7491 then put the result in place */
7493 if (AOP_TYPE(result) != AOP_CRY)
7494 pic16_outAcc(result);
7496 /* leave the result in acc */
7500 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7501 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7502 pic16_freeAsmop(result,NULL,ic,TRUE);
7506 /*-----------------------------------------------------------------*/
7507 /* ifxForOp - returns the icode containing the ifx for operand */
7508 /*-----------------------------------------------------------------*/
7509 static iCode *ifxForOp ( operand *op, iCode *ic )
7513 /* if true symbol then needs to be assigned */
7514 if (IS_TRUE_SYMOP(op))
7517 /* if this has register type condition and
7518 the next instruction is ifx with the same operand
7519 and live to of the operand is upto the ifx only then */
7521 && ic->next->op == IFX
7522 && IC_COND(ic->next)->key == op->key
7523 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7525 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7531 ic->next->op == IFX &&
7532 IC_COND(ic->next)->key == op->key) {
7533 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7538 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7540 ic->next->op == IFX)
7541 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7544 ic->next->op == IFX &&
7545 IC_COND(ic->next)->key == op->key) {
7546 DEBUGpic16_emitcode ("; "," key is okay");
7547 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7548 OP_SYMBOL(op)->liveTo,
7553 /* the code below is completely untested
7554 * it just allows ulong2fs.c compile -- VR */
7557 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7558 __FILE__, __FUNCTION__, __LINE__);
7560 /* if this has register type condition and
7561 the next instruction is ifx with the same operand
7562 and live to of the operand is upto the ifx only then */
7564 ic->next->op == IFX &&
7565 IC_COND(ic->next)->key == op->key &&
7566 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7570 ic->next->op == IFX &&
7571 IC_COND(ic->next)->key == op->key) {
7572 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7576 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7577 __FILE__, __FUNCTION__, __LINE__);
7579 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7584 /*-----------------------------------------------------------------*/
7585 /* genAndOp - for && operation */
7586 /*-----------------------------------------------------------------*/
7587 static void genAndOp (iCode *ic)
7589 operand *left,*right, *result;
7594 /* note here that && operations that are in an
7595 if statement are taken away by backPatchLabels
7596 only those used in arthmetic operations remain */
7597 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7598 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7599 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7601 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7603 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7604 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7605 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7607 /* if both are bit variables */
7608 /* if (AOP_TYPE(left) == AOP_CRY && */
7609 /* AOP_TYPE(right) == AOP_CRY ) { */
7610 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7611 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7612 /* pic16_outBitC(result); */
7614 /* tlbl = newiTempLabel(NULL); */
7615 /* pic16_toBoolean(left); */
7616 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7617 /* pic16_toBoolean(right); */
7618 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7619 /* pic16_outBitAcc(result); */
7622 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7623 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7624 pic16_freeAsmop(result,NULL,ic,TRUE);
7628 /*-----------------------------------------------------------------*/
7629 /* genOrOp - for || operation */
7630 /*-----------------------------------------------------------------*/
7633 modified this code, but it doesn't appear to ever get called
7636 static void genOrOp (iCode *ic)
7638 operand *left,*right, *result;
7643 /* note here that || operations that are in an
7644 if statement are taken away by backPatchLabels
7645 only those used in arthmetic operations remain */
7646 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7647 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7648 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7650 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7652 /* if both are bit variables */
7653 if (AOP_TYPE(left) == AOP_CRY &&
7654 AOP_TYPE(right) == AOP_CRY ) {
7655 pic16_emitcode("clrc","");
7656 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7657 AOP(left)->aopu.aop_dir,
7658 AOP(left)->aopu.aop_dir);
7659 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7660 AOP(right)->aopu.aop_dir,
7661 AOP(right)->aopu.aop_dir);
7662 pic16_emitcode("setc","");
7665 tlbl = newiTempLabel(NULL);
7666 pic16_toBoolean(left);
7668 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7669 pic16_toBoolean(right);
7670 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7672 pic16_outBitAcc(result);
7675 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7677 pic16_freeAsmop(result,NULL,ic,TRUE);
7680 /*-----------------------------------------------------------------*/
7681 /* isLiteralBit - test if lit == 2^n */
7682 /*-----------------------------------------------------------------*/
7683 static int isLiteralBit(unsigned long lit)
7685 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7686 0x100L,0x200L,0x400L,0x800L,
7687 0x1000L,0x2000L,0x4000L,0x8000L,
7688 0x10000L,0x20000L,0x40000L,0x80000L,
7689 0x100000L,0x200000L,0x400000L,0x800000L,
7690 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7691 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7694 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7695 for(idx = 0; idx < 32; idx++)
7701 /*-----------------------------------------------------------------*/
7702 /* continueIfTrue - */
7703 /*-----------------------------------------------------------------*/
7704 static void continueIfTrue (iCode *ic)
7708 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7712 /*-----------------------------------------------------------------*/
7714 /*-----------------------------------------------------------------*/
7715 static void jumpIfTrue (iCode *ic)
7719 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7723 /*-----------------------------------------------------------------*/
7724 /* jmpTrueOrFalse - */
7725 /*-----------------------------------------------------------------*/
7726 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7728 // ugly but optimized by peephole
7731 symbol *nlbl = newiTempLabel(NULL);
7732 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7733 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7734 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7735 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7737 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7738 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7743 /*-----------------------------------------------------------------*/
7744 /* genAnd - code for and */
7745 /*-----------------------------------------------------------------*/
7746 static void genAnd (iCode *ic, iCode *ifx)
7748 operand *left, *right, *result;
7750 unsigned long lit = 0L;
7756 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7757 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7758 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7760 resolveIfx(&rIfx,ifx);
7762 /* if left is a literal & right is not then exchange them */
7763 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7764 AOP_NEEDSACC(left)) {
7765 operand *tmp = right ;
7770 /* if result = right then exchange them */
7771 if(pic16_sameRegs(AOP(result),AOP(right))){
7772 operand *tmp = right ;
7777 /* if right is bit then exchange them */
7778 if (AOP_TYPE(right) == AOP_CRY &&
7779 AOP_TYPE(left) != AOP_CRY){
7780 operand *tmp = right ;
7784 if(AOP_TYPE(right) == AOP_LIT)
7785 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7787 size = AOP_SIZE(result);
7789 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7792 // result = bit & yy;
7793 if (AOP_TYPE(left) == AOP_CRY){
7794 // c = bit & literal;
7795 if(AOP_TYPE(right) == AOP_LIT){
7797 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7800 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7803 if(size && (AOP_TYPE(result) == AOP_CRY)){
7804 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7807 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7811 pic16_emitcode("clr","c");
7814 if (AOP_TYPE(right) == AOP_CRY){
7816 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7817 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7820 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7822 pic16_emitcode("rrc","a");
7823 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7829 pic16_outBitC(result);
7831 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7832 genIfxJump(ifx, "c");
7836 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7837 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7838 if((AOP_TYPE(right) == AOP_LIT) &&
7839 (AOP_TYPE(result) == AOP_CRY) &&
7840 (AOP_TYPE(left) != AOP_CRY)){
7841 int posbit = isLiteralBit(lit);
7845 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7848 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7854 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7857 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7858 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7861 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7862 size = AOP_SIZE(left);
7865 int bp = posbit, ofs=0;
7872 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7873 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7877 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7878 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7880 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7887 symbol *tlbl = newiTempLabel(NULL);
7888 int sizel = AOP_SIZE(left);
7894 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7896 /* patch provided by Aaron Colwell */
7897 if((posbit = isLiteralBit(bytelit)) != 0) {
7898 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7899 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7900 (posbit-1),0, PO_GPR_REGISTER));
7902 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7903 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7905 if (bytelit == 0xff) {
7906 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7907 * a peephole could optimize it out -- VR */
7908 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7910 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7911 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7914 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7915 pic16_popGetLabel(tlbl->key));
7919 /* old code, left here for reference -- VR 09/2004 */
7920 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7922 if((posbit = isLiteralBit(bytelit)) != 0)
7923 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7925 if(bytelit != 0x0FFL)
7926 pic16_emitcode("anl","a,%s",
7927 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7928 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7934 // bit = left & literal
7937 pic16_emitpLabel(tlbl->key);
7939 // if(left & literal)
7942 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7945 pic16_emitpLabel(tlbl->key);
7950 pic16_outBitC(result);
7954 /* if left is same as result */
7955 if(pic16_sameRegs(AOP(result),AOP(left))){
7957 for(;size--; offset++,lit>>=8) {
7958 if(AOP_TYPE(right) == AOP_LIT){
7959 switch(lit & 0xff) {
7961 /* and'ing with 0 has clears the result */
7962 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7963 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7966 /* and'ing with 0xff is a nop when the result and left are the same */
7971 int p = pic16_my_powof2( (~lit) & 0xff );
7973 /* only one bit is set in the literal, so use a bcf instruction */
7974 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7975 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7978 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7979 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7980 if(know_W != (lit&0xff))
7981 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7983 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7988 if (AOP_TYPE(left) == AOP_ACC) {
7989 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7991 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7992 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7999 // left & result in different registers
8000 if(AOP_TYPE(result) == AOP_CRY){
8002 // if(size), result in bit
8003 // if(!size && ifx), conditional oper: if(left & right)
8004 symbol *tlbl = newiTempLabel(NULL);
8005 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8007 pic16_emitcode("setb","c");
8009 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8010 pic16_emitcode("anl","a,%s",
8011 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8012 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8017 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8018 pic16_outBitC(result);
8020 jmpTrueOrFalse(ifx, tlbl);
8022 for(;(size--);offset++) {
8024 // result = left & right
8025 if(AOP_TYPE(right) == AOP_LIT){
8026 int t = (lit >> (offset*8)) & 0x0FFL;
8029 pic16_emitcode("clrf","%s",
8030 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8031 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8034 pic16_emitcode("movf","%s,w",
8035 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8036 pic16_emitcode("movwf","%s",
8037 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8038 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8039 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8042 pic16_emitcode("movlw","0x%x",t);
8043 pic16_emitcode("andwf","%s,w",
8044 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8045 pic16_emitcode("movwf","%s",
8046 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8048 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8049 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8050 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8055 if (AOP_TYPE(left) == AOP_ACC) {
8056 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8057 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8059 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8060 pic16_emitcode("andwf","%s,w",
8061 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8062 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8063 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8065 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8066 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8072 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8073 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8074 pic16_freeAsmop(result,NULL,ic,TRUE);
8077 /*-----------------------------------------------------------------*/
8078 /* genOr - code for or */
8079 /*-----------------------------------------------------------------*/
8080 static void genOr (iCode *ic, iCode *ifx)
8082 operand *left, *right, *result;
8084 unsigned long lit = 0L;
8086 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8088 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8089 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8090 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8092 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8094 /* if left is a literal & right is not then exchange them */
8095 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8096 AOP_NEEDSACC(left)) {
8097 operand *tmp = right ;
8102 /* if result = right then exchange them */
8103 if(pic16_sameRegs(AOP(result),AOP(right))){
8104 operand *tmp = right ;
8109 /* if right is bit then exchange them */
8110 if (AOP_TYPE(right) == AOP_CRY &&
8111 AOP_TYPE(left) != AOP_CRY){
8112 operand *tmp = right ;
8117 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8119 if(AOP_TYPE(right) == AOP_LIT)
8120 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8122 size = AOP_SIZE(result);
8126 if (AOP_TYPE(left) == AOP_CRY){
8127 if(AOP_TYPE(right) == AOP_LIT){
8128 // c = bit & literal;
8130 // lit != 0 => result = 1
8131 if(AOP_TYPE(result) == AOP_CRY){
8133 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8134 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8135 // AOP(result)->aopu.aop_dir,
8136 // AOP(result)->aopu.aop_dir);
8138 continueIfTrue(ifx);
8142 // lit == 0 => result = left
8143 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8145 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8148 if (AOP_TYPE(right) == AOP_CRY){
8149 if(pic16_sameRegs(AOP(result),AOP(left))){
8151 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8152 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8153 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8155 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8156 AOP(result)->aopu.aop_dir,
8157 AOP(result)->aopu.aop_dir);
8158 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8159 AOP(right)->aopu.aop_dir,
8160 AOP(right)->aopu.aop_dir);
8161 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8162 AOP(result)->aopu.aop_dir,
8163 AOP(result)->aopu.aop_dir);
8165 if( AOP_TYPE(result) == AOP_ACC) {
8166 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8167 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8168 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8169 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8173 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8174 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8175 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8176 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8178 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8179 AOP(result)->aopu.aop_dir,
8180 AOP(result)->aopu.aop_dir);
8181 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8182 AOP(right)->aopu.aop_dir,
8183 AOP(right)->aopu.aop_dir);
8184 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8185 AOP(left)->aopu.aop_dir,
8186 AOP(left)->aopu.aop_dir);
8187 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8188 AOP(result)->aopu.aop_dir,
8189 AOP(result)->aopu.aop_dir);
8194 symbol *tlbl = newiTempLabel(NULL);
8195 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8198 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8199 if( AOP_TYPE(right) == AOP_ACC) {
8200 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8202 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8203 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8208 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8209 pic16_emitcode(";XXX setb","c");
8210 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8211 AOP(left)->aopu.aop_dir,tlbl->key+100);
8212 pic16_toBoolean(right);
8213 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8214 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8215 jmpTrueOrFalse(ifx, tlbl);
8219 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8226 pic16_outBitC(result);
8228 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8229 genIfxJump(ifx, "c");
8233 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8234 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8235 if((AOP_TYPE(right) == AOP_LIT) &&
8236 (AOP_TYPE(result) == AOP_CRY) &&
8237 (AOP_TYPE(left) != AOP_CRY)){
8239 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8242 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8244 continueIfTrue(ifx);
8247 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8248 // lit = 0, result = boolean(left)
8250 pic16_emitcode(";XXX setb","c");
8251 pic16_toBoolean(right);
8253 symbol *tlbl = newiTempLabel(NULL);
8254 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8256 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8258 genIfxJump (ifx,"a");
8262 pic16_outBitC(result);
8266 /* if left is same as result */
8267 if(pic16_sameRegs(AOP(result),AOP(left))){
8269 for(;size--; offset++,lit>>=8) {
8270 if(AOP_TYPE(right) == AOP_LIT){
8271 if((lit & 0xff) == 0)
8272 /* or'ing with 0 has no effect */
8275 int p = pic16_my_powof2(lit & 0xff);
8277 /* only one bit is set in the literal, so use a bsf instruction */
8278 pic16_emitpcode(POC_BSF,
8279 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8281 if(know_W != (lit & 0xff))
8282 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8283 know_W = lit & 0xff;
8284 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8289 if (AOP_TYPE(left) == AOP_ACC) {
8290 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8291 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8293 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8294 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8296 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8297 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8303 // left & result in different registers
8304 if(AOP_TYPE(result) == AOP_CRY){
8306 // if(size), result in bit
8307 // if(!size && ifx), conditional oper: if(left | right)
8308 symbol *tlbl = newiTempLabel(NULL);
8309 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8310 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8314 pic16_emitcode(";XXX setb","c");
8316 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8317 pic16_emitcode(";XXX orl","a,%s",
8318 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8319 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8324 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8325 pic16_outBitC(result);
8327 jmpTrueOrFalse(ifx, tlbl);
8328 } else for(;(size--);offset++){
8330 // result = left & right
8331 if(AOP_TYPE(right) == AOP_LIT){
8332 int t = (lit >> (offset*8)) & 0x0FFL;
8335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8338 pic16_emitcode("movf","%s,w",
8339 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8340 pic16_emitcode("movwf","%s",
8341 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8344 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8345 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8348 pic16_emitcode("movlw","0x%x",t);
8349 pic16_emitcode("iorwf","%s,w",
8350 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8351 pic16_emitcode("movwf","%s",
8352 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8358 // faster than result <- left, anl result,right
8359 // and better if result is SFR
8360 if (AOP_TYPE(left) == AOP_ACC) {
8361 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8362 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8364 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8365 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8367 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8368 pic16_emitcode("iorwf","%s,w",
8369 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8371 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8372 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8377 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8378 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8379 pic16_freeAsmop(result,NULL,ic,TRUE);
8382 /*-----------------------------------------------------------------*/
8383 /* genXor - code for xclusive or */
8384 /*-----------------------------------------------------------------*/
8385 static void genXor (iCode *ic, iCode *ifx)
8387 operand *left, *right, *result;
8389 unsigned long lit = 0L;
8391 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8393 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8394 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8395 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8397 /* if left is a literal & right is not ||
8398 if left needs acc & right does not */
8399 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8400 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8401 operand *tmp = right ;
8406 /* if result = right then exchange them */
8407 if(pic16_sameRegs(AOP(result),AOP(right))){
8408 operand *tmp = right ;
8413 /* if right is bit then exchange them */
8414 if (AOP_TYPE(right) == AOP_CRY &&
8415 AOP_TYPE(left) != AOP_CRY){
8416 operand *tmp = right ;
8420 if(AOP_TYPE(right) == AOP_LIT)
8421 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8423 size = AOP_SIZE(result);
8427 if (AOP_TYPE(left) == AOP_CRY){
8428 if(AOP_TYPE(right) == AOP_LIT){
8429 // c = bit & literal;
8431 // lit>>1 != 0 => result = 1
8432 if(AOP_TYPE(result) == AOP_CRY){
8434 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8435 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8437 continueIfTrue(ifx);
8440 pic16_emitcode("setb","c");
8444 // lit == 0, result = left
8445 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8447 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8449 // lit == 1, result = not(left)
8450 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8451 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8452 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8453 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8456 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8457 pic16_emitcode("cpl","c");
8464 symbol *tlbl = newiTempLabel(NULL);
8465 if (AOP_TYPE(right) == AOP_CRY){
8467 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8470 int sizer = AOP_SIZE(right);
8472 // if val>>1 != 0, result = 1
8473 pic16_emitcode("setb","c");
8475 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8477 // test the msb of the lsb
8478 pic16_emitcode("anl","a,#0xfe");
8479 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8483 pic16_emitcode("rrc","a");
8485 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8486 pic16_emitcode("cpl","c");
8487 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8492 pic16_outBitC(result);
8494 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8495 genIfxJump(ifx, "c");
8499 if(pic16_sameRegs(AOP(result),AOP(left))){
8500 /* if left is same as result */
8501 for(;size--; offset++) {
8502 if(AOP_TYPE(right) == AOP_LIT){
8503 int t = (lit >> (offset*8)) & 0x0FFL;
8507 if (IS_AOP_PREG(left)) {
8508 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8509 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8510 pic16_aopPut(AOP(result),"a",offset);
8512 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8513 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8514 pic16_emitcode("xrl","%s,%s",
8515 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8516 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8519 if (AOP_TYPE(left) == AOP_ACC)
8520 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8522 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8523 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8525 if (IS_AOP_PREG(left)) {
8526 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8527 pic16_aopPut(AOP(result),"a",offset);
8529 pic16_emitcode("xrl","%s,a",
8530 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8536 // left & result in different registers
8537 if(AOP_TYPE(result) == AOP_CRY){
8539 // if(size), result in bit
8540 // if(!size && ifx), conditional oper: if(left ^ right)
8541 symbol *tlbl = newiTempLabel(NULL);
8542 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8544 pic16_emitcode("setb","c");
8546 if((AOP_TYPE(right) == AOP_LIT) &&
8547 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8548 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8550 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8551 pic16_emitcode("xrl","a,%s",
8552 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8554 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8559 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8560 pic16_outBitC(result);
8562 jmpTrueOrFalse(ifx, tlbl);
8563 } else for(;(size--);offset++){
8565 // result = left & right
8566 if(AOP_TYPE(right) == AOP_LIT){
8567 int t = (lit >> (offset*8)) & 0x0FFL;
8570 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8571 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8572 pic16_emitcode("movf","%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_COMFW,pic16_popGet(AOP(left),offset));
8579 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8580 pic16_emitcode("comf","%s,w",
8581 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8582 pic16_emitcode("movwf","%s",
8583 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8586 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8587 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8588 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8589 pic16_emitcode("movlw","0x%x",t);
8590 pic16_emitcode("xorwf","%s,w",
8591 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8592 pic16_emitcode("movwf","%s",
8593 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8599 // faster than result <- left, anl result,right
8600 // and better if result is SFR
8601 if (AOP_TYPE(left) == AOP_ACC) {
8602 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8603 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8605 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8606 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8607 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8608 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8610 if ( AOP_TYPE(result) != AOP_ACC){
8611 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8612 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8618 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8619 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8620 pic16_freeAsmop(result,NULL,ic,TRUE);
8623 /*-----------------------------------------------------------------*/
8624 /* genInline - write the inline code out */
8625 /*-----------------------------------------------------------------*/
8626 static void genInline (iCode *ic)
8628 char *buffer, *bp, *bp1;
8630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8632 _G.inLine += (!options.asmpeep);
8634 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8635 strcpy(buffer,IC_INLINE(ic));
8637 while((bp1=strstr(bp, "\\n"))) {
8644 /* emit each line as a code */
8650 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8658 /* print label, use this special format with NULL directive
8659 * to denote that the argument should not be indented with tab */
8660 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8667 if ((bp1 != bp) && *bp1)
8668 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8673 _G.inLine -= (!options.asmpeep);
8676 /*-----------------------------------------------------------------*/
8677 /* genRRC - rotate right with carry */
8678 /*-----------------------------------------------------------------*/
8679 static void genRRC (iCode *ic)
8681 operand *left , *result ;
8682 int size, offset = 0, same;
8684 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8686 /* rotate right with carry */
8688 result=IC_RESULT(ic);
8689 pic16_aopOp (left,ic,FALSE);
8690 pic16_aopOp (result,ic,FALSE);
8692 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8694 same = pic16_sameRegs(AOP(result),AOP(left));
8696 size = AOP_SIZE(result);
8698 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8700 /* get the lsb and put it into the carry */
8701 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8708 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8710 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8717 pic16_freeAsmop(left,NULL,ic,TRUE);
8718 pic16_freeAsmop(result,NULL,ic,TRUE);
8721 /*-----------------------------------------------------------------*/
8722 /* genRLC - generate code for rotate left with carry */
8723 /*-----------------------------------------------------------------*/
8724 static void genRLC (iCode *ic)
8726 operand *left , *result ;
8727 int size, offset = 0;
8730 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8731 /* rotate right with carry */
8733 result=IC_RESULT(ic);
8734 pic16_aopOp (left,ic,FALSE);
8735 pic16_aopOp (result,ic,FALSE);
8737 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8739 same = pic16_sameRegs(AOP(result),AOP(left));
8741 /* move it to the result */
8742 size = AOP_SIZE(result);
8744 /* get the msb and put it into the carry */
8745 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8752 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8754 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8762 pic16_freeAsmop(left,NULL,ic,TRUE);
8763 pic16_freeAsmop(result,NULL,ic,TRUE);
8767 /* gpasm can get the highest order bit with HIGH/UPPER
8768 * so the following probably is not needed -- VR */
8770 /*-----------------------------------------------------------------*/
8771 /* genGetHbit - generates code get highest order bit */
8772 /*-----------------------------------------------------------------*/
8773 static void genGetHbit (iCode *ic)
8775 operand *left, *result;
8777 result=IC_RESULT(ic);
8778 pic16_aopOp (left,ic,FALSE);
8779 pic16_aopOp (result,ic,FALSE);
8781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8782 /* get the highest order byte into a */
8783 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8784 if(AOP_TYPE(result) == AOP_CRY){
8785 pic16_emitcode("rlc","a");
8786 pic16_outBitC(result);
8789 pic16_emitcode("rl","a");
8790 pic16_emitcode("anl","a,#0x01");
8791 pic16_outAcc(result);
8795 pic16_freeAsmop(left,NULL,ic,TRUE);
8796 pic16_freeAsmop(result,NULL,ic,TRUE);
8800 /*-----------------------------------------------------------------*/
8801 /* AccRol - rotate left accumulator by known count */
8802 /*-----------------------------------------------------------------*/
8803 static void AccRol (int shCount)
8805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8806 shCount &= 0x0007; // shCount : 0..7
8811 pic16_emitcode("rl","a");
8814 pic16_emitcode("rl","a");
8815 pic16_emitcode("rl","a");
8818 pic16_emitcode("swap","a");
8819 pic16_emitcode("rr","a");
8822 pic16_emitcode("swap","a");
8825 pic16_emitcode("swap","a");
8826 pic16_emitcode("rl","a");
8829 pic16_emitcode("rr","a");
8830 pic16_emitcode("rr","a");
8833 pic16_emitcode("rr","a");
8839 /*-----------------------------------------------------------------*/
8840 /* AccLsh - left shift accumulator by known count */
8841 /*-----------------------------------------------------------------*/
8842 static void AccLsh (int shCount)
8844 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8850 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8853 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8854 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8857 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8858 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8861 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8864 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8865 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8868 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8869 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8872 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8876 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8879 /*-----------------------------------------------------------------*/
8880 /* AccRsh - right shift accumulator by known count */
8881 /*-----------------------------------------------------------------*/
8882 static void AccRsh (int shCount, int andmask)
8884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8889 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8892 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8893 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8896 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8897 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8900 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8903 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8904 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8907 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8908 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8911 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8916 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8918 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8922 /*-----------------------------------------------------------------*/
8923 /* AccSRsh - signed right shift accumulator by known count */
8924 /*-----------------------------------------------------------------*/
8925 static void AccSRsh (int shCount)
8928 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8931 pic16_emitcode("mov","c,acc.7");
8932 pic16_emitcode("rrc","a");
8933 } else if(shCount == 2){
8934 pic16_emitcode("mov","c,acc.7");
8935 pic16_emitcode("rrc","a");
8936 pic16_emitcode("mov","c,acc.7");
8937 pic16_emitcode("rrc","a");
8939 tlbl = newiTempLabel(NULL);
8940 /* rotate right accumulator */
8941 AccRol(8 - shCount);
8942 /* and kill the higher order bits */
8943 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8944 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8945 pic16_emitcode("orl","a,#0x%02x",
8946 (unsigned char)~SRMask[shCount]);
8947 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8953 /*-----------------------------------------------------------------*/
8954 /* shiftR1Left2Result - shift right one byte from left to result */
8955 /*-----------------------------------------------------------------*/
8956 static void shiftR1Left2ResultSigned (operand *left, int offl,
8957 operand *result, int offr,
8962 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8964 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8968 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8970 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8973 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8981 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8983 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8984 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8987 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8996 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8999 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9000 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9003 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9004 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9011 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9012 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9013 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
9014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9025 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9026 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
9027 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9033 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9034 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9035 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9036 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9041 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9043 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9049 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9050 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9051 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9054 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9056 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9064 /*-----------------------------------------------------------------*/
9065 /* shiftR1Left2Result - shift right one byte from left to result */
9066 /*-----------------------------------------------------------------*/
9067 static void shiftR1Left2Result (operand *left, int offl,
9068 operand *result, int offr,
9069 int shCount, int sign)
9073 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9075 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9077 /* Copy the msb into the carry if signed. */
9079 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9089 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9091 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9092 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9100 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9101 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9104 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9112 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9116 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9117 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9118 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9123 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9124 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9129 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9130 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9132 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9138 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9139 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9140 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9147 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9148 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9157 /*-----------------------------------------------------------------*/
9158 /* shiftL1Left2Result - shift left one byte from left to result */
9159 /*-----------------------------------------------------------------*/
9160 static void shiftL1Left2Result (operand *left, int offl,
9161 operand *result, int offr, int shCount)
9166 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9168 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9169 DEBUGpic16_emitcode ("; ***","same = %d",same);
9170 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9172 /* shift left accumulator */
9173 //AccLsh(shCount); // don't comment out just yet...
9174 // pic16_aopPut(AOP(result),"a",offr);
9178 /* Shift left 1 bit position */
9179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9181 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9183 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9184 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9188 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9189 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9190 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9194 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9195 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9196 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9197 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9198 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9201 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9202 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9203 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9206 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9207 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9212 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9213 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9216 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9219 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9220 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9221 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9225 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9230 /*-----------------------------------------------------------------*/
9231 /* movLeft2Result - move byte from left to result */
9232 /*-----------------------------------------------------------------*/
9233 static void movLeft2Result (operand *left, int offl,
9234 operand *result, int offr)
9237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9238 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9239 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9241 if (*l == '@' && (IS_AOP_PREG(result))) {
9242 pic16_emitcode("mov","a,%s",l);
9243 pic16_aopPut(AOP(result),"a",offr);
9245 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9246 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9251 /*-----------------------------------------------------------------*/
9252 /* shiftL2Left2Result - shift left two bytes from left to result */
9253 /*-----------------------------------------------------------------*/
9254 static void shiftL2Left2Result (operand *left, int offl,
9255 operand *result, int offr, int shCount)
9257 int same = pic16_sameRegs(AOP(result), AOP(left));
9260 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9262 if (same && (offl != offr)) { // shift bytes
9265 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9266 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9268 } else { // just treat as different later on
9281 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9282 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9283 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9287 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9288 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9294 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9295 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9297 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9298 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9299 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9300 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9302 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9307 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9308 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9309 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9310 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9311 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9312 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9313 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9314 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9315 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9316 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9319 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9320 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9321 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9322 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9323 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9333 /* note, use a mov/add for the shift since the mov has a
9334 chance of getting optimized out */
9335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9337 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9338 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9339 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9343 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9344 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9350 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9351 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9352 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9353 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9354 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9355 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9356 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9357 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9361 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9362 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9366 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9367 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9368 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9369 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9371 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9372 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9373 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9374 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9375 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9376 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9377 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9378 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9381 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9382 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9383 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9384 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9385 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9390 /*-----------------------------------------------------------------*/
9391 /* shiftR2Left2Result - shift right two bytes from left to result */
9392 /*-----------------------------------------------------------------*/
9393 static void shiftR2Left2Result (operand *left, int offl,
9394 operand *result, int offr,
9395 int shCount, int sign)
9397 int same = pic16_sameRegs(AOP(result), AOP(left));
9399 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9401 if (same && (offl != offr)) { // shift right bytes
9404 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9405 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9407 } else { // just treat as different later on
9419 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9424 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9425 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9427 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9428 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9429 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9430 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9435 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9438 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9439 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9446 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9447 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9448 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9450 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9451 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9452 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9453 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9455 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9456 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9457 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9459 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9460 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9461 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9462 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9463 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9467 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9468 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9472 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9473 pic16_emitpcode(POC_BTFSC,
9474 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9475 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9483 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9484 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9486 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9487 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9488 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9489 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9491 pic16_emitpcode(POC_BTFSC,
9492 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9493 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9495 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9496 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9497 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9498 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9500 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9501 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9502 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9503 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9504 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9505 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9506 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9507 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9509 pic16_emitpcode(POC_BTFSC,
9510 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9511 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9513 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9514 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9521 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9522 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9523 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9524 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9527 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9529 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9534 /*-----------------------------------------------------------------*/
9535 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9536 /*-----------------------------------------------------------------*/
9537 static void shiftLLeftOrResult (operand *left, int offl,
9538 operand *result, int offr, int shCount)
9540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9542 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9543 /* shift left accumulator */
9545 /* or with result */
9546 /* back to result */
9547 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9550 /*-----------------------------------------------------------------*/
9551 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9552 /*-----------------------------------------------------------------*/
9553 static void shiftRLeftOrResult (operand *left, int offl,
9554 operand *result, int offr, int shCount)
9556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9558 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9559 /* shift right accumulator */
9561 /* or with result */
9562 /* back to result */
9563 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9566 /*-----------------------------------------------------------------*/
9567 /* genlshOne - left shift a one byte quantity by known count */
9568 /*-----------------------------------------------------------------*/
9569 static void genlshOne (operand *result, operand *left, int shCount)
9571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9572 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9575 /*-----------------------------------------------------------------*/
9576 /* genlshTwo - left shift two bytes by known amount != 0 */
9577 /*-----------------------------------------------------------------*/
9578 static void genlshTwo (operand *result,operand *left, int shCount)
9582 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9583 size = pic16_getDataSize(result);
9585 /* if shCount >= 8 */
9591 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9593 movLeft2Result(left, LSB, result, MSB16);
9595 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9598 /* 1 <= shCount <= 7 */
9601 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9603 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9607 /*-----------------------------------------------------------------*/
9608 /* shiftLLong - shift left one long from left to result */
9609 /* offr = LSB or MSB16 */
9610 /*-----------------------------------------------------------------*/
9611 static void shiftLLong (operand *left, operand *result, int offr )
9613 int size = AOP_SIZE(result);
9614 int same = pic16_sameRegs(AOP(left),AOP(result));
9617 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9619 if (same && (offr == MSB16)) { //shift one byte
9620 for(i=size-1;i>=MSB16;i--) {
9621 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9622 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9625 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9628 if (size > LSB+offr ){
9630 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9632 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9633 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9637 if(size > MSB16+offr){
9639 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9641 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9642 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9646 if(size > MSB24+offr){
9648 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9650 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9651 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9655 if(size > MSB32+offr){
9657 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9659 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9660 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9664 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668 /*-----------------------------------------------------------------*/
9669 /* genlshFour - shift four byte by a known amount != 0 */
9670 /*-----------------------------------------------------------------*/
9671 static void genlshFour (operand *result, operand *left, int shCount)
9675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9676 size = AOP_SIZE(result);
9678 /* if shifting more that 3 bytes */
9679 if (shCount >= 24 ) {
9682 /* lowest order of left goes to the highest
9683 order of the destination */
9684 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9686 movLeft2Result(left, LSB, result, MSB32);
9688 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9689 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9690 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9695 /* more than two bytes */
9696 else if ( shCount >= 16 ) {
9697 /* lower order two bytes goes to higher order two bytes */
9699 /* if some more remaining */
9701 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9703 movLeft2Result(left, MSB16, result, MSB32);
9704 movLeft2Result(left, LSB, result, MSB24);
9706 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9707 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9711 /* if more than 1 byte */
9712 else if ( shCount >= 8 ) {
9713 /* lower order three bytes goes to higher order three bytes */
9717 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9719 movLeft2Result(left, LSB, result, MSB16);
9721 else{ /* size = 4 */
9723 movLeft2Result(left, MSB24, result, MSB32);
9724 movLeft2Result(left, MSB16, result, MSB24);
9725 movLeft2Result(left, LSB, result, MSB16);
9726 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9728 else if(shCount == 1)
9729 shiftLLong(left, result, MSB16);
9731 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9732 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9733 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9734 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9739 /* 1 <= shCount <= 7 */
9740 else if(shCount <= 3)
9742 shiftLLong(left, result, LSB);
9743 while(--shCount >= 1)
9744 shiftLLong(result, result, LSB);
9746 /* 3 <= shCount <= 7, optimize */
9748 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9749 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9750 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9754 /*-----------------------------------------------------------------*/
9755 /* genLeftShiftLiteral - left shifting by known count */
9756 /*-----------------------------------------------------------------*/
9757 void pic16_genLeftShiftLiteral (operand *left,
9762 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9766 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9767 pic16_freeAsmop(right,NULL,ic,TRUE);
9769 pic16_aopOp(left,ic,FALSE);
9770 pic16_aopOp(result,ic,FALSE);
9772 size = getSize(operandType(result));
9775 pic16_emitcode("; shift left ","result %d, left %d",size,
9779 /* I suppose that the left size >= result size */
9782 movLeft2Result(left, size, result, size);
9786 else if(shCount >= (size * 8))
9788 pic16_aopPut(AOP(result),zero,size);
9792 genlshOne (result,left,shCount);
9797 genlshTwo (result,left,shCount);
9801 genlshFour (result,left,shCount);
9805 pic16_freeAsmop(left,NULL,ic,TRUE);
9806 pic16_freeAsmop(result,NULL,ic,TRUE);
9809 /*-----------------------------------------------------------------*
9810 * genMultiAsm - repeat assembly instruction for size of register.
9811 * if endian == 1, then the high byte (i.e base address + size of
9812 * register) is used first else the low byte is used first;
9813 *-----------------------------------------------------------------*/
9814 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9832 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9838 #if !(USE_GENERIC_SIGNED_SHIFT)
9839 /*-----------------------------------------------------------------*/
9840 /* genLeftShift - generates code for left shifting */
9841 /*-----------------------------------------------------------------*/
9842 static void genLeftShift (iCode *ic)
9844 operand *left,*right, *result;
9847 symbol *tlbl , *tlbl1;
9850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9852 right = IC_RIGHT(ic);
9854 result = IC_RESULT(ic);
9856 pic16_aopOp(right,ic,FALSE);
9858 /* if the shift count is known then do it
9859 as efficiently as possible */
9860 if (AOP_TYPE(right) == AOP_LIT) {
9861 pic16_genLeftShiftLiteral (left,right,result,ic);
9865 /* shift count is unknown then we have to form
9866 * a loop. Get the loop count in WREG : Note: we take
9867 * only the lower order byte since shifting
9868 * more than 32 bits make no sense anyway, ( the
9869 * largest size of an object can be only 32 bits ) */
9871 pic16_aopOp(left,ic,FALSE);
9872 pic16_aopOp(result,ic,FALSE);
9874 /* now move the left to the result if they are not the
9875 * same, and if size > 1,
9876 * and if right is not same to result (!!!) -- VR */
9877 if (!pic16_sameRegs(AOP(left),AOP(result))
9878 && (AOP_SIZE(result) > 1)) {
9880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9882 size = AOP_SIZE(result);
9887 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9888 if (*l == '@' && (IS_AOP_PREG(result))) {
9890 pic16_emitcode("mov","a,%s",l);
9891 pic16_aopPut(AOP(result),"a",offset);
9895 /* we don't know if left is a literal or a register, take care -- VR */
9896 mov2f(AOP(result), AOP(left), offset);
9902 size = AOP_SIZE(result);
9904 /* if it is only one byte then */
9906 if(optimized_for_speed) {
9907 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9908 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9909 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9910 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9911 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9912 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9913 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9914 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9915 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9916 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9917 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9918 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9921 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9923 tlbl = newiTempLabel(NULL);
9926 /* this is already done, why change it? */
9927 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9928 mov2f(AOP(result), AOP(left), 0);
9932 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9933 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9934 pic16_emitpLabel(tlbl->key);
9935 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9936 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9938 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9943 if (pic16_sameRegs(AOP(left),AOP(result))) {
9945 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9947 tlbl = newiTempLabel(NULL);
9948 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9949 genMultiAsm(POC_RRCF, result, size,1);
9950 pic16_emitpLabel(tlbl->key);
9951 genMultiAsm(POC_RLCF, result, size,0);
9952 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9954 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9958 //tlbl = newiTempLabel(NULL);
9960 //tlbl1 = newiTempLabel(NULL);
9962 //reAdjustPreg(AOP(result));
9964 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9965 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9966 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9968 //pic16_emitcode("add","a,acc");
9969 //pic16_aopPut(AOP(result),"a",offset++);
9971 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9973 // pic16_emitcode("rlc","a");
9974 // pic16_aopPut(AOP(result),"a",offset++);
9976 //reAdjustPreg(AOP(result));
9978 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9979 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9982 tlbl = newiTempLabel(NULL);
9983 tlbl1= newiTempLabel(NULL);
9985 size = AOP_SIZE(result);
9988 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9990 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9992 /* offset should be 0, 1 or 3 */
9994 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9996 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9998 pic16_emitpcode(POC_MOVWF, pctemp);
10001 pic16_emitpLabel(tlbl->key);
10004 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10006 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10008 pic16_emitpcode(POC_DECFSZ, pctemp);
10009 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10010 pic16_emitpLabel(tlbl1->key);
10012 pic16_popReleaseTempReg(pctemp,1);
10016 pic16_freeAsmop (right,NULL,ic,TRUE);
10017 pic16_freeAsmop(left,NULL,ic,TRUE);
10018 pic16_freeAsmop(result,NULL,ic,TRUE);
10024 #error old code (left here for reference)
10025 /*-----------------------------------------------------------------*/
10026 /* genLeftShift - generates code for left shifting */
10027 /*-----------------------------------------------------------------*/
10028 static void genLeftShift (iCode *ic)
10030 operand *left,*right, *result;
10033 symbol *tlbl , *tlbl1;
10036 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10038 right = IC_RIGHT(ic);
10039 left = IC_LEFT(ic);
10040 result = IC_RESULT(ic);
10042 pic16_aopOp(right,ic,FALSE);
10044 /* if the shift count is known then do it
10045 as efficiently as possible */
10046 if (AOP_TYPE(right) == AOP_LIT) {
10047 pic16_genLeftShiftLiteral (left,right,result,ic);
10051 /* shift count is unknown then we have to form
10052 a loop get the loop count in B : Note: we take
10053 only the lower order byte since shifting
10054 more that 32 bits make no sense anyway, ( the
10055 largest size of an object can be only 32 bits ) */
10058 pic16_aopOp(left,ic,FALSE);
10059 pic16_aopOp(result,ic,FALSE);
10061 /* now move the left to the result if they are not the
10063 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10064 AOP_SIZE(result) > 1) {
10066 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10068 size = AOP_SIZE(result);
10071 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10072 if (*l == '@' && (IS_AOP_PREG(result))) {
10074 pic16_emitcode("mov","a,%s",l);
10075 pic16_aopPut(AOP(result),"a",offset);
10078 /* we don't know if left is a literal or a register, take care -- VR */
10079 mov2f(AOP(result), AOP(left), offset);
10085 size = AOP_SIZE(result);
10087 /* if it is only one byte then */
10089 if(optimized_for_speed) {
10090 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10091 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10092 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10093 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10094 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10095 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10096 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10097 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10098 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10099 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10100 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10101 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10104 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10106 tlbl = newiTempLabel(NULL);
10107 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10108 mov2f(AOP(result), AOP(left), 0);
10110 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10111 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10114 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10115 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10116 pic16_emitpLabel(tlbl->key);
10117 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10118 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10120 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10125 if (pic16_sameRegs(AOP(left),AOP(result))) {
10127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10129 tlbl = newiTempLabel(NULL);
10130 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10131 genMultiAsm(POC_RRCF, result, size,1);
10132 pic16_emitpLabel(tlbl->key);
10133 genMultiAsm(POC_RLCF, result, size,0);
10134 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10136 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10140 //tlbl = newiTempLabel(NULL);
10142 //tlbl1 = newiTempLabel(NULL);
10144 //reAdjustPreg(AOP(result));
10146 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10147 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10148 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10150 //pic16_emitcode("add","a,acc");
10151 //pic16_aopPut(AOP(result),"a",offset++);
10153 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10155 // pic16_emitcode("rlc","a");
10156 // pic16_aopPut(AOP(result),"a",offset++);
10158 //reAdjustPreg(AOP(result));
10160 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10161 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10164 tlbl = newiTempLabel(NULL);
10165 tlbl1= newiTempLabel(NULL);
10167 size = AOP_SIZE(result);
10170 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10172 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10174 /* offset should be 0, 1 or 3 */
10176 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10178 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10180 pic16_emitpcode(POC_MOVWF, pctemp);
10183 pic16_emitpLabel(tlbl->key);
10186 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10188 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10190 pic16_emitpcode(POC_DECFSZ, pctemp);
10191 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10192 pic16_emitpLabel(tlbl1->key);
10194 pic16_popReleaseTempReg(pctemp,1);
10198 pic16_freeAsmop (right,NULL,ic,TRUE);
10199 pic16_freeAsmop(left,NULL,ic,TRUE);
10200 pic16_freeAsmop(result,NULL,ic,TRUE);
10204 /*-----------------------------------------------------------------*/
10205 /* genrshOne - right shift a one byte quantity by known count */
10206 /*-----------------------------------------------------------------*/
10207 static void genrshOne (operand *result, operand *left,
10208 int shCount, int sign)
10210 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10211 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10214 /*-----------------------------------------------------------------*/
10215 /* genrshTwo - right shift two bytes by known amount != 0 */
10216 /*-----------------------------------------------------------------*/
10217 static void genrshTwo (operand *result,operand *left,
10218 int shCount, int sign)
10220 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10221 /* if shCount >= 8 */
10222 if (shCount >= 8) {
10225 shiftR1Left2Result(left, MSB16, result, LSB,
10228 movLeft2Result(left, MSB16, result, LSB);
10230 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10233 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10234 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10238 /* 1 <= shCount <= 7 */
10240 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10243 /*-----------------------------------------------------------------*/
10244 /* shiftRLong - shift right one long from left to result */
10245 /* offl = LSB or MSB16 */
10246 /*-----------------------------------------------------------------*/
10247 static void shiftRLong (operand *left, int offl,
10248 operand *result, int sign)
10250 int size = AOP_SIZE(result);
10251 int same = pic16_sameRegs(AOP(left),AOP(result));
10253 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10255 if (same && (offl == MSB16)) { //shift one byte right
10256 for(i=MSB16;i<size;i++) {
10257 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10258 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10263 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10269 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10271 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10272 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10275 if(offl == MSB16) {
10276 /* add sign of "a" */
10277 pic16_addSign(result, MSB32, sign);
10281 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10283 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10284 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10288 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10290 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10291 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10295 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10298 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10299 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10304 /*-----------------------------------------------------------------*/
10305 /* genrshFour - shift four byte by a known amount != 0 */
10306 /*-----------------------------------------------------------------*/
10307 static void genrshFour (operand *result, operand *left,
10308 int shCount, int sign)
10310 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10311 /* if shifting more that 3 bytes */
10312 if(shCount >= 24 ) {
10315 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10317 movLeft2Result(left, MSB32, result, LSB);
10319 pic16_addSign(result, MSB16, sign);
10321 else if(shCount >= 16){
10324 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10326 movLeft2Result(left, MSB24, result, LSB);
10327 movLeft2Result(left, MSB32, result, MSB16);
10329 pic16_addSign(result, MSB24, sign);
10331 else if(shCount >= 8){
10334 shiftRLong(left, MSB16, result, sign);
10335 else if(shCount == 0){
10336 movLeft2Result(left, MSB16, result, LSB);
10337 movLeft2Result(left, MSB24, result, MSB16);
10338 movLeft2Result(left, MSB32, result, MSB24);
10339 pic16_addSign(result, MSB32, sign);
10341 else{ //shcount >= 2
10342 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10343 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10344 /* the last shift is signed */
10345 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10346 pic16_addSign(result, MSB32, sign);
10349 else{ /* 1 <= shCount <= 7 */
10351 shiftRLong(left, LSB, result, sign);
10353 shiftRLong(result, LSB, result, sign);
10356 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10357 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10358 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10363 /*-----------------------------------------------------------------*/
10364 /* genRightShiftLiteral - right shifting by known count */
10365 /*-----------------------------------------------------------------*/
10366 static void genRightShiftLiteral (operand *left,
10372 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10373 int lsize,res_size;
10375 pic16_freeAsmop(right,NULL,ic,TRUE);
10377 pic16_aopOp(left,ic,FALSE);
10378 pic16_aopOp(result,ic,FALSE);
10380 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10383 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10387 lsize = pic16_getDataSize(left);
10388 res_size = pic16_getDataSize(result);
10389 /* test the LEFT size !!! */
10391 /* I suppose that the left size >= result size */
10394 movLeft2Result(left, lsize, result, res_size);
10397 else if(shCount >= (lsize * 8)){
10399 if(res_size == 1) {
10400 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10402 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10403 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10408 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10409 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10410 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10412 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10417 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10422 switch (res_size) {
10424 genrshOne (result,left,shCount,sign);
10428 genrshTwo (result,left,shCount,sign);
10432 genrshFour (result,left,shCount,sign);
10440 pic16_freeAsmop(left,NULL,ic,TRUE);
10441 pic16_freeAsmop(result,NULL,ic,TRUE);
10444 #if !(USE_GENERIC_SIGNED_SHIFT)
10445 /*-----------------------------------------------------------------*/
10446 /* genSignedRightShift - right shift of signed number */
10447 /*-----------------------------------------------------------------*/
10448 static void genSignedRightShift (iCode *ic)
10450 operand *right, *left, *result;
10453 symbol *tlbl, *tlbl1 ;
10456 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10458 /* we do it the hard way put the shift count in b
10459 and loop thru preserving the sign */
10460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10462 right = IC_RIGHT(ic);
10463 left = IC_LEFT(ic);
10464 result = IC_RESULT(ic);
10466 pic16_aopOp(right,ic,FALSE);
10467 pic16_aopOp(left,ic,FALSE);
10468 pic16_aopOp(result,ic,FALSE);
10471 if ( AOP_TYPE(right) == AOP_LIT) {
10472 genRightShiftLiteral (left,right,result,ic,1);
10475 /* shift count is unknown then we have to form
10476 a loop get the loop count in B : Note: we take
10477 only the lower order byte since shifting
10478 more that 32 bits make no sense anyway, ( the
10479 largest size of an object can be only 32 bits ) */
10481 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10482 //pic16_emitcode("inc","b");
10483 //pic16_freeAsmop (right,NULL,ic,TRUE);
10484 //pic16_aopOp(left,ic,FALSE);
10485 //pic16_aopOp(result,ic,FALSE);
10487 /* now move the left to the result if they are not the
10489 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10490 AOP_SIZE(result) > 1) {
10492 size = AOP_SIZE(result);
10496 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10497 if (*l == '@' && IS_AOP_PREG(result)) {
10499 pic16_emitcode("mov","a,%s",l);
10500 pic16_aopPut(AOP(result),"a",offset);
10502 pic16_aopPut(AOP(result),l,offset);
10504 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10505 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10511 /* mov the highest order bit to OVR */
10512 tlbl = newiTempLabel(NULL);
10513 tlbl1= newiTempLabel(NULL);
10515 size = AOP_SIZE(result);
10518 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10520 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10522 /* offset should be 0, 1 or 3 */
10523 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10525 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10527 pic16_emitpcode(POC_MOVWF, pctemp);
10530 pic16_emitpLabel(tlbl->key);
10532 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10533 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10536 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10539 pic16_emitpcode(POC_DECFSZ, pctemp);
10540 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10541 pic16_emitpLabel(tlbl1->key);
10543 pic16_popReleaseTempReg(pctemp,1);
10545 size = AOP_SIZE(result);
10547 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10548 pic16_emitcode("rlc","a");
10549 pic16_emitcode("mov","ov,c");
10550 /* if it is only one byte then */
10552 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10554 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10555 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10556 pic16_emitcode("mov","c,ov");
10557 pic16_emitcode("rrc","a");
10558 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10559 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10560 pic16_aopPut(AOP(result),"a",0);
10564 reAdjustPreg(AOP(result));
10565 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10566 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10567 pic16_emitcode("mov","c,ov");
10569 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10571 pic16_emitcode("rrc","a");
10572 pic16_aopPut(AOP(result),"a",offset--);
10574 reAdjustPreg(AOP(result));
10575 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10576 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10581 pic16_freeAsmop(left,NULL,ic,TRUE);
10582 pic16_freeAsmop(result,NULL,ic,TRUE);
10583 pic16_freeAsmop(right,NULL,ic,TRUE);
10587 #if !(USE_GENERIC_SIGNED_SHIFT)
10588 #warning This implementation of genRightShift() is incomplete!
10589 /*-----------------------------------------------------------------*/
10590 /* genRightShift - generate code for right shifting */
10591 /*-----------------------------------------------------------------*/
10592 static void genRightShift (iCode *ic)
10594 operand *right, *left, *result;
10598 symbol *tlbl, *tlbl1 ;
10600 /* if signed then we do it the hard way preserve the
10601 sign bit moving it inwards */
10602 letype = getSpec(operandType(IC_LEFT(ic)));
10603 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10605 if (!SPEC_USIGN(letype)) {
10606 genSignedRightShift (ic);
10610 /* signed & unsigned types are treated the same : i.e. the
10611 signed is NOT propagated inwards : quoting from the
10612 ANSI - standard : "for E1 >> E2, is equivalent to division
10613 by 2**E2 if unsigned or if it has a non-negative value,
10614 otherwise the result is implementation defined ", MY definition
10615 is that the sign does not get propagated */
10617 right = IC_RIGHT(ic);
10618 left = IC_LEFT(ic);
10619 result = IC_RESULT(ic);
10621 pic16_aopOp(right,ic,FALSE);
10623 /* if the shift count is known then do it
10624 as efficiently as possible */
10625 if (AOP_TYPE(right) == AOP_LIT) {
10626 genRightShiftLiteral (left,right,result,ic, 0);
10630 /* shift count is unknown then we have to form
10631 a loop get the loop count in B : Note: we take
10632 only the lower order byte since shifting
10633 more that 32 bits make no sense anyway, ( the
10634 largest size of an object can be only 32 bits ) */
10636 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10637 pic16_emitcode("inc","b");
10638 pic16_aopOp(left,ic,FALSE);
10639 pic16_aopOp(result,ic,FALSE);
10641 /* now move the left to the result if they are not the
10643 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10644 AOP_SIZE(result) > 1) {
10646 size = AOP_SIZE(result);
10649 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10650 if (*l == '@' && IS_AOP_PREG(result)) {
10652 pic16_emitcode("mov","a,%s",l);
10653 pic16_aopPut(AOP(result),"a",offset);
10655 pic16_aopPut(AOP(result),l,offset);
10660 tlbl = newiTempLabel(NULL);
10661 tlbl1= newiTempLabel(NULL);
10662 size = AOP_SIZE(result);
10665 /* if it is only one byte then */
10668 tlbl = newiTempLabel(NULL);
10669 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10670 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10671 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10674 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10675 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10676 pic16_emitpLabel(tlbl->key);
10677 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10678 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10680 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10685 reAdjustPreg(AOP(result));
10686 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10687 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10690 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10692 pic16_emitcode("rrc","a");
10693 pic16_aopPut(AOP(result),"a",offset--);
10695 reAdjustPreg(AOP(result));
10697 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10698 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10701 pic16_freeAsmop(left,NULL,ic,TRUE);
10702 pic16_freeAsmop (right,NULL,ic,TRUE);
10703 pic16_freeAsmop(result,NULL,ic,TRUE);
10707 #if (USE_GENERIC_SIGNED_SHIFT)
10708 /*-----------------------------------------------------------------*/
10709 /* genGenericShift - generates code for left or right shifting */
10710 /*-----------------------------------------------------------------*/
10711 static void genGenericShift (iCode *ic, int isShiftLeft) {
10712 operand *left,*right, *result;
10714 int sign, signedCount;
10715 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10716 PIC_OPCODE pos_shift, neg_shift;
10720 right = IC_RIGHT(ic);
10721 left = IC_LEFT(ic);
10722 result = IC_RESULT(ic);
10724 pic16_aopOp(right,ic,FALSE);
10725 pic16_aopOp(left,ic,FALSE);
10726 pic16_aopOp(result,ic,FALSE);
10728 sign = !SPEC_USIGN(operandType (left));
10729 signedCount = !SPEC_USIGN(operandType (right));
10731 /* if the shift count is known then do it
10732 as efficiently as possible */
10733 if (AOP_TYPE(right) == AOP_LIT) {
10734 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10735 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10736 // we should modify right->aopu.aop_lit here!
10737 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10738 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10740 pic16_genLeftShiftLiteral (left,right,result,ic);
10742 genRightShiftLiteral (left,right,result,ic, sign);
10745 } // if (right is literal)
10747 /* shift count is unknown then we have to form a loop.
10748 * Note: we take only the lower order byte since shifting
10749 * more than 32 bits make no sense anyway, ( the
10750 * largest size of an object can be only 32 bits )
10751 * Note: we perform arithmetic shifts if the left operand is
10752 * signed and we do an (effective) right shift, i. e. we
10753 * shift in the sign bit from the left. */
10755 label_complete = newiTempLabel ( NULL );
10756 label_loop_pos = newiTempLabel ( NULL );
10757 label_loop_neg = NULL;
10758 label_negative = NULL;
10759 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10760 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10763 // additional labels needed
10764 label_loop_neg = newiTempLabel ( NULL );
10765 label_negative = newiTempLabel ( NULL );
10768 // copy source to result -- this will effectively truncate the left operand to the size of result!
10769 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10770 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10771 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10772 mov2f (AOP(result),AOP(left), offset);
10775 // if result is longer than left, fill with zeros (or sign)
10776 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10777 if (sign && AOP_SIZE(left) > 0) {
10778 // shift signed operand -- fill with sign
10779 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10780 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10781 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10782 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10783 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10786 // shift unsigned operand -- fill result with zeros
10787 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10788 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10791 } // if (size mismatch)
10793 pic16_mov2w (AOP(right), 0);
10794 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10795 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->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]+({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])
10801 pic16_emitpLabel (label_loop_pos->key);
10803 if (sign && (pos_shift == POC_RRCF)) {
10804 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10807 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10808 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10809 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10811 // perform a shift by one (shift count is positive)
10812 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10813 // 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])
10814 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10815 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10817 pic16_emitpLabel (label_loop_pos->key);
10818 if (sign && (pos_shift == POC_RRCF)) {
10819 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10822 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10823 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10824 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10825 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10829 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10831 pic16_emitpLabel (label_negative->key);
10832 // perform a shift by -1 (shift count is negative)
10833 // 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)
10835 pic16_emitpLabel (label_loop_neg->key);
10836 if (sign && (neg_shift == POC_RRCF)) {
10837 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10840 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10841 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10842 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10843 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10844 } // if (signedCount)
10846 pic16_emitpLabel (label_complete->key);
10849 pic16_freeAsmop (right,NULL,ic,TRUE);
10850 pic16_freeAsmop(left,NULL,ic,TRUE);
10851 pic16_freeAsmop(result,NULL,ic,TRUE);
10854 static void genLeftShift (iCode *ic) {
10855 genGenericShift (ic, 1);
10858 static void genRightShift (iCode *ic) {
10859 genGenericShift (ic, 0);
10864 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10865 void pic16_loadFSR0(operand *op, int lit)
10867 if(is_LitOp( op ) || lit) {
10868 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10870 // set up FSR0 with address of result
10871 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10872 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10876 /*-----------------------------------------------------------------*/
10877 /* genUnpackBits - generates code for unpacking bits */
10878 /*-----------------------------------------------------------------*/
10879 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10883 sym_link *etype, *letype;
10884 int blen=0, bstr=0;
10888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10889 etype = getSpec(operandType(result));
10890 letype = getSpec(operandType(left));
10892 // if(IS_BITFIELD(etype)) {
10893 blen = SPEC_BLEN(etype);
10894 bstr = SPEC_BSTR(etype);
10897 lbstr = SPEC_BSTR( letype );
10900 if((blen == 1) && (bstr < 8)) {
10901 /* it is a single bit, so use the appropriate bit instructions */
10902 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10904 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10906 if((ptype == POINTER) && (result)) {
10907 /* workaround to reduce the extra lfsr instruction */
10908 pic16_emitpcode(POC_BTFSC,
10909 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10911 pic16_emitpcode(POC_BTFSC,
10912 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10915 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10917 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10923 /* the following call to pic16_loadFSR0 is temporary until
10924 * optimization to handle single bit assignments is added
10925 * to the function. Until then use the old safe way! -- VR */
10926 pic16_loadFSR0( left, 1 );
10928 /* read the first byte */
10935 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10938 pic16_emitcode("clr","a");
10939 pic16_emitcode("movc","a","@a+dptr");
10944 /* if we have bitdisplacement then it fits */
10945 /* into this byte completely or if length is */
10946 /* less than a byte */
10947 if ((shCnt = SPEC_BSTR(etype)) ||
10948 (SPEC_BLEN(etype) <= 8)) {
10950 /* shift right acc */
10953 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10954 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10956 /* VR -- normally I would use the following, but since we use the hack,
10957 * to avoid the masking from AccRsh, why not mask it right now? */
10960 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10969 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10970 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10973 /* bit field did not fit in a byte */
10974 rlen = SPEC_BLEN(etype) - 8;
10975 pic16_aopPut(AOP(result),"a",offset++);
10982 pic16_emitcode("inc","%s",rname);
10983 pic16_emitcode("mov","a,@%s",rname);
10987 pic16_emitcode("inc","%s",rname);
10988 pic16_emitcode("movx","a,@%s",rname);
10992 pic16_emitcode("inc","dptr");
10993 pic16_emitcode("movx","a,@dptr");
10997 pic16_emitcode("clr","a");
10998 pic16_emitcode("inc","dptr");
10999 pic16_emitcode("movc","a","@a+dptr");
11003 pic16_emitcode("inc","dptr");
11004 pic16_emitcode("lcall","__gptrget");
11009 /* if we are done */
11013 pic16_aopPut(AOP(result),"a",offset++);
11018 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11019 pic16_aopPut(AOP(result),"a",offset);
11026 static void genDataPointerGet(operand *left,
11030 int size, offset = 0, leoffset=0 ;
11032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11033 pic16_aopOp(result, ic, FALSE);
11035 size = AOP_SIZE(result);
11036 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11040 /* The following tests may save a redudant movff instruction when
11041 * accessing unions */
11043 /* if they are the same */
11044 if (operandsEqu (left, result)) {
11045 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11051 /* if they are the same registers */
11052 if (pic16_sameRegs(AOP(left),AOP(result))) {
11053 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11059 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11060 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11061 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11068 if ( AOP_TYPE(left) == AOP_PCODE) {
11069 fprintf(stderr,"genDataPointerGet %s, %d\n",
11070 AOP(left)->aopu.pcop->name,
11071 (AOP(left)->aopu.pcop->type == PO_DIR)?
11072 PCOR(AOP(left)->aopu.pcop)->instance:
11073 PCOI(AOP(left)->aopu.pcop)->offset);
11077 if(AOP(left)->aopu.pcop->type == PO_DIR)
11078 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11080 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11083 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11085 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11086 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11087 pic16_mov2w(AOP(left), offset); // patch 8
11088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11091 pic16_popGet(AOP(left), offset), //patch 8
11092 pic16_popGet(AOP(result), offset)));
11100 pic16_freeAsmop(result,NULL,ic,TRUE);
11105 /*-----------------------------------------------------------------*/
11106 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11107 /*-----------------------------------------------------------------*/
11108 static void genNearPointerGet (operand *left,
11112 // asmop *aop = NULL;
11113 //regs *preg = NULL ;
11114 sym_link *rtype, *retype;
11115 sym_link *ltype = operandType(left);
11119 rtype = operandType(result);
11120 retype= getSpec(rtype);
11122 pic16_aopOp(left,ic,FALSE);
11124 // pic16_DumpOp("(left)",left);
11125 // pic16_DumpOp("(result)",result);
11127 /* if left is rematerialisable and
11128 * result is not bit variable type and
11129 * the left is pointer to data space i.e
11130 * lower 128 bytes of space */
11132 if (AOP_TYPE(left) == AOP_PCODE
11133 && !IS_BITFIELD(retype)
11134 && DCL_TYPE(ltype) == POINTER) {
11136 genDataPointerGet (left,result,ic);
11137 pic16_freeAsmop(left, NULL, ic, TRUE);
11141 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11142 pic16_aopOp (result,ic,FALSE);
11144 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11147 if(IS_BITFIELD( retype )
11148 && (SPEC_BLEN(operandType(result))==1)
11152 int bitstrt, bytestrt;
11154 /* if this is bitfield of size 1, see if we are checking the value
11155 * of a single bit in an if-statement,
11156 * if yes, then don't generate usual code, but execute the
11157 * genIfx directly -- VR */
11161 /* CHECK: if next iCode is IFX
11162 * and current result operand is nextic's conditional operand
11163 * and current result operand live ranges ends at nextic's key number
11165 if((nextic->op == IFX)
11166 && (result == IC_COND(nextic))
11167 && (OP_LIVETO(result) == nextic->seq)
11169 /* everything is ok then */
11170 /* find a way to optimize the genIfx iCode */
11172 bytestrt = SPEC_BSTR(operandType(result))/8;
11173 bitstrt = SPEC_BSTR(operandType(result))%8;
11175 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11177 genIfxpCOpJump(nextic, jop);
11179 pic16_freeAsmop(left, NULL, ic, TRUE);
11180 pic16_freeAsmop(result, NULL, ic, TRUE);
11187 /* if the value is already in a pointer register
11188 * then don't need anything more */
11189 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11190 /* otherwise get a free pointer register */
11191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11196 /* if bitfield then unpack the bits */
11197 if (IS_BITFIELD(retype))
11198 genUnpackBits (result, left, NULL, POINTER);
11200 /* we have can just get the values */
11201 int size = AOP_SIZE(result);
11204 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11206 pic16_loadFSR0( left, 0 );
11210 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11211 pic16_popGet(AOP(result), offset++)));
11213 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11214 pic16_popGet(AOP(result), offset++)));
11220 /* now some housekeeping stuff */
11222 /* we had to allocate for this iCode */
11223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11224 pic16_freeAsmop(NULL,aop,ic,TRUE);
11226 /* we did not allocate which means left
11227 * already in a pointer register, then
11228 * if size > 0 && this could be used again
11229 * we have to point it back to where it
11231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11232 if (AOP_SIZE(result) > 1
11233 && !OP_SYMBOL(left)->remat
11234 && ( OP_SYMBOL(left)->liveTo > ic->seq
11236 // int size = AOP_SIZE(result) - 1;
11238 // pic16_emitcode("dec","%s",rname);
11244 pic16_freeAsmop(left,NULL,ic,TRUE);
11245 pic16_freeAsmop(result,NULL,ic,TRUE);
11248 /*-----------------------------------------------------------------*/
11249 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11250 /*-----------------------------------------------------------------*/
11251 static void genPagedPointerGet (operand *left,
11256 regs *preg = NULL ;
11258 sym_link *rtype, *retype;
11260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11262 rtype = operandType(result);
11263 retype= getSpec(rtype);
11265 pic16_aopOp(left,ic,FALSE);
11267 /* if the value is already in a pointer register
11268 then don't need anything more */
11269 if (!AOP_INPREG(AOP(left))) {
11270 /* otherwise get a free pointer register */
11272 preg = getFreePtr(ic,&aop,FALSE);
11273 pic16_emitcode("mov","%s,%s",
11275 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11276 rname = preg->name ;
11278 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11280 pic16_freeAsmop(left,NULL,ic,TRUE);
11281 pic16_aopOp (result,ic,FALSE);
11283 /* if bitfield then unpack the bits */
11284 if (IS_BITFIELD(retype))
11285 genUnpackBits (result,left,rname,PPOINTER);
11287 /* we have can just get the values */
11288 int size = AOP_SIZE(result);
11293 pic16_emitcode("movx","a,@%s",rname);
11294 pic16_aopPut(AOP(result),"a",offset);
11299 pic16_emitcode("inc","%s",rname);
11303 /* now some housekeeping stuff */
11305 /* we had to allocate for this iCode */
11306 pic16_freeAsmop(NULL,aop,ic,TRUE);
11308 /* we did not allocate which means left
11309 already in a pointer register, then
11310 if size > 0 && this could be used again
11311 we have to point it back to where it
11313 if (AOP_SIZE(result) > 1 &&
11314 !OP_SYMBOL(left)->remat &&
11315 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11317 int size = AOP_SIZE(result) - 1;
11319 pic16_emitcode("dec","%s",rname);
11324 pic16_freeAsmop(result,NULL,ic,TRUE);
11329 /*-----------------------------------------------------------------*/
11330 /* genFarPointerGet - gget value from far space */
11331 /*-----------------------------------------------------------------*/
11332 static void genFarPointerGet (operand *left,
11333 operand *result, iCode *ic)
11336 sym_link *retype = getSpec(operandType(result));
11338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11340 pic16_aopOp(left,ic,FALSE);
11342 /* if the operand is already in dptr
11343 then we do nothing else we move the value to dptr */
11344 if (AOP_TYPE(left) != AOP_STR) {
11345 /* if this is remateriazable */
11346 if (AOP_TYPE(left) == AOP_IMMD)
11347 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11348 else { /* we need to get it byte by byte */
11349 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11350 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11351 if (options.model == MODEL_FLAT24)
11353 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11357 /* so dptr know contains the address */
11358 pic16_freeAsmop(left,NULL,ic,TRUE);
11359 pic16_aopOp(result,ic,FALSE);
11361 /* if bit then unpack */
11362 if (IS_BITFIELD(retype))
11363 genUnpackBits(result,left,"dptr",FPOINTER);
11365 size = AOP_SIZE(result);
11369 pic16_emitcode("movx","a,@dptr");
11370 pic16_aopPut(AOP(result),"a",offset++);
11372 pic16_emitcode("inc","dptr");
11376 pic16_freeAsmop(result,NULL,ic,TRUE);
11380 /*-----------------------------------------------------------------*/
11381 /* genCodePointerGet - get value from code space */
11382 /*-----------------------------------------------------------------*/
11383 static void genCodePointerGet (operand *left,
11384 operand *result, iCode *ic)
11387 sym_link *retype = getSpec(operandType(result));
11389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11391 pic16_aopOp(left,ic,FALSE);
11393 /* if the operand is already in dptr
11394 then we do nothing else we move the value to dptr */
11395 if (AOP_TYPE(left) != AOP_STR) {
11396 /* if this is remateriazable */
11397 if (AOP_TYPE(left) == AOP_IMMD)
11398 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11399 else { /* we need to get it byte by byte */
11400 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11401 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11402 if (options.model == MODEL_FLAT24)
11404 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11408 /* so dptr know contains the address */
11409 pic16_freeAsmop(left,NULL,ic,TRUE);
11410 pic16_aopOp(result,ic,FALSE);
11412 /* if bit then unpack */
11413 if (IS_BITFIELD(retype))
11414 genUnpackBits(result,left,"dptr",CPOINTER);
11416 size = AOP_SIZE(result);
11420 pic16_emitcode("clr","a");
11421 pic16_emitcode("movc","a,@a+dptr");
11422 pic16_aopPut(AOP(result),"a",offset++);
11424 pic16_emitcode("inc","dptr");
11428 pic16_freeAsmop(result,NULL,ic,TRUE);
11433 /*-----------------------------------------------------------------*/
11434 /* genGenPointerGet - gget value from generic pointer space */
11435 /*-----------------------------------------------------------------*/
11436 static void genGenPointerGet (operand *left,
11437 operand *result, iCode *ic)
11439 int size, offset, lit;
11440 sym_link *retype = getSpec(operandType(result));
11442 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11443 pic16_aopOp(left,ic,FALSE);
11444 pic16_aopOp(result,ic,FALSE);
11445 size = AOP_SIZE(result);
11447 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11449 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11451 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11452 // load FSR0 from immediate
11453 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11455 // pic16_loadFSR0( left );
11460 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11462 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11469 else { /* we need to get it byte by byte */
11470 // set up FSR0 with address from left
11471 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11472 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11478 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11480 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11487 /* if bit then unpack */
11488 if (IS_BITFIELD(retype))
11489 genUnpackBits(result,left,"BAD",GPOINTER);
11492 pic16_freeAsmop(left,NULL,ic,TRUE);
11493 pic16_freeAsmop(result,NULL,ic,TRUE);
11499 /*-----------------------------------------------------------------*/
11500 /* genGenPointerGet - gget value from generic pointer space */
11501 /*-----------------------------------------------------------------*/
11502 static void genGenPointerGet (operand *left,
11503 operand *result, iCode *ic)
11505 int size, offset, lit;
11506 sym_link *retype = getSpec(operandType(result));
11509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11510 pic16_aopOp(left,ic,FALSE);
11511 pic16_aopOp(result,ic,FALSE);
11512 size = AOP_SIZE(result);
11514 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11516 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11518 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11519 // load FSR0 from immediate
11520 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11522 werror(W_POSSBUG2, __FILE__, __LINE__);
11527 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11529 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11536 } else { /* we need to get it byte by byte */
11538 /* set up WREG:PRODL:FSR0L with address from left */
11539 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11540 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11541 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11544 case 1: strcpy(fgptrget, "__gptrget1"); break;
11545 case 2: strcpy(fgptrget, "__gptrget2"); break;
11546 case 3: strcpy(fgptrget, "__gptrget3"); break;
11547 case 4: strcpy(fgptrget, "__gptrget4"); break;
11549 werror(W_POSSBUG2, __FILE__, __LINE__);
11553 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11555 assignResultValue(result, 1);
11560 sym = newSymbol( fgptrget, 0 );
11562 strcpy(sym->rname, fgptrget);
11563 checkAddSym(&externs, sym);
11565 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11571 /* if bit then unpack */
11572 if (IS_BITFIELD(retype))
11573 genUnpackBits(result,left,"BAD",GPOINTER);
11576 pic16_freeAsmop(left,NULL,ic,TRUE);
11577 pic16_freeAsmop(result,NULL,ic,TRUE);
11580 /*-----------------------------------------------------------------*/
11581 /* genConstPointerGet - get value from const generic pointer space */
11582 /*-----------------------------------------------------------------*/
11583 static void genConstPointerGet (operand *left,
11584 operand *result, iCode *ic)
11586 //sym_link *retype = getSpec(operandType(result));
11587 // symbol *albl = newiTempLabel(NULL); // patch 15
11588 // symbol *blbl = newiTempLabel(NULL); //
11589 // PIC_OPCODE poc; // patch 15
11593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11594 pic16_aopOp(left,ic,FALSE);
11595 pic16_aopOp(result,ic,TRUE);
11596 size = AOP_SIZE(result);
11598 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11600 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11602 // set up table pointer
11603 if( (AOP_TYPE(left) == AOP_PCODE)
11604 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11605 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11607 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11608 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11609 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11610 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11611 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11612 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11614 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11615 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11616 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11620 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11621 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11625 pic16_freeAsmop(left,NULL,ic,TRUE);
11626 pic16_freeAsmop(result,NULL,ic,TRUE);
11630 /*-----------------------------------------------------------------*/
11631 /* genPointerGet - generate code for pointer get */
11632 /*-----------------------------------------------------------------*/
11633 static void genPointerGet (iCode *ic)
11635 operand *left, *result ;
11636 sym_link *type, *etype;
11641 left = IC_LEFT(ic);
11642 result = IC_RESULT(ic) ;
11644 /* depending on the type of pointer we need to
11645 move it to the correct pointer register */
11646 type = operandType(left);
11647 etype = getSpec(type);
11650 if (IS_PTR_CONST(type))
11652 if (IS_CODEPTR(type))
11654 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11656 /* if left is of type of pointer then it is simple */
11657 if (IS_PTR(type) && !IS_FUNC(type->next))
11658 p_type = DCL_TYPE(type);
11660 /* we have to go by the storage class */
11661 p_type = PTR_TYPE(SPEC_OCLS(etype));
11663 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11665 if (SPEC_OCLS(etype)->codesp ) {
11666 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11667 //p_type = CPOINTER ;
11669 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11670 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11671 /*p_type = FPOINTER ;*/
11673 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11674 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11675 /* p_type = PPOINTER; */
11677 if (SPEC_OCLS(etype) == idata ) {
11678 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11679 /* p_type = IPOINTER; */
11681 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11682 /* p_type = POINTER ; */
11686 /* now that we have the pointer type we assign
11687 the pointer values */
11691 genNearPointerGet (left,result,ic);
11695 genPagedPointerGet(left,result,ic);
11699 genFarPointerGet (left,result,ic);
11703 genConstPointerGet (left,result,ic);
11704 //pic16_emitcodePointerGet (left,result,ic);
11709 if (IS_PTR_CONST(type))
11710 genConstPointerGet (left,result,ic);
11713 genGenPointerGet (left,result,ic);
11717 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11718 "genPointerGet: illegal pointer type");
11723 /*-----------------------------------------------------------------*/
11724 /* genPackBits - generates code for packed bit storage */
11725 /*-----------------------------------------------------------------*/
11726 static void genPackBits (sym_link *etype , operand *result,
11728 char *rname, int p_type)
11736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11737 blen = SPEC_BLEN(etype);
11738 bstr = SPEC_BSTR(etype);
11740 retype = getSpec(operandType(right));
11742 if(AOP_TYPE(right) == AOP_LIT) {
11743 if((blen == 1) && (bstr < 8)) {
11745 /* it is a single bit, so use the appropriate bit instructions */
11747 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11749 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11750 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11751 if((p_type == POINTER) && (result)) {
11752 /* workaround to reduce the extra lfsr instruction */
11754 pic16_emitpcode(POC_BSF,
11755 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11757 pic16_emitpcode(POC_BCF,
11758 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11761 pic16_loadFSR0(result, 1);
11763 pic16_emitpcode(POC_BSF,
11764 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11766 pic16_emitpcode(POC_BCF,
11767 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11773 /* move literal to W */
11774 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11777 if(IS_BITFIELD(retype)
11778 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11782 rblen = SPEC_BLEN( retype );
11783 rbstr = SPEC_BSTR( retype );
11786 if(IS_BITFIELD(etype)) {
11787 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11788 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11790 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11793 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11795 if(IS_BITFIELD(etype)) {
11796 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11798 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11801 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11805 /* move right to W */
11806 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11809 /* if the bit length is less than or */
11810 /* it exactly fits a byte then */
11811 if((shCnt=SPEC_BSTR(etype))
11812 || SPEC_BLEN(etype) <= 8 ) {
11813 int fsr0_setup = 0;
11815 if (blen != 8 || bstr != 0) {
11816 // we need to combine the value with the old value
11817 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11819 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11820 SPEC_BSTR(etype), SPEC_BLEN(etype));
11822 /* shift left acc */
11825 /* using PRODH as a temporary register here */
11826 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11828 /* get old value */
11832 pic16_loadFSR0( result, 1 );
11834 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11835 // pic16_emitcode ("mov","b,a");
11836 // pic16_emitcode("mov","a,@%s",rname);
11840 if (AOP(result)->aopu.aop_reg[2]) {
11841 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11842 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11843 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11844 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11845 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11848 sym = newSymbol( "__gptrget1", 0 );
11849 strcpy(sym->rname, "__gptrget1");
11850 checkAddSym(&externs, sym);
11853 // data pointer (just 2 byte given)
11854 pic16_loadFSR0( result, 1 );
11856 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11859 // warnings will be emitted below
11860 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11861 //werror(W_POSSBUG2, __FILE__, __LINE__);
11865 assert (0 && "invalid pointer type specified");
11869 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11870 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11871 (unsigned char)(0xff >> (8-bstr))) ));
11872 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11873 } // if (blen != 8 || bstr != 0)
11875 /* write new value back */
11879 if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11880 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11884 if (AOP(result)->aopu.aop_reg[2]) {
11885 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11886 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11887 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11888 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11889 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11890 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11893 sym = newSymbol( "__gptrput1", 0 );
11894 strcpy(sym->rname, "__gptrput1");
11895 checkAddSym(&externs, sym);
11898 // data pointer (just 2 byte given)
11899 if (!fsr0_setup) pic16_loadFSR0( result, 1 );
11900 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11903 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11904 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11905 werror(W_POSSBUG2, __FILE__, __LINE__);
11909 assert (0 && "invalid pointer type specified");
11919 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11920 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11925 pic16_loadFSR0(result, 1); // load FSR0 with address of result
11926 rLen = SPEC_BLEN(etype)-8;
11928 /* now generate for lengths greater than one byte */
11932 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11938 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11944 pic16_emitcode("movx","@dptr,a");
11949 DEBUGpic16_emitcode(";lcall","__gptrput");
11957 pic16_mov2w(AOP(right), offset++);
11960 /* last last was not complete */
11962 /* save the byte & read byte */
11965 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11966 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11971 pic16_emitcode ("mov","b,a");
11972 pic16_emitcode("movx","a,@dptr");
11976 pic16_emitcode ("push","b");
11977 pic16_emitcode ("push","acc");
11978 pic16_emitcode ("lcall","__gptrget");
11979 pic16_emitcode ("pop","b");
11985 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11986 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11987 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11988 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11989 // pic16_emitcode ("orl","a,b");
11992 // if (p_type == GPOINTER)
11993 // pic16_emitcode("pop","b");
11998 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11999 // pic16_emitcode("mov","@%s,a",rname);
12003 pic16_emitcode("movx","@dptr,a");
12007 DEBUGpic16_emitcode(";lcall","__gptrput");
12014 // pic16_freeAsmop(right, NULL, ic, TRUE);
12016 /*-----------------------------------------------------------------*/
12017 /* genDataPointerSet - remat pointer to data space */
12018 /*-----------------------------------------------------------------*/
12019 static void genDataPointerSet(operand *right,
12023 int size, offset = 0, resoffset=0 ;
12025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12026 pic16_aopOp(right,ic,FALSE);
12028 size = AOP_SIZE(right);
12030 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12033 if ( AOP_TYPE(result) == AOP_PCODE) {
12034 fprintf(stderr,"genDataPointerSet %s, %d\n",
12035 AOP(result)->aopu.pcop->name,
12036 (AOP(result)->aopu.pcop->type == PO_DIR)?
12037 PCOR(AOP(result)->aopu.pcop)->instance:
12038 PCOI(AOP(result)->aopu.pcop)->offset);
12042 if(AOP(result)->aopu.pcop->type == PO_DIR)
12043 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12046 if (AOP_TYPE(right) == AOP_LIT) {
12049 if(!IS_FLOAT(operandType( right )))
12050 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12053 unsigned long lit_int;
12057 /* take care if literal is a float */
12058 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12059 lit = info.lit_int;
12062 lit = lit >> (8*offset);
12064 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12067 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12070 pic16_mov2w(AOP(right), offset);
12071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12077 pic16_freeAsmop(right,NULL,ic,TRUE);
12082 /*-----------------------------------------------------------------*/
12083 /* genNearPointerSet - pic16_emitcode for near pointer put */
12084 /*-----------------------------------------------------------------*/
12085 static void genNearPointerSet (operand *right,
12091 sym_link *ptype = operandType(result);
12092 sym_link *resetype;
12094 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12095 retype= getSpec(operandType(right));
12096 resetype = getSpec(operandType(result));
12098 pic16_aopOp(result,ic,FALSE);
12100 /* if the result is rematerializable &
12101 * in data space & not a bit variable */
12103 /* and result is not a bit variable */
12104 if (AOP_TYPE(result) == AOP_PCODE
12105 // && AOP_TYPE(result) == AOP_IMMD
12106 && DCL_TYPE(ptype) == POINTER
12107 && !IS_BITFIELD(retype)
12108 && !IS_BITFIELD(resetype)) {
12110 genDataPointerSet (right,result,ic);
12111 pic16_freeAsmop(result,NULL,ic,TRUE);
12115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12116 pic16_aopOp(right,ic,FALSE);
12117 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12119 /* if the value is already in a pointer register
12120 * then don't need anything more */
12121 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12122 /* otherwise get a free pointer register */
12123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12128 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12130 /* if bitfield then unpack the bits */
12131 if (IS_BITFIELD(resetype)) {
12132 genPackBits (resetype, result, right, NULL, POINTER);
12134 /* we have can just get the values */
12135 int size = AOP_SIZE(right);
12138 pic16_loadFSR0(result, 0);
12140 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12142 if (AOP_TYPE(right) == AOP_LIT) {
12143 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12145 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12147 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12149 } else { // no literal
12151 pic16_emitpcode(POC_MOVFF,
12152 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12153 pic16_popCopyReg(&pic16_pc_postinc0)));
12155 pic16_emitpcode(POC_MOVFF,
12156 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12157 pic16_popCopyReg(&pic16_pc_indf0)));
12164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12165 /* now some housekeeping stuff */
12167 /* we had to allocate for this iCode */
12168 pic16_freeAsmop(NULL,aop,ic,TRUE);
12170 /* we did not allocate which means left
12171 * already in a pointer register, then
12172 * if size > 0 && this could be used again
12173 * we have to point it back to where it
12175 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12176 if (AOP_SIZE(right) > 1
12177 && !OP_SYMBOL(result)->remat
12178 && ( OP_SYMBOL(result)->liveTo > ic->seq
12181 int size = AOP_SIZE(right) - 1;
12184 pic16_emitcode("decf","fsr0,f");
12185 //pic16_emitcode("dec","%s",rname);
12189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12192 pic16_freeAsmop(right,NULL,ic,TRUE);
12193 pic16_freeAsmop(result,NULL,ic,TRUE);
12196 /*-----------------------------------------------------------------*/
12197 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12198 /*-----------------------------------------------------------------*/
12199 static void genPagedPointerSet (operand *right,
12204 regs *preg = NULL ;
12208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12210 retype= getSpec(operandType(right));
12212 pic16_aopOp(result,ic,FALSE);
12214 /* if the value is already in a pointer register
12215 then don't need anything more */
12216 if (!AOP_INPREG(AOP(result))) {
12217 /* otherwise get a free pointer register */
12219 preg = getFreePtr(ic,&aop,FALSE);
12220 pic16_emitcode("mov","%s,%s",
12222 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12223 rname = preg->name ;
12225 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12227 pic16_freeAsmop(result,NULL,ic,TRUE);
12228 pic16_aopOp (right,ic,FALSE);
12230 /* if bitfield then unpack the bits */
12231 if (IS_BITFIELD(retype))
12232 genPackBits (retype,result,right,rname,PPOINTER);
12234 /* we have can just get the values */
12235 int size = AOP_SIZE(right);
12239 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12242 pic16_emitcode("movx","@%s,a",rname);
12245 pic16_emitcode("inc","%s",rname);
12251 /* now some housekeeping stuff */
12253 /* we had to allocate for this iCode */
12254 pic16_freeAsmop(NULL,aop,ic,TRUE);
12256 /* we did not allocate which means left
12257 already in a pointer register, then
12258 if size > 0 && this could be used again
12259 we have to point it back to where it
12261 if (AOP_SIZE(right) > 1 &&
12262 !OP_SYMBOL(result)->remat &&
12263 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12265 int size = AOP_SIZE(right) - 1;
12267 pic16_emitcode("dec","%s",rname);
12272 pic16_freeAsmop(right,NULL,ic,TRUE);
12277 /*-----------------------------------------------------------------*/
12278 /* genFarPointerSet - set value from far space */
12279 /*-----------------------------------------------------------------*/
12280 static void genFarPointerSet (operand *right,
12281 operand *result, iCode *ic)
12284 sym_link *retype = getSpec(operandType(right));
12286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12287 pic16_aopOp(result,ic,FALSE);
12289 /* if the operand is already in dptr
12290 then we do nothing else we move the value to dptr */
12291 if (AOP_TYPE(result) != AOP_STR) {
12292 /* if this is remateriazable */
12293 if (AOP_TYPE(result) == AOP_IMMD)
12294 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12295 else { /* we need to get it byte by byte */
12296 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12297 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12298 if (options.model == MODEL_FLAT24)
12300 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12304 /* so dptr know contains the address */
12305 pic16_freeAsmop(result,NULL,ic,TRUE);
12306 pic16_aopOp(right,ic,FALSE);
12308 /* if bit then unpack */
12309 if (IS_BITFIELD(retype))
12310 genPackBits(retype,result,right,"dptr",FPOINTER);
12312 size = AOP_SIZE(right);
12316 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12318 pic16_emitcode("movx","@dptr,a");
12320 pic16_emitcode("inc","dptr");
12324 pic16_freeAsmop(right,NULL,ic,TRUE);
12327 /*-----------------------------------------------------------------*/
12328 /* genGenPointerSet - set value from generic pointer space */
12329 /*-----------------------------------------------------------------*/
12331 static void genGenPointerSet (operand *right,
12332 operand *result, iCode *ic)
12334 int i, size, offset, lit;
12335 sym_link *retype = getSpec(operandType(right));
12337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12339 pic16_aopOp(result,ic,FALSE);
12340 pic16_aopOp(right,ic,FALSE);
12341 size = AOP_SIZE(right);
12344 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12346 /* if the operand is already in dptr
12347 then we do nothing else we move the value to dptr */
12348 if (AOP_TYPE(result) != AOP_STR) {
12349 /* if this is remateriazable */
12350 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12351 // WARNING: anythig until "else" is untested!
12352 if (AOP_TYPE(result) == AOP_IMMD) {
12353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12354 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12355 // load FSR0 from immediate
12356 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12360 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12362 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12368 else { /* we need to get it byte by byte */
12369 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12370 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12372 // set up FSR0 with address of result
12373 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12374 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12376 /* hack hack! see if this the FSR. If so don't load W */
12377 if(AOP_TYPE(right) != AOP_ACC) {
12379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12381 if(AOP_TYPE(right) == AOP_LIT)
12384 // note: pic16_popGet handles sign extension
12385 for(i=0;i<size;i++) {
12386 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12388 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12390 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12395 for(i=0;i<size;i++) {
12397 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12398 pic16_popCopyReg(&pic16_pc_postinc0)));
12400 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12401 pic16_popCopyReg(&pic16_pc_indf0)));
12407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12408 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12410 } // if (AOP_TYPE(result) != AOP_IMMD)
12412 } // if (AOP_TYPE(result) != AOP_STR)
12413 /* so dptr know contains the address */
12416 /* if bit then unpack */
12417 if (IS_BITFIELD(retype))
12418 genPackBits(retype,result,right,"dptr",GPOINTER);
12420 size = AOP_SIZE(right);
12423 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12425 // set up FSR0 with address of result
12426 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12427 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12430 if (AOP_TYPE(right) == AOP_LIT) {
12431 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12433 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12435 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12437 } else { // no literal
12439 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12441 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12449 pic16_freeAsmop(right,NULL,ic,TRUE);
12450 pic16_freeAsmop(result,NULL,ic,TRUE);
12454 static void genGenPointerSet (operand *right,
12455 operand *result, iCode *ic)
12458 sym_link *retype = getSpec(operandType(right));
12461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12463 pic16_aopOp(result,ic,FALSE);
12464 pic16_aopOp(right,ic,FALSE);
12465 size = AOP_SIZE(right);
12467 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12470 /* if bit then unpack */
12471 if (IS_BITFIELD(retype)) {
12472 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12473 genPackBits(retype,result,right,"dptr",GPOINTER);
12477 size = AOP_SIZE(right);
12479 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12483 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12485 /* value of right+0 is placed on stack, which will be retrieved
12486 * by the support function this restoring the stack. The important
12487 * thing is that there is no need to manually restore stack pointer
12489 pushaop(AOP(right), 0);
12490 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12491 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12492 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12493 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12495 /* load address to write to in WREG:FSR0H:FSR0L */
12496 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12497 pic16_popCopyReg(&pic16_pc_fsr0l)));
12498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12499 pic16_popCopyReg(&pic16_pc_prodl)));
12500 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12503 /* put code here */
12505 case 1: strcpy(fgptrput, "__gptrput1"); break;
12506 case 2: strcpy(fgptrput, "__gptrput2"); break;
12507 case 3: strcpy(fgptrput, "__gptrput3"); break;
12508 case 4: strcpy(fgptrput, "__gptrput4"); break;
12510 werror(W_POSSBUG2, __FILE__, __LINE__);
12514 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12519 sym = newSymbol( fgptrput, 0 );
12521 strcpy(sym->rname, fgptrput);
12522 checkAddSym(&externs, sym);
12526 pic16_freeAsmop(right,NULL,ic,TRUE);
12527 pic16_freeAsmop(result,NULL,ic,TRUE);
12530 /*-----------------------------------------------------------------*/
12531 /* genPointerSet - stores the value into a pointer location */
12532 /*-----------------------------------------------------------------*/
12533 static void genPointerSet (iCode *ic)
12535 operand *right, *result ;
12536 sym_link *type, *etype;
12541 right = IC_RIGHT(ic);
12542 result = IC_RESULT(ic) ;
12544 /* depending on the type of pointer we need to
12545 move it to the correct pointer register */
12546 type = operandType(result);
12547 etype = getSpec(type);
12548 /* if left is of type of pointer then it is simple */
12549 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12550 p_type = DCL_TYPE(type);
12553 /* we have to go by the storage class */
12554 p_type = PTR_TYPE(SPEC_OCLS(etype));
12556 /* if (SPEC_OCLS(etype)->codesp ) { */
12557 /* p_type = CPOINTER ; */
12560 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12561 /* p_type = FPOINTER ; */
12563 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12564 /* p_type = PPOINTER ; */
12566 /* if (SPEC_OCLS(etype) == idata ) */
12567 /* p_type = IPOINTER ; */
12569 /* p_type = POINTER ; */
12572 /* now that we have the pointer type we assign
12573 the pointer values */
12577 genNearPointerSet (right,result,ic);
12581 genPagedPointerSet (right,result,ic);
12585 genFarPointerSet (right,result,ic);
12589 genGenPointerSet (right,result,ic);
12593 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12594 "genPointerSet: illegal pointer type");
12598 /*-----------------------------------------------------------------*/
12599 /* genIfx - generate code for Ifx statement */
12600 /*-----------------------------------------------------------------*/
12601 static void genIfx (iCode *ic, iCode *popIc)
12603 operand *cond = IC_COND(ic);
12608 pic16_aopOp(cond,ic,FALSE);
12610 /* get the value into acc */
12611 if (AOP_TYPE(cond) != AOP_CRY)
12612 pic16_toBoolean(cond);
12615 /* the result is now in the accumulator */
12616 pic16_freeAsmop(cond,NULL,ic,TRUE);
12618 /* if there was something to be popped then do it */
12622 /* if the condition is a bit variable */
12623 if (isbit && IS_ITEMP(cond) &&
12625 genIfxJump(ic,"c");
12626 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12628 if (isbit && !IS_ITEMP(cond))
12629 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12631 genIfxJump(ic,"a");
12636 /*-----------------------------------------------------------------*/
12637 /* genAddrOf - generates code for address of */
12638 /*-----------------------------------------------------------------*/
12639 static void genAddrOf (iCode *ic)
12641 operand *result, *left;
12643 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12644 pCodeOp *pcop0, *pcop1, *pcop2;
12648 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12650 sym = OP_SYMBOL( IC_LEFT(ic) );
12653 /* get address of symbol on stack */
12654 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12656 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12657 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12660 // operands on stack are accessible via "FSR2 + index" with index
12661 // starting at 2 for arguments and growing from 0 downwards for
12662 // local variables (index == 0 is not assigned so we add one here)
12664 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12666 assert (soffs < 0);
12669 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12670 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12671 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12672 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12673 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12674 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12675 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12681 // if(pic16_debug_verbose) {
12682 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12683 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12686 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12687 size = AOP_SIZE(IC_RESULT(ic));
12689 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12690 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12691 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12694 pic16_emitpcode(POC_MOVLW, pcop0);
12695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12696 pic16_emitpcode(POC_MOVLW, pcop1);
12697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12698 pic16_emitpcode(POC_MOVLW, pcop2);
12699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12702 pic16_emitpcode(POC_MOVLW, pcop0);
12703 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12704 pic16_emitpcode(POC_MOVLW, pcop1);
12705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12707 pic16_emitpcode(POC_MOVLW, pcop0);
12708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12711 pic16_freeAsmop(left, NULL, ic, FALSE);
12713 pic16_freeAsmop(result,NULL,ic,TRUE);
12718 /*-----------------------------------------------------------------*/
12719 /* genFarFarAssign - assignment when both are in far space */
12720 /*-----------------------------------------------------------------*/
12721 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12723 int size = AOP_SIZE(right);
12726 /* first push the right side on to the stack */
12728 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12730 pic16_emitcode ("push","acc");
12733 pic16_freeAsmop(right,NULL,ic,FALSE);
12734 /* now assign DPTR to result */
12735 pic16_aopOp(result,ic,FALSE);
12736 size = AOP_SIZE(result);
12738 pic16_emitcode ("pop","acc");
12739 pic16_aopPut(AOP(result),"a",--offset);
12741 pic16_freeAsmop(result,NULL,ic,FALSE);
12746 /*-----------------------------------------------------------------*/
12747 /* genAssign - generate code for assignment */
12748 /*-----------------------------------------------------------------*/
12749 static void genAssign (iCode *ic)
12751 operand *result, *right;
12752 int size, offset,know_W;
12753 unsigned long lit = 0L;
12755 result = IC_RESULT(ic);
12756 right = IC_RIGHT(ic) ;
12760 /* if they are the same */
12761 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12764 /* reversed order operands are aopOp'ed so that result operand
12765 * is effective in case right is a stack symbol. This maneauver
12766 * allows to use the _G.resDirect flag later */
12767 pic16_aopOp(result,ic,TRUE);
12768 pic16_aopOp(right,ic,FALSE);
12770 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12772 /* if they are the same registers */
12773 if (pic16_sameRegs(AOP(right),AOP(result)))
12776 /* if the result is a bit */
12777 if (AOP_TYPE(result) == AOP_CRY) {
12778 /* if the right size is a literal then
12779 we know what the value is */
12780 if (AOP_TYPE(right) == AOP_LIT) {
12782 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12783 pic16_popGet(AOP(result),0));
12785 if (((int) operandLitValue(right)))
12786 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12787 AOP(result)->aopu.aop_dir,
12788 AOP(result)->aopu.aop_dir);
12790 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12791 AOP(result)->aopu.aop_dir,
12792 AOP(result)->aopu.aop_dir);
12796 /* the right is also a bit variable */
12797 if (AOP_TYPE(right) == AOP_CRY) {
12798 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12799 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12800 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12802 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12803 AOP(result)->aopu.aop_dir,
12804 AOP(result)->aopu.aop_dir);
12805 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12806 AOP(right)->aopu.aop_dir,
12807 AOP(right)->aopu.aop_dir);
12808 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12809 AOP(result)->aopu.aop_dir,
12810 AOP(result)->aopu.aop_dir);
12814 /* we need to or */
12815 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12816 pic16_toBoolean(right);
12818 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12819 //pic16_aopPut(AOP(result),"a",0);
12823 /* bit variables done */
12825 size = AOP_SIZE(result);
12828 if(AOP_TYPE(right) == AOP_LIT) {
12829 if(!IS_FLOAT(operandType( right )))
12830 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12833 unsigned long lit_int;
12837 /* take care if literal is a float */
12838 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12839 lit = info.lit_int;
12843 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12844 // sizeof(unsigned long int), sizeof(float));
12847 if (AOP_TYPE(right) == AOP_REG) {
12848 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12851 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12856 if(AOP_TYPE(right) != AOP_LIT
12857 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12858 && !IS_FUNC(OP_SYM_TYPE(right))
12860 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12861 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12863 // set up table pointer
12864 if(is_LitOp(right)) {
12865 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12866 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12867 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12868 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12869 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12870 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12871 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12873 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12874 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12875 pic16_popCopyReg(&pic16_pc_tblptrl)));
12876 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12877 pic16_popCopyReg(&pic16_pc_tblptrh)));
12878 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12879 pic16_popCopyReg(&pic16_pc_tblptru)));
12882 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12884 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12885 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12886 pic16_popGet(AOP(result),offset)));
12890 size = getSize(OP_SYM_ETYPE(right));
12891 if(AOP_SIZE(result) > size) {
12892 size = AOP_SIZE(result) - size;
12894 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12904 /* VR - What is this?! */
12905 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12906 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12907 if(aopIdx(AOP(result),0) == 4) {
12909 /* this is a workaround to save value of right into wreg too,
12910 * value of wreg is going to be used later */
12911 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12912 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12917 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12923 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12924 if(AOP_TYPE(right) == AOP_LIT) {
12926 if(know_W != (lit&0xff))
12927 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12931 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12935 } else if (AOP_TYPE(right) == AOP_CRY) {
12936 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12938 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12939 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12940 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12942 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12943 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12948 if(!_G.resDirect) /* use this aopForSym feature */
12949 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12956 pic16_freeAsmop (right,NULL,ic,FALSE);
12957 pic16_freeAsmop (result,NULL,ic,TRUE);
12960 /*-----------------------------------------------------------------*/
12961 /* genJumpTab - generates code for jump table */
12962 /*-----------------------------------------------------------------*/
12963 static void genJumpTab (iCode *ic)
12968 pCodeOp *jt_offs_hi;
12973 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12974 /* get the condition into accumulator */
12975 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12977 /* multiply by three */
12978 pic16_emitcode("add","a,acc");
12979 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12981 jtab = newiTempLabel(NULL);
12982 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12983 pic16_emitcode("jmp","@a+dptr");
12984 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12987 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12988 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12990 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12991 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12992 pic16_emitpLabel(jtab->key);
12996 jt_offs = pic16_popGetTempReg(0);
12997 jt_offs_hi = pic16_popGetTempReg(1);
12998 jt_label = pic16_popGetLabel (jtab->key);
12999 //fprintf (stderr, "Creating jump table...\n");
13001 // calculate offset into jump table (idx * sizeof (GOTO))
13002 pic16_emitpcode(POC_CLRF , jt_offs_hi);
13003 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13004 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13005 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13006 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13007 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13008 pic16_emitpcode(POC_MOVWF , jt_offs);
13010 // prepare PCLATx (set to first entry in jump table)
13011 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13012 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13013 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13014 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13015 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13017 // set PCLATx to selected entry (new PCL is stored in jt_offs)
13018 pic16_emitpcode(POC_ADDWF , jt_offs);
13019 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13020 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13022 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
13024 // release temporaries and prepare jump into table (new PCL --> WREG)
13025 pic16_emitpcode(POC_MOVFW , jt_offs);
13026 pic16_popReleaseTempReg (jt_offs_hi, 1);
13027 pic16_popReleaseTempReg (jt_offs, 0);
13029 // jump into the table
13030 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13032 pic16_emitpLabelFORCE(jtab->key);
13035 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13037 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13038 /* now generate the jump labels */
13039 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13040 jtab = setNextItem(IC_JTLABELS(ic))) {
13041 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13042 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13045 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13049 /*-----------------------------------------------------------------*/
13050 /* genMixedOperation - gen code for operators between mixed types */
13051 /*-----------------------------------------------------------------*/
13053 TSD - Written for the PIC port - but this unfortunately is buggy.
13054 This routine is good in that it is able to efficiently promote
13055 types to different (larger) sizes. Unfortunately, the temporary
13056 variables that are optimized out by this routine are sometimes
13057 used in other places. So until I know how to really parse the
13058 iCode tree, I'm going to not be using this routine :(.
13060 static int genMixedOperation (iCode *ic)
13063 operand *result = IC_RESULT(ic);
13064 sym_link *ctype = operandType(IC_LEFT(ic));
13065 operand *right = IC_RIGHT(ic);
13071 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13073 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13079 nextright = IC_RIGHT(nextic);
13080 nextleft = IC_LEFT(nextic);
13081 nextresult = IC_RESULT(nextic);
13083 pic16_aopOp(right,ic,FALSE);
13084 pic16_aopOp(result,ic,FALSE);
13085 pic16_aopOp(nextright, nextic, FALSE);
13086 pic16_aopOp(nextleft, nextic, FALSE);
13087 pic16_aopOp(nextresult, nextic, FALSE);
13089 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13091 operand *t = right;
13095 pic16_emitcode(";remove right +","");
13097 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13099 operand *t = right;
13103 pic16_emitcode(";remove left +","");
13107 big = AOP_SIZE(nextleft);
13108 small = AOP_SIZE(nextright);
13110 switch(nextic->op) {
13113 pic16_emitcode(";optimize a +","");
13114 /* if unsigned or not an integral type */
13115 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13116 pic16_emitcode(";add a bit to something","");
13119 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13121 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13122 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13123 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13125 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13133 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13134 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13135 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13138 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13140 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13141 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13142 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13143 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13144 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13147 pic16_emitcode("rlf","known_zero,w");
13154 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13155 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13156 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13158 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13168 pic16_freeAsmop(right,NULL,ic,TRUE);
13169 pic16_freeAsmop(result,NULL,ic,TRUE);
13170 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13171 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13173 nextic->generated = 1;
13180 /*-----------------------------------------------------------------*/
13181 /* genCast - gen code for casting */
13182 /*-----------------------------------------------------------------*/
13183 static void genCast (iCode *ic)
13185 operand *result = IC_RESULT(ic);
13186 sym_link *ctype = operandType(IC_LEFT(ic));
13187 sym_link *rtype = operandType(IC_RIGHT(ic));
13188 sym_link *restype = operandType(IC_RESULT(ic));
13189 operand *right = IC_RIGHT(ic);
13195 /* if they are equivalent then do nothing */
13196 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13199 pic16_aopOp(right,ic,FALSE) ;
13200 pic16_aopOp(result,ic,FALSE);
13202 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13205 /* if the result is a bit */
13206 if (AOP_TYPE(result) == AOP_CRY) {
13208 /* if the right size is a literal then
13209 * we know what the value is */
13210 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13212 if (AOP_TYPE(right) == AOP_LIT) {
13213 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13214 pic16_popGet(AOP(result),0));
13216 if (((int) operandLitValue(right)))
13217 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13218 AOP(result)->aopu.aop_dir,
13219 AOP(result)->aopu.aop_dir);
13221 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13222 AOP(result)->aopu.aop_dir,
13223 AOP(result)->aopu.aop_dir);
13227 /* the right is also a bit variable */
13228 if (AOP_TYPE(right) == AOP_CRY) {
13230 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13232 pic16_emitcode("clrc","");
13233 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13234 AOP(right)->aopu.aop_dir,
13235 AOP(right)->aopu.aop_dir);
13236 pic16_aopPut(AOP(result),"c",0);
13240 /* we need to or */
13241 if (AOP_TYPE(right) == AOP_REG) {
13242 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13243 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13244 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13246 pic16_toBoolean(right);
13247 pic16_aopPut(AOP(result),"a",0);
13251 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13254 size = AOP_SIZE(result);
13256 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13258 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13259 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13260 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13263 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13268 if(IS_BITFIELD(getSpec(restype))
13269 && IS_BITFIELD(getSpec(rtype))) {
13270 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13273 /* if they are the same size : or less */
13274 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13276 /* if they are in the same place */
13277 if (pic16_sameRegs(AOP(right),AOP(result)))
13280 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13282 if (IS_PTR_CONST(rtype))
13284 if (IS_CODEPTR(rtype))
13286 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13289 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13291 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13293 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13296 if(AOP_TYPE(right) == AOP_IMMD) {
13297 pCodeOp *pcop0, *pcop1, *pcop2;
13298 symbol *sym = OP_SYMBOL( right );
13300 size = AOP_SIZE(result);
13302 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13304 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13306 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13309 pic16_emitpcode(POC_MOVLW, pcop0);
13310 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13311 pic16_emitpcode(POC_MOVLW, pcop1);
13312 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13313 pic16_emitpcode(POC_MOVLW, pcop2);
13314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13317 pic16_emitpcode(POC_MOVLW, pcop0);
13318 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13319 pic16_emitpcode(POC_MOVLW, pcop1);
13320 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13322 pic16_emitpcode(POC_MOVLW, pcop0);
13323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13327 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13328 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13329 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13330 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13332 if(AOP_SIZE(result) <2)
13333 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13335 /* if they in different places then copy */
13336 size = AOP_SIZE(result);
13339 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13340 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13347 /* if the result is of type pointer */
13348 if (IS_PTR(ctype)) {
13350 sym_link *type = operandType(right);
13351 sym_link *etype = getSpec(type);
13353 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13355 /* pointer to generic pointer */
13356 if (IS_GENPTR(ctype)) {
13360 p_type = DCL_TYPE(type);
13362 /* we have to go by the storage class */
13363 p_type = PTR_TYPE(SPEC_OCLS(etype));
13365 /* if (SPEC_OCLS(etype)->codesp ) */
13366 /* p_type = CPOINTER ; */
13368 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13369 /* p_type = FPOINTER ; */
13371 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13372 /* p_type = PPOINTER; */
13374 /* if (SPEC_OCLS(etype) == idata ) */
13375 /* p_type = IPOINTER ; */
13377 /* p_type = POINTER ; */
13380 /* the first two bytes are known */
13381 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13382 size = GPTRSIZE - 1;
13385 if(offset < AOP_SIZE(right)) {
13386 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13387 mov2f(AOP(result), AOP(right), offset);
13389 if ((AOP_TYPE(right) == AOP_PCODE) &&
13390 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13391 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13392 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13395 pic16_aopPut(AOP(result),
13396 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13401 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13404 /* the last byte depending on type */
13408 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13409 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13410 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13414 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13418 pic16_emitcode(";BUG!? ","%d",__LINE__);
13422 pic16_emitcode(";BUG!? ","%d",__LINE__);
13427 if (GPTRSIZE > AOP_SIZE(right)) {
13428 // assume data pointer... THIS MIGHT BE WRONG!
13429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13430 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13432 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13437 /* this should never happen */
13438 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13439 "got unknown pointer type");
13442 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13446 /* just copy the pointers */
13447 size = AOP_SIZE(result);
13450 pic16_aopPut(AOP(result),
13451 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13460 /* so we now know that the size of destination is greater
13461 than the size of the source.
13462 Now, if the next iCode is an operator then we might be
13463 able to optimize the operation without performing a cast.
13465 if(genMixedOperation(ic))
13468 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13470 /* we move to result for the size of source */
13471 size = AOP_SIZE(right);
13474 mov2f(AOP(result), AOP(right), offset);
13478 /* now depending on the sign of the destination */
13479 size = AOP_SIZE(result) - AOP_SIZE(right);
13480 /* if unsigned or not an integral type */
13481 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13483 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13485 /* we need to extend the sign :( */
13488 /* Save one instruction of casting char to int */
13489 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13490 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13491 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13493 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13496 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13498 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13500 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13503 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13508 pic16_freeAsmop(right,NULL,ic,TRUE);
13509 pic16_freeAsmop(result,NULL,ic,TRUE);
13513 /*-----------------------------------------------------------------*/
13514 /* genDjnz - generate decrement & jump if not zero instrucion */
13515 /*-----------------------------------------------------------------*/
13516 static int genDjnz (iCode *ic, iCode *ifx)
13518 symbol *lbl, *lbl1;
13519 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13524 /* if the if condition has a false label
13525 then we cannot save */
13529 /* if the minus is not of the form
13531 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13532 !IS_OP_LITERAL(IC_RIGHT(ic)))
13535 if (operandLitValue(IC_RIGHT(ic)) != 1)
13538 /* if the size of this greater than one then no
13540 if (getSize(operandType(IC_RESULT(ic))) > 1)
13543 /* otherwise we can save BIG */
13544 lbl = newiTempLabel(NULL);
13545 lbl1= newiTempLabel(NULL);
13547 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13549 if (IS_AOP_PREG(IC_RESULT(ic))) {
13550 pic16_emitcode("dec","%s",
13551 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13552 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13553 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13557 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13558 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13560 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13561 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13565 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13566 ifx->generated = 1;
13570 /*-----------------------------------------------------------------*/
13571 /* genReceive - generate code for a receive iCode */
13572 /*-----------------------------------------------------------------*/
13573 static void genReceive (iCode *ic)
13579 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13580 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13582 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13584 if (isOperandInFarSpace(IC_RESULT(ic))
13585 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13586 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13588 int size = getSize(operandType(IC_RESULT(ic)));
13589 int offset = pic16_fReturnSizePic - size;
13593 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13594 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13598 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13600 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13601 size = AOP_SIZE(IC_RESULT(ic));
13604 pic16_emitcode ("pop","acc");
13605 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13608 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13610 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13613 /* set pseudo stack pointer to where it should be - dw*/
13614 GpsuedoStkPtr = ic->parmBytes;
13616 /* setting GpsuedoStkPtr has side effects here: */
13617 assignResultValue(IC_RESULT(ic), 0);
13620 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13623 /*-----------------------------------------------------------------*/
13624 /* genDummyRead - generate code for dummy read of volatiles */
13625 /*-----------------------------------------------------------------*/
13627 genDummyRead (iCode * ic)
13633 if (op && IS_SYMOP(op)) {
13634 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13635 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13638 pic16_aopOp (op, ic, FALSE);
13639 for (i=0; i < AOP_SIZE(op); i++) {
13640 // may need to protect this from the peepholer -- this is not nice but works...
13641 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13642 pic16_mov2w (AOP(op),i);
13643 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13645 pic16_freeAsmop (op, NULL, ic, TRUE);
13647 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13651 /*-----------------------------------------------------------------*/
13652 /* genpic16Code - generate code for pic16 based controllers */
13653 /*-----------------------------------------------------------------*/
13655 * At this point, ralloc.c has gone through the iCode and attempted
13656 * to optimize in a way suitable for a PIC. Now we've got to generate
13657 * PIC instructions that correspond to the iCode.
13659 * Once the instructions are generated, we'll pass through both the
13660 * peep hole optimizer and the pCode optimizer.
13661 *-----------------------------------------------------------------*/
13663 void genpic16Code (iCode *lic)
13668 lineHead = lineCurr = NULL;
13670 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13671 pic16_addpBlock(pb);
13674 /* if debug information required */
13675 if (options.debug && currFunc) {
13677 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13682 for (ic = lic ; ic ; ic = ic->next ) {
13684 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13685 if ( cln != ic->lineno ) {
13686 if ( options.debug ) {
13687 debugFile->writeCLine (ic);
13690 if(!options.noCcodeInAsm) {
13691 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13692 printCLine(ic->filename, ic->lineno)));
13698 if(options.iCodeInAsm) {
13701 /* insert here code to print iCode as comment */
13702 l = Safe_strdup(printILine(ic));
13703 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13706 /* if the result is marked as
13707 * spilt and rematerializable or code for
13708 * this has already been generated then
13710 if (resultRemat(ic) || ic->generated )
13713 /* depending on the operation */
13732 /* IPOP happens only when trying to restore a
13733 * spilt live range, if there is an ifx statement
13734 * following this pop then the if statement might
13735 * be using some of the registers being popped which
13736 * would destroy the contents of the register so
13737 * we need to check for this condition and handle it */
13739 && ic->next->op == IFX
13740 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13741 genIfx (ic->next,ic);
13759 genEndFunction (ic);
13775 pic16_genPlus (ic) ;
13779 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13780 pic16_genMinus (ic);
13796 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13800 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13806 /* note these two are xlated by algebraic equivalence
13807 * during parsing SDCC.y */
13808 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13809 "got '>=' or '<=' shouldn't have come here");
13813 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13825 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13829 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13833 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13857 genRightShift (ic);
13860 case GET_VALUE_AT_ADDRESS:
13865 if (POINTER_SET(ic))
13892 addSet(&_G.sendSet,ic);
13895 case DUMMY_READ_VOLATILE:
13905 /* now we are ready to call the
13906 peep hole optimizer */
13907 if (!options.nopeep)
13908 peepHole (&lineHead);
13910 /* now do the actual printing */
13911 printLine (lineHead, codeOutFile);
13914 DFPRINTF((stderr,"printing pBlock\n\n"));
13915 pic16_printpBlock(stdout,pb);