1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
141 static char *accUse[] = {"WREG"};
143 //static short rbank = -1;
158 int stack_lat; /* stack offset latency */
160 int useWreg; /* flag when WREG is used to pass function parameter */
163 /* Resolved ifx structure. This structure stores information
164 about an iCode ifx that makes it easier to generate code.
166 typedef struct resolvedIfx {
167 symbol *lbl; /* pointer to a label */
168 int condition; /* true or false ifx */
169 int generated; /* set true when the code associated with the ifx
173 extern int pic16_ptrRegReq ;
174 extern int pic16_nRegs;
175 extern FILE *codeOutFile;
176 //static void saverbank (int, iCode *,bool);
178 static lineNode *lineHead = NULL;
179 static lineNode *lineCurr = NULL;
181 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
182 0xE0, 0xC0, 0x80, 0x00};
183 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
188 /*-----------------------------------------------------------------*/
189 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
190 /* exponent of 2 is returned, otherwise -1 is */
192 /* note that this is similar to the function `powof2' in SDCCsymt */
196 /*-----------------------------------------------------------------*/
197 int pic16_my_powof2 (unsigned long num)
200 if( (num & (num-1)) == 0) {
213 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
215 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
217 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
218 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
219 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
220 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
221 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
222 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
223 ((result) ? AOP_SIZE(result) : 0));
226 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
229 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
231 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
232 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
233 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
234 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
235 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
236 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
240 void pic16_emitpcomment (char *fmt, ...)
243 char lb[INITIAL_INLINEASM];
249 vsprintf(lb+1,fmt,ap);
251 while (isspace(*lbp)) lbp++;
254 lineCurr = (lineCurr ?
255 connectLine(lineCurr,newLineNode(lb)) :
256 (lineHead = newLineNode(lb)));
257 lineCurr->isInline = _G.inLine;
258 lineCurr->isDebug = _G.debugLine;
260 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
263 // fprintf(stderr, "%s\n", lb);
266 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
269 char lb[INITIAL_INLINEASM];
272 if(!pic16_debug_verbose)
279 sprintf(lb,"%s\t",inst);
281 sprintf(lb,"%s",inst);
282 vsprintf(lb+(strlen(lb)),fmt,ap);
286 while (isspace(*lbp)) lbp++;
289 lineCurr = (lineCurr ?
290 connectLine(lineCurr,newLineNode(lb)) :
291 (lineHead = newLineNode(lb)));
292 lineCurr->isInline = _G.inLine;
293 lineCurr->isDebug = _G.debugLine;
295 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
298 // fprintf(stderr, "%s\n", lb);
303 void pic16_emitpLabel(int key)
305 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
308 void pic16_emitpLabelFORCE(int key)
310 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
313 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
317 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
319 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
322 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
325 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
327 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
330 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
333 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
339 #define pic16_emitcode DEBUGpic16_emitcode
341 /*-----------------------------------------------------------------*/
342 /* pic16_emitcode - writes the code into a file : for now it is simple */
343 /*-----------------------------------------------------------------*/
344 void pic16_emitcode (char *inst,char *fmt, ...)
347 char lb[INITIAL_INLINEASM];
354 sprintf(lb,"%s\t",inst);
356 sprintf(lb,"%s",inst);
357 vsprintf(lb+(strlen(lb)),fmt,ap);
361 while (isspace(*lbp)) lbp++;
364 lineCurr = (lineCurr ?
365 connectLine(lineCurr,newLineNode(lb)) :
366 (lineHead = newLineNode(lb)));
367 lineCurr->isInline = _G.inLine;
368 lineCurr->isDebug = _G.debugLine;
370 // VR fprintf(stderr, "lb = <%s>\n", lbp);
372 // if(pic16_debug_verbose)
373 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
380 /*-----------------------------------------------------------------*/
381 /* pic16_emitDebuggerSymbol - associate the current code location */
382 /* with a debugger symbol */
383 /*-----------------------------------------------------------------*/
385 pic16_emitDebuggerSymbol (char * debugSym)
388 pic16_emitcode (";", "%s ==.", debugSym);
393 /*-----------------------------------------------------------------*/
394 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
395 /*-----------------------------------------------------------------*/
396 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
398 // bool r0iu = FALSE , r1iu = FALSE;
399 // bool r0ou = FALSE , r1ou = FALSE;
400 bool fsr0iu = FALSE, fsr0ou;
401 bool fsr2iu = FALSE, fsr2ou;
403 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
406 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
407 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
409 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
410 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
412 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
413 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
414 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
417 if(!fsr0iu && !fsr0ou) {
418 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
419 (*aopp)->type = AOP_FSR0;
421 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
423 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
427 /* no usage of FSR2 */
428 if(!fsr2iu && !fsr2ou) {
429 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
430 (*aopp)->type = AOP_FSR2;
432 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
436 /* now we know they both have usage */
437 /* if fsr0 not used in this instruction */
439 if (!_G.fsr0Pushed) {
440 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
441 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
445 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
446 (*aopp)->type = AOP_FSR0;
448 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
450 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
454 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
459 /* the logic: if r0 & r1 used in the instruction
460 then we are in trouble otherwise */
462 /* first check if r0 & r1 are used by this
463 instruction, in which case we are in trouble */
464 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
465 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
470 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
471 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
473 /* if no usage of r0 then return it */
474 if (!r0iu && !r0ou) {
475 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
476 (*aopp)->type = AOP_R0;
478 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
481 /* if no usage of r1 then return it */
482 if (!r1iu && !r1ou) {
483 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
484 (*aopp)->type = AOP_R1;
486 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
489 /* now we know they both have usage */
490 /* if r0 not used in this instruction */
492 /* push it if not already pushed */
494 //pic16_emitcode ("push","%s",
495 // pic16_regWithIdx(R0_IDX)->dname);
499 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
500 (*aopp)->type = AOP_R0;
502 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
505 /* if r1 not used then */
508 /* push it if not already pushed */
510 //pic16_emitcode ("push","%s",
511 // pic16_regWithIdx(R1_IDX)->dname);
515 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
516 (*aopp)->type = AOP_R1;
517 return pic16_regWithIdx(R1_IDX);
521 /* I said end of world but not quite end of world yet */
522 /* if this is a result then we can push it on the stack*/
524 (*aopp)->type = AOP_STK;
528 /* other wise this is true end of the world */
529 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
530 "getFreePtr should never reach here");
535 /*-----------------------------------------------------------------*/
536 /* newAsmop - creates a new asmOp */
537 /*-----------------------------------------------------------------*/
538 static asmop *newAsmop (short type)
542 aop = Safe_calloc(1,sizeof(asmop));
547 static void genSetDPTR(int n)
551 pic16_emitcode(";", "Select standard DPTR");
552 pic16_emitcode("mov", "dps, #0x00");
556 pic16_emitcode(";", "Select alternate DPTR");
557 pic16_emitcode("mov", "dps, #0x01");
561 /*-----------------------------------------------------------------*/
562 /* resolveIfx - converts an iCode ifx into a form more useful for */
563 /* generating code */
564 /*-----------------------------------------------------------------*/
565 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
569 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
575 resIfx->condition = 1; /* assume that the ifx is true */
576 resIfx->generated = 0; /* indicate that the ifx has not been used */
579 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
582 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
583 __FUNCTION__,__LINE__,resIfx->lbl->key);
588 resIfx->lbl = IC_TRUE(ifx);
590 resIfx->lbl = IC_FALSE(ifx);
591 resIfx->condition = 0;
596 DEBUGpic16_emitcode("; +++","ifx true is non-null");
598 DEBUGpic16_emitcode("; +++","ifx true is null");
600 DEBUGpic16_emitcode("; +++","ifx false is non-null");
602 DEBUGpic16_emitcode("; +++","ifx false is null");
606 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type */
612 /*-----------------------------------------------------------------*/
613 static int pointerCode (sym_link *etype)
616 return PTR_TYPE(SPEC_OCLS(etype));
621 /*-----------------------------------------------------------------*/
622 /* aopForSym - for a true symbol */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForSym (iCode *ic, operand *op, bool result)
626 symbol *sym=OP_SYMBOL(op);
628 memmap *space= SPEC_OCLS(sym->etype);
632 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
634 // sym = OP_SYMBOL(op);
636 /* if already has one */
638 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
643 /* if symbol was initially placed onStack then we must re-place it
644 * to direct memory, since pic16 does not have a specific stack */
646 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
654 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
656 sym->aop = aop = newAsmop (AOP_PAGED);
657 aop->aopu.aop_dir = sym->rname ;
658 aop->size = getSize(sym->type);
659 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660 pic16_allocDirReg( IC_LEFT(ic) );
668 /* assign depending on the storage class */
669 /* if it is on the stack or indirectly addressable */
670 /* space we need to assign either r0 or r1 to it */
671 if (sym->onStack) // || sym->iaccess)
676 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
677 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
679 /* acquire a temporary register -- it is saved in function */
681 sym->aop = aop = newAsmop(AOP_STA);
682 aop->aopu.stk.stk = sym->stack;
683 aop->size = getSize(sym->type);
686 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
687 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
688 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
689 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
691 for(i=0;i<aop->size;i++)
692 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
693 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
695 for(i=0;i<aop->size;i++) {
696 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
697 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
701 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
704 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
707 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
710 for(i=0;i<aop->size;i++) {
712 /* initialise for stack access via frame pointer */
713 // operands on stack are accessible via "FSR2 + index" with index
714 // starting at 2 for arguments and growing from 0 downwards for
715 // local variables (index == 0 is not assigned so we add one here)
717 int soffs = sym->stack;
722 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
723 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
724 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
729 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
736 /* now assign the address of the variable to
737 the pointer register */
738 if (aop->type != AOP_STK) {
742 pic16_emitcode("push","acc");
744 pic16_emitcode("mov","a,_bp");
745 pic16_emitcode("add","a,#0x%02x",
747 ((char)(sym->stack - _G.nRegsSaved )) :
748 ((char)sym->stack)) & 0xff);
749 pic16_emitcode("mov","%s,a",
750 aop->aopu.aop_ptr->name);
753 pic16_emitcode("pop","acc");
755 pic16_emitcode("mov","%s,#%s",
756 aop->aopu.aop_ptr->name,
758 aop->paged = space->paged;
760 aop->aopu.aop_stk = sym->stack;
768 if (sym->onStack && options.stack10bit)
770 /* It's on the 10 bit stack, which is located in
774 //DEBUGpic16_emitcode(";","%d",__LINE__);
777 pic16_emitcode("push","acc");
779 pic16_emitcode("mov","a,_bp");
780 pic16_emitcode("add","a,#0x%02x",
782 ((char)(sym->stack - _G.nRegsSaved )) :
783 ((char)sym->stack)) & 0xff);
786 pic16_emitcode ("mov","dpx1,#0x40");
787 pic16_emitcode ("mov","dph1,#0x00");
788 pic16_emitcode ("mov","dpl1, a");
792 pic16_emitcode("pop","acc");
794 sym->aop = aop = newAsmop(AOP_DPTR2);
795 aop->size = getSize(sym->type);
801 /* special case for a function */
802 if (IS_FUNC(sym->type)) {
803 sym->aop = aop = newAsmop(AOP_PCODE);
804 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
805 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
806 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
807 PCOI(aop->aopu.pcop)->index = 0;
808 aop->size = FPTRSIZE;
809 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
816 //DEBUGpic16_emitcode(";","%d",__LINE__);
817 /* if in bit space */
818 if (IN_BITSPACE(space)) {
819 sym->aop = aop = newAsmop (AOP_CRY);
820 aop->aopu.aop_dir = sym->rname ;
821 aop->size = getSize(sym->type);
822 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
825 /* if it is in direct space */
826 if (IN_DIRSPACE(space)) {
827 sym->aop = aop = newAsmop (AOP_DIR);
828 aop->aopu.aop_dir = sym->rname ;
829 aop->size = getSize(sym->type);
830 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
831 pic16_allocDirReg( IC_LEFT(ic) );
836 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
837 sym->aop = aop = newAsmop (AOP_DIR);
838 aop->aopu.aop_dir = sym->rname ;
839 aop->size = getSize(sym->type);
840 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841 pic16_allocDirReg( IC_LEFT(ic) );
846 /* only remaining is far space */
847 sym->aop = aop = newAsmop(AOP_PCODE);
849 /* change the next if to 1 to revert to good old immediate code */
850 if(IN_CODESPACE(space)) {
851 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
852 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
853 PCOI(aop->aopu.pcop)->index = 0;
855 /* try to allocate via direct register */
856 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
857 // aop->size = getSize( sym->type );
860 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
861 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
864 if(!pic16_allocDirReg (IC_LEFT(ic)))
868 if(IN_DIRSPACE( space ))
870 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
871 aop->size = FPTRSIZE;
872 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
873 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
874 else if(sym->onStack) {
877 if(SPEC_SCLS(sym->etype) == S_PDATA) {
878 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
879 aop->size = FPTRSIZE;
884 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
886 /* if it is in code space */
887 if (IN_CODESPACE(space))
893 /*-----------------------------------------------------------------*/
894 /* aopForRemat - rematerialzes an object */
895 /*-----------------------------------------------------------------*/
896 static asmop *aopForRemat (operand *op) // x symbol *sym)
898 symbol *sym = OP_SYMBOL(op);
900 iCode *ic = NULL, *oldic;
901 asmop *aop = newAsmop(AOP_PCODE);
908 ic = sym->rematiCode;
910 if(IS_OP_POINTER(op)) {
911 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
917 // pic16_emitpcomment("ic: %s\n", printILine(ic));
920 val += (int) operandLitValue(IC_RIGHT(ic));
921 } else if (ic->op == '-') {
922 val -= (int) operandLitValue(IC_RIGHT(ic));
926 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
929 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
932 if(!op->isaddr)viaimmd++; else viaimmd=0;
934 /* set the following if to 1 to revert to good old immediate code */
935 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
938 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
940 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
943 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
945 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
948 PCOI(aop->aopu.pcop)->index = val;
950 aop->size = getSize( sym->type );
952 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
954 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
955 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
957 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
961 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
962 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
964 val, IS_PTR_CONST(operandType(op)));
966 val, IS_CODEPTR(operandType(op)));
969 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
971 pic16_allocDirReg (IC_LEFT(ic));
973 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
980 static int aopIdx (asmop *aop, int offset)
985 if(aop->type != AOP_REG)
988 return aop->aopu.aop_reg[offset]->rIdx;
993 /*-----------------------------------------------------------------*/
994 /* regsInCommon - two operands have some registers in common */
995 /*-----------------------------------------------------------------*/
996 static bool regsInCommon (operand *op1, operand *op2)
1001 /* if they have registers in common */
1002 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1005 sym1 = OP_SYMBOL(op1);
1006 sym2 = OP_SYMBOL(op2);
1008 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1011 for (i = 0 ; i < sym1->nRegs ; i++) {
1016 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1020 if (sym2->regs[j] == sym1->regs[i])
1028 /*-----------------------------------------------------------------*/
1029 /* operandsEqu - equivalent */
1030 /*-----------------------------------------------------------------*/
1031 static bool operandsEqu ( operand *op1, operand *op2)
1033 symbol *sym1, *sym2;
1035 /* if they not symbols */
1036 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1039 sym1 = OP_SYMBOL(op1);
1040 sym2 = OP_SYMBOL(op2);
1042 /* if both are itemps & one is spilt
1043 and the other is not then false */
1044 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1045 sym1->isspilt != sym2->isspilt )
1048 /* if they are the same */
1052 if (sym1->rname[0] && sym2->rname[0]
1053 && strcmp (sym1->rname, sym2->rname) == 0)
1057 /* if left is a tmp & right is not */
1058 if (IS_ITEMP(op1) &&
1061 (sym1->usl.spillLoc == sym2))
1064 if (IS_ITEMP(op2) &&
1068 (sym2->usl.spillLoc == sym1))
1074 /*-----------------------------------------------------------------*/
1075 /* pic16_sameRegs - two asmops have the same registers */
1076 /*-----------------------------------------------------------------*/
1077 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1084 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1085 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1087 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1089 if (aop1->type != AOP_REG ||
1090 aop2->type != AOP_REG )
1093 /* This is a bit too restrictive if one is a subset of the other...
1094 if (aop1->size != aop2->size )
1098 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1099 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1101 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1102 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1109 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1111 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1112 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1114 if(aop1 == aop2)return TRUE;
1115 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1117 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1123 /*-----------------------------------------------------------------*/
1124 /* pic16_aopOp - allocates an asmop for an operand : */
1125 /*-----------------------------------------------------------------*/
1126 void pic16_aopOp (operand *op, iCode *ic, bool result)
1135 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1137 /* if this a literal */
1138 if (IS_OP_LITERAL(op)) {
1139 op->aop = aop = newAsmop(AOP_LIT);
1140 aop->aopu.aop_lit = op->operand.valOperand;
1141 aop->size = getSize(operandType(op));
1146 sym_link *type = operandType(op);
1148 if(IS_PTR_CONST(type))
1150 if(IS_CODEPTR(type))
1152 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1155 /* if already has a asmop then continue */
1159 /* if the underlying symbol has a aop */
1160 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1161 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1162 op->aop = OP_SYMBOL(op)->aop;
1166 /* if this is a true symbol */
1167 if (IS_TRUE_SYMOP(op)) {
1168 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1169 op->aop = aopForSym(ic, op, result);
1173 /* this is a temporary : this has
1179 e) can be a return use only */
1181 sym = OP_SYMBOL(op);
1183 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1184 /* if the type is a conditional */
1185 if (sym->regType == REG_CND) {
1186 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1191 /* if it is spilt then two situations
1193 b) has a spill location */
1194 if (sym->isspilt || sym->nRegs == 0) {
1196 // debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
1197 DEBUGpic16_emitcode(";","%d",__LINE__);
1198 /* rematerialize it NOW */
1201 sym->aop = op->aop = aop = aopForRemat (op);
1202 // aop->size = getSize(sym->type);
1203 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1210 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1211 aop->size = getSize(sym->type);
1212 for ( i = 0 ; i < 1 ; i++ ) {
1213 aop->aopu.aop_str[i] = accUse[i];
1214 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1216 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1217 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1225 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1226 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1227 //pic16_allocDirReg (IC_LEFT(ic));
1228 aop->size = getSize(sym->type);
1233 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1234 aop->size = getSize(sym->type);
1235 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1236 aop->aopu.aop_str[i] = fReturn[i];
1238 DEBUGpic16_emitcode(";","%d",__LINE__);
1242 /* else spill location */
1243 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1244 /* force a new aop if sizes differ */
1245 sym->usl.spillLoc->aop = NULL;
1249 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1250 __FUNCTION__,__LINE__,
1251 sym->usl.spillLoc->rname,
1252 sym->rname, sym->usl.spillLoc->offset);
1255 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1256 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1257 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1258 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1260 sym->usl.spillLoc->offset, op);
1262 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1263 DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1264 assert (getSize(sym->type) <= 1);
1265 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
1267 aop->size = getSize(sym->type);
1273 sym_link *type = operandType(op);
1275 if(IS_PTR_CONST(type))
1277 if(IS_CODEPTR(type))
1279 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1282 /* must be in a register */
1283 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1284 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1285 aop->size = sym->nRegs;
1286 for ( i = 0 ; i < sym->nRegs ;i++)
1287 aop->aopu.aop_reg[i] = sym->regs[i];
1290 /*-----------------------------------------------------------------*/
1291 /* pic16_freeAsmop - free up the asmop given to an operand */
1292 /*----------------------------------------------------------------*/
1293 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1310 /* depending on the asmop type only three cases need work AOP_RO
1311 , AOP_R1 && AOP_STK */
1313 switch (aop->type) {
1315 if (_G.fsr0Pushed ) {
1317 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1318 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1319 // pic16_emitcode ("pop","ar0");
1323 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1327 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1333 pic16_emitcode ("pop","ar0");
1337 bitVectUnSetBit(ic->rUsed,R0_IDX);
1343 pic16_emitcode ("pop","ar1");
1347 bitVectUnSetBit(ic->rUsed,R1_IDX);
1354 /* we must store the result on stack */
1355 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1356 // operands on stack are accessible via "FSR2 + index" with index
1357 // starting at 2 for arguments and growing from 0 downwards for
1358 // local variables (index == 0 is not assigned so we add one here)
1359 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1364 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1365 for(i=0;i<aop->size;i++) {
1366 /* initialise for stack access via frame pointer */
1367 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1368 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1369 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1372 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1376 for(i=0;i<aop->size;i++)
1377 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1386 int stk = aop->aopu.aop_stk + aop->size;
1387 bitVectUnSetBit(ic->rUsed,R0_IDX);
1388 bitVectUnSetBit(ic->rUsed,R1_IDX);
1390 getFreePtr(ic,&aop,FALSE);
1392 if (options.stack10bit)
1394 /* I'm not sure what to do here yet... */
1397 "*** Warning: probably generating bad code for "
1398 "10 bit stack mode.\n");
1402 pic16_emitcode ("mov","a,_bp");
1403 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1404 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1406 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1410 pic16_emitcode("pop","acc");
1411 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1413 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1416 pic16_freeAsmop(op,NULL,ic,TRUE);
1418 pic16_emitcode("pop","ar0");
1423 pic16_emitcode("pop","ar1");
1433 /* all other cases just dealloc */
1437 OP_SYMBOL(op)->aop = NULL;
1438 /* if the symbol has a spill */
1440 SPIL_LOC(op)->aop = NULL;
1445 /*-----------------------------------------------------------------*/
1446 /* pic16_aopGet - for fetching value of the aop */
1447 /*-----------------------------------------------------------------*/
1448 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1453 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1455 /* offset is greater than size then zero */
1456 if (offset > (aop->size - 1) &&
1457 aop->type != AOP_LIT)
1460 /* depending on type */
1461 switch (aop->type) {
1465 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1466 rs = Safe_calloc(1, strlen(s)+1);
1471 /* if we need to increment it */
1472 while (offset > aop->coff)
1474 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478 while (offset < aop->coff)
1480 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1486 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1487 return (dname ? "acc" : "a");
1489 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1490 rs = Safe_calloc (1, strlen (s) + 1);
1498 sprintf (s,"%s",aop->aopu.aop_immd);
1501 sprintf(s,"(%s >> %d)",
1506 aop->aopu.aop_immd);
1507 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1508 rs = Safe_calloc(1,strlen(s)+1);
1514 sprintf(s,"(%s + %d)",
1517 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1519 sprintf(s,"%s",aop->aopu.aop_dir);
1520 rs = Safe_calloc(1,strlen(s)+1);
1526 // return aop->aopu.aop_reg[offset]->dname;
1528 return aop->aopu.aop_reg[offset]->name;
1531 //pic16_emitcode(";","%d",__LINE__);
1532 return aop->aopu.aop_dir;
1535 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1536 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1538 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1539 rs = Safe_strdup("WREG");
1543 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1544 rs = Safe_calloc(1,strlen(s)+1);
1549 aop->coff = offset ;
1550 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1553 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1555 return aop->aopu.aop_str[offset];
1559 pCodeOp *pcop = aop->aopu.pcop;
1560 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1562 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1563 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1565 sprintf(s,"(%s + %d)", pcop->name, offset);
1567 sprintf(s,"%s", pcop->name);
1570 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1573 rs = Safe_calloc(1,strlen(s)+1);
1579 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1581 sprintf(s,"(%s + %d)",
1585 sprintf(s,"%s",aop->aopu.aop_dir);
1586 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1587 rs = Safe_calloc(1,strlen(s)+1);
1593 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1597 // pCodeOp *pcop = aop->aop
1602 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1603 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1604 "aopget got unsupported aop->type");
1610 /* lock has the following meaning: When allocating temporary registers
1611 * for stack variables storage, the value of the temporary register is
1612 * saved on stack. Its value is restored at the end. This procedure is
1613 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1614 * a possibility that before a call to pic16_aopOp, a temporary register
1615 * is allocated for a while and it is freed after some time, this will
1616 * mess the stack and values will not be restored properly. So use lock=1
1617 * to allocate temporary registers used internally by the programmer, and
1618 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1619 * to inform the compiler developer about a possible bug. This is an internal
1620 * feature for developing the compiler -- VR */
1622 int _TempReg_lock = 0;
1623 /*-----------------------------------------------------------------*/
1624 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1625 /*-----------------------------------------------------------------*/
1626 pCodeOp *pic16_popGetTempReg(int lock)
1631 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1633 // werror(W_POSSBUG2, __FILE__, __LINE__);
1636 _TempReg_lock += lock;
1641 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1642 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1643 PCOR(pcop)->r->wasUsed=1;
1644 PCOR(pcop)->r->isFree=0;
1646 /* push value on stack */
1647 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1655 /*-----------------------------------------------------------------*/
1656 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1657 /* don't save if inside v */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1664 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1667 // werror(W_POSSBUG2, __FILE__, __LINE__);
1670 _TempReg_lock += lock;
1675 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1676 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1677 PCOR(pcop)->r->wasUsed=1;
1678 PCOR(pcop)->r->isFree=0;
1680 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1681 /* push value on stack */
1682 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1694 /*-----------------------------------------------------------------*/
1695 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1699 _TempReg_lock -= lock;
1701 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1702 PCOR(pcop)->r->isFree = 1;
1703 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1706 /*-----------------------------------------------------------------*/
1707 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1708 /*-----------------------------------------------------------------*/
1709 pCodeOp *pic16_popGetLabel(unsigned int key)
1712 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1717 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1720 /*-----------------------------------------------------------------*/
1721 /* pic16_popCopyReg - copy a pcode operator */
1722 /*-----------------------------------------------------------------*/
1723 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1727 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1728 pcor->pcop.type = pc->pcop.type;
1730 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1731 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1733 pcor->pcop.name = NULL;
1736 pcor->rIdx = pc->rIdx;
1738 pcor->instance = pc->instance;
1740 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1745 /*-----------------------------------------------------------------*/
1746 /* pic16_popGetLit - asm operator to pcode operator conversion */
1747 /*-----------------------------------------------------------------*/
1748 pCodeOp *pic16_popGetLit(int lit)
1750 return pic16_newpCodeOpLit(lit);
1753 /*-----------------------------------------------------------------*/
1754 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1755 /*-----------------------------------------------------------------*/
1756 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1758 return pic16_newpCodeOpLit2(lit, arg2);
1762 /*-----------------------------------------------------------------*/
1763 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1764 /*-----------------------------------------------------------------*/
1765 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1767 return pic16_newpCodeOpImmd(name, offset,index, 0);
1771 /*-----------------------------------------------------------------*/
1772 /* pic16_popGet - asm operator to pcode operator conversion */
1773 /*-----------------------------------------------------------------*/
1774 pCodeOp *pic16_popGetWithString(char *str)
1780 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1784 pcop = pic16_newpCodeOp(str,PO_STR);
1789 /*-----------------------------------------------------------------*/
1790 /* pic16_popRegFromString - */
1791 /*-----------------------------------------------------------------*/
1792 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1795 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1796 pcop->type = PO_DIR;
1798 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1799 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1804 pcop->name = Safe_calloc(1,strlen(str)+1);
1805 strcpy(pcop->name,str);
1807 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1809 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1811 /* make sure that register doesn't exist,
1812 * and operand isn't NULL
1813 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1814 if((PCOR(pcop)->r == NULL)
1816 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1817 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1818 // __FUNCTION__, __LINE__, str, size, offset);
1820 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1821 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1824 PCOR(pcop)->instance = offset;
1829 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1833 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1835 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1836 PCOR(pcop)->rIdx = rIdx;
1837 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1839 PCOR(pcop)->r->isFree = 0;
1840 PCOR(pcop)->r->wasUsed = 1;
1842 pcop->type = PCOR(pcop)->r->pc_type;
1847 /*---------------------------------------------------------------------------------*/
1848 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1850 /*---------------------------------------------------------------------------------*/
1851 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1856 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1858 /* comment the following check, so errors to throw up */
1859 // if(!pcop2)return NULL;
1861 temp = pic16_popGet(aop_dst, offset);
1862 pcop2->pcop2 = temp;
1869 /*--------------------------------------------------------------------------------.-*/
1870 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1871 /* VR 030601 , adapted by Hans Dorn */
1872 /*--------------------------------------------------------------------------------.-*/
1873 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1877 pcop2 = (pCodeOpReg2 *)src;
1885 /*---------------------------------------------------------------------------------*/
1886 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1887 /* movff instruction */
1888 /*---------------------------------------------------------------------------------*/
1889 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1894 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1895 pcop2->pcop2 = pic16_popCopyReg(dst);
1897 /* the pCodeOp may be already allocated */
1898 pcop2 = (pCodeOpReg2 *)(src);
1899 pcop2->pcop2 = (pCodeOp *)(dst);
1906 /*-----------------------------------------------------------------*/
1907 /* pic16_popGet - asm operator to pcode operator conversion */
1908 /*-----------------------------------------------------------------*/
1909 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1911 //char *s = buffer ;
1916 /* offset is greater than
1919 // if (offset > (aop->size - 1) &&
1920 // aop->type != AOP_LIT)
1921 // return NULL; //zero;
1923 /* depending on type */
1924 switch (aop->type) {
1930 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1931 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1938 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1939 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1940 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1941 PCOR(pcop)->r->wasUsed = 1;
1942 PCOR(pcop)->r->isFree = 0;
1944 PCOR(pcop)->instance = offset;
1945 pcop->type = PCOR(pcop)->r->pc_type;
1949 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1950 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1953 /* pCodeOp is already allocated from aopForSym */
1954 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1955 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1961 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1963 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1965 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1967 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1968 PCOR(pcop)->rIdx = rIdx;
1969 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1970 PCOR(pcop)->r->wasUsed=1;
1971 PCOR(pcop)->r->isFree=0;
1973 PCOR(pcop)->instance = offset;
1974 pcop->type = PCOR(pcop)->r->pc_type;
1975 // rs = aop->aopu.aop_reg[offset]->name;
1976 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1980 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1981 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1987 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1988 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1992 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1993 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1999 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2000 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2002 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2004 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2005 // pcop->type = PO_GPR_REGISTER;
2006 PCOR(pcop)->rIdx = rIdx;
2007 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2008 PCOR(pcop)->r->wasUsed=1;
2009 PCOR(pcop)->r->isFree=0;
2011 PCOR(pcop)->instance = offset;
2012 pcop->type = PCOR(pcop)->r->pc_type;
2014 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2015 rs = aop->aopu.aop_reg[offset]->name;
2016 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2021 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2023 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2024 PCOR(pcop)->instance = offset;
2025 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2026 //if(PCOR(pcop)->r == NULL)
2027 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2031 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2032 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2035 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2036 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2039 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2040 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2041 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2042 pcop->type = PCOR(pcop)->r->pc_type;
2043 pcop->name = PCOR(pcop)->r->name;
2049 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2051 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2052 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2053 switch( aop->aopu.pcop->type ) {
2054 case PO_DIR: PCOR(pcop)->instance += offset; break;
2055 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2056 case PO_WREG: assert (offset==0); break;
2058 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2059 assert( 0 ); /* should never reach here */;
2064 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2065 "pic16_popGet got unsupported aop->type");
2068 /*-----------------------------------------------------------------*/
2069 /* pic16_aopPut - puts a string for a aop */
2070 /*-----------------------------------------------------------------*/
2071 void pic16_aopPut (asmop *aop, char *s, int offset)
2078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2080 if (aop->size && offset > ( aop->size - 1)) {
2081 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2082 "pic16_aopPut got offset > aop->size");
2086 /* will assign value to value */
2087 /* depending on where it is ofcourse */
2088 switch (aop->type) {
2091 sprintf(d,"(%s + %d)",
2092 aop->aopu.aop_dir,offset);
2093 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2096 sprintf(d,"%s",aop->aopu.aop_dir);
2099 DEBUGpic16_emitcode(";","%d",__LINE__);
2101 pic16_emitcode("movf","%s,w",s);
2102 pic16_emitcode("movwf","%s",d);
2105 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2106 if(offset >= aop->size) {
2107 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2110 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2113 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2120 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2121 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2124 strcmp(s,"r0") == 0 ||
2125 strcmp(s,"r1") == 0 ||
2126 strcmp(s,"r2") == 0 ||
2127 strcmp(s,"r3") == 0 ||
2128 strcmp(s,"r4") == 0 ||
2129 strcmp(s,"r5") == 0 ||
2130 strcmp(s,"r6") == 0 ||
2131 strcmp(s,"r7") == 0 )
2132 pic16_emitcode("mov","%s,%s ; %d",
2133 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2137 if(strcmp(s,"W")==0 )
2138 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2140 pic16_emitcode("movwf","%s",
2141 aop->aopu.aop_reg[offset]->name);
2143 if(strcmp(s,zero)==0) {
2144 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2146 } else if(strcmp(s,"W")==0) {
2147 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2148 pcop->type = PO_GPR_REGISTER;
2150 PCOR(pcop)->rIdx = -1;
2151 PCOR(pcop)->r = NULL;
2153 DEBUGpic16_emitcode(";","%d",__LINE__);
2154 pcop->name = Safe_strdup(s);
2155 pic16_emitpcode(POC_MOVFW,pcop);
2156 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2157 } else if(strcmp(s,one)==0) {
2158 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2159 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2161 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2169 if (aop->type == AOP_DPTR2)
2175 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2176 "pic16_aopPut writting to code space");
2180 while (offset > aop->coff) {
2182 pic16_emitcode ("inc","dptr");
2185 while (offset < aop->coff) {
2187 pic16_emitcode("lcall","__decdptr");
2192 /* if not in accumulater */
2195 pic16_emitcode ("movx","@dptr,a");
2197 if (aop->type == AOP_DPTR2)
2205 while (offset > aop->coff) {
2207 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2209 while (offset < aop->coff) {
2211 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2217 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2222 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2224 if (strcmp(s,"r0") == 0 ||
2225 strcmp(s,"r1") == 0 ||
2226 strcmp(s,"r2") == 0 ||
2227 strcmp(s,"r3") == 0 ||
2228 strcmp(s,"r4") == 0 ||
2229 strcmp(s,"r5") == 0 ||
2230 strcmp(s,"r6") == 0 ||
2231 strcmp(s,"r7") == 0 ) {
2233 sprintf(buffer,"a%s",s);
2234 pic16_emitcode("mov","@%s,%s",
2235 aop->aopu.aop_ptr->name,buffer);
2237 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2242 if (strcmp(s,"a") == 0)
2243 pic16_emitcode("push","acc");
2245 pic16_emitcode("push","%s",s);
2250 /* if bit variable */
2251 if (!aop->aopu.aop_dir) {
2252 pic16_emitcode("clr","a");
2253 pic16_emitcode("rlc","a");
2256 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2259 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2262 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2264 lbl = newiTempLabel(NULL);
2266 if (strcmp(s,"a")) {
2269 pic16_emitcode("clr","c");
2270 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2271 pic16_emitcode("cpl","c");
2272 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2273 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2280 if (strcmp(aop->aopu.aop_str[offset],s))
2281 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2286 if (!offset && (strcmp(s,"acc") == 0))
2289 if (strcmp(aop->aopu.aop_str[offset],s))
2290 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2294 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2295 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2296 // "pic16_aopPut got unsupported aop->type");
2302 /*-----------------------------------------------------------------*/
2303 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2304 /*-----------------------------------------------------------------*/
2305 void pic16_mov2w (asmop *aop, int offset)
2307 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2310 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2312 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2315 static void mov2f(asmop *dst, asmop *src, int offset)
2317 if(is_LitAOp(src)) {
2318 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2319 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2321 if(pic16_sameRegsOfs(src, dst, offset))return;
2322 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2323 pic16_popGet(dst, offset)));
2327 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2329 if(is_LitAOp(src)) {
2330 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2331 pic16_emitpcode(POC_MOVWF, dst);
2333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2337 void pic16_testStackOverflow(void)
2339 #define GSTACK_TEST_NAME "__gstack_test"
2341 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2346 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2347 strcpy(sym->rname, GSTACK_TEST_NAME);
2348 checkAddSym(&externs, sym);
2353 /* push pcop into stack */
2354 void pic16_pushpCodeOp(pCodeOp *pcop)
2356 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2357 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2358 if(pic16_options.gstack)
2359 pic16_testStackOverflow();
2363 /* pop pcop from stack */
2364 void pic16_poppCodeOp(pCodeOp *pcop)
2366 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2367 if(pic16_options.gstack)
2368 pic16_testStackOverflow();
2372 /*-----------------------------------------------------------------*/
2373 /* pushw - pushes wreg to stack */
2374 /*-----------------------------------------------------------------*/
2377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2378 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2379 if(pic16_options.gstack)
2380 pic16_testStackOverflow();
2384 /*-----------------------------------------------------------------*/
2385 /* pushaop - pushes aop to stack */
2386 /*-----------------------------------------------------------------*/
2387 void pushaop(asmop *aop, int offset)
2389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2391 if(is_LitAOp(aop)) {
2392 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2393 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2395 pic16_emitpcode(POC_MOVFF,
2396 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2399 if(pic16_options.gstack)
2400 pic16_testStackOverflow();
2403 /*-----------------------------------------------------------------*/
2404 /* popaop - pops aop from stack */
2405 /*-----------------------------------------------------------------*/
2406 void popaop(asmop *aop, int offset)
2408 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2409 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2410 if(pic16_options.gstack)
2411 pic16_testStackOverflow();
2414 void popaopidx(asmop *aop, int offset, int index)
2418 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2420 if(STACK_MODEL_LARGE)ofs++;
2422 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2423 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2424 if(pic16_options.gstack)
2425 pic16_testStackOverflow();
2428 #if !(USE_GENERIC_SIGNED_SHIFT)
2429 /*-----------------------------------------------------------------*/
2430 /* reAdjustPreg - points a register back to where it should */
2431 /*-----------------------------------------------------------------*/
2432 static void reAdjustPreg (asmop *aop)
2436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2438 if ((size = aop->size) <= 1)
2441 switch (aop->type) {
2445 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2449 if (aop->type == AOP_DPTR2)
2455 pic16_emitcode("lcall","__decdptr");
2458 if (aop->type == AOP_DPTR2)
2470 /*-----------------------------------------------------------------*/
2471 /* opIsGptr: returns non-zero if the passed operand is */
2472 /* a generic pointer type. */
2473 /*-----------------------------------------------------------------*/
2474 static int opIsGptr(operand *op)
2476 sym_link *type = operandType(op);
2478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2479 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2487 /*-----------------------------------------------------------------*/
2488 /* pic16_getDataSize - get the operand data size */
2489 /*-----------------------------------------------------------------*/
2490 int pic16_getDataSize(operand *op)
2492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2495 return AOP_SIZE(op);
2497 // tsd- in the pic port, the genptr size is 1, so this code here
2498 // fails. ( in the 8051 port, the size was 4).
2501 size = AOP_SIZE(op);
2502 if (size == GPTRSIZE)
2504 sym_link *type = operandType(op);
2505 if (IS_GENPTR(type))
2507 /* generic pointer; arithmetic operations
2508 * should ignore the high byte (pointer type).
2511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2518 /*-----------------------------------------------------------------*/
2519 /* pic16_outAcc - output Acc */
2520 /*-----------------------------------------------------------------*/
2521 void pic16_outAcc(operand *result)
2524 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2525 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2528 size = pic16_getDataSize(result);
2530 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2533 /* unsigned or positive */
2535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2540 /*-----------------------------------------------------------------*/
2541 /* pic16_outBitC - output a bit C */
2542 /* Move to result the value of Carry flag -- VR */
2543 /*-----------------------------------------------------------------*/
2544 void pic16_outBitC(operand *result)
2548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2550 /* if the result is bit */
2551 if (AOP_TYPE(result) == AOP_CRY) {
2552 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2553 pic16_aopPut(AOP(result),"c",0);
2556 i = AOP_SIZE(result);
2558 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2560 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2564 /*-----------------------------------------------------------------*/
2565 /* pic16_outBitOp - output a bit from Op */
2566 /* Move to result the value of set/clr op -- VR */
2567 /*-----------------------------------------------------------------*/
2568 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2574 /* if the result is bit */
2575 if (AOP_TYPE(result) == AOP_CRY) {
2576 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2577 pic16_aopPut(AOP(result),"c",0);
2580 i = AOP_SIZE(result);
2582 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2584 pic16_emitpcode(POC_RRCF, pcop);
2585 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2591 /*-----------------------------------------------------------------*/
2592 void pic16_toBoolean(operand *oper)
2594 int size = AOP_SIZE(oper) - 1;
2597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2599 if ( AOP_TYPE(oper) != AOP_ACC) {
2600 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2603 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2608 #if !defined(GEN_Not)
2609 /*-----------------------------------------------------------------*/
2610 /* genNot - generate code for ! operation */
2611 /*-----------------------------------------------------------------*/
2612 static void pic16_genNot (iCode *ic)
2618 /* assign asmOps to operand & result */
2619 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2620 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2622 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2623 /* if in bit space then a special case */
2624 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2625 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2626 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2627 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2629 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2630 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2631 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2636 size = AOP_SIZE(IC_LEFT(ic));
2638 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2639 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2640 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2643 pic16_toBoolean(IC_LEFT(ic));
2645 tlbl = newiTempLabel(NULL);
2646 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2647 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2648 pic16_outBitC(IC_RESULT(ic));
2651 /* release the aops */
2652 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2653 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2658 #if !defined(GEN_Cpl)
2659 /*-----------------------------------------------------------------*/
2660 /* genCpl - generate code for complement */
2661 /*-----------------------------------------------------------------*/
2662 static void pic16_genCpl (iCode *ic)
2668 /* assign asmOps to operand & result */
2669 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2670 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2672 /* if both are in bit space then
2674 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2675 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2677 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2678 pic16_emitcode("cpl","c");
2679 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2683 size = AOP_SIZE(IC_RESULT(ic));
2686 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2688 pic16_emitcode("cpl","a");
2689 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2691 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2692 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2694 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2703 /* release the aops */
2704 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2705 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2709 /*-----------------------------------------------------------------*/
2710 /* genUminusFloat - unary minus for floating points */
2711 /*-----------------------------------------------------------------*/
2712 static void genUminusFloat(operand *op,operand *result)
2714 int size ,offset =0 ;
2717 /* for this we just need to flip the
2718 first it then copy the rest in place */
2719 size = AOP_SIZE(op);
2722 mov2f(AOP(result), AOP(op), offset);
2726 /* toggle the MSB's highest bit */
2727 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2730 /*-----------------------------------------------------------------*/
2731 /* genUminus - unary minus code generation */
2732 /*-----------------------------------------------------------------*/
2733 static void genUminus (iCode *ic)
2736 sym_link *optype, *rtype;
2743 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2744 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2746 /* if both in bit space then special case */
2747 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2748 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2750 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2751 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2752 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2756 optype = operandType(IC_LEFT(ic));
2757 rtype = operandType(IC_RESULT(ic));
2759 /* if float then do float stuff */
2760 if (IS_FLOAT(optype)) {
2761 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2765 /* otherwise subtract from zero by taking the 2's complement */
2766 size = AOP_SIZE(IC_LEFT(ic));
2767 label = newiTempLabel ( NULL );
2769 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2770 for (i=size-1; i > 0; i--) {
2771 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2773 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2774 for (i=1; i < size; i++) {
2775 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2776 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2779 for (i=size-1; i >= 0; i--) {
2780 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2781 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2784 for (i=0; i < size-2; i++) {
2785 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2786 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2788 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2790 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2793 pic16_emitpLabel (label->key);
2796 /* release the aops */
2797 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2798 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2802 /*-----------------------------------------------------------------*/
2803 /* saveRegisters - will look for a call and save the registers */
2804 /*-----------------------------------------------------------------*/
2805 static void saveRegisters(iCode *lic)
2812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2814 for (ic = lic ; ic ; ic = ic->next)
2815 if (ic->op == CALL || ic->op == PCALL)
2819 fprintf(stderr,"found parameter push with no function call\n");
2823 /* if the registers have been saved already then
2825 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2828 /* find the registers in use at this time
2829 and push them away to safety */
2830 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2834 if (options.useXstack) {
2835 if (bitVectBitValue(rsave,R0_IDX))
2836 pic16_emitcode("mov","b,r0");
2837 pic16_emitcode("mov","r0,%s",spname);
2838 for (i = 0 ; i < pic16_nRegs ; i++) {
2839 if (bitVectBitValue(rsave,i)) {
2841 pic16_emitcode("mov","a,b");
2843 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2844 pic16_emitcode("movx","@r0,a");
2845 pic16_emitcode("inc","r0");
2848 pic16_emitcode("mov","%s,r0",spname);
2849 if (bitVectBitValue(rsave,R0_IDX))
2850 pic16_emitcode("mov","r0,b");
2852 //for (i = 0 ; i < pic16_nRegs ; i++) {
2853 // if (bitVectBitValue(rsave,i))
2854 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2857 dtype = operandType(IC_LEFT(ic));
2858 if (currFunc && dtype &&
2859 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2860 IFFUNC_ISISR(currFunc->type) &&
2863 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2866 /*-----------------------------------------------------------------*/
2867 /* unsaveRegisters - pop the pushed registers */
2868 /*-----------------------------------------------------------------*/
2869 static void unsaveRegisters (iCode *ic)
2874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2875 /* find the registers in use at this time
2876 and push them away to safety */
2877 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2880 if (options.useXstack) {
2881 pic16_emitcode("mov","r0,%s",spname);
2882 for (i = pic16_nRegs ; i >= 0 ; i--) {
2883 if (bitVectBitValue(rsave,i)) {
2884 pic16_emitcode("dec","r0");
2885 pic16_emitcode("movx","a,@r0");
2887 pic16_emitcode("mov","b,a");
2889 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2893 pic16_emitcode("mov","%s,r0",spname);
2894 if (bitVectBitValue(rsave,R0_IDX))
2895 pic16_emitcode("mov","r0,b");
2897 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2898 // if (bitVectBitValue(rsave,i))
2899 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2906 /*-----------------------------------------------------------------*/
2908 /*-----------------------------------------------------------------*/
2909 static void pushSide(operand * oper, int size)
2912 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2914 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2915 if (AOP_TYPE(oper) != AOP_REG &&
2916 AOP_TYPE(oper) != AOP_DIR &&
2918 pic16_emitcode("mov","a,%s",l);
2919 pic16_emitcode("push","acc");
2921 pic16_emitcode("push","%s",l);
2926 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2928 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2929 pic16_emitpcode(POC_MOVFW, src);
2930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2932 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2933 src, pic16_popGet(AOP(op), offset)));
2938 /*-----------------------------------------------------------------*/
2939 /* assignResultValue - assign results to oper, rescall==1 is */
2940 /* called from genCall() or genPcall() */
2941 /*-----------------------------------------------------------------*/
2942 static void assignResultValue(operand * oper, int rescall)
2944 int size = AOP_SIZE(oper);
2948 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2949 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2952 /* assign result from a call/pcall function() */
2954 /* function results are stored in a special order,
2955 * see top of file with Function return policy, or manual */
2958 /* 8-bits, result in WREG */
2959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2962 /* 16-bits, result in PRODL:WREG */
2963 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2967 /* 24-bits, result in PRODH:PRODL:WREG */
2968 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2972 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2973 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2977 /* >32-bits, result on stack, and FSR0 points to beginning.
2978 * Fix stack when done */
2980 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2982 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2983 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2985 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2990 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2991 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2992 if(STACK_MODEL_LARGE) {
2994 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2998 int areg = 0; /* matching argument register */
3000 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3001 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3004 /* its called from genReceive (probably) -- VR */
3005 /* I hope this code will not be called from somewhere else in the future!
3006 * We manually set the pseudo stack pointer in genReceive. - dw
3008 if(!GpsuedoStkPtr && _G.useWreg) {
3009 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3011 /* The last byte in the assignment is in W */
3012 if(areg <= GpsuedoStkPtr) {
3014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3016 // debugf("receive from WREG\n", 0);
3018 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3021 _G.stack_lat = AOP_SIZE(oper)-1;
3026 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3027 // debugf("receive from STACK\n", 0);
3034 /*-----------------------------------------------------------------*/
3035 /* genIpush - generate code for pushing this gets a little complex */
3036 /*-----------------------------------------------------------------*/
3037 static void genIpush (iCode *ic)
3039 // int size, offset=0;
3042 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3045 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3047 /* send to stack as normal */
3048 addSet(&_G.sendSet,ic);
3049 // addSetHead(&_G.sendSet,ic);
3050 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3055 int size, offset = 0 ;
3059 /* if this is not a parm push : ie. it is spill push
3060 and spill push is always done on the local stack */
3061 if (!ic->parmPush) {
3063 /* and the item is spilt then do nothing */
3064 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3067 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3068 size = AOP_SIZE(IC_LEFT(ic));
3069 /* push it on the stack */
3071 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3076 pic16_emitcode("push","%s",l);
3081 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3085 /*-----------------------------------------------------------------*/
3086 /* genIpop - recover the registers: can happen only for spilling */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpop (iCode *ic)
3091 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3096 /* if the temp was not pushed then */
3097 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3100 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3101 size = AOP_SIZE(IC_LEFT(ic));
3104 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3107 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3112 /*-----------------------------------------------------------------*/
3113 /* unsaverbank - restores the resgister bank from stack */
3114 /*-----------------------------------------------------------------*/
3115 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3117 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3125 if (options.useXstack) {
3127 r = getFreePtr(ic,&aop,FALSE);
3130 pic16_emitcode("mov","%s,_spx",r->name);
3131 pic16_emitcode("movx","a,@%s",r->name);
3132 pic16_emitcode("mov","psw,a");
3133 pic16_emitcode("dec","%s",r->name);
3136 pic16_emitcode ("pop","psw");
3139 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3140 if (options.useXstack) {
3141 pic16_emitcode("movx","a,@%s",r->name);
3142 //pic16_emitcode("mov","(%s+%d),a",
3143 // regspic16[i].base,8*bank+regspic16[i].offset);
3144 pic16_emitcode("dec","%s",r->name);
3147 pic16_emitcode("pop",""); //"(%s+%d)",
3148 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3151 if (options.useXstack) {
3153 pic16_emitcode("mov","_spx,%s",r->name);
3154 pic16_freeAsmop(NULL,aop,ic,TRUE);
3160 /*-----------------------------------------------------------------*/
3161 /* saverbank - saves an entire register bank on the stack */
3162 /*-----------------------------------------------------------------*/
3163 static void saverbank (int bank, iCode *ic, bool pushPsw)
3165 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3172 if (options.useXstack) {
3175 r = getFreePtr(ic,&aop,FALSE);
3176 pic16_emitcode("mov","%s,_spx",r->name);
3180 for (i = 0 ; i < pic16_nRegs ;i++) {
3181 if (options.useXstack) {
3182 pic16_emitcode("inc","%s",r->name);
3183 //pic16_emitcode("mov","a,(%s+%d)",
3184 // regspic16[i].base,8*bank+regspic16[i].offset);
3185 pic16_emitcode("movx","@%s,a",r->name);
3187 pic16_emitcode("push","");// "(%s+%d)",
3188 //regspic16[i].base,8*bank+regspic16[i].offset);
3192 if (options.useXstack) {
3193 pic16_emitcode("mov","a,psw");
3194 pic16_emitcode("movx","@%s,a",r->name);
3195 pic16_emitcode("inc","%s",r->name);
3196 pic16_emitcode("mov","_spx,%s",r->name);
3197 pic16_freeAsmop (NULL,aop,ic,TRUE);
3200 pic16_emitcode("push","psw");
3202 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3210 static int wparamCmp(void *p1, void *p2)
3212 return (!strcmp((char *)p1, (char *)p2));
3215 int inWparamList(char *s)
3217 return isinSetWith(wparamList, s, wparamCmp);
3221 /*-----------------------------------------------------------------*/
3222 /* genCall - generates a call statement */
3223 /*-----------------------------------------------------------------*/
3224 static void genCall (iCode *ic)
3234 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3235 /* if caller saves & we have not saved then */
3236 // if (!ic->regsSaved)
3237 // saveRegisters(ic);
3239 /* initialise stackParms for IPUSH pushes */
3240 // stackParms = psuedoStkPtr;
3241 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3242 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3243 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3246 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3249 /* if send set is not empty the assign */
3252 int psuedoStkPtr=-1;
3253 int firstTimeThruLoop = 1;
3256 /* reverse sendSet if function is not reentrant */
3257 if(!IFFUNC_ISREENT(ftype))
3258 _G.sendSet = reverseSet(_G.sendSet);
3260 /* First figure how many parameters are getting passed */
3264 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3268 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3269 size = AOP_SIZE(IC_LEFT(sic));
3273 /* pass the last byte through WREG */
3277 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3278 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3279 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3281 if(!firstTimeThruLoop) {
3282 /* If this is not the first time we've been through the loop
3283 * then we need to save the parameter in a temporary
3284 * register. The last byte of the last parameter is
3288 // --psuedoStkPtr; // sanity check
3292 firstTimeThruLoop=0;
3294 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3299 /* all arguments are passed via stack */
3303 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3304 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3305 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3307 // pushaop(AOP(IC_LEFT(sic)), size);
3308 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3313 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3317 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3318 pushw(); /* save last parameter to stack if functions has varargs */
3322 } else use_wreg = 0;
3324 _G.stackRegSet = _G.sendSet;
3329 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3333 /* if we need to assign a result value */
3334 if ((IS_ITEMP(IC_RESULT(ic))
3335 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3336 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3337 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3340 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3343 assignResultValue(IC_RESULT(ic), 1);
3345 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3348 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3351 if(!stackParms && ic->parmBytes) {
3352 stackParms = ic->parmBytes;
3355 stackParms -= use_wreg;
3358 if(stackParms == 1) {
3359 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3361 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3362 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3364 if(STACK_MODEL_LARGE) {
3366 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3371 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3374 /* adjust the stack for parameters if required */
3375 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3378 /* if register bank was saved then pop them */
3380 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3382 /* if we hade saved some registers then unsave them */
3383 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3384 unsaveRegisters (ic);
3390 /*-----------------------------------------------------------------*/
3391 /* genPcall - generates a call by pointer statement */
3392 /* new version, created from genCall - HJD */
3393 /*-----------------------------------------------------------------*/
3394 static void genPcall (iCode *ic)
3396 sym_link *ftype, *fntype;
3398 symbol *retlbl = newiTempLabel(NULL);
3399 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3403 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3404 fntype = operandType( IC_LEFT(ic) )->next;
3406 /* if send set is not empty the assign */
3409 int psuedoStkPtr=-1;
3411 /* reverse sendSet if function is not reentrant */
3412 if(!IFFUNC_ISREENT(fntype))
3413 _G.sendSet = reverseSet(_G.sendSet);
3417 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3420 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3421 size = AOP_SIZE(IC_LEFT(sic));
3424 /* all parameters are passed via stack, since WREG is clobbered
3425 * by the calling sequence */
3427 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3428 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3429 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3431 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3435 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3438 _G.stackRegSet = _G.sendSet;
3442 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3444 // push return address
3445 // push $ on return stack, then replace with retlbl
3447 /* Thanks to Thorsten Klose for pointing out that the following
3448 * snippet should be interrupt safe */
3449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3450 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3452 pic16_emitpcodeNULLop(POC_PUSH);
3454 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3455 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3456 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3457 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3458 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3459 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3462 /* restore interrupt control register */
3463 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3464 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3466 /* make the call by writing the pointer into pc */
3467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3470 // note: MOVFF to PCL not allowed
3471 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3472 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3475 /* return address is here: (X) */
3476 pic16_emitpLabelFORCE(retlbl->key);
3478 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3481 /* if we need assign a result value */
3482 if ((IS_ITEMP(IC_RESULT(ic))
3483 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3484 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3485 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3488 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3491 assignResultValue(IC_RESULT(ic), 1);
3493 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3494 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3496 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3499 // stackParms -= use_wreg;
3502 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3503 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3504 if(STACK_MODEL_LARGE) {
3506 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3511 /*-----------------------------------------------------------------*/
3512 /* resultRemat - result is rematerializable */
3513 /*-----------------------------------------------------------------*/
3514 static int resultRemat (iCode *ic)
3516 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3517 if (SKIP_IC(ic) || ic->op == IFX)
3520 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3521 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3522 if (sym->remat && !POINTER_SET(ic))
3529 #if defined(__BORLANDC__) || defined(_MSC_VER)
3530 #define STRCASECMP stricmp
3532 #define STRCASECMP strcasecmp
3536 /*-----------------------------------------------------------------*/
3537 /* inExcludeList - return 1 if the string is in exclude Reg list */
3538 /*-----------------------------------------------------------------*/
3539 static bool inExcludeList(char *s)
3541 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3545 if (options.excludeRegs[i] &&
3546 STRCASECMP(options.excludeRegs[i],"none") == 0)
3549 for ( i = 0 ; options.excludeRegs[i]; i++) {
3550 if (options.excludeRegs[i] &&
3551 STRCASECMP(s,options.excludeRegs[i]) == 0)
3558 /*-----------------------------------------------------------------*/
3559 /* genFunction - generated code for function entry */
3560 /*-----------------------------------------------------------------*/
3561 static void genFunction (iCode *ic)
3567 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3569 pic16_labelOffset += (max_key+4);
3574 ftype = operandType(IC_LEFT(ic));
3575 sym = OP_SYMBOL(IC_LEFT(ic));
3577 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3578 /* create an absolute section at the interrupt vector:
3579 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3585 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3591 sym = OP_SYMBOL( IC_LEFT(ic));
3593 if(interrupts[i]->name
3594 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3601 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3602 __FILE__, __LINE__, sym->name);
3605 _G.interruptvector = found;
3609 if(FUNC_INTNO(sym->type) == 256)
3610 sprintf(asymname, "ivec_%s", sym->name);
3612 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3613 asym = newSymbol(asymname, 0);
3615 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3616 pic16_addpBlock( apb );
3618 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3619 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3620 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3622 /* mark the end of this tiny function */
3623 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3628 abSym = Safe_calloc(1, sizeof(absSym));
3629 strcpy(abSym->name, asymname);
3631 switch( FUNC_INTNO(sym->type) ) {
3632 case 0: abSym->address = 0x000000; break;
3633 case 1: abSym->address = 0x000008; break;
3634 case 2: abSym->address = 0x000018; break;
3637 abSym->address = -1; break;
3640 /* relocate interrupt vectors if needed */
3641 if(abSym->address != -1)
3642 abSym->address += pic16_options.ivt_loc;
3644 addSet(&absSymSet, abSym);
3648 /* create the function header */
3649 pic16_emitcode(";","-----------------------------------------");
3650 pic16_emitcode(";"," function %s",sym->name);
3651 pic16_emitcode(";","-----------------------------------------");
3653 pic16_emitcode("","%s:",sym->rname);
3654 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3660 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3661 if(!strcmp(ab->name, sym->rname)) {
3662 pic16_pBlockConvert2Absolute(pb);
3669 if(IFFUNC_ISNAKED(ftype)) {
3670 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3674 /* if critical function then turn interrupts off */
3675 if (IFFUNC_ISCRITICAL(ftype)) {
3676 //pic16_emitcode("clr","ea");
3679 _G.fregsUsed = sym->regsUsed;
3681 /* if this is an interrupt service routine then
3682 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3683 if (IFFUNC_ISISR(sym->type)) {
3684 _G.usefastretfie = 1; /* use shadow registers by default */
3686 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3687 if(!FUNC_ISSHADOWREGS(sym->type)) {
3688 /* do not save WREG,STATUS,BSR for high priority interrupts
3689 * because they are stored in the hardware shadow registers already */
3690 _G.usefastretfie = 0;
3691 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3692 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3693 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3696 /* these should really be optimized somehow, because not all
3697 * interrupt handlers modify them */
3698 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3699 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3700 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3701 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3703 // pic16_pBlockConvert2ISR(pb);
3707 /* emit code to setup stack frame if user enabled,
3708 * and function is not main() */
3710 //fprintf(stderr, "function name: %s\n", sym->name);
3711 if(strcmp(sym->name, "main")) {
3712 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3713 /* setup the stack frame */
3714 if(STACK_MODEL_LARGE)
3715 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3716 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3718 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3719 if(STACK_MODEL_LARGE)
3720 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3724 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3727 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3729 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3730 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3732 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3735 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3736 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3743 /* if callee-save to be used for this function
3744 * then save the registers being used in this function */
3745 // if (IFFUNC_CALLEESAVES(sym->type))
3749 /* if any registers used */
3750 if (sym->regsUsed) {
3751 /* save the registers used */
3752 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3753 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3754 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3755 if (bitVectBitValue(sym->regsUsed,i)) {
3756 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3759 if(!pic16_regWithIdx(i)->wasUsed) {
3760 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3761 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3762 pic16_regWithIdx(i)->wasUsed = 1;
3766 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3770 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3771 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3774 /*-----------------------------------------------------------------*/
3775 /* genEndFunction - generates epilogue for functions */
3776 /*-----------------------------------------------------------------*/
3777 static void genEndFunction (iCode *ic)
3779 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3783 if(IFFUNC_ISNAKED(sym->type)) {
3784 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3790 /* add code for ISCRITICAL */
3791 if(IFFUNC_ISCRITICAL(sym->type)) {
3792 /* if critical function, turn on interrupts */
3794 /* TODO: add code here -- VR */
3797 // sym->regsUsed = _G.fregsUsed;
3799 /* now we need to restore the registers */
3800 /* if any registers used */
3801 if (sym->regsUsed) {
3804 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3805 /* restore registers used */
3806 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3807 for ( i = sym->regsUsed->size; i >= 0; i--) {
3808 if (bitVectBitValue(sym->regsUsed,i)) {
3809 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3813 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3817 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3819 if (sym->stack == 1) {
3820 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3821 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3823 // we have to add more than one...
3824 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3825 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3826 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3828 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3829 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3830 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3834 if(strcmp(sym->name, "main")) {
3835 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3836 /* restore stack frame */
3837 if(STACK_MODEL_LARGE)
3838 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3839 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3845 if (IFFUNC_ISISR(sym->type)) {
3846 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3847 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3848 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3849 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3851 if(!FUNC_ISSHADOWREGS(sym->type)) {
3852 /* do not restore interrupt vector for WREG,STATUS,BSR
3853 * for high priority interrupt, see genFunction */
3854 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3855 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3856 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3858 // _G.interruptvector = 0; /* sanity check */
3861 /* if debug then send end of function */
3862 /* if (options.debug && currFunc) */
3864 debugFile->writeEndFunction (currFunc, ic, 1);
3867 if(_G.usefastretfie)
3868 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3870 pic16_emitpcodeNULLop(POC_RETFIE);
3872 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3874 _G.usefastretfie = 0;
3878 if (IFFUNC_ISCRITICAL(sym->type)) {
3879 pic16_emitcode("setb","ea");
3882 /* if debug then send end of function */
3884 debugFile->writeEndFunction (currFunc, ic, 1);
3887 /* insert code to restore stack frame, if user enabled it
3888 * and function is not main() */
3891 pic16_emitpcodeNULLop(POC_RETURN);
3893 /* Mark the end of a function */
3894 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3898 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3900 unsigned long lit=1;
3902 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3903 if(AOP_TYPE(op) == AOP_LIT) {
3904 if(!IS_FLOAT(operandType( op ))) {
3905 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3908 unsigned long lit_int;
3912 /* take care if literal is a float */
3913 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3920 pic16_emitpcode(POC_CLRF, dest);
3922 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3923 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3926 if(dest->type == PO_WREG && (offset == 0)) {
3927 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3930 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3934 /*-----------------------------------------------------------------*/
3935 /* genRet - generate code for return statement */
3936 /*-----------------------------------------------------------------*/
3937 static void genRet (iCode *ic)
3943 /* if we have no return value then
3944 * just generate the "ret" */
3949 /* we have something to return then
3950 * move the return value into place */
3951 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3952 size = AOP_SIZE(IC_LEFT(ic));
3956 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3957 // pic16_emitpcode(POC_MOVFF,
3958 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3961 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3962 // pic16_emitpcode(POC_MOVFF,
3963 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3966 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3967 // pic16_emitpcode(POC_MOVFF,
3968 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3971 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3973 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3974 // pic16_emitpcode(POC_MOVFF,
3975 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3978 /* >32-bits, setup stack and FSR0 */
3980 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3981 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3983 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3985 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3990 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3991 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3993 if(STACK_MODEL_LARGE) {
3994 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3995 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3997 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4002 /* old code, left here for reference -- VR */
4006 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4008 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4009 pic16_emitpcomment("push %s",l);
4012 DEBUGpic16_emitcode(";", "%d", __LINE__);
4013 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4014 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4016 if (strcmp(fReturn[offset],l)) {
4017 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4018 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4019 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4021 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4025 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4035 if (strcmp(fReturn[pushed],"a"))
4036 pic16_emitcode("pop",fReturn[pushed]);
4038 pic16_emitcode("pop","acc");
4044 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4047 /* generate a jump to the return label
4048 * if the next is not the return statement */
4049 if (!(ic->next && ic->next->op == LABEL
4050 && IC_LABEL(ic->next) == returnLabel)) {
4052 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4053 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4057 /*-----------------------------------------------------------------*/
4058 /* genLabel - generates a label */
4059 /*-----------------------------------------------------------------*/
4060 static void genLabel (iCode *ic)
4064 /* special case never generate */
4065 if (IC_LABEL(ic) == entryLabel)
4068 pic16_emitpLabel(IC_LABEL(ic)->key);
4069 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4072 /*-----------------------------------------------------------------*/
4073 /* genGoto - generates a goto */
4074 /*-----------------------------------------------------------------*/
4076 static void genGoto (iCode *ic)
4079 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4080 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4084 /*-----------------------------------------------------------------*/
4085 /* genMultbits :- multiplication of bits */
4086 /*-----------------------------------------------------------------*/
4087 static void genMultbits (operand *left,
4093 if(!pic16_sameRegs(AOP(result),AOP(right)))
4094 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4096 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4097 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4098 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4103 /*-----------------------------------------------------------------*/
4104 /* genMultOneByte : 8 bit multiplication & division */
4105 /*-----------------------------------------------------------------*/
4106 static void genMultOneByte (operand *left,
4112 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4113 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4115 /* (if two literals, the value is computed before) */
4116 /* if one literal, literal on the right */
4117 if (AOP_TYPE(left) == AOP_LIT){
4123 /* size is already checked in genMult == 1 */
4124 // size = AOP_SIZE(result);
4126 if (AOP_TYPE(right) == AOP_LIT){
4127 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4128 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4129 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4130 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4132 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4133 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4134 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4135 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4138 pic16_genMult8X8_8 (left, right,result);
4141 /*-----------------------------------------------------------------*/
4142 /* genMultOneWord : 16 bit multiplication */
4143 /*-----------------------------------------------------------------*/
4144 static void genMultOneWord (operand *left,
4149 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4150 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4152 /* (if two literals, the value is computed before)
4153 * if one literal, literal on the right */
4154 if (AOP_TYPE(left) == AOP_LIT){
4160 /* size is checked already == 2 */
4161 // size = AOP_SIZE(result);
4163 if (AOP_TYPE(right) == AOP_LIT) {
4164 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4165 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4166 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4167 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4169 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4170 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4171 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4172 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4175 pic16_genMult16X16_16(left, right,result);
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneLong : 32 bit multiplication */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneLong (operand *left,
4186 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4187 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4189 /* (if two literals, the value is computed before)
4190 * if one literal, literal on the right */
4191 if (AOP_TYPE(left) == AOP_LIT){
4197 /* size is checked already == 4 */
4198 // size = AOP_SIZE(result);
4200 if (AOP_TYPE(right) == AOP_LIT) {
4201 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4202 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4203 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4204 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4206 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4207 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212 pic16_genMult32X32_32(left, right,result);
4217 /*-----------------------------------------------------------------*/
4218 /* genMult - generates code for multiplication */
4219 /*-----------------------------------------------------------------*/
4220 static void genMult (iCode *ic)
4222 operand *left = IC_LEFT(ic);
4223 operand *right = IC_RIGHT(ic);
4224 operand *result= IC_RESULT(ic);
4227 /* assign the amsops */
4228 pic16_aopOp (left,ic,FALSE);
4229 pic16_aopOp (right,ic,FALSE);
4230 pic16_aopOp (result,ic,TRUE);
4232 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4234 /* special cases first *
4236 if (AOP_TYPE(left) == AOP_CRY
4237 && AOP_TYPE(right)== AOP_CRY) {
4238 genMultbits(left,right,result);
4242 /* if both are of size == 1 */
4243 if(AOP_SIZE(left) == 1
4244 && AOP_SIZE(right) == 1) {
4245 genMultOneByte(left,right,result);
4249 /* if both are of size == 2 */
4250 if(AOP_SIZE(left) == 2
4251 && AOP_SIZE(right) == 2) {
4252 genMultOneWord(left, right, result);
4256 /* if both are of size == 4 */
4257 if(AOP_SIZE(left) == 4
4258 && AOP_SIZE(right) == 4) {
4259 genMultOneLong(left, right, result);
4263 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4266 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4267 /* should have been converted to function call */
4271 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273 pic16_freeAsmop(result,NULL,ic,TRUE);
4276 /*-----------------------------------------------------------------*/
4277 /* genDivbits :- division of bits */
4278 /*-----------------------------------------------------------------*/
4279 static void genDivbits (operand *left,
4286 /* the result must be bit */
4287 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4288 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4292 pic16_emitcode("div","ab");
4293 pic16_emitcode("rrc","a");
4294 pic16_aopPut(AOP(result),"c",0);
4297 /*-----------------------------------------------------------------*/
4298 /* genDivOneByte : 8 bit division */
4299 /*-----------------------------------------------------------------*/
4300 static void genDivOneByte (operand *left,
4304 sym_link *opetype = operandType(result);
4309 /* result = divident / divisor
4310 * - divident may be a register or a literal,
4311 * - divisor may be a register or a literal,
4312 * so there are 3 cases (literal / literal is optimized
4313 * by the front-end) to handle.
4314 * In addition we must handle signed and unsigned, which
4315 * result in 6 final different cases -- VR */
4319 size = AOP_SIZE(result) - 1;
4321 /* signed or unsigned */
4322 if (SPEC_USIGN(opetype)) {
4323 pCodeOp *pct1, /* count */
4326 symbol *label1, *label2, *label3;;
4329 /* unsigned is easy */
4331 pct1 = pic16_popGetTempReg(1);
4332 pct2 = pic16_popGetTempReg(1);
4333 pct3 = pic16_popGetTempReg(1);
4335 label1 = newiTempLabel(NULL);
4336 label2 = newiTempLabel(NULL);
4337 label3 = newiTempLabel(NULL);
4339 /* the following algorithm is extracted from divuint.c */
4341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4342 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4344 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4346 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4348 pic16_emitpLabel(label1->key);
4351 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4355 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4359 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4361 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4362 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4364 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4365 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4366 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4368 pic16_emitpLabel( label3->key );
4369 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4370 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4374 pic16_emitpLabel(label2->key);
4375 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4376 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4377 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4379 /* result is in wreg */
4380 if(AOP_TYPE(result) != AOP_ACC)
4381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4383 pic16_popReleaseTempReg( pct3, 1);
4384 pic16_popReleaseTempReg( pct2, 1);
4385 pic16_popReleaseTempReg( pct1, 1);
4390 /* signed is a little bit more difficult */
4392 /* save the signs of the operands */
4393 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4395 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4396 pic16_emitcode("push","acc"); /* save it on the stack */
4398 /* now sign adjust for both left & right */
4399 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4401 lbl = newiTempLabel(NULL);
4402 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4403 pic16_emitcode("cpl","a");
4404 pic16_emitcode("inc","a");
4405 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4406 pic16_emitcode("mov","b,a");
4408 /* sign adjust left side */
4409 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4412 lbl = newiTempLabel(NULL);
4413 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4414 pic16_emitcode("cpl","a");
4415 pic16_emitcode("inc","a");
4416 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4418 /* now the division */
4419 pic16_emitcode("div","ab");
4420 /* we are interested in the lower order
4422 pic16_emitcode("mov","b,a");
4423 lbl = newiTempLabel(NULL);
4424 pic16_emitcode("pop","acc");
4425 /* if there was an over flow we don't
4426 adjust the sign of the result */
4427 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4428 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4430 pic16_emitcode("clr","a");
4431 pic16_emitcode("subb","a,b");
4432 pic16_emitcode("mov","b,a");
4433 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4435 /* now we are done */
4436 pic16_aopPut(AOP(result),"b",0);
4438 pic16_emitcode("mov","c,b.7");
4439 pic16_emitcode("subb","a,acc");
4442 pic16_aopPut(AOP(result),"a",offset++);
4446 /*-----------------------------------------------------------------*/
4447 /* genDiv - generates code for division */
4448 /*-----------------------------------------------------------------*/
4449 static void genDiv (iCode *ic)
4451 operand *left = IC_LEFT(ic);
4452 operand *right = IC_RIGHT(ic);
4453 operand *result= IC_RESULT(ic);
4456 /* Division is a very lengthy algorithm, so it is better
4457 * to call support routines than inlining algorithm.
4458 * Division functions written here just in case someone
4459 * wants to inline and not use the support libraries -- VR */
4463 /* assign the amsops */
4464 pic16_aopOp (left,ic,FALSE);
4465 pic16_aopOp (right,ic,FALSE);
4466 pic16_aopOp (result,ic,TRUE);
4468 /* special cases first */
4470 if (AOP_TYPE(left) == AOP_CRY &&
4471 AOP_TYPE(right)== AOP_CRY) {
4472 genDivbits(left,right,result);
4476 /* if both are of size == 1 */
4477 if (AOP_SIZE(left) == 1 &&
4478 AOP_SIZE(right) == 1 ) {
4479 genDivOneByte(left,right,result);
4483 /* should have been converted to function call */
4486 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488 pic16_freeAsmop(result,NULL,ic,TRUE);
4491 /*-----------------------------------------------------------------*/
4492 /* genModbits :- modulus of bits */
4493 /*-----------------------------------------------------------------*/
4494 static void genModbits (operand *left,
4502 werror(W_POSSBUG2, __FILE__, __LINE__);
4503 /* the result must be bit */
4504 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4505 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4509 pic16_emitcode("div","ab");
4510 pic16_emitcode("mov","a,b");
4511 pic16_emitcode("rrc","a");
4512 pic16_aopPut(AOP(result),"c",0);
4515 /*-----------------------------------------------------------------*/
4516 /* genModOneByte : 8 bit modulus */
4517 /*-----------------------------------------------------------------*/
4518 static void genModOneByte (operand *left,
4522 sym_link *opetype = operandType(result);
4527 werror(W_POSSBUG2, __FILE__, __LINE__);
4529 /* signed or unsigned */
4530 if (SPEC_USIGN(opetype)) {
4531 /* unsigned is easy */
4532 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4533 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4535 pic16_emitcode("div","ab");
4536 pic16_aopPut(AOP(result),"b",0);
4540 /* signed is a little bit more difficult */
4542 /* save the signs of the operands */
4543 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4546 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4547 pic16_emitcode("push","acc"); /* save it on the stack */
4549 /* now sign adjust for both left & right */
4550 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4553 lbl = newiTempLabel(NULL);
4554 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4555 pic16_emitcode("cpl","a");
4556 pic16_emitcode("inc","a");
4557 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4558 pic16_emitcode("mov","b,a");
4560 /* sign adjust left side */
4561 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4564 lbl = newiTempLabel(NULL);
4565 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4566 pic16_emitcode("cpl","a");
4567 pic16_emitcode("inc","a");
4568 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4570 /* now the multiplication */
4571 pic16_emitcode("div","ab");
4572 /* we are interested in the lower order
4574 lbl = newiTempLabel(NULL);
4575 pic16_emitcode("pop","acc");
4576 /* if there was an over flow we don't
4577 adjust the sign of the result */
4578 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4579 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4581 pic16_emitcode("clr","a");
4582 pic16_emitcode("subb","a,b");
4583 pic16_emitcode("mov","b,a");
4584 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4586 /* now we are done */
4587 pic16_aopPut(AOP(result),"b",0);
4591 /*-----------------------------------------------------------------*/
4592 /* genMod - generates code for division */
4593 /*-----------------------------------------------------------------*/
4594 static void genMod (iCode *ic)
4596 operand *left = IC_LEFT(ic);
4597 operand *right = IC_RIGHT(ic);
4598 operand *result= IC_RESULT(ic);
4602 /* assign the amsops */
4603 pic16_aopOp (left,ic,FALSE);
4604 pic16_aopOp (right,ic,FALSE);
4605 pic16_aopOp (result,ic,TRUE);
4607 /* special cases first */
4609 if (AOP_TYPE(left) == AOP_CRY &&
4610 AOP_TYPE(right)== AOP_CRY) {
4611 genModbits(left,right,result);
4615 /* if both are of size == 1 */
4616 if (AOP_SIZE(left) == 1 &&
4617 AOP_SIZE(right) == 1 ) {
4618 genModOneByte(left,right,result);
4622 /* should have been converted to function call */
4626 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4627 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628 pic16_freeAsmop(result,NULL,ic,TRUE);
4631 /*-----------------------------------------------------------------*/
4632 /* genIfxJump :- will create a jump depending on the ifx */
4633 /*-----------------------------------------------------------------*/
4635 note: May need to add parameter to indicate when a variable is in bit space.
4637 static void genIfxJump (iCode *ic, char *jval)
4641 /* if true label then we jump if condition
4643 if ( IC_TRUE(ic) ) {
4645 if(strcmp(jval,"a") == 0)
4647 else if (strcmp(jval,"c") == 0)
4650 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4651 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4654 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4655 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4659 /* false label is present */
4660 if(strcmp(jval,"a") == 0)
4662 else if (strcmp(jval,"c") == 0)
4665 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4666 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4669 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4670 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4675 /* mark the icode as generated */
4679 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4683 /* if true label then we jump if condition
4685 if ( IC_TRUE(ic) ) {
4686 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4687 pic16_emitpcode(POC_BTFSC, jop);
4689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4690 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4693 /* false label is present */
4694 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4695 pic16_emitpcode(POC_BTFSS, jop);
4697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4698 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4702 /* mark the icode as generated */
4709 /*-----------------------------------------------------------------*/
4711 /*-----------------------------------------------------------------*/
4712 static void genSkip(iCode *ifx,int status_bit)
4714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4718 if ( IC_TRUE(ifx) ) {
4719 switch(status_bit) {
4734 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4735 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4739 switch(status_bit) {
4753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4754 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4761 /*-----------------------------------------------------------------*/
4763 /*-----------------------------------------------------------------*/
4764 static void genSkipc(resolvedIfx *rifx)
4766 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4776 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4777 rifx->generated = 1;
4780 #if !(USE_SIMPLE_GENCMP)
4781 /*-----------------------------------------------------------------*/
4783 /*-----------------------------------------------------------------*/
4784 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4786 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4791 if( (rifx->condition ^ invert_condition) & 1)
4796 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4797 rifx->generated = 1;
4802 /*-----------------------------------------------------------------*/
4804 /*-----------------------------------------------------------------*/
4805 static void genSkipz(iCode *ifx, int condition)
4816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4818 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4821 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4823 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4828 #if !(USE_SIMPLE_GENCMP)
4829 /*-----------------------------------------------------------------*/
4831 /*-----------------------------------------------------------------*/
4832 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4838 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4840 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4843 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4844 rifx->generated = 1;
4849 /*-----------------------------------------------------------------*/
4850 /* genChkZeroes :- greater or less than comparison */
4851 /* For each byte in a literal that is zero, inclusive or the */
4852 /* the corresponding byte in the operand with W */
4853 /* returns true if any of the bytes are zero */
4854 /*-----------------------------------------------------------------*/
4855 static int genChkZeroes(operand *op, int lit, int size)
4862 i = (lit >> (size*8)) & 0xff;
4866 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4868 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4877 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4878 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4880 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4881 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4883 /*-----------------------------------------------------------------*/
4884 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4885 /* aop (if it's NOT a literal) or from lit (if */
4886 /* aop is a literal) */
4887 /*-----------------------------------------------------------------*/
4888 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4889 if (aop->type == AOP_LIT) {
4890 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4892 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4896 /*-----------------------------------------------------------------*/
4897 /* genCmp :- greater or less than comparison */
4898 /*-----------------------------------------------------------------*/
4900 #if USE_SIMPLE_GENCMP
4902 /* genCmp performs a left < right comparison, stores
4903 * the outcome in result (if != NULL) and generates
4904 * control flow code for the ifx (if != NULL).
4906 * This version leaves in sequences like
4907 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4908 * which should be optmized by the peephole
4909 * optimizer - RN 2005-01-01 */
4910 static void genCmp (operand *left,operand *right,
4911 operand *result, iCode *ifx, int sign)
4924 assert (AOP_SIZE(left) == AOP_SIZE(right));
4925 assert (left && right);
4927 size = AOP_SIZE(right) - 1;
4928 mask = (0x100UL << (size*8)) - 1;
4929 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4934 resolveIfx (&rIfx, ifx);
4936 /**********************************************************************
4937 * handle bits - bit compares are promoted to int compares seemingly! *
4938 **********************************************************************/
4940 // THIS IS COMPLETELY UNTESTED!
4941 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4942 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4943 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4944 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4947 // 1 < {0,1} is false --> clear C by skipping the next instruction
4948 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4949 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4950 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4951 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4952 emitCLRC; // only skipped for left=0 && right=1
4954 goto correct_result_in_carry;
4958 /*************************************************
4959 * make sure that left is register (or the like) *
4960 *************************************************/
4961 if (!isAOP_REGlike(left)) {
4962 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4963 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4965 assert (isAOP_LIT(left));
4966 assert (isAOP_REGlike(right));
4967 // swap left and right
4968 // left < right <==> right > left <==> (right >= left + 1)
4969 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4971 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4972 // MAXVALUE < right? always false
4973 if (performedLt) emitCLRC; else emitSETC;
4974 goto correct_result_in_carry;
4977 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4978 // that's we handled it above.
4985 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4986 } else if (isAOP_LIT(right)) {
4987 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4990 assert (isAOP_REGlike(left)); // left must be register or the like
4991 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4993 /*************************************************
4994 * special cases go here *
4995 *************************************************/
4997 if (isAOP_LIT(right)) {
4999 // unsigned comparison to a literal
5000 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5001 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5004 // unsigned left < 0? always false
5005 if (performedLt) emitCLRC; else emitSETC;
5006 goto correct_result_in_carry;
5009 // signed comparison to a literal
5010 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
5011 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5013 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5014 // signed left < 0x80000000? always false
5015 if (performedLt) emitCLRC; else emitSETC;
5016 goto correct_result_in_carry;
5017 } else if (lit == 0) {
5018 // compare left < 0; set CARRY if SIGNBIT(left) is set
5019 if (performedLt) emitSETC; else emitCLRC;
5020 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5021 if (performedLt) emitCLRC; else emitSETC;
5022 goto correct_result_in_carry;
5025 } // right is literal
5027 /*************************************************
5028 * perform a general case comparison *
5029 * make sure we get CARRY==1 <==> left >= right *
5030 *************************************************/
5031 // compare most significant bytes
5032 //DEBUGpc ("comparing bytes at offset %d", size);
5034 // unsigned comparison
5035 mov2w_regOrLit (AOP(right), lit, size);
5036 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5038 // signed comparison
5039 // (add 2^n to both operands then perform an unsigned comparison)
5040 if (isAOP_LIT(right)) {
5041 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5042 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5044 if (litbyte == 0x80) {
5045 // left >= 0x80 -- always true, but more bytes to come
5046 pic16_mov2w (AOP(left), size);
5047 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5050 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5051 pic16_mov2w (AOP(left), size);
5052 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5053 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5056 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5057 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5058 pic16_mov2w (AOP(left), size);
5059 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5060 pic16_emitpcode (POC_MOVWF, pctemp);
5061 pic16_mov2w (AOP(right), size);
5062 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5063 pic16_emitpcode (POC_SUBFW, pctemp);
5064 //pic16_popReleaseTempReg(pctemp, 1);
5068 // compare remaining bytes (treat as unsigned case from above)
5069 templbl = newiTempLabel ( NULL );
5072 //DEBUGpc ("comparing bytes at offset %d", offs);
5073 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5074 mov2w_regOrLit (AOP(right), lit, offs);
5075 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5077 pic16_emitpLabel (templbl->key);
5078 goto result_in_carry;
5082 /****************************************************
5083 * now CARRY contains the result of the comparison: *
5084 * SUBWF sets CARRY iff *
5085 * F-W >= 0 <==> F >= W <==> !(F < W) *
5087 ****************************************************/
5090 if (result && AOP_TYPE(result) != AOP_CRY) {
5091 // value will be stored
5094 // value wil only be used in the following genSkipc()
5095 rIfx.condition ^= 1;
5099 correct_result_in_carry:
5101 // assign result to variable (if neccessary)
5102 if (result && AOP_TYPE(result) != AOP_CRY) {
5103 //DEBUGpc ("assign result");
5104 size = AOP_SIZE(result);
5106 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5108 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5111 // perform conditional jump
5112 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5114 //DEBUGpc ("generate control flow");
5115 rIfx.condition ^= 1;
5124 static void genCmp (operand *left,operand *right,
5125 operand *result, iCode *ifx, int sign)
5127 int size; //, offset = 0 ;
5128 unsigned long lit = 0L,i = 0;
5129 resolvedIfx rFalseIfx;
5130 // resolvedIfx rTrueIfx;
5132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5135 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5136 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5142 resolveIfx(&rFalseIfx,ifx);
5143 truelbl = newiTempLabel(NULL);
5144 size = max(AOP_SIZE(left),AOP_SIZE(right));
5146 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5150 /* if literal is on the right then swap with left */
5151 if ((AOP_TYPE(right) == AOP_LIT)) {
5152 operand *tmp = right ;
5153 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5154 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5157 lit = (lit - 1) & mask;
5160 rFalseIfx.condition ^= 1;
5163 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5164 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5168 //if(IC_TRUE(ifx) == NULL)
5169 /* if left & right are bit variables */
5170 if (AOP_TYPE(left) == AOP_CRY &&
5171 AOP_TYPE(right) == AOP_CRY ) {
5172 assert (0 && "bit variables used in genCmp");
5173 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5174 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5176 /* subtract right from left if at the
5177 end the carry flag is set then we know that
5178 left is greater than right */
5180 symbol *lbl = newiTempLabel(NULL);
5183 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5184 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5188 if(AOP_TYPE(right) == AOP_LIT) {
5190 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5192 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5199 genSkipCond(&rFalseIfx,left,size-1,7);
5201 /* no need to compare to 0...*/
5202 /* NOTE: this is a de-generate compare that most certainly
5203 * creates some dead code. */
5204 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5206 if(ifx) ifx->generated = 1;
5213 //i = (lit >> (size*8)) & 0xff;
5214 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5216 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5218 i = ((0-lit) & 0xff);
5221 /* lit is 0x7f, all signed chars are less than
5222 * this except for 0x7f itself */
5223 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5224 genSkipz2(&rFalseIfx,0);
5226 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5228 genSkipc(&rFalseIfx);
5233 genSkipz2(&rFalseIfx,1);
5235 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5236 genSkipc(&rFalseIfx);
5240 if(ifx) ifx->generated = 1;
5244 /* chars are out of the way. now do ints and longs */
5247 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5254 genSkipCond(&rFalseIfx,left,size,7);
5255 if(ifx) ifx->generated = 1;
5260 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5262 //rFalseIfx.condition ^= 1;
5263 //genSkipCond(&rFalseIfx,left,size,7);
5264 //rFalseIfx.condition ^= 1;
5266 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5267 if(rFalseIfx.condition)
5268 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5270 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5272 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5273 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5274 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5277 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5279 if(rFalseIfx.condition) {
5281 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5287 genSkipc(&rFalseIfx);
5288 pic16_emitpLabel(truelbl->key);
5289 if(ifx) ifx->generated = 1;
5296 if( (lit & 0xff) == 0) {
5297 /* lower byte is zero */
5298 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5299 i = ((lit >> 8) & 0xff) ^0x80;
5300 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5301 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5302 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5303 genSkipc(&rFalseIfx);
5306 if(ifx) ifx->generated = 1;
5311 /* Special cases for signed longs */
5312 if( (lit & 0xffffff) == 0) {
5313 /* lower byte is zero */
5314 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5315 i = ((lit >> 8*3) & 0xff) ^0x80;
5316 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5317 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5318 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5319 genSkipc(&rFalseIfx);
5322 if(ifx) ifx->generated = 1;
5330 if(lit & (0x80 << (size*8))) {
5331 /* lit is negative */
5332 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334 //genSkipCond(&rFalseIfx,left,size,7);
5336 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5338 if(rFalseIfx.condition)
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5341 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5345 /* lit is positive */
5346 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5347 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5348 if(rFalseIfx.condition)
5349 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5351 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5356 This works, but is only good for ints.
5357 It also requires a "known zero" register.
5358 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5359 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5360 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5361 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5362 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5363 genSkipc(&rFalseIfx);
5365 pic16_emitpLabel(truelbl->key);
5366 if(ifx) ifx->generated = 1;
5370 /* There are no more special cases, so perform a general compare */
5372 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5373 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5377 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5379 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5381 //rFalseIfx.condition ^= 1;
5382 genSkipc(&rFalseIfx);
5384 pic16_emitpLabel(truelbl->key);
5386 if(ifx) ifx->generated = 1;
5393 /* sign is out of the way. So now do an unsigned compare */
5394 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5397 /* General case - compare to an unsigned literal on the right.*/
5399 i = (lit >> (size*8)) & 0xff;
5400 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5401 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5403 i = (lit >> (size*8)) & 0xff;
5406 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5408 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5410 /* this byte of the lit is zero,
5411 *if it's not the last then OR in the variable */
5413 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5418 pic16_emitpLabel(lbl->key);
5419 // pic16_emitpLabel(truelbl->key);
5420 //if(emitFinalCheck)
5421 genSkipc(&rFalseIfx);
5423 pic16_emitpLabel(truelbl->key);
5425 if(ifx) ifx->generated = 1;
5432 if(AOP_TYPE(left) == AOP_LIT) {
5433 //symbol *lbl = newiTempLabel(NULL);
5435 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5438 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5441 if((lit == 0) && (sign == 0)){
5444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5446 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5448 genSkipz2(&rFalseIfx,0);
5449 if(ifx) ifx->generated = 1;
5456 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5457 /* degenerate compare can never be true */
5458 if(rFalseIfx.condition == 0)
5459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5461 if(ifx) ifx->generated = 1;
5466 /* signed comparisons to a literal byte */
5468 int lp1 = (lit+1) & 0xff;
5470 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5473 rFalseIfx.condition ^= 1;
5474 genSkipCond(&rFalseIfx,right,0,7);
5477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5478 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5479 genSkipz2(&rFalseIfx,1);
5482 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5483 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5484 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5485 rFalseIfx.condition ^= 1;
5486 genSkipc(&rFalseIfx);
5490 /* unsigned comparisons to a literal byte */
5492 switch(lit & 0xff ) {
5494 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5495 genSkipz2(&rFalseIfx,0);
5498 rFalseIfx.condition ^= 1;
5499 genSkipCond(&rFalseIfx,right,0,7);
5503 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5504 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5506 rFalseIfx.condition ^= 1;
5507 if (AOP_TYPE(result) == AOP_CRY)
5508 genSkipc(&rFalseIfx);
5510 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5511 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5517 if(ifx) ifx->generated = 1;
5518 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5524 /* Size is greater than 1 */
5532 /* this means lit = 0xffffffff, or -1 */
5535 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5536 rFalseIfx.condition ^= 1;
5537 genSkipCond(&rFalseIfx,right,size,7);
5538 if(ifx) ifx->generated = 1;
5540 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5549 if(rFalseIfx.condition) {
5550 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5551 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5556 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5560 if(rFalseIfx.condition) {
5561 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5562 pic16_emitpLabel(truelbl->key);
5564 rFalseIfx.condition ^= 1;
5565 genSkipCond(&rFalseIfx,right,s,7);
5568 if(ifx) ifx->generated = 1;
5570 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5576 if((size == 1) && (0 == (lp1&0xff))) {
5577 /* lower byte of signed word is zero */
5578 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5579 i = ((lp1 >> 8) & 0xff) ^0x80;
5580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5581 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5582 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5584 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5586 if(ifx) ifx->generated = 1;
5589 rFalseIfx.condition ^= 1;
5590 genSkipc(&rFalseIfx);
5591 if(ifx) ifx->generated = 1;
5597 if(lit & (0x80 << (size*8))) {
5598 /* Lit is less than zero */
5599 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5600 //rFalseIfx.condition ^= 1;
5601 //genSkipCond(&rFalseIfx,left,size,7);
5602 //rFalseIfx.condition ^= 1;
5603 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5604 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5606 if(rFalseIfx.condition)
5607 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5609 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5613 /* Lit is greater than or equal to zero */
5614 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5615 //rFalseIfx.condition ^= 1;
5616 //genSkipCond(&rFalseIfx,right,size,7);
5617 //rFalseIfx.condition ^= 1;
5619 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5620 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5622 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5623 if(rFalseIfx.condition)
5624 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5626 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5630 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5631 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5635 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5637 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5639 rFalseIfx.condition ^= 1;
5640 //rFalseIfx.condition = 1;
5641 genSkipc(&rFalseIfx);
5643 pic16_emitpLabel(truelbl->key);
5645 if(ifx) ifx->generated = 1;
5648 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5655 /* compare word or long to an unsigned literal on the right.*/
5660 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5663 break; /* handled above */
5666 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5668 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5669 genSkipz2(&rFalseIfx,0);
5673 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5675 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5678 if(rFalseIfx.condition)
5679 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5681 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5684 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5685 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5687 rFalseIfx.condition ^= 1;
5688 genSkipc(&rFalseIfx);
5691 pic16_emitpLabel(truelbl->key);
5693 if(ifx) ifx->generated = 1;
5695 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5703 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5704 i = (lit >> (size*8)) & 0xff;
5706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5707 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5710 i = (lit >> (size*8)) & 0xff;
5713 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5715 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5717 /* this byte of the lit is zero,
5718 * if it's not the last then OR in the variable */
5720 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5725 pic16_emitpLabel(lbl->key);
5727 rFalseIfx.condition ^= 1;
5729 genSkipc(&rFalseIfx);
5733 pic16_emitpLabel(truelbl->key);
5734 if(ifx) ifx->generated = 1;
5736 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5742 /* Compare two variables */
5744 DEBUGpic16_emitcode(";sign","%d",sign);
5748 /* Sigh. thus sucks... */
5752 pctemp = pic16_popGetTempReg(1);
5753 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5754 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5755 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5756 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5757 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5758 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5759 pic16_popReleaseTempReg(pctemp, 1);
5761 /* Signed char comparison */
5762 /* Special thanks to Nikolai Golovchenko for this snippet */
5763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5764 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5765 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5766 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5767 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5768 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5771 genSkipc(&rFalseIfx);
5773 if(ifx) ifx->generated = 1;
5775 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5783 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5784 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5788 /* The rest of the bytes of a multi-byte compare */
5792 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5795 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5796 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5801 pic16_emitpLabel(lbl->key);
5803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5804 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5805 (AOP_TYPE(result) == AOP_REG)) {
5806 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5807 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5809 genSkipc(&rFalseIfx);
5811 //genSkipc(&rFalseIfx);
5812 if(ifx) ifx->generated = 1;
5815 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5823 if ((AOP_TYPE(result) != AOP_CRY)
5824 && AOP_SIZE(result)) {
5825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5827 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5829 pic16_outBitC(result);
5831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5832 /* if the result is used in the next
5833 ifx conditional branch then generate
5834 code a little differently */
5836 genIfxJump (ifx,"c");
5838 pic16_outBitC(result);
5839 /* leave the result in acc */
5844 #else /* old version of genCmp() */ /* } else { */
5846 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5847 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5848 operand *result, int offset, int invert_op)
5852 /* check condition, > or < ?? */
5853 if(rIfx->condition != 0)invert_op ^= 1;
5855 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5857 if(!ifx)invert_op ^= 1;
5859 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5860 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5863 if(!invert_op)return POC_CPFSGT;
5864 else return POC_CPFSLT;
5867 static int compareAopfirstpass=1;
5869 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5870 operand *oper, int offset, operand *result,
5871 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5877 /* invert if there is a result to be loaded, in order to fit,
5878 * SETC/CLRC sequence */
5879 if(AOP_SIZE(result))invert_op ^= 1;
5881 // if(sign && !offset)invert_op ^= 1;
5883 // if(sign)invert_op ^= 1;
5885 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5887 if(AOP_SIZE(result) && compareAopfirstpass) {
5890 pic16_emitpcode(POC_SETF, pcop2);
5895 pic16_emitpcode(POC_CLRF, pcop2);
5901 compareAopfirstpass = 0;
5903 /* there is a bug when comparing operands with size > 1,
5904 * because higher bytes can be equal and test should be performed
5905 * to the next lower byte, current algorithm, considers operands
5906 * inequal in these cases! -- VR 20041107 */
5910 pic16_emitpcode(op, pcop);
5912 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5915 if((!sign || !offset) && AOP_SIZE(result)) {
5918 pic16_emitpcode(POC_CLRF, pcop2);
5923 pic16_emitpcode(POC_SETF, pcop2);
5928 /* don't emit final branch (offset == 0) */
5932 pic16_emitpcode(POC_RRCF, pcop2);
5934 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5937 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5938 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5939 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5941 truelbl = newiTempLabel( NULL );
5942 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5943 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5946 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5947 pic16_emitpLabel(truelbl->key);
5949 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5958 static void genCmp (operand *left, operand *right,
5959 operand *result, iCode *ifx, int sign)
5963 resolvedIfx rFalseIfx;
5964 symbol *falselbl, *tlbl;
5968 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5970 resolveIfx(&rFalseIfx, ifx);
5971 size = max(AOP_SIZE(left), AOP_SIZE(right));
5973 /* if left & right are bit variables */
5974 if(AOP_TYPE(left) == AOP_CRY
5975 && AOP_TYPE(right) == AOP_CRY ) {
5977 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5978 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5980 werror(W_POSSBUG2, __FILE__, __LINE__);
5984 /* if literal is on the right then swap with left */
5985 if((AOP_TYPE(right) == AOP_LIT)) {
5986 operand *tmp = right ;
5987 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5989 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5991 // lit = (lit - 1) & mask;
5994 rFalseIfx.condition ^= 1; /* reverse compare */
5996 if ((AOP_TYPE(left) == AOP_LIT)) {
5997 /* float compares are handled by support functions */
5998 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6001 /* actual comparing algorithm */
6002 // size = AOP_SIZE( right );
6004 falselbl = newiTempLabel( NULL );
6005 if(AOP_TYPE(left) == AOP_LIT) {
6006 /* compare to literal */
6007 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6010 pCodeOp *pct, *pct2;
6013 /* signed compare */
6014 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6016 pct = pic16_popCopyReg(&pic16_pc_prodl);
6017 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6018 tlbl = newiTempLabel( NULL );
6020 /* first compare signs:
6021 * a. if both are positive, compare just like unsigned
6022 * b. if both are negative, invert cmpop, compare just like unsigned
6023 * c. if different signs, determine the result directly */
6029 tlbl1 = newiTempLabel( NULL );
6030 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6034 /* literal is zero or positive:
6035 * a. if carry is zero, too, continue compare,
6036 * b. if carry is set, then continue depending on cmpop ^ condition:
6037 * 1. '<' return false (literal < variable),
6038 * 2. '>' return true (literal > variable) */
6039 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6040 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6043 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6044 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6048 /* literal is negative:
6049 * a. if carry is set, too, continue compare,
6050 * b. if carry is zero, then continue depending on cmpop ^ condition:
6051 * 1. '<' return true (literal < variable),
6052 * 2. '>' return false (literal > variable) */
6053 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6054 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6056 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6057 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6062 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6064 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6065 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6070 pic16_emitpLabel( tlbl1->key );
6073 compareAopfirstpass=1;
6074 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6075 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6076 // pic16_emitpcode(POC_MOVWF, pct);
6078 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6079 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6080 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6081 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6085 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6086 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6087 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6088 // pic16_emitpcode(POC_MOVWF, pct);
6090 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6091 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6092 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6093 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6094 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6098 if(ifx)ifx->generated = 1;
6100 if(AOP_SIZE(result)) {
6101 pic16_emitpLabel(tlbl->key);
6102 pic16_emitpLabel(falselbl->key);
6103 pic16_outBitOp( result, pct2 );
6105 pic16_emitpLabel(tlbl->key);
6110 /* unsigned compare */
6111 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6113 compareAopfirstpass=1;
6116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6117 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6121 if(ifx)ifx->generated = 1;
6124 if(AOP_SIZE(result)) {
6125 pic16_emitpLabel(falselbl->key);
6126 pic16_outBitC( result );
6131 /* compare registers */
6132 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6136 pCodeOp *pct, *pct2;
6138 /* signed compare */
6139 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6141 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6142 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6143 tlbl = newiTempLabel( NULL );
6145 compareAopfirstpass=1;
6148 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6149 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6150 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6151 pic16_emitpcode(POC_MOVWF, pct);
6153 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6154 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6155 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6157 /* WREG already holds left + 0x80 */
6158 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6161 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6162 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6163 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6164 pic16_emitpcode(POC_MOVWF, pct);
6166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6167 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6168 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6170 /* WREG already holds left + 0x80 */
6171 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6172 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6175 if(ifx)ifx->generated = 1;
6177 if(AOP_SIZE(result)) {
6178 pic16_emitpLabel(tlbl->key);
6179 pic16_emitpLabel(falselbl->key);
6180 pic16_outBitOp( result, pct2 );
6182 pic16_emitpLabel(tlbl->key);
6186 /* unsigned compare */
6187 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6189 compareAopfirstpass=1;
6192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6193 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6197 if(ifx)ifx->generated = 1;
6198 if(AOP_SIZE(result)) {
6200 pic16_emitpLabel(falselbl->key);
6201 pic16_outBitC( result );
6208 #else /* } else { */
6210 /* new version of genCmp -- VR 20041012 */
6211 static void genCmp (operand *left,operand *right,
6212 operand *result, iCode *ifx, int sign)
6214 int size; //, offset = 0 ;
6215 unsigned long lit = 0L,i = 0;
6216 resolvedIfx rFalseIfx;
6217 int willCheckCarry=0;
6218 // resolvedIfx rTrueIfx;
6224 * subtract right from left if at the end the carry flag is set then we
6225 * know that left is greater than right */
6227 resolveIfx(&rFalseIfx,ifx);
6228 truelbl = newiTempLabel(NULL);
6229 size = max(AOP_SIZE(left),AOP_SIZE(right));
6231 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6233 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6234 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6237 /* if literal is on the right then swap with left */
6238 if ((AOP_TYPE(right) == AOP_LIT)) {
6239 operand *tmp = right ;
6240 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6242 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6244 // lit = (lit - 1) & mask;
6247 rFalseIfx.condition ^= 1; /* reverse compare */
6249 if ((AOP_TYPE(left) == AOP_LIT)) {
6250 /* float compares are handled by support functions */
6251 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6255 //if(IC_TRUE(ifx) == NULL)
6256 /* if left & right are bit variables */
6257 if (AOP_TYPE(left) == AOP_CRY &&
6258 AOP_TYPE(right) == AOP_CRY ) {
6260 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6261 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6264 symbol *lbl = newiTempLabel(NULL);
6266 if(AOP_TYPE(left) == AOP_LIT) {
6267 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6269 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6271 else willCheckCarry = 0;
6274 if((lit == 0) && (sign == 0)) {
6275 /* unsigned compare to 0 */
6276 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6279 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6281 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6283 genSkipz2(&rFalseIfx,0);
6284 if(ifx)ifx->generated = 1;
6291 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6292 /* degenerate compare can never be true */
6293 if(rFalseIfx.condition == 0)
6294 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6296 if(ifx) ifx->generated = 1;
6301 /* signed comparisons to a literal byte */
6302 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6304 int lp1 = (lit+1) & 0xff;
6306 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6309 rFalseIfx.condition ^= 1;
6310 genSkipCond(&rFalseIfx,right,0,7);
6313 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6314 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6315 genSkipz2(&rFalseIfx,1);
6318 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6320 if(rFalseIfx.condition)
6321 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6323 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6325 if(willCheckCarry) {
6326 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6327 else { emitSETC; emitCLRC; }
6330 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6333 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6334 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6336 rFalseIfx.condition ^= 1;
6337 genSkipc(&rFalseIfx);
6342 /* unsigned comparisons to a literal byte */
6343 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6345 switch(lit & 0xff ) {
6348 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6349 genSkipz2(&rFalseIfx,0);
6352 rFalseIfx.condition ^= 1;
6353 genSkipCond(&rFalseIfx,right,0,7);
6356 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6357 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6358 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6359 rFalseIfx.condition ^= 1;
6360 if (AOP_TYPE(result) == AOP_CRY)
6361 genSkipc(&rFalseIfx);
6363 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6364 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6370 if(ifx) ifx->generated = 1;
6371 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6377 /* Size is greater than 1 */
6385 /* this means lit = 0xffffffff, or -1 */
6388 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6389 rFalseIfx.condition ^= 1;
6390 genSkipCond(&rFalseIfx,right,size,7);
6391 if(ifx) ifx->generated = 1;
6398 if(rFalseIfx.condition) {
6399 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6400 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6403 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6405 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6409 if(rFalseIfx.condition) {
6410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6411 pic16_emitpLabel(truelbl->key);
6413 rFalseIfx.condition ^= 1;
6414 genSkipCond(&rFalseIfx,right,s,7);
6417 if(ifx) ifx->generated = 1;
6421 if((size == 1) && (0 == (lp1&0xff))) {
6422 /* lower byte of signed word is zero */
6423 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6424 i = ((lp1 >> 8) & 0xff) ^0x80;
6425 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6426 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6427 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6428 rFalseIfx.condition ^= 1;
6429 genSkipc(&rFalseIfx);
6432 if(ifx) ifx->generated = 1;
6436 if(lit & (0x80 << (size*8))) {
6437 /* Lit is less than zero */
6438 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6439 //rFalseIfx.condition ^= 1;
6440 //genSkipCond(&rFalseIfx,left,size,7);
6441 //rFalseIfx.condition ^= 1;
6442 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6443 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6445 if(rFalseIfx.condition)
6446 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6448 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6452 /* Lit is greater than or equal to zero */
6453 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6454 //rFalseIfx.condition ^= 1;
6455 //genSkipCond(&rFalseIfx,right,size,7);
6456 //rFalseIfx.condition ^= 1;
6458 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6459 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6461 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6462 if(rFalseIfx.condition)
6463 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6465 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6470 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6471 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6479 rFalseIfx.condition ^= 1;
6480 //rFalseIfx.condition = 1;
6481 genSkipc(&rFalseIfx);
6483 pic16_emitpLabel(truelbl->key);
6485 if(ifx) ifx->generated = 1;
6490 /* compare word or long to an unsigned literal on the right.*/
6495 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6498 break; /* handled above */
6501 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6503 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6504 genSkipz2(&rFalseIfx,0);
6508 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6510 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6513 if(rFalseIfx.condition)
6514 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6516 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6519 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6520 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6522 rFalseIfx.condition ^= 1;
6523 genSkipc(&rFalseIfx);
6526 pic16_emitpLabel(truelbl->key);
6528 if(ifx) ifx->generated = 1;
6534 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6535 i = (lit >> (size*8)) & 0xff;
6537 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6538 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6541 i = (lit >> (size*8)) & 0xff;
6544 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6546 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6548 /* this byte of the lit is zero,
6549 * if it's not the last then OR in the variable */
6551 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6556 pic16_emitpLabel(lbl->key);
6558 rFalseIfx.condition ^= 1;
6560 genSkipc(&rFalseIfx);
6564 pic16_emitpLabel(truelbl->key);
6565 if(ifx) ifx->generated = 1;
6569 /* Compare two variables */
6571 DEBUGpic16_emitcode(";sign","%d",sign);
6575 /* Sigh. thus sucks... */
6579 pctemp = pic16_popGetTempReg(1);
6580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6581 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6583 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6584 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6585 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6586 pic16_popReleaseTempReg(pctemp, 1);
6588 /* Signed char comparison */
6589 /* Special thanks to Nikolai Golovchenko for this snippet */
6590 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6591 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6592 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6593 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6594 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6598 genSkipc(&rFalseIfx);
6600 if(ifx) ifx->generated = 1;
6606 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6607 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6611 /* The rest of the bytes of a multi-byte compare */
6615 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6618 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6619 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6624 pic16_emitpLabel(lbl->key);
6626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6627 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6628 (AOP_TYPE(result) == AOP_REG)) {
6629 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6630 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6632 genSkipc(&rFalseIfx);
6634 //genSkipc(&rFalseIfx);
6635 if(ifx) ifx->generated = 1;
6642 if ((AOP_TYPE(result) != AOP_CRY)
6643 && AOP_SIZE(result)) {
6644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6646 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6648 pic16_outBitC(result);
6650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6651 /* if the result is used in the next
6652 ifx conditional branch then generate
6653 code a little differently */
6655 genIfxJump (ifx,"c");
6657 pic16_outBitC(result);
6658 /* leave the result in acc */
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpGt :- greater than comparison */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpGt (iCode *ic, iCode *ifx)
6674 operand *left, *right, *result;
6675 sym_link *letype , *retype;
6681 right= IC_RIGHT(ic);
6682 result = IC_RESULT(ic);
6684 letype = getSpec(operandType(left));
6685 retype =getSpec(operandType(right));
6686 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6687 /* assign the amsops */
6688 pic16_aopOp (left,ic,FALSE);
6689 pic16_aopOp (right,ic,FALSE);
6690 pic16_aopOp (result,ic,TRUE);
6692 genCmp(right, left, result, ifx, sign);
6694 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6695 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6696 pic16_freeAsmop(result,NULL,ic,TRUE);
6699 /*-----------------------------------------------------------------*/
6700 /* genCmpLt - less than comparisons */
6701 /*-----------------------------------------------------------------*/
6702 static void genCmpLt (iCode *ic, iCode *ifx)
6704 operand *left, *right, *result;
6705 sym_link *letype , *retype;
6711 right= IC_RIGHT(ic);
6712 result = IC_RESULT(ic);
6714 letype = getSpec(operandType(left));
6715 retype =getSpec(operandType(right));
6716 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6718 /* assign the amsops */
6719 pic16_aopOp (left,ic,FALSE);
6720 pic16_aopOp (right,ic,FALSE);
6721 pic16_aopOp (result,ic,TRUE);
6723 genCmp(left, right, result, ifx, sign);
6725 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6726 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6727 pic16_freeAsmop(result,NULL,ic,TRUE);
6732 // FIXME reenable literal optimisation when the pic16 port is stable
6734 /*-----------------------------------------------------------------*/
6735 /* genc16bit2lit - compare a 16 bit value to a literal */
6736 /*-----------------------------------------------------------------*/
6737 static void genc16bit2lit(operand *op, int lit, int offset)
6741 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6742 if( (lit&0xff) == 0)
6747 switch( BYTEofLONG(lit,i)) {
6749 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6752 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6755 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6758 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6759 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6764 switch( BYTEofLONG(lit,i)) {
6766 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6770 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6774 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6777 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6779 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6788 /*-----------------------------------------------------------------*/
6789 /* gencjneshort - compare and jump if not equal */
6790 /*-----------------------------------------------------------------*/
6791 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6793 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6795 int res_offset = 0; /* the result may be a different size then left or right */
6796 int res_size = AOP_SIZE(result);
6798 symbol *lbl, *lbl_done;
6800 unsigned long lit = 0L;
6801 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6804 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6806 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6807 resolveIfx(&rIfx,ifx);
6808 lbl = newiTempLabel(NULL);
6809 lbl_done = newiTempLabel(NULL);
6812 /* if the left side is a literal or
6813 if the right is in a pointer register and left
6815 if ((AOP_TYPE(left) == AOP_LIT) ||
6816 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821 if(AOP_TYPE(right) == AOP_LIT)
6822 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6824 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6825 preserve_result = 1;
6827 if(result && !preserve_result)
6830 for(i = 0; i < AOP_SIZE(result); i++)
6831 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6835 /* if the right side is a literal then anything goes */
6836 if (AOP_TYPE(right) == AOP_LIT &&
6837 AOP_TYPE(left) != AOP_DIR ) {
6840 genc16bit2lit(left, lit, 0);
6842 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6848 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6849 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6851 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6857 if(res_offset < res_size-1)
6865 /* if the right side is in a register or in direct space or
6866 if the left is a pointer register & right is not */
6867 else if (AOP_TYPE(right) == AOP_REG ||
6868 AOP_TYPE(right) == AOP_DIR ||
6869 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6870 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6871 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6872 int lbl_key = lbl->key;
6875 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6876 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6878 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6879 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6880 __FUNCTION__,__LINE__);
6884 /* switch(size) { */
6886 /* genc16bit2lit(left, lit, 0); */
6888 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6893 if((AOP_TYPE(left) == AOP_DIR) &&
6894 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6896 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6897 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6899 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6901 switch (lit & 0xff) {
6903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6906 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6907 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6912 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6913 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6914 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6915 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6919 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6920 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6925 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6928 if(AOP_TYPE(result) == AOP_CRY) {
6929 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6934 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6936 /* fix me. probably need to check result size too */
6937 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6942 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6943 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6950 if(res_offset < res_size-1)
6955 } else if(AOP_TYPE(right) == AOP_REG &&
6956 AOP_TYPE(left) != AOP_DIR){
6959 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6960 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6961 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6966 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6968 if(res_offset < res_size-1)
6973 /* right is a pointer reg need both a & b */
6975 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6977 pic16_emitcode("mov","b,%s",l);
6978 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6979 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6984 if(result && preserve_result)
6987 for(i = 0; i < AOP_SIZE(result); i++)
6988 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6991 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6993 if(result && preserve_result)
6994 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6997 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6999 pic16_emitpLabel(lbl->key);
7001 if(result && preserve_result)
7004 for(i = 0; i < AOP_SIZE(result); i++)
7005 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7007 pic16_emitpLabel(lbl_done->key);
7010 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7018 /*-----------------------------------------------------------------*/
7019 /* gencjne - compare and jump if not equal */
7020 /*-----------------------------------------------------------------*/
7021 static void gencjne(operand *left, operand *right, iCode *ifx)
7023 symbol *tlbl = newiTempLabel(NULL);
7025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7026 gencjneshort(left, right, lbl);
7028 pic16_emitcode("mov","a,%s",one);
7029 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7030 pic16_emitcode("","%05d_DS_:",lbl->key+100);
7031 pic16_emitcode("clr","a");
7032 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7034 pic16_emitpLabel(lbl->key);
7035 pic16_emitpLabel(tlbl->key);
7041 /*-----------------------------------------------------------------*/
7042 /* is_LitOp - check if operand has to be treated as literal */
7043 /*-----------------------------------------------------------------*/
7044 static bool is_LitOp(operand *op)
7046 return ((AOP_TYPE(op) == AOP_LIT)
7047 || ( (AOP_TYPE(op) == AOP_PCODE)
7048 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7049 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7052 /*-----------------------------------------------------------------*/
7053 /* is_LitAOp - check if operand has to be treated as literal */
7054 /*-----------------------------------------------------------------*/
7055 static bool is_LitAOp(asmop *aop)
7057 return ((aop->type == AOP_LIT)
7058 || ( (aop->type == AOP_PCODE)
7059 && ( (aop->aopu.pcop->type == PO_LITERAL)
7060 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7065 /*-----------------------------------------------------------------*/
7066 /* genCmpEq - generates code for equal to */
7067 /*-----------------------------------------------------------------*/
7068 static void genCmpEq (iCode *ic, iCode *ifx)
7070 operand *left, *right, *result;
7071 symbol *falselbl = newiTempLabel(NULL);
7072 symbol *donelbl = newiTempLabel(NULL);
7074 int preserve_result = 0;
7075 int generate_result = 0;
7077 unsigned long lit = -1;
7081 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7082 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7083 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7085 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7087 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7089 werror(W_POSSBUG2, __FILE__, __LINE__);
7090 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7091 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7095 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7097 operand *tmp = right ;
7102 if (AOP_TYPE(right) == AOP_LIT) {
7103 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
7106 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7107 preserve_result = 1;
7109 if(result && AOP_SIZE(result))
7110 generate_result = 1;
7112 if(generate_result && !preserve_result)
7114 for(i = 0; i < AOP_SIZE(result); i++)
7115 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7118 for(i=0; i < AOP_SIZE(left); i++)
7120 if(AOP_TYPE(left) != AOP_ACC)
7123 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7125 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7127 if(is_LitOp(right)) {
7128 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
7129 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7132 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7134 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7139 if(generate_result && preserve_result)
7141 for(i = 0; i < AOP_SIZE(result); i++)
7142 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7146 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7148 if(generate_result && preserve_result)
7149 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7151 if(ifx && IC_TRUE(ifx))
7152 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7154 if(ifx && IC_FALSE(ifx))
7155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7157 pic16_emitpLabel(falselbl->key);
7161 if(ifx && IC_FALSE(ifx))
7162 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7164 if(generate_result && preserve_result)
7166 for(i = 0; i < AOP_SIZE(result); i++)
7167 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7170 pic16_emitpLabel(donelbl->key);
7176 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7177 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7178 pic16_freeAsmop(result,NULL,ic,TRUE);
7184 // old version kept for reference
7186 /*-----------------------------------------------------------------*/
7187 /* genCmpEq - generates code for equal to */
7188 /*-----------------------------------------------------------------*/
7189 static void genCmpEq (iCode *ic, iCode *ifx)
7191 operand *left, *right, *result;
7192 unsigned long lit = 0L;
7194 symbol *falselbl = newiTempLabel(NULL);
7197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7200 DEBUGpic16_emitcode ("; ifx is non-null","");
7202 DEBUGpic16_emitcode ("; ifx is null","");
7204 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7205 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7206 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7208 size = max(AOP_SIZE(left),AOP_SIZE(right));
7210 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7212 /* if literal, literal on the right or
7213 if the right is in a pointer register and left
7215 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7216 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7217 operand *tmp = right ;
7223 if(ifx && !AOP_SIZE(result)){
7225 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7226 /* if they are both bit variables */
7227 if (AOP_TYPE(left) == AOP_CRY &&
7228 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7229 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7230 if(AOP_TYPE(right) == AOP_LIT){
7231 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7233 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7234 pic16_emitcode("cpl","c");
7235 } else if(lit == 1L) {
7236 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7238 pic16_emitcode("clr","c");
7240 /* AOP_TYPE(right) == AOP_CRY */
7242 symbol *lbl = newiTempLabel(NULL);
7243 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7244 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7245 pic16_emitcode("cpl","c");
7246 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7248 /* if true label then we jump if condition
7250 tlbl = newiTempLabel(NULL);
7251 if ( IC_TRUE(ifx) ) {
7252 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7253 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7255 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7256 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7258 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7261 /* left and right are both bit variables, result is carry */
7264 resolveIfx(&rIfx,ifx);
7266 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7267 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7268 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7269 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7274 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7276 /* They're not both bit variables. Is the right a literal? */
7277 if(AOP_TYPE(right) == AOP_LIT) {
7278 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7283 switch(lit & 0xff) {
7285 if ( IC_TRUE(ifx) ) {
7286 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7288 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7290 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7291 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7295 if ( IC_TRUE(ifx) ) {
7296 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7298 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7300 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7301 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7305 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7307 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7312 /* end of size == 1 */
7316 genc16bit2lit(left,lit,offset);
7319 /* end of size == 2 */
7324 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7325 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7326 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7327 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7330 /* search for patterns that can be optimized */
7332 genc16bit2lit(left,lit,0);
7336 emitSKPZ; // if hi word unequal
7338 emitSKPNZ; // if hi word equal
7340 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7341 genc16bit2lit(left,lit,2);
7344 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7345 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7349 pic16_emitpLabel(falselbl->key);
7358 } else if(AOP_TYPE(right) == AOP_CRY ) {
7359 /* we know the left is not a bit, but that the right is */
7360 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7361 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7362 pic16_popGet(AOP(right),offset));
7363 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7365 /* if the two are equal, then W will be 0 and the Z bit is set
7366 * we could test Z now, or go ahead and check the high order bytes if
7367 * the variable we're comparing is larger than a byte. */
7370 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7372 if ( IC_TRUE(ifx) ) {
7374 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7375 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7378 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7379 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7383 /* They're both variables that are larger than bits */
7386 tlbl = newiTempLabel(NULL);
7389 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7390 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7392 if ( IC_TRUE(ifx) ) {
7396 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7398 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7399 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7403 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7406 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7407 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7412 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7414 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7415 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7419 if(s>1 && IC_TRUE(ifx)) {
7420 pic16_emitpLabel(tlbl->key);
7421 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7425 /* mark the icode as generated */
7430 /* if they are both bit variables */
7431 if (AOP_TYPE(left) == AOP_CRY &&
7432 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7433 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7434 if(AOP_TYPE(right) == AOP_LIT){
7435 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7437 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7438 pic16_emitcode("cpl","c");
7439 } else if(lit == 1L) {
7440 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7442 pic16_emitcode("clr","c");
7444 /* AOP_TYPE(right) == AOP_CRY */
7446 symbol *lbl = newiTempLabel(NULL);
7447 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7448 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7449 pic16_emitcode("cpl","c");
7450 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7453 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7454 pic16_outBitC(result);
7458 genIfxJump (ifx,"c");
7461 /* if the result is used in an arithmetic operation
7462 then put the result in place */
7463 pic16_outBitC(result);
7466 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7467 gencjne(left,right,result,ifx);
7470 gencjne(left,right,newiTempLabel(NULL));
7472 if(IC_TRUE(ifx)->key)
7473 gencjne(left,right,IC_TRUE(ifx)->key);
7475 gencjne(left,right,IC_FALSE(ifx)->key);
7479 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7480 pic16_aopPut(AOP(result),"a",0);
7485 genIfxJump (ifx,"a");
7489 /* if the result is used in an arithmetic operation
7490 then put the result in place */
7492 if (AOP_TYPE(result) != AOP_CRY)
7493 pic16_outAcc(result);
7495 /* leave the result in acc */
7499 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7500 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7501 pic16_freeAsmop(result,NULL,ic,TRUE);
7505 /*-----------------------------------------------------------------*/
7506 /* ifxForOp - returns the icode containing the ifx for operand */
7507 /*-----------------------------------------------------------------*/
7508 static iCode *ifxForOp ( operand *op, iCode *ic )
7512 /* if true symbol then needs to be assigned */
7513 if (IS_TRUE_SYMOP(op))
7516 /* if this has register type condition and
7517 the next instruction is ifx with the same operand
7518 and live to of the operand is upto the ifx only then */
7520 && ic->next->op == IFX
7521 && IC_COND(ic->next)->key == op->key
7522 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7524 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7530 ic->next->op == IFX &&
7531 IC_COND(ic->next)->key == op->key) {
7532 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7537 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7539 ic->next->op == IFX)
7540 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7543 ic->next->op == IFX &&
7544 IC_COND(ic->next)->key == op->key) {
7545 DEBUGpic16_emitcode ("; "," key is okay");
7546 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7547 OP_SYMBOL(op)->liveTo,
7552 /* the code below is completely untested
7553 * it just allows ulong2fs.c compile -- VR */
7556 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7557 __FILE__, __FUNCTION__, __LINE__);
7559 /* if this has register type condition and
7560 the next instruction is ifx with the same operand
7561 and live to of the operand is upto the ifx only then */
7563 ic->next->op == IFX &&
7564 IC_COND(ic->next)->key == op->key &&
7565 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7569 ic->next->op == IFX &&
7570 IC_COND(ic->next)->key == op->key) {
7571 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7575 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7576 __FILE__, __FUNCTION__, __LINE__);
7578 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7583 /*-----------------------------------------------------------------*/
7584 /* genAndOp - for && operation */
7585 /*-----------------------------------------------------------------*/
7586 static void genAndOp (iCode *ic)
7588 operand *left,*right, *result;
7593 /* note here that && operations that are in an
7594 if statement are taken away by backPatchLabels
7595 only those used in arthmetic operations remain */
7596 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7597 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7598 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7600 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7602 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7603 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7604 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7606 /* if both are bit variables */
7607 /* if (AOP_TYPE(left) == AOP_CRY && */
7608 /* AOP_TYPE(right) == AOP_CRY ) { */
7609 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7610 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7611 /* pic16_outBitC(result); */
7613 /* tlbl = newiTempLabel(NULL); */
7614 /* pic16_toBoolean(left); */
7615 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7616 /* pic16_toBoolean(right); */
7617 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7618 /* pic16_outBitAcc(result); */
7621 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7622 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7623 pic16_freeAsmop(result,NULL,ic,TRUE);
7627 /*-----------------------------------------------------------------*/
7628 /* genOrOp - for || operation */
7629 /*-----------------------------------------------------------------*/
7632 modified this code, but it doesn't appear to ever get called
7635 static void genOrOp (iCode *ic)
7637 operand *left,*right, *result;
7642 /* note here that || operations that are in an
7643 if statement are taken away by backPatchLabels
7644 only those used in arthmetic operations remain */
7645 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7646 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7647 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7649 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7651 /* if both are bit variables */
7652 if (AOP_TYPE(left) == AOP_CRY &&
7653 AOP_TYPE(right) == AOP_CRY ) {
7654 pic16_emitcode("clrc","");
7655 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7656 AOP(left)->aopu.aop_dir,
7657 AOP(left)->aopu.aop_dir);
7658 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7659 AOP(right)->aopu.aop_dir,
7660 AOP(right)->aopu.aop_dir);
7661 pic16_emitcode("setc","");
7664 tlbl = newiTempLabel(NULL);
7665 pic16_toBoolean(left);
7667 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7668 pic16_toBoolean(right);
7669 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7671 pic16_outBitAcc(result);
7674 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676 pic16_freeAsmop(result,NULL,ic,TRUE);
7679 /*-----------------------------------------------------------------*/
7680 /* isLiteralBit - test if lit == 2^n */
7681 /*-----------------------------------------------------------------*/
7682 static int isLiteralBit(unsigned long lit)
7684 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7685 0x100L,0x200L,0x400L,0x800L,
7686 0x1000L,0x2000L,0x4000L,0x8000L,
7687 0x10000L,0x20000L,0x40000L,0x80000L,
7688 0x100000L,0x200000L,0x400000L,0x800000L,
7689 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7690 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7694 for(idx = 0; idx < 32; idx++)
7700 /*-----------------------------------------------------------------*/
7701 /* continueIfTrue - */
7702 /*-----------------------------------------------------------------*/
7703 static void continueIfTrue (iCode *ic)
7707 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7711 /*-----------------------------------------------------------------*/
7713 /*-----------------------------------------------------------------*/
7714 static void jumpIfTrue (iCode *ic)
7718 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7722 /*-----------------------------------------------------------------*/
7723 /* jmpTrueOrFalse - */
7724 /*-----------------------------------------------------------------*/
7725 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7727 // ugly but optimized by peephole
7730 symbol *nlbl = newiTempLabel(NULL);
7731 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7732 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7733 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7734 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7736 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7737 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7742 /*-----------------------------------------------------------------*/
7743 /* genAnd - code for and */
7744 /*-----------------------------------------------------------------*/
7745 static void genAnd (iCode *ic, iCode *ifx)
7747 operand *left, *right, *result;
7749 unsigned long lit = 0L;
7755 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7756 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7757 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7759 resolveIfx(&rIfx,ifx);
7761 /* if left is a literal & right is not then exchange them */
7762 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7763 AOP_NEEDSACC(left)) {
7764 operand *tmp = right ;
7769 /* if result = right then exchange them */
7770 if(pic16_sameRegs(AOP(result),AOP(right))){
7771 operand *tmp = right ;
7776 /* if right is bit then exchange them */
7777 if (AOP_TYPE(right) == AOP_CRY &&
7778 AOP_TYPE(left) != AOP_CRY){
7779 operand *tmp = right ;
7783 if(AOP_TYPE(right) == AOP_LIT)
7784 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7786 size = AOP_SIZE(result);
7788 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7791 // result = bit & yy;
7792 if (AOP_TYPE(left) == AOP_CRY){
7793 // c = bit & literal;
7794 if(AOP_TYPE(right) == AOP_LIT){
7796 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7799 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7802 if(size && (AOP_TYPE(result) == AOP_CRY)){
7803 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7806 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7810 pic16_emitcode("clr","c");
7813 if (AOP_TYPE(right) == AOP_CRY){
7815 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7816 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7819 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7821 pic16_emitcode("rrc","a");
7822 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7828 pic16_outBitC(result);
7830 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7831 genIfxJump(ifx, "c");
7835 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7836 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7837 if((AOP_TYPE(right) == AOP_LIT) &&
7838 (AOP_TYPE(result) == AOP_CRY) &&
7839 (AOP_TYPE(left) != AOP_CRY)){
7840 int posbit = isLiteralBit(lit);
7844 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7847 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7853 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7854 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7856 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7857 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7860 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7861 size = AOP_SIZE(left);
7864 int bp = posbit, ofs=0;
7871 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7872 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7876 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7877 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7879 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7886 symbol *tlbl = newiTempLabel(NULL);
7887 int sizel = AOP_SIZE(left);
7893 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7895 /* patch provided by Aaron Colwell */
7896 if((posbit = isLiteralBit(bytelit)) != 0) {
7897 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7898 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7899 (posbit-1),0, PO_GPR_REGISTER));
7901 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7902 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7904 if (bytelit == 0xff) {
7905 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7906 * a peephole could optimize it out -- VR */
7907 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7909 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7910 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7913 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7914 pic16_popGetLabel(tlbl->key));
7918 /* old code, left here for reference -- VR 09/2004 */
7919 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921 if((posbit = isLiteralBit(bytelit)) != 0)
7922 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7924 if(bytelit != 0x0FFL)
7925 pic16_emitcode("anl","a,%s",
7926 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7927 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7933 // bit = left & literal
7936 pic16_emitpLabel(tlbl->key);
7938 // if(left & literal)
7941 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7944 pic16_emitpLabel(tlbl->key);
7949 pic16_outBitC(result);
7953 /* if left is same as result */
7954 if(pic16_sameRegs(AOP(result),AOP(left))){
7956 for(;size--; offset++,lit>>=8) {
7957 if(AOP_TYPE(right) == AOP_LIT){
7958 switch(lit & 0xff) {
7960 /* and'ing with 0 has clears the result */
7961 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7962 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7965 /* and'ing with 0xff is a nop when the result and left are the same */
7970 int p = pic16_my_powof2( (~lit) & 0xff );
7972 /* only one bit is set in the literal, so use a bcf instruction */
7973 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7974 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7977 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7978 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7979 if(know_W != (lit&0xff))
7980 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7982 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7987 if (AOP_TYPE(left) == AOP_ACC) {
7988 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7990 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7991 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7998 // left & result in different registers
7999 if(AOP_TYPE(result) == AOP_CRY){
8001 // if(size), result in bit
8002 // if(!size && ifx), conditional oper: if(left & right)
8003 symbol *tlbl = newiTempLabel(NULL);
8004 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
8006 pic16_emitcode("setb","c");
8008 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8009 pic16_emitcode("anl","a,%s",
8010 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8011 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8016 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8017 pic16_outBitC(result);
8019 jmpTrueOrFalse(ifx, tlbl);
8021 for(;(size--);offset++) {
8023 // result = left & right
8024 if(AOP_TYPE(right) == AOP_LIT){
8025 int t = (lit >> (offset*8)) & 0x0FFL;
8028 pic16_emitcode("clrf","%s",
8029 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8030 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8033 pic16_emitcode("movf","%s,w",
8034 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8035 pic16_emitcode("movwf","%s",
8036 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8037 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8038 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8041 pic16_emitcode("movlw","0x%x",t);
8042 pic16_emitcode("andwf","%s,w",
8043 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8044 pic16_emitcode("movwf","%s",
8045 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8047 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8048 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8049 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8054 if (AOP_TYPE(left) == AOP_ACC) {
8055 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8056 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8058 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8059 pic16_emitcode("andwf","%s,w",
8060 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8061 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8062 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8064 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8065 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8071 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8072 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8073 pic16_freeAsmop(result,NULL,ic,TRUE);
8076 /*-----------------------------------------------------------------*/
8077 /* genOr - code for or */
8078 /*-----------------------------------------------------------------*/
8079 static void genOr (iCode *ic, iCode *ifx)
8081 operand *left, *right, *result;
8083 unsigned long lit = 0L;
8085 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8087 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8088 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8089 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8091 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8093 /* if left is a literal & right is not then exchange them */
8094 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8095 AOP_NEEDSACC(left)) {
8096 operand *tmp = right ;
8101 /* if result = right then exchange them */
8102 if(pic16_sameRegs(AOP(result),AOP(right))){
8103 operand *tmp = right ;
8108 /* if right is bit then exchange them */
8109 if (AOP_TYPE(right) == AOP_CRY &&
8110 AOP_TYPE(left) != AOP_CRY){
8111 operand *tmp = right ;
8116 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8118 if(AOP_TYPE(right) == AOP_LIT)
8119 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8121 size = AOP_SIZE(result);
8125 if (AOP_TYPE(left) == AOP_CRY){
8126 if(AOP_TYPE(right) == AOP_LIT){
8127 // c = bit & literal;
8129 // lit != 0 => result = 1
8130 if(AOP_TYPE(result) == AOP_CRY){
8132 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8133 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8134 // AOP(result)->aopu.aop_dir,
8135 // AOP(result)->aopu.aop_dir);
8137 continueIfTrue(ifx);
8141 // lit == 0 => result = left
8142 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8144 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8147 if (AOP_TYPE(right) == AOP_CRY){
8148 if(pic16_sameRegs(AOP(result),AOP(left))){
8150 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8151 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8152 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8154 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8155 AOP(result)->aopu.aop_dir,
8156 AOP(result)->aopu.aop_dir);
8157 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8158 AOP(right)->aopu.aop_dir,
8159 AOP(right)->aopu.aop_dir);
8160 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8161 AOP(result)->aopu.aop_dir,
8162 AOP(result)->aopu.aop_dir);
8164 if( AOP_TYPE(result) == AOP_ACC) {
8165 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8166 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8167 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8168 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8172 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8173 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8174 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8175 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8177 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8178 AOP(result)->aopu.aop_dir,
8179 AOP(result)->aopu.aop_dir);
8180 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8181 AOP(right)->aopu.aop_dir,
8182 AOP(right)->aopu.aop_dir);
8183 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8184 AOP(left)->aopu.aop_dir,
8185 AOP(left)->aopu.aop_dir);
8186 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8187 AOP(result)->aopu.aop_dir,
8188 AOP(result)->aopu.aop_dir);
8193 symbol *tlbl = newiTempLabel(NULL);
8194 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8197 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8198 if( AOP_TYPE(right) == AOP_ACC) {
8199 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8201 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8202 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8207 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8208 pic16_emitcode(";XXX setb","c");
8209 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8210 AOP(left)->aopu.aop_dir,tlbl->key+100);
8211 pic16_toBoolean(right);
8212 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8213 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8214 jmpTrueOrFalse(ifx, tlbl);
8218 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8225 pic16_outBitC(result);
8227 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8228 genIfxJump(ifx, "c");
8232 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8233 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8234 if((AOP_TYPE(right) == AOP_LIT) &&
8235 (AOP_TYPE(result) == AOP_CRY) &&
8236 (AOP_TYPE(left) != AOP_CRY)){
8238 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8241 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8243 continueIfTrue(ifx);
8246 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8247 // lit = 0, result = boolean(left)
8249 pic16_emitcode(";XXX setb","c");
8250 pic16_toBoolean(right);
8252 symbol *tlbl = newiTempLabel(NULL);
8253 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8255 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8257 genIfxJump (ifx,"a");
8261 pic16_outBitC(result);
8265 /* if left is same as result */
8266 if(pic16_sameRegs(AOP(result),AOP(left))){
8268 for(;size--; offset++,lit>>=8) {
8269 if(AOP_TYPE(right) == AOP_LIT){
8270 if((lit & 0xff) == 0)
8271 /* or'ing with 0 has no effect */
8274 int p = pic16_my_powof2(lit & 0xff);
8276 /* only one bit is set in the literal, so use a bsf instruction */
8277 pic16_emitpcode(POC_BSF,
8278 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8280 if(know_W != (lit & 0xff))
8281 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8282 know_W = lit & 0xff;
8283 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8288 if (AOP_TYPE(left) == AOP_ACC) {
8289 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8290 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8292 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8293 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8295 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8296 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8302 // left & result in different registers
8303 if(AOP_TYPE(result) == AOP_CRY){
8305 // if(size), result in bit
8306 // if(!size && ifx), conditional oper: if(left | right)
8307 symbol *tlbl = newiTempLabel(NULL);
8308 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8309 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8313 pic16_emitcode(";XXX setb","c");
8315 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8316 pic16_emitcode(";XXX orl","a,%s",
8317 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8318 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8323 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8324 pic16_outBitC(result);
8326 jmpTrueOrFalse(ifx, tlbl);
8327 } else for(;(size--);offset++){
8329 // result = left & right
8330 if(AOP_TYPE(right) == AOP_LIT){
8331 int t = (lit >> (offset*8)) & 0x0FFL;
8334 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8335 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8337 pic16_emitcode("movf","%s,w",
8338 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8339 pic16_emitcode("movwf","%s",
8340 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8343 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8344 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8345 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8347 pic16_emitcode("movlw","0x%x",t);
8348 pic16_emitcode("iorwf","%s,w",
8349 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8350 pic16_emitcode("movwf","%s",
8351 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8357 // faster than result <- left, anl result,right
8358 // and better if result is SFR
8359 if (AOP_TYPE(left) == AOP_ACC) {
8360 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8361 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8364 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8366 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8367 pic16_emitcode("iorwf","%s,w",
8368 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8370 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8371 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8376 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8377 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8378 pic16_freeAsmop(result,NULL,ic,TRUE);
8381 /*-----------------------------------------------------------------*/
8382 /* genXor - code for xclusive or */
8383 /*-----------------------------------------------------------------*/
8384 static void genXor (iCode *ic, iCode *ifx)
8386 operand *left, *right, *result;
8388 unsigned long lit = 0L;
8390 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8392 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8393 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8394 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8396 /* if left is a literal & right is not ||
8397 if left needs acc & right does not */
8398 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8399 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8400 operand *tmp = right ;
8405 /* if result = right then exchange them */
8406 if(pic16_sameRegs(AOP(result),AOP(right))){
8407 operand *tmp = right ;
8412 /* if right is bit then exchange them */
8413 if (AOP_TYPE(right) == AOP_CRY &&
8414 AOP_TYPE(left) != AOP_CRY){
8415 operand *tmp = right ;
8419 if(AOP_TYPE(right) == AOP_LIT)
8420 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8422 size = AOP_SIZE(result);
8426 if (AOP_TYPE(left) == AOP_CRY){
8427 if(AOP_TYPE(right) == AOP_LIT){
8428 // c = bit & literal;
8430 // lit>>1 != 0 => result = 1
8431 if(AOP_TYPE(result) == AOP_CRY){
8433 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8434 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8436 continueIfTrue(ifx);
8439 pic16_emitcode("setb","c");
8443 // lit == 0, result = left
8444 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8446 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8448 // lit == 1, result = not(left)
8449 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8450 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8451 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8452 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8455 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8456 pic16_emitcode("cpl","c");
8463 symbol *tlbl = newiTempLabel(NULL);
8464 if (AOP_TYPE(right) == AOP_CRY){
8466 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8469 int sizer = AOP_SIZE(right);
8471 // if val>>1 != 0, result = 1
8472 pic16_emitcode("setb","c");
8474 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8476 // test the msb of the lsb
8477 pic16_emitcode("anl","a,#0xfe");
8478 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8482 pic16_emitcode("rrc","a");
8484 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8485 pic16_emitcode("cpl","c");
8486 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8491 pic16_outBitC(result);
8493 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8494 genIfxJump(ifx, "c");
8498 if(pic16_sameRegs(AOP(result),AOP(left))){
8499 /* if left is same as result */
8500 for(;size--; offset++) {
8501 if(AOP_TYPE(right) == AOP_LIT){
8502 int t = (lit >> (offset*8)) & 0x0FFL;
8506 if (IS_AOP_PREG(left)) {
8507 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8508 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8509 pic16_aopPut(AOP(result),"a",offset);
8511 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8512 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8513 pic16_emitcode("xrl","%s,%s",
8514 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8515 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8518 if (AOP_TYPE(left) == AOP_ACC)
8519 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8521 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8522 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8524 if (IS_AOP_PREG(left)) {
8525 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8526 pic16_aopPut(AOP(result),"a",offset);
8528 pic16_emitcode("xrl","%s,a",
8529 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8535 // left & result in different registers
8536 if(AOP_TYPE(result) == AOP_CRY){
8538 // if(size), result in bit
8539 // if(!size && ifx), conditional oper: if(left ^ right)
8540 symbol *tlbl = newiTempLabel(NULL);
8541 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8543 pic16_emitcode("setb","c");
8545 if((AOP_TYPE(right) == AOP_LIT) &&
8546 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8547 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8549 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8550 pic16_emitcode("xrl","a,%s",
8551 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8553 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8558 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8559 pic16_outBitC(result);
8561 jmpTrueOrFalse(ifx, tlbl);
8562 } else for(;(size--);offset++){
8564 // result = left & right
8565 if(AOP_TYPE(right) == AOP_LIT){
8566 int t = (lit >> (offset*8)) & 0x0FFL;
8569 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8570 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8571 pic16_emitcode("movf","%s,w",
8572 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8573 pic16_emitcode("movwf","%s",
8574 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8577 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8578 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8579 pic16_emitcode("comf","%s,w",
8580 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8581 pic16_emitcode("movwf","%s",
8582 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8585 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8586 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8587 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8588 pic16_emitcode("movlw","0x%x",t);
8589 pic16_emitcode("xorwf","%s,w",
8590 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8591 pic16_emitcode("movwf","%s",
8592 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8598 // faster than result <- left, anl result,right
8599 // and better if result is SFR
8600 if (AOP_TYPE(left) == AOP_ACC) {
8601 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8602 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8604 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8605 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8606 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8607 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8609 if ( AOP_TYPE(result) != AOP_ACC){
8610 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8611 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8617 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8618 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8619 pic16_freeAsmop(result,NULL,ic,TRUE);
8622 /*-----------------------------------------------------------------*/
8623 /* genInline - write the inline code out */
8624 /*-----------------------------------------------------------------*/
8625 static void genInline (iCode *ic)
8627 char *buffer, *bp, *bp1;
8629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8631 _G.inLine += (!options.asmpeep);
8633 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8634 strcpy(buffer,IC_INLINE(ic));
8636 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8638 /* emit each line as a code */
8644 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8652 /* print label, use this special format with NULL directive
8653 * to denote that the argument should not be indented with tab */
8654 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8661 if ((bp1 != bp) && *bp1)
8662 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8667 _G.inLine -= (!options.asmpeep);
8670 /*-----------------------------------------------------------------*/
8671 /* genRRC - rotate right with carry */
8672 /*-----------------------------------------------------------------*/
8673 static void genRRC (iCode *ic)
8675 operand *left , *result ;
8676 int size, offset = 0, same;
8678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8680 /* rotate right with carry */
8682 result=IC_RESULT(ic);
8683 pic16_aopOp (left,ic,FALSE);
8684 pic16_aopOp (result,ic,FALSE);
8686 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8688 same = pic16_sameRegs(AOP(result),AOP(left));
8690 size = AOP_SIZE(result);
8692 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8694 /* get the lsb and put it into the carry */
8695 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8702 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8704 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8711 pic16_freeAsmop(left,NULL,ic,TRUE);
8712 pic16_freeAsmop(result,NULL,ic,TRUE);
8715 /*-----------------------------------------------------------------*/
8716 /* genRLC - generate code for rotate left with carry */
8717 /*-----------------------------------------------------------------*/
8718 static void genRLC (iCode *ic)
8720 operand *left , *result ;
8721 int size, offset = 0;
8724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8725 /* rotate right with carry */
8727 result=IC_RESULT(ic);
8728 pic16_aopOp (left,ic,FALSE);
8729 pic16_aopOp (result,ic,FALSE);
8731 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8733 same = pic16_sameRegs(AOP(result),AOP(left));
8735 /* move it to the result */
8736 size = AOP_SIZE(result);
8738 /* get the msb and put it into the carry */
8739 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8746 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8748 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8756 pic16_freeAsmop(left,NULL,ic,TRUE);
8757 pic16_freeAsmop(result,NULL,ic,TRUE);
8761 /* gpasm can get the highest order bit with HIGH/UPPER
8762 * so the following probably is not needed -- VR */
8764 /*-----------------------------------------------------------------*/
8765 /* genGetHbit - generates code get highest order bit */
8766 /*-----------------------------------------------------------------*/
8767 static void genGetHbit (iCode *ic)
8769 operand *left, *result;
8771 result=IC_RESULT(ic);
8772 pic16_aopOp (left,ic,FALSE);
8773 pic16_aopOp (result,ic,FALSE);
8775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8776 /* get the highest order byte into a */
8777 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8778 if(AOP_TYPE(result) == AOP_CRY){
8779 pic16_emitcode("rlc","a");
8780 pic16_outBitC(result);
8783 pic16_emitcode("rl","a");
8784 pic16_emitcode("anl","a,#0x01");
8785 pic16_outAcc(result);
8789 pic16_freeAsmop(left,NULL,ic,TRUE);
8790 pic16_freeAsmop(result,NULL,ic,TRUE);
8794 /*-----------------------------------------------------------------*/
8795 /* AccRol - rotate left accumulator by known count */
8796 /*-----------------------------------------------------------------*/
8797 static void AccRol (int shCount)
8799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8800 shCount &= 0x0007; // shCount : 0..7
8805 pic16_emitcode("rl","a");
8808 pic16_emitcode("rl","a");
8809 pic16_emitcode("rl","a");
8812 pic16_emitcode("swap","a");
8813 pic16_emitcode("rr","a");
8816 pic16_emitcode("swap","a");
8819 pic16_emitcode("swap","a");
8820 pic16_emitcode("rl","a");
8823 pic16_emitcode("rr","a");
8824 pic16_emitcode("rr","a");
8827 pic16_emitcode("rr","a");
8833 /*-----------------------------------------------------------------*/
8834 /* AccLsh - left shift accumulator by known count */
8835 /*-----------------------------------------------------------------*/
8836 static void AccLsh (int shCount)
8838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8844 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8847 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8848 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8851 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8852 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8855 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8858 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8859 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8862 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8863 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8866 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8870 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8873 /*-----------------------------------------------------------------*/
8874 /* AccRsh - right shift accumulator by known count */
8875 /*-----------------------------------------------------------------*/
8876 static void AccRsh (int shCount, int andmask)
8878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8883 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8886 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8887 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8890 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8891 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8894 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8897 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8898 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8901 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8902 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8905 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8910 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8912 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8916 /*-----------------------------------------------------------------*/
8917 /* AccSRsh - signed right shift accumulator by known count */
8918 /*-----------------------------------------------------------------*/
8919 static void AccSRsh (int shCount)
8922 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8925 pic16_emitcode("mov","c,acc.7");
8926 pic16_emitcode("rrc","a");
8927 } else if(shCount == 2){
8928 pic16_emitcode("mov","c,acc.7");
8929 pic16_emitcode("rrc","a");
8930 pic16_emitcode("mov","c,acc.7");
8931 pic16_emitcode("rrc","a");
8933 tlbl = newiTempLabel(NULL);
8934 /* rotate right accumulator */
8935 AccRol(8 - shCount);
8936 /* and kill the higher order bits */
8937 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8938 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8939 pic16_emitcode("orl","a,#0x%02x",
8940 (unsigned char)~SRMask[shCount]);
8941 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8947 /*-----------------------------------------------------------------*/
8948 /* shiftR1Left2Result - shift right one byte from left to result */
8949 /*-----------------------------------------------------------------*/
8950 static void shiftR1Left2ResultSigned (operand *left, int offl,
8951 operand *result, int offr,
8956 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8958 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8962 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8975 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8978 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8987 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8994 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8997 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8998 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9004 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9005 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9006 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9007 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9017 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9019 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9020 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
9021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9027 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9028 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9029 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9030 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9031 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9035 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9037 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9043 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9044 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9045 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9046 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9050 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9058 /*-----------------------------------------------------------------*/
9059 /* shiftR1Left2Result - shift right one byte from left to result */
9060 /*-----------------------------------------------------------------*/
9061 static void shiftR1Left2Result (operand *left, int offl,
9062 operand *result, int offr,
9063 int shCount, int sign)
9067 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9069 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9071 /* Copy the msb into the carry if signed. */
9073 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9083 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9085 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9092 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9095 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9106 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9110 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9112 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9117 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
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(0x0e));
9124 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9126 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9132 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9133 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9134 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9141 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9151 /*-----------------------------------------------------------------*/
9152 /* shiftL1Left2Result - shift left one byte from left to result */
9153 /*-----------------------------------------------------------------*/
9154 static void shiftL1Left2Result (operand *left, int offl,
9155 operand *result, int offr, int shCount)
9160 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9162 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9163 DEBUGpic16_emitcode ("; ***","same = %d",same);
9164 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9166 /* shift left accumulator */
9167 //AccLsh(shCount); // don't comment out just yet...
9168 // pic16_aopPut(AOP(result),"a",offr);
9172 /* Shift left 1 bit position */
9173 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9175 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9177 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9178 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9182 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9183 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9184 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9185 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9188 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9189 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9190 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9192 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9195 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9196 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9200 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9201 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9202 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9203 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9206 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9207 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9210 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9213 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9214 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9219 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9224 /*-----------------------------------------------------------------*/
9225 /* movLeft2Result - move byte from left to result */
9226 /*-----------------------------------------------------------------*/
9227 static void movLeft2Result (operand *left, int offl,
9228 operand *result, int offr)
9231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9232 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9233 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9235 if (*l == '@' && (IS_AOP_PREG(result))) {
9236 pic16_emitcode("mov","a,%s",l);
9237 pic16_aopPut(AOP(result),"a",offr);
9239 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9240 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9245 /*-----------------------------------------------------------------*/
9246 /* shiftL2Left2Result - shift left two bytes from left to result */
9247 /*-----------------------------------------------------------------*/
9248 static void shiftL2Left2Result (operand *left, int offl,
9249 operand *result, int offr, int shCount)
9251 int same = pic16_sameRegs(AOP(result), AOP(left));
9254 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9256 if (same && (offl != offr)) { // shift bytes
9259 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9260 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9262 } else { // just treat as different later on
9275 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9276 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9277 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9281 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9282 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9288 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9289 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9291 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9292 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9293 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9294 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9297 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9301 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9302 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9304 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9305 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9306 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9307 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9308 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9309 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9313 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9314 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9315 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9316 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9317 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9327 /* note, use a mov/add for the shift since the mov has a
9328 chance of getting optimized out */
9329 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9331 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9332 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9333 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9337 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9338 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9344 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9345 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9347 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9348 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9349 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9350 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9351 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9355 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9356 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9360 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9361 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9362 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9365 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9366 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9367 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9368 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9369 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9370 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9371 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9372 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9375 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9376 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9377 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9378 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9379 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9384 /*-----------------------------------------------------------------*/
9385 /* shiftR2Left2Result - shift right two bytes from left to result */
9386 /*-----------------------------------------------------------------*/
9387 static void shiftR2Left2Result (operand *left, int offl,
9388 operand *result, int offr,
9389 int shCount, int sign)
9391 int same = pic16_sameRegs(AOP(result), AOP(left));
9393 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9395 if (same && (offl != offr)) { // shift right bytes
9398 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9399 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9401 } else { // just treat as different later on
9413 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9418 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9419 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9421 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9422 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9424 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9429 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9432 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9433 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9440 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9441 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9442 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9444 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9445 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9446 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9447 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9449 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9450 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9451 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9453 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9454 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9455 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9456 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9457 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9461 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9462 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9466 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9467 pic16_emitpcode(POC_BTFSC,
9468 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9469 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9477 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9478 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9480 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9481 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9482 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9483 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9485 pic16_emitpcode(POC_BTFSC,
9486 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9487 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9489 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9490 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9491 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9492 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9494 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9495 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9496 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9497 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9498 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9499 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9500 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9501 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9503 pic16_emitpcode(POC_BTFSC,
9504 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9505 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9507 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9508 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9515 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9516 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9517 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9518 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9521 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9523 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9528 /*-----------------------------------------------------------------*/
9529 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9530 /*-----------------------------------------------------------------*/
9531 static void shiftLLeftOrResult (operand *left, int offl,
9532 operand *result, int offr, int shCount)
9534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9536 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9537 /* shift left accumulator */
9539 /* or with result */
9540 /* back to result */
9541 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9544 /*-----------------------------------------------------------------*/
9545 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9546 /*-----------------------------------------------------------------*/
9547 static void shiftRLeftOrResult (operand *left, int offl,
9548 operand *result, int offr, int shCount)
9550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9552 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9553 /* shift right accumulator */
9555 /* or with result */
9556 /* back to result */
9557 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9560 /*-----------------------------------------------------------------*/
9561 /* genlshOne - left shift a one byte quantity by known count */
9562 /*-----------------------------------------------------------------*/
9563 static void genlshOne (operand *result, operand *left, int shCount)
9565 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9566 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9569 /*-----------------------------------------------------------------*/
9570 /* genlshTwo - left shift two bytes by known amount != 0 */
9571 /*-----------------------------------------------------------------*/
9572 static void genlshTwo (operand *result,operand *left, int shCount)
9576 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9577 size = pic16_getDataSize(result);
9579 /* if shCount >= 8 */
9585 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9587 movLeft2Result(left, LSB, result, MSB16);
9589 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9592 /* 1 <= shCount <= 7 */
9595 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9597 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9601 /*-----------------------------------------------------------------*/
9602 /* shiftLLong - shift left one long from left to result */
9603 /* offr = LSB or MSB16 */
9604 /*-----------------------------------------------------------------*/
9605 static void shiftLLong (operand *left, operand *result, int offr )
9607 int size = AOP_SIZE(result);
9608 int same = pic16_sameRegs(AOP(left),AOP(result));
9611 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9613 if (same && (offr == MSB16)) { //shift one byte
9614 for(i=size-1;i>=MSB16;i--) {
9615 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9616 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9619 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9622 if (size > LSB+offr ){
9624 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9626 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9627 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9631 if(size > MSB16+offr){
9633 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9635 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9636 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9640 if(size > MSB24+offr){
9642 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9644 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9645 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9649 if(size > MSB32+offr){
9651 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9653 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9654 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9658 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9662 /*-----------------------------------------------------------------*/
9663 /* genlshFour - shift four byte by a known amount != 0 */
9664 /*-----------------------------------------------------------------*/
9665 static void genlshFour (operand *result, operand *left, int shCount)
9669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9670 size = AOP_SIZE(result);
9672 /* if shifting more that 3 bytes */
9673 if (shCount >= 24 ) {
9676 /* lowest order of left goes to the highest
9677 order of the destination */
9678 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9680 movLeft2Result(left, LSB, result, MSB32);
9682 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9683 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9684 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9689 /* more than two bytes */
9690 else if ( shCount >= 16 ) {
9691 /* lower order two bytes goes to higher order two bytes */
9693 /* if some more remaining */
9695 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9697 movLeft2Result(left, MSB16, result, MSB32);
9698 movLeft2Result(left, LSB, result, MSB24);
9700 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9701 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9705 /* if more than 1 byte */
9706 else if ( shCount >= 8 ) {
9707 /* lower order three bytes goes to higher order three bytes */
9711 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9713 movLeft2Result(left, LSB, result, MSB16);
9715 else{ /* size = 4 */
9717 movLeft2Result(left, MSB24, result, MSB32);
9718 movLeft2Result(left, MSB16, result, MSB24);
9719 movLeft2Result(left, LSB, result, MSB16);
9720 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9722 else if(shCount == 1)
9723 shiftLLong(left, result, MSB16);
9725 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9726 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9727 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9728 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9733 /* 1 <= shCount <= 7 */
9734 else if(shCount <= 3)
9736 shiftLLong(left, result, LSB);
9737 while(--shCount >= 1)
9738 shiftLLong(result, result, LSB);
9740 /* 3 <= shCount <= 7, optimize */
9742 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9743 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9744 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9748 /*-----------------------------------------------------------------*/
9749 /* genLeftShiftLiteral - left shifting by known count */
9750 /*-----------------------------------------------------------------*/
9751 void pic16_genLeftShiftLiteral (operand *left,
9756 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9760 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9761 pic16_freeAsmop(right,NULL,ic,TRUE);
9763 pic16_aopOp(left,ic,FALSE);
9764 pic16_aopOp(result,ic,FALSE);
9766 size = getSize(operandType(result));
9769 pic16_emitcode("; shift left ","result %d, left %d",size,
9773 /* I suppose that the left size >= result size */
9776 movLeft2Result(left, size, result, size);
9780 else if(shCount >= (size * 8))
9782 pic16_aopPut(AOP(result),zero,size);
9786 genlshOne (result,left,shCount);
9791 genlshTwo (result,left,shCount);
9795 genlshFour (result,left,shCount);
9799 pic16_freeAsmop(left,NULL,ic,TRUE);
9800 pic16_freeAsmop(result,NULL,ic,TRUE);
9803 /*-----------------------------------------------------------------*
9804 * genMultiAsm - repeat assembly instruction for size of register.
9805 * if endian == 1, then the high byte (i.e base address + size of
9806 * register) is used first else the low byte is used first;
9807 *-----------------------------------------------------------------*/
9808 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9826 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9832 #if !(USE_GENERIC_SIGNED_SHIFT)
9833 /*-----------------------------------------------------------------*/
9834 /* genLeftShift - generates code for left shifting */
9835 /*-----------------------------------------------------------------*/
9836 static void genLeftShift (iCode *ic)
9838 operand *left,*right, *result;
9841 symbol *tlbl , *tlbl1;
9844 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9846 right = IC_RIGHT(ic);
9848 result = IC_RESULT(ic);
9850 pic16_aopOp(right,ic,FALSE);
9852 /* if the shift count is known then do it
9853 as efficiently as possible */
9854 if (AOP_TYPE(right) == AOP_LIT) {
9855 pic16_genLeftShiftLiteral (left,right,result,ic);
9859 /* shift count is unknown then we have to form
9860 * a loop. Get the loop count in WREG : Note: we take
9861 * only the lower order byte since shifting
9862 * more than 32 bits make no sense anyway, ( the
9863 * largest size of an object can be only 32 bits ) */
9865 pic16_aopOp(left,ic,FALSE);
9866 pic16_aopOp(result,ic,FALSE);
9868 /* now move the left to the result if they are not the
9869 * same, and if size > 1,
9870 * and if right is not same to result (!!!) -- VR */
9871 if (!pic16_sameRegs(AOP(left),AOP(result))
9872 && (AOP_SIZE(result) > 1)) {
9874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9876 size = AOP_SIZE(result);
9881 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9882 if (*l == '@' && (IS_AOP_PREG(result))) {
9884 pic16_emitcode("mov","a,%s",l);
9885 pic16_aopPut(AOP(result),"a",offset);
9889 /* we don't know if left is a literal or a register, take care -- VR */
9890 mov2f(AOP(result), AOP(left), offset);
9896 size = AOP_SIZE(result);
9898 /* if it is only one byte then */
9900 if(optimized_for_speed) {
9901 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9902 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9903 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9906 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9907 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9908 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9909 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9910 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9911 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9912 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9917 tlbl = newiTempLabel(NULL);
9920 /* this is already done, why change it? */
9921 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9922 mov2f(AOP(result), AOP(left), 0);
9926 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9927 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9928 pic16_emitpLabel(tlbl->key);
9929 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9930 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9932 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9937 if (pic16_sameRegs(AOP(left),AOP(result))) {
9939 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9941 tlbl = newiTempLabel(NULL);
9942 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9943 genMultiAsm(POC_RRCF, result, size,1);
9944 pic16_emitpLabel(tlbl->key);
9945 genMultiAsm(POC_RLCF, result, size,0);
9946 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9948 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9952 //tlbl = newiTempLabel(NULL);
9954 //tlbl1 = newiTempLabel(NULL);
9956 //reAdjustPreg(AOP(result));
9958 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9959 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9960 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9962 //pic16_emitcode("add","a,acc");
9963 //pic16_aopPut(AOP(result),"a",offset++);
9965 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9967 // pic16_emitcode("rlc","a");
9968 // pic16_aopPut(AOP(result),"a",offset++);
9970 //reAdjustPreg(AOP(result));
9972 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9973 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9976 tlbl = newiTempLabel(NULL);
9977 tlbl1= newiTempLabel(NULL);
9979 size = AOP_SIZE(result);
9982 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9984 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9986 /* offset should be 0, 1 or 3 */
9988 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9990 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9992 pic16_emitpcode(POC_MOVWF, pctemp);
9995 pic16_emitpLabel(tlbl->key);
9998 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10000 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10002 pic16_emitpcode(POC_DECFSZ, pctemp);
10003 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10004 pic16_emitpLabel(tlbl1->key);
10006 pic16_popReleaseTempReg(pctemp,1);
10010 pic16_freeAsmop (right,NULL,ic,TRUE);
10011 pic16_freeAsmop(left,NULL,ic,TRUE);
10012 pic16_freeAsmop(result,NULL,ic,TRUE);
10018 #error old code (left here for reference)
10019 /*-----------------------------------------------------------------*/
10020 /* genLeftShift - generates code for left shifting */
10021 /*-----------------------------------------------------------------*/
10022 static void genLeftShift (iCode *ic)
10024 operand *left,*right, *result;
10027 symbol *tlbl , *tlbl1;
10030 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10032 right = IC_RIGHT(ic);
10033 left = IC_LEFT(ic);
10034 result = IC_RESULT(ic);
10036 pic16_aopOp(right,ic,FALSE);
10038 /* if the shift count is known then do it
10039 as efficiently as possible */
10040 if (AOP_TYPE(right) == AOP_LIT) {
10041 pic16_genLeftShiftLiteral (left,right,result,ic);
10045 /* shift count is unknown then we have to form
10046 a loop get the loop count in B : Note: we take
10047 only the lower order byte since shifting
10048 more that 32 bits make no sense anyway, ( the
10049 largest size of an object can be only 32 bits ) */
10052 pic16_aopOp(left,ic,FALSE);
10053 pic16_aopOp(result,ic,FALSE);
10055 /* now move the left to the result if they are not the
10057 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10058 AOP_SIZE(result) > 1) {
10060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10062 size = AOP_SIZE(result);
10065 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10066 if (*l == '@' && (IS_AOP_PREG(result))) {
10068 pic16_emitcode("mov","a,%s",l);
10069 pic16_aopPut(AOP(result),"a",offset);
10072 /* we don't know if left is a literal or a register, take care -- VR */
10073 mov2f(AOP(result), AOP(left), offset);
10079 size = AOP_SIZE(result);
10081 /* if it is only one byte then */
10083 if(optimized_for_speed) {
10084 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10085 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10086 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10087 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10089 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10090 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10091 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10092 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10093 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10094 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10095 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10100 tlbl = newiTempLabel(NULL);
10101 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10102 mov2f(AOP(result), AOP(left), 0);
10104 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10105 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10108 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10109 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10110 pic16_emitpLabel(tlbl->key);
10111 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10112 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10114 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10119 if (pic16_sameRegs(AOP(left),AOP(result))) {
10121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10123 tlbl = newiTempLabel(NULL);
10124 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10125 genMultiAsm(POC_RRCF, result, size,1);
10126 pic16_emitpLabel(tlbl->key);
10127 genMultiAsm(POC_RLCF, result, size,0);
10128 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10130 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10134 //tlbl = newiTempLabel(NULL);
10136 //tlbl1 = newiTempLabel(NULL);
10138 //reAdjustPreg(AOP(result));
10140 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10141 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10142 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10144 //pic16_emitcode("add","a,acc");
10145 //pic16_aopPut(AOP(result),"a",offset++);
10147 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10149 // pic16_emitcode("rlc","a");
10150 // pic16_aopPut(AOP(result),"a",offset++);
10152 //reAdjustPreg(AOP(result));
10154 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10155 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10158 tlbl = newiTempLabel(NULL);
10159 tlbl1= newiTempLabel(NULL);
10161 size = AOP_SIZE(result);
10164 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10168 /* offset should be 0, 1 or 3 */
10170 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10172 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10174 pic16_emitpcode(POC_MOVWF, pctemp);
10177 pic16_emitpLabel(tlbl->key);
10180 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10182 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10184 pic16_emitpcode(POC_DECFSZ, pctemp);
10185 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10186 pic16_emitpLabel(tlbl1->key);
10188 pic16_popReleaseTempReg(pctemp,1);
10192 pic16_freeAsmop (right,NULL,ic,TRUE);
10193 pic16_freeAsmop(left,NULL,ic,TRUE);
10194 pic16_freeAsmop(result,NULL,ic,TRUE);
10198 /*-----------------------------------------------------------------*/
10199 /* genrshOne - right shift a one byte quantity by known count */
10200 /*-----------------------------------------------------------------*/
10201 static void genrshOne (operand *result, operand *left,
10202 int shCount, int sign)
10204 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10205 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10208 /*-----------------------------------------------------------------*/
10209 /* genrshTwo - right shift two bytes by known amount != 0 */
10210 /*-----------------------------------------------------------------*/
10211 static void genrshTwo (operand *result,operand *left,
10212 int shCount, int sign)
10214 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10215 /* if shCount >= 8 */
10216 if (shCount >= 8) {
10219 shiftR1Left2Result(left, MSB16, result, LSB,
10222 movLeft2Result(left, MSB16, result, LSB);
10224 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10227 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10228 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10232 /* 1 <= shCount <= 7 */
10234 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10237 /*-----------------------------------------------------------------*/
10238 /* shiftRLong - shift right one long from left to result */
10239 /* offl = LSB or MSB16 */
10240 /*-----------------------------------------------------------------*/
10241 static void shiftRLong (operand *left, int offl,
10242 operand *result, int sign)
10244 int size = AOP_SIZE(result);
10245 int same = pic16_sameRegs(AOP(left),AOP(result));
10247 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10249 if (same && (offl == MSB16)) { //shift one byte right
10250 for(i=MSB16;i<size;i++) {
10251 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10252 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10257 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10263 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10265 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10266 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10269 if(offl == MSB16) {
10270 /* add sign of "a" */
10271 pic16_addSign(result, MSB32, sign);
10275 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10277 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10282 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10284 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10285 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10289 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10292 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10293 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10298 /*-----------------------------------------------------------------*/
10299 /* genrshFour - shift four byte by a known amount != 0 */
10300 /*-----------------------------------------------------------------*/
10301 static void genrshFour (operand *result, operand *left,
10302 int shCount, int sign)
10304 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10305 /* if shifting more that 3 bytes */
10306 if(shCount >= 24 ) {
10309 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10311 movLeft2Result(left, MSB32, result, LSB);
10313 pic16_addSign(result, MSB16, sign);
10315 else if(shCount >= 16){
10318 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10320 movLeft2Result(left, MSB24, result, LSB);
10321 movLeft2Result(left, MSB32, result, MSB16);
10323 pic16_addSign(result, MSB24, sign);
10325 else if(shCount >= 8){
10328 shiftRLong(left, MSB16, result, sign);
10329 else if(shCount == 0){
10330 movLeft2Result(left, MSB16, result, LSB);
10331 movLeft2Result(left, MSB24, result, MSB16);
10332 movLeft2Result(left, MSB32, result, MSB24);
10333 pic16_addSign(result, MSB32, sign);
10335 else{ //shcount >= 2
10336 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10337 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10338 /* the last shift is signed */
10339 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10340 pic16_addSign(result, MSB32, sign);
10343 else{ /* 1 <= shCount <= 7 */
10345 shiftRLong(left, LSB, result, sign);
10347 shiftRLong(result, LSB, result, sign);
10350 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10351 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10352 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10357 /*-----------------------------------------------------------------*/
10358 /* genRightShiftLiteral - right shifting by known count */
10359 /*-----------------------------------------------------------------*/
10360 static void genRightShiftLiteral (operand *left,
10366 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10367 int lsize,res_size;
10369 pic16_freeAsmop(right,NULL,ic,TRUE);
10371 pic16_aopOp(left,ic,FALSE);
10372 pic16_aopOp(result,ic,FALSE);
10374 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10377 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10381 lsize = pic16_getDataSize(left);
10382 res_size = pic16_getDataSize(result);
10383 /* test the LEFT size !!! */
10385 /* I suppose that the left size >= result size */
10388 movLeft2Result(left, lsize, result, res_size);
10391 else if(shCount >= (lsize * 8)){
10393 if(res_size == 1) {
10394 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10396 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10397 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10402 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10403 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10404 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10411 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10416 switch (res_size) {
10418 genrshOne (result,left,shCount,sign);
10422 genrshTwo (result,left,shCount,sign);
10426 genrshFour (result,left,shCount,sign);
10434 pic16_freeAsmop(left,NULL,ic,TRUE);
10435 pic16_freeAsmop(result,NULL,ic,TRUE);
10438 #if !(USE_GENERIC_SIGNED_SHIFT)
10439 /*-----------------------------------------------------------------*/
10440 /* genSignedRightShift - right shift of signed number */
10441 /*-----------------------------------------------------------------*/
10442 static void genSignedRightShift (iCode *ic)
10444 operand *right, *left, *result;
10447 symbol *tlbl, *tlbl1 ;
10450 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10452 /* we do it the hard way put the shift count in b
10453 and loop thru preserving the sign */
10454 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10456 right = IC_RIGHT(ic);
10457 left = IC_LEFT(ic);
10458 result = IC_RESULT(ic);
10460 pic16_aopOp(right,ic,FALSE);
10461 pic16_aopOp(left,ic,FALSE);
10462 pic16_aopOp(result,ic,FALSE);
10465 if ( AOP_TYPE(right) == AOP_LIT) {
10466 genRightShiftLiteral (left,right,result,ic,1);
10469 /* shift count is unknown then we have to form
10470 a loop get the loop count in B : Note: we take
10471 only the lower order byte since shifting
10472 more that 32 bits make no sense anyway, ( the
10473 largest size of an object can be only 32 bits ) */
10475 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10476 //pic16_emitcode("inc","b");
10477 //pic16_freeAsmop (right,NULL,ic,TRUE);
10478 //pic16_aopOp(left,ic,FALSE);
10479 //pic16_aopOp(result,ic,FALSE);
10481 /* now move the left to the result if they are not the
10483 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10484 AOP_SIZE(result) > 1) {
10486 size = AOP_SIZE(result);
10490 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10491 if (*l == '@' && IS_AOP_PREG(result)) {
10493 pic16_emitcode("mov","a,%s",l);
10494 pic16_aopPut(AOP(result),"a",offset);
10496 pic16_aopPut(AOP(result),l,offset);
10498 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10499 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10505 /* mov the highest order bit to OVR */
10506 tlbl = newiTempLabel(NULL);
10507 tlbl1= newiTempLabel(NULL);
10509 size = AOP_SIZE(result);
10512 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10514 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10516 /* offset should be 0, 1 or 3 */
10517 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10519 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10521 pic16_emitpcode(POC_MOVWF, pctemp);
10524 pic16_emitpLabel(tlbl->key);
10526 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10527 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10530 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10533 pic16_emitpcode(POC_DECFSZ, pctemp);
10534 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10535 pic16_emitpLabel(tlbl1->key);
10537 pic16_popReleaseTempReg(pctemp,1);
10539 size = AOP_SIZE(result);
10541 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10542 pic16_emitcode("rlc","a");
10543 pic16_emitcode("mov","ov,c");
10544 /* if it is only one byte then */
10546 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10548 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10549 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10550 pic16_emitcode("mov","c,ov");
10551 pic16_emitcode("rrc","a");
10552 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10553 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10554 pic16_aopPut(AOP(result),"a",0);
10558 reAdjustPreg(AOP(result));
10559 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10560 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10561 pic16_emitcode("mov","c,ov");
10563 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10565 pic16_emitcode("rrc","a");
10566 pic16_aopPut(AOP(result),"a",offset--);
10568 reAdjustPreg(AOP(result));
10569 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10570 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10575 pic16_freeAsmop(left,NULL,ic,TRUE);
10576 pic16_freeAsmop(result,NULL,ic,TRUE);
10577 pic16_freeAsmop(right,NULL,ic,TRUE);
10581 #if !(USE_GENERIC_SIGNED_SHIFT)
10582 #warning This implementation of genRightShift() is incomplete!
10583 /*-----------------------------------------------------------------*/
10584 /* genRightShift - generate code for right shifting */
10585 /*-----------------------------------------------------------------*/
10586 static void genRightShift (iCode *ic)
10588 operand *right, *left, *result;
10592 symbol *tlbl, *tlbl1 ;
10594 /* if signed then we do it the hard way preserve the
10595 sign bit moving it inwards */
10596 letype = getSpec(operandType(IC_LEFT(ic)));
10597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10599 if (!SPEC_USIGN(letype)) {
10600 genSignedRightShift (ic);
10604 /* signed & unsigned types are treated the same : i.e. the
10605 signed is NOT propagated inwards : quoting from the
10606 ANSI - standard : "for E1 >> E2, is equivalent to division
10607 by 2**E2 if unsigned or if it has a non-negative value,
10608 otherwise the result is implementation defined ", MY definition
10609 is that the sign does not get propagated */
10611 right = IC_RIGHT(ic);
10612 left = IC_LEFT(ic);
10613 result = IC_RESULT(ic);
10615 pic16_aopOp(right,ic,FALSE);
10617 /* if the shift count is known then do it
10618 as efficiently as possible */
10619 if (AOP_TYPE(right) == AOP_LIT) {
10620 genRightShiftLiteral (left,right,result,ic, 0);
10624 /* shift count is unknown then we have to form
10625 a loop get the loop count in B : Note: we take
10626 only the lower order byte since shifting
10627 more that 32 bits make no sense anyway, ( the
10628 largest size of an object can be only 32 bits ) */
10630 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10631 pic16_emitcode("inc","b");
10632 pic16_aopOp(left,ic,FALSE);
10633 pic16_aopOp(result,ic,FALSE);
10635 /* now move the left to the result if they are not the
10637 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10638 AOP_SIZE(result) > 1) {
10640 size = AOP_SIZE(result);
10643 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10644 if (*l == '@' && IS_AOP_PREG(result)) {
10646 pic16_emitcode("mov","a,%s",l);
10647 pic16_aopPut(AOP(result),"a",offset);
10649 pic16_aopPut(AOP(result),l,offset);
10654 tlbl = newiTempLabel(NULL);
10655 tlbl1= newiTempLabel(NULL);
10656 size = AOP_SIZE(result);
10659 /* if it is only one byte then */
10662 tlbl = newiTempLabel(NULL);
10663 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10664 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10668 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10669 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10670 pic16_emitpLabel(tlbl->key);
10671 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10672 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10674 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10679 reAdjustPreg(AOP(result));
10680 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10681 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10684 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10686 pic16_emitcode("rrc","a");
10687 pic16_aopPut(AOP(result),"a",offset--);
10689 reAdjustPreg(AOP(result));
10691 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10692 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10695 pic16_freeAsmop(left,NULL,ic,TRUE);
10696 pic16_freeAsmop (right,NULL,ic,TRUE);
10697 pic16_freeAsmop(result,NULL,ic,TRUE);
10701 #if (USE_GENERIC_SIGNED_SHIFT)
10702 /*-----------------------------------------------------------------*/
10703 /* genGenericShift - generates code for left or right shifting */
10704 /*-----------------------------------------------------------------*/
10705 static void genGenericShift (iCode *ic, int isShiftLeft) {
10706 operand *left,*right, *result;
10708 int sign, signedCount;
10709 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10710 PIC_OPCODE pos_shift, neg_shift;
10714 right = IC_RIGHT(ic);
10715 left = IC_LEFT(ic);
10716 result = IC_RESULT(ic);
10718 pic16_aopOp(right,ic,FALSE);
10719 pic16_aopOp(left,ic,FALSE);
10720 pic16_aopOp(result,ic,FALSE);
10722 sign = !SPEC_USIGN(operandType (left));
10723 signedCount = !SPEC_USIGN(operandType (right));
10725 /* if the shift count is known then do it
10726 as efficiently as possible */
10727 if (AOP_TYPE(right) == AOP_LIT) {
10728 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10729 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10730 // we should modify right->aopu.aop_lit here!
10731 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10732 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10734 pic16_genLeftShiftLiteral (left,right,result,ic);
10736 genRightShiftLiteral (left,right,result,ic, sign);
10739 } // if (right is literal)
10741 /* shift count is unknown then we have to form a loop.
10742 * Note: we take only the lower order byte since shifting
10743 * more than 32 bits make no sense anyway, ( the
10744 * largest size of an object can be only 32 bits )
10745 * Note: we perform arithmetic shifts if the left operand is
10746 * signed and we do an (effective) right shift, i. e. we
10747 * shift in the sign bit from the left. */
10749 label_complete = newiTempLabel ( NULL );
10750 label_loop_pos = newiTempLabel ( NULL );
10751 label_loop_neg = NULL;
10752 label_negative = NULL;
10753 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10754 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10757 // additional labels needed
10758 label_loop_neg = newiTempLabel ( NULL );
10759 label_negative = newiTempLabel ( NULL );
10762 // copy source to result -- this will effectively truncate the left operand to the size of result!
10763 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10764 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10765 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10766 mov2f (AOP(result),AOP(left), offset);
10769 // if result is longer than left, fill with zeros (or sign)
10770 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10771 if (sign && AOP_SIZE(left) > 0) {
10772 // shift signed operand -- fill with sign
10773 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10774 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10775 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10776 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10777 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10780 // shift unsigned operand -- fill result with zeros
10781 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10782 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10785 } // if (size mismatch)
10787 pic16_mov2w (AOP(right), 0);
10788 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10789 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10792 // perform a shift by one (shift count is positive)
10793 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10794 // 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])
10795 pic16_emitpLabel (label_loop_pos->key);
10797 if (sign && (pos_shift == POC_RRCF)) {
10798 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10801 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10802 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10803 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10805 // perform a shift by one (shift count is positive)
10806 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10807 // 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])
10808 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10809 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10811 pic16_emitpLabel (label_loop_pos->key);
10812 if (sign && (pos_shift == POC_RRCF)) {
10813 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10816 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10817 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10818 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10819 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10823 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10825 pic16_emitpLabel (label_negative->key);
10826 // perform a shift by -1 (shift count is negative)
10827 // 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)
10829 pic16_emitpLabel (label_loop_neg->key);
10830 if (sign && (neg_shift == POC_RRCF)) {
10831 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10834 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10835 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10836 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10837 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10838 } // if (signedCount)
10840 pic16_emitpLabel (label_complete->key);
10843 pic16_freeAsmop (right,NULL,ic,TRUE);
10844 pic16_freeAsmop(left,NULL,ic,TRUE);
10845 pic16_freeAsmop(result,NULL,ic,TRUE);
10848 static void genLeftShift (iCode *ic) {
10849 genGenericShift (ic, 1);
10852 static void genRightShift (iCode *ic) {
10853 genGenericShift (ic, 0);
10858 void pic16_loadFSR0(operand *op)
10860 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10863 /*-----------------------------------------------------------------*/
10864 /* genUnpackBits - generates code for unpacking bits */
10865 /*-----------------------------------------------------------------*/
10866 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10870 sym_link *etype, *letype;
10871 int blen=0, bstr=0;
10875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10876 etype = getSpec(operandType(result));
10877 letype = getSpec(operandType(left));
10879 // if(IS_BITFIELD(etype)) {
10880 blen = SPEC_BLEN(etype);
10881 bstr = SPEC_BSTR(etype);
10884 lbstr = SPEC_BSTR( letype );
10887 if((blen == 1) && (bstr < 8)) {
10888 /* it is a single bit, so use the appropriate bit instructions */
10889 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10891 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10893 if((ptype == POINTER) && (result)) {
10894 /* workaround to reduce the extra lfsr instruction */
10895 pic16_emitpcode(POC_BTFSC,
10896 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10898 pic16_emitpcode(POC_BTFSC,
10899 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10902 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10904 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10910 /* the following call to pic16_loadFSR0 is temporary until
10911 * optimization to handle single bit assignments is added
10912 * to the function. Until then use the old safe way! -- VR */
10913 pic16_loadFSR0( left );
10915 /* read the first byte */
10922 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10925 pic16_emitcode("clr","a");
10926 pic16_emitcode("movc","a","@a+dptr");
10931 /* if we have bitdisplacement then it fits */
10932 /* into this byte completely or if length is */
10933 /* less than a byte */
10934 if ((shCnt = SPEC_BSTR(etype)) ||
10935 (SPEC_BLEN(etype) <= 8)) {
10937 /* shift right acc */
10940 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10941 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10943 /* VR -- normally I would use the following, but since we use the hack,
10944 * to avoid the masking from AccRsh, why not mask it right now? */
10947 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10956 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10957 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10960 /* bit field did not fit in a byte */
10961 rlen = SPEC_BLEN(etype) - 8;
10962 pic16_aopPut(AOP(result),"a",offset++);
10969 pic16_emitcode("inc","%s",rname);
10970 pic16_emitcode("mov","a,@%s",rname);
10974 pic16_emitcode("inc","%s",rname);
10975 pic16_emitcode("movx","a,@%s",rname);
10979 pic16_emitcode("inc","dptr");
10980 pic16_emitcode("movx","a,@dptr");
10984 pic16_emitcode("clr","a");
10985 pic16_emitcode("inc","dptr");
10986 pic16_emitcode("movc","a","@a+dptr");
10990 pic16_emitcode("inc","dptr");
10991 pic16_emitcode("lcall","__gptrget");
10996 /* if we are done */
11000 pic16_aopPut(AOP(result),"a",offset++);
11005 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
11006 pic16_aopPut(AOP(result),"a",offset);
11013 static void genDataPointerGet(operand *left,
11017 int size, offset = 0, leoffset=0 ;
11019 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11020 pic16_aopOp(result, ic, FALSE);
11022 size = AOP_SIZE(result);
11023 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11027 /* The following tests may save a redudant movff instruction when
11028 * accessing unions */
11030 /* if they are the same */
11031 if (operandsEqu (left, result)) {
11032 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11038 /* if they are the same registers */
11039 if (pic16_sameRegs(AOP(left),AOP(result))) {
11040 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11046 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11047 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11048 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11055 if ( AOP_TYPE(left) == AOP_PCODE) {
11056 fprintf(stderr,"genDataPointerGet %s, %d\n",
11057 AOP(left)->aopu.pcop->name,
11058 (AOP(left)->aopu.pcop->type == PO_DIR)?
11059 PCOR(AOP(left)->aopu.pcop)->instance:
11060 PCOI(AOP(left)->aopu.pcop)->offset);
11064 if(AOP(left)->aopu.pcop->type == PO_DIR)
11065 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11067 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11070 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11072 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11073 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11074 pic16_mov2w(AOP(left), offset); // patch 8
11075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11077 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11078 pic16_popGet(AOP(left), offset), //patch 8
11079 pic16_popGet(AOP(result), offset)));
11087 pic16_freeAsmop(result,NULL,ic,TRUE);
11092 /*-----------------------------------------------------------------*/
11093 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11094 /*-----------------------------------------------------------------*/
11095 static void genNearPointerGet (operand *left,
11100 //regs *preg = NULL ;
11101 sym_link *rtype, *retype;
11102 sym_link *ltype = operandType(left);
11106 rtype = operandType(result);
11107 retype= getSpec(rtype);
11109 pic16_aopOp(left,ic,FALSE);
11111 // pic16_DumpOp("(left)",left);
11112 // pic16_DumpOp("(result)",result);
11114 /* if left is rematerialisable and
11115 * result is not bit variable type and
11116 * the left is pointer to data space i.e
11117 * lower 128 bytes of space */
11119 if (AOP_TYPE(left) == AOP_PCODE
11120 && !IS_BITFIELD(retype)
11121 && DCL_TYPE(ltype) == POINTER) {
11123 genDataPointerGet (left,result,ic);
11124 pic16_freeAsmop(left, NULL, ic, TRUE);
11128 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11129 pic16_aopOp (result,ic,FALSE);
11131 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11134 if(IS_BITFIELD( retype )
11135 && (SPEC_BLEN(operandType(result))==1)
11139 int bitstrt, bytestrt;
11141 /* if this is bitfield of size 1, see if we are checking the value
11142 * of a single bit in an if-statement,
11143 * if yes, then don't generate usual code, but execute the
11144 * genIfx directly -- VR */
11148 /* CHECK: if next iCode is IFX
11149 * and current result operand is nextic's conditional operand
11150 * and current result operand live ranges ends at nextic's key number
11152 if((nextic->op == IFX)
11153 && (result == IC_COND(nextic))
11154 && (OP_LIVETO(result) == nextic->seq)
11156 /* everything is ok then */
11157 /* find a way to optimize the genIfx iCode */
11159 bytestrt = SPEC_BSTR(operandType(result))/8;
11160 bitstrt = SPEC_BSTR(operandType(result))%8;
11162 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11164 genIfxpCOpJump(nextic, jop);
11166 pic16_freeAsmop(left, NULL, ic, TRUE);
11167 pic16_freeAsmop(result, NULL, ic, TRUE);
11174 /* if the value is already in a pointer register
11175 * then don't need anything more */
11176 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11177 /* otherwise get a free pointer register */
11178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11180 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11181 /* bitfields will be handled by genUnpackBits */
11182 if(!IS_BITFIELD(retype)) {
11184 if(is_LitAOp( AOP(left) )) {
11185 pic16_loadFSR0( left );
11187 // set up FSR0 with address from left
11188 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11189 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11194 /* if bitfield then unpack the bits */
11195 if (IS_BITFIELD(retype))
11196 genUnpackBits (result, left, NULL, POINTER);
11198 /* we have can just get the values */
11199 int size = AOP_SIZE(result);
11202 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11204 /* fsr0 is loaded already -- VR */
11205 // pic16_loadFSR0( left );
11207 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11208 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11211 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11212 pic16_popGet(AOP(result), offset++)));
11214 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11215 pic16_popGet(AOP(result), offset++)));
11219 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11220 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11222 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11226 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11228 pic16_emitcode("mov","a,@%s",rname);
11229 pic16_aopPut(AOP(result),"a",offset);
11231 sprintf(buffer,"@%s",rname);
11232 pic16_aopPut(AOP(result),buffer,offset);
11236 pic16_emitcode("inc","%s",rname);
11241 /* now some housekeeping stuff */
11243 /* we had to allocate for this iCode */
11244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11245 pic16_freeAsmop(NULL,aop,ic,TRUE);
11247 /* we did not allocate which means left
11248 * already in a pointer register, then
11249 * if size > 0 && this could be used again
11250 * we have to point it back to where it
11252 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11253 if (AOP_SIZE(result) > 1
11254 && !OP_SYMBOL(left)->remat
11255 && ( OP_SYMBOL(left)->liveTo > ic->seq
11257 // int size = AOP_SIZE(result) - 1;
11259 // pic16_emitcode("dec","%s",rname);
11264 pic16_freeAsmop(left,NULL,ic,TRUE);
11265 pic16_freeAsmop(result,NULL,ic,TRUE);
11268 /*-----------------------------------------------------------------*/
11269 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11270 /*-----------------------------------------------------------------*/
11271 static void genPagedPointerGet (operand *left,
11276 regs *preg = NULL ;
11278 sym_link *rtype, *retype;
11280 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11282 rtype = operandType(result);
11283 retype= getSpec(rtype);
11285 pic16_aopOp(left,ic,FALSE);
11287 /* if the value is already in a pointer register
11288 then don't need anything more */
11289 if (!AOP_INPREG(AOP(left))) {
11290 /* otherwise get a free pointer register */
11292 preg = getFreePtr(ic,&aop,FALSE);
11293 pic16_emitcode("mov","%s,%s",
11295 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11296 rname = preg->name ;
11298 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11300 pic16_freeAsmop(left,NULL,ic,TRUE);
11301 pic16_aopOp (result,ic,FALSE);
11303 /* if bitfield then unpack the bits */
11304 if (IS_BITFIELD(retype))
11305 genUnpackBits (result,left,rname,PPOINTER);
11307 /* we have can just get the values */
11308 int size = AOP_SIZE(result);
11313 pic16_emitcode("movx","a,@%s",rname);
11314 pic16_aopPut(AOP(result),"a",offset);
11319 pic16_emitcode("inc","%s",rname);
11323 /* now some housekeeping stuff */
11325 /* we had to allocate for this iCode */
11326 pic16_freeAsmop(NULL,aop,ic,TRUE);
11328 /* we did not allocate which means left
11329 already in a pointer register, then
11330 if size > 0 && this could be used again
11331 we have to point it back to where it
11333 if (AOP_SIZE(result) > 1 &&
11334 !OP_SYMBOL(left)->remat &&
11335 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11337 int size = AOP_SIZE(result) - 1;
11339 pic16_emitcode("dec","%s",rname);
11344 pic16_freeAsmop(result,NULL,ic,TRUE);
11349 /*-----------------------------------------------------------------*/
11350 /* genFarPointerGet - gget value from far space */
11351 /*-----------------------------------------------------------------*/
11352 static void genFarPointerGet (operand *left,
11353 operand *result, iCode *ic)
11356 sym_link *retype = getSpec(operandType(result));
11358 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11360 pic16_aopOp(left,ic,FALSE);
11362 /* if the operand is already in dptr
11363 then we do nothing else we move the value to dptr */
11364 if (AOP_TYPE(left) != AOP_STR) {
11365 /* if this is remateriazable */
11366 if (AOP_TYPE(left) == AOP_IMMD)
11367 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11368 else { /* we need to get it byte by byte */
11369 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11370 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11371 if (options.model == MODEL_FLAT24)
11373 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11377 /* so dptr know contains the address */
11378 pic16_freeAsmop(left,NULL,ic,TRUE);
11379 pic16_aopOp(result,ic,FALSE);
11381 /* if bit then unpack */
11382 if (IS_BITFIELD(retype))
11383 genUnpackBits(result,left,"dptr",FPOINTER);
11385 size = AOP_SIZE(result);
11389 pic16_emitcode("movx","a,@dptr");
11390 pic16_aopPut(AOP(result),"a",offset++);
11392 pic16_emitcode("inc","dptr");
11396 pic16_freeAsmop(result,NULL,ic,TRUE);
11400 /*-----------------------------------------------------------------*/
11401 /* genCodePointerGet - get value from code space */
11402 /*-----------------------------------------------------------------*/
11403 static void genCodePointerGet (operand *left,
11404 operand *result, iCode *ic)
11407 sym_link *retype = getSpec(operandType(result));
11409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11411 pic16_aopOp(left,ic,FALSE);
11413 /* if the operand is already in dptr
11414 then we do nothing else we move the value to dptr */
11415 if (AOP_TYPE(left) != AOP_STR) {
11416 /* if this is remateriazable */
11417 if (AOP_TYPE(left) == AOP_IMMD)
11418 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11419 else { /* we need to get it byte by byte */
11420 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11421 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11422 if (options.model == MODEL_FLAT24)
11424 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11428 /* so dptr know contains the address */
11429 pic16_freeAsmop(left,NULL,ic,TRUE);
11430 pic16_aopOp(result,ic,FALSE);
11432 /* if bit then unpack */
11433 if (IS_BITFIELD(retype))
11434 genUnpackBits(result,left,"dptr",CPOINTER);
11436 size = AOP_SIZE(result);
11440 pic16_emitcode("clr","a");
11441 pic16_emitcode("movc","a,@a+dptr");
11442 pic16_aopPut(AOP(result),"a",offset++);
11444 pic16_emitcode("inc","dptr");
11448 pic16_freeAsmop(result,NULL,ic,TRUE);
11453 /*-----------------------------------------------------------------*/
11454 /* genGenPointerGet - gget value from generic pointer space */
11455 /*-----------------------------------------------------------------*/
11456 static void genGenPointerGet (operand *left,
11457 operand *result, iCode *ic)
11459 int size, offset, lit;
11460 sym_link *retype = getSpec(operandType(result));
11462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11463 pic16_aopOp(left,ic,FALSE);
11464 pic16_aopOp(result,ic,FALSE);
11465 size = AOP_SIZE(result);
11467 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11469 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11471 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11472 // load FSR0 from immediate
11473 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11475 // pic16_loadFSR0( left );
11480 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11482 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11489 else { /* we need to get it byte by byte */
11490 // set up FSR0 with address from left
11491 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11500 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11507 /* if bit then unpack */
11508 if (IS_BITFIELD(retype))
11509 genUnpackBits(result,left,"BAD",GPOINTER);
11512 pic16_freeAsmop(left,NULL,ic,TRUE);
11513 pic16_freeAsmop(result,NULL,ic,TRUE);
11519 /*-----------------------------------------------------------------*/
11520 /* genGenPointerGet - gget value from generic pointer space */
11521 /*-----------------------------------------------------------------*/
11522 static void genGenPointerGet (operand *left,
11523 operand *result, iCode *ic)
11525 int size, offset, lit;
11526 sym_link *retype = getSpec(operandType(result));
11529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11530 pic16_aopOp(left,ic,FALSE);
11531 pic16_aopOp(result,ic,FALSE);
11532 size = AOP_SIZE(result);
11534 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11536 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11538 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11539 // load FSR0 from immediate
11540 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11542 werror(W_POSSBUG2, __FILE__, __LINE__);
11547 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11549 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11556 } else { /* we need to get it byte by byte */
11558 /* set up WREG:PRODL:FSR0L with address from left */
11559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11560 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11561 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11564 case 1: strcpy(fgptrget, "__gptrget1"); break;
11565 case 2: strcpy(fgptrget, "__gptrget2"); break;
11566 case 3: strcpy(fgptrget, "__gptrget3"); break;
11567 case 4: strcpy(fgptrget, "__gptrget4"); break;
11569 werror(W_POSSBUG2, __FILE__, __LINE__);
11573 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11575 assignResultValue(result, 1);
11580 sym = newSymbol( fgptrget, 0 );
11581 strcpy(sym->rname, fgptrget);
11582 checkAddSym(&externs, sym);
11584 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11590 /* if bit then unpack */
11591 if (IS_BITFIELD(retype))
11592 genUnpackBits(result,left,"BAD",GPOINTER);
11595 pic16_freeAsmop(left,NULL,ic,TRUE);
11596 pic16_freeAsmop(result,NULL,ic,TRUE);
11599 /*-----------------------------------------------------------------*/
11600 /* genConstPointerGet - get value from const generic pointer space */
11601 /*-----------------------------------------------------------------*/
11602 static void genConstPointerGet (operand *left,
11603 operand *result, iCode *ic)
11605 //sym_link *retype = getSpec(operandType(result));
11606 // symbol *albl = newiTempLabel(NULL); // patch 15
11607 // symbol *blbl = newiTempLabel(NULL); //
11608 // PIC_OPCODE poc; // patch 15
11612 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11613 pic16_aopOp(left,ic,FALSE);
11614 pic16_aopOp(result,ic,TRUE);
11615 size = AOP_SIZE(result);
11617 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11619 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11621 // set up table pointer
11622 if( (AOP_TYPE(left) == AOP_PCODE)
11623 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11624 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11626 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11627 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11628 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11629 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11630 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11631 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11633 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11634 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11635 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11639 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11640 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11644 pic16_freeAsmop(left,NULL,ic,TRUE);
11645 pic16_freeAsmop(result,NULL,ic,TRUE);
11649 /*-----------------------------------------------------------------*/
11650 /* genPointerGet - generate code for pointer get */
11651 /*-----------------------------------------------------------------*/
11652 static void genPointerGet (iCode *ic)
11654 operand *left, *result ;
11655 sym_link *type, *etype;
11660 left = IC_LEFT(ic);
11661 result = IC_RESULT(ic) ;
11663 /* depending on the type of pointer we need to
11664 move it to the correct pointer register */
11665 type = operandType(left);
11666 etype = getSpec(type);
11669 if (IS_PTR_CONST(type))
11671 if (IS_CODEPTR(type))
11673 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11675 /* if left is of type of pointer then it is simple */
11676 if (IS_PTR(type) && !IS_FUNC(type->next))
11677 p_type = DCL_TYPE(type);
11679 /* we have to go by the storage class */
11680 p_type = PTR_TYPE(SPEC_OCLS(etype));
11682 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11684 if (SPEC_OCLS(etype)->codesp ) {
11685 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11686 //p_type = CPOINTER ;
11688 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11689 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11690 /*p_type = FPOINTER ;*/
11692 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11693 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11694 /* p_type = PPOINTER; */
11696 if (SPEC_OCLS(etype) == idata ) {
11697 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11698 /* p_type = IPOINTER; */
11700 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11701 /* p_type = POINTER ; */
11705 /* now that we have the pointer type we assign
11706 the pointer values */
11710 genNearPointerGet (left,result,ic);
11714 genPagedPointerGet(left,result,ic);
11718 genFarPointerGet (left,result,ic);
11722 genConstPointerGet (left,result,ic);
11723 //pic16_emitcodePointerGet (left,result,ic);
11728 if (IS_PTR_CONST(type))
11729 genConstPointerGet (left,result,ic);
11732 genGenPointerGet (left,result,ic);
11736 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11737 "genPointerGet: illegal pointer type");
11742 /*-----------------------------------------------------------------*/
11743 /* genPackBits - generates code for packed bit storage */
11744 /*-----------------------------------------------------------------*/
11745 static void genPackBits (sym_link *etype , operand *result,
11747 char *rname, int p_type)
11756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11757 blen = SPEC_BLEN(etype);
11758 bstr = SPEC_BSTR(etype);
11760 retype = getSpec(operandType(right));
11762 if(AOP_TYPE(right) == AOP_LIT) {
11763 if((blen == 1) && (bstr < 8)) {
11765 /* it is a single bit, so use the appropriate bit instructions */
11767 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11769 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11770 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11771 if((p_type == POINTER) && (result)) {
11772 /* workaround to reduce the extra lfsr instruction */
11774 pic16_emitpcode(POC_BSF,
11775 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11777 pic16_emitpcode(POC_BCF,
11778 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11781 pic16_loadFSR0( result );
11783 pic16_emitpcode(POC_BSF,
11784 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11786 pic16_emitpcode(POC_BCF,
11787 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11794 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11797 if(IS_BITFIELD(retype)
11798 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11802 rblen = SPEC_BLEN( retype );
11803 rbstr = SPEC_BSTR( retype );
11806 if(IS_BITFIELD(etype)) {
11807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11808 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11810 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11813 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11815 if(IS_BITFIELD(etype)) {
11816 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11818 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11821 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11825 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11827 /* if the bit length is less than or */
11828 /* it exactly fits a byte then */
11829 if((shCnt=SPEC_BSTR(etype))
11830 || SPEC_BLEN(etype) <= 8 ) {
11831 int fsr0_setup = 0;
11833 if (blen != 8 || bstr != 0) {
11834 // we need to combine the value with the old value
11835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11837 /* shift left acc */
11840 /* using PRODH as a temporary register here */
11841 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11843 /* get old value */
11847 pic16_loadFSR0( result );
11849 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11850 // pic16_emitcode ("mov","b,a");
11851 // pic16_emitcode("mov","a,@%s",rname);
11855 if (AOP(result)->aopu.aop_reg[2]) {
11856 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11857 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11858 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11859 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11860 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
11863 sym = newSymbol( "__gptrget1", 0 );
11864 strcpy(sym->rname, "__gptrget1");
11865 checkAddSym(&externs, sym);
11868 // data pointer (just 2 byte given)
11869 pic16_loadFSR0( result );
11871 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11874 // warnings will be emitted below
11875 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11876 //werror(W_POSSBUG2, __FILE__, __LINE__);
11880 assert (0 && "invalid pointer type specified");
11884 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11885 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11886 (unsigned char)(0xff >> (8-bstr))) ));
11887 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11888 } // if (blen != 8 || bstr != 0)
11890 /* write new value back */
11894 if (!fsr0_setup) pic16_loadFSR0( result );
11895 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11899 if (AOP(result)->aopu.aop_reg[2]) {
11900 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11901 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11902 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11903 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11904 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11905 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
11908 sym = newSymbol( "__gptrput1", 0 );
11909 strcpy(sym->rname, "__gptrput1");
11910 checkAddSym(&externs, sym);
11913 // data pointer (just 2 byte given)
11914 if (!fsr0_setup) pic16_loadFSR0( result );
11915 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11918 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11919 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11920 werror(W_POSSBUG2, __FILE__, __LINE__);
11924 assert (0 && "invalid pointer type specified");
11933 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11934 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11939 if ( SPEC_BLEN(etype) <= 8 )
11942 pic16_emitcode("inc","%s",rname);
11943 rLen = SPEC_BLEN(etype) ;
11947 /* now generate for lengths greater than one byte */
11950 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11960 pic16_emitcode("mov","@%s,a",rname);
11962 pic16_emitcode("mov","@%s,%s",rname,l);
11967 pic16_emitcode("movx","@dptr,a");
11972 DEBUGpic16_emitcode(";lcall","__gptrput");
11975 pic16_emitcode ("inc","%s",rname);
11980 /* last last was not complete */
11982 /* save the byte & read byte */
11985 pic16_emitcode ("mov","b,a");
11986 pic16_emitcode("mov","a,@%s",rname);
11990 pic16_emitcode ("mov","b,a");
11991 pic16_emitcode("movx","a,@dptr");
11995 pic16_emitcode ("push","b");
11996 pic16_emitcode ("push","acc");
11997 pic16_emitcode ("lcall","__gptrget");
11998 pic16_emitcode ("pop","b");
12002 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
12003 pic16_emitcode ("orl","a,b");
12006 if (p_type == GPOINTER)
12007 pic16_emitcode("pop","b");
12012 pic16_emitcode("mov","@%s,a",rname);
12016 pic16_emitcode("movx","@dptr,a");
12020 DEBUGpic16_emitcode(";lcall","__gptrput");
12024 /*-----------------------------------------------------------------*/
12025 /* genDataPointerSet - remat pointer to data space */
12026 /*-----------------------------------------------------------------*/
12027 static void genDataPointerSet(operand *right,
12031 int size, offset = 0, resoffset=0 ;
12033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12034 pic16_aopOp(right,ic,FALSE);
12036 size = AOP_SIZE(right);
12038 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12041 if ( AOP_TYPE(result) == AOP_PCODE) {
12042 fprintf(stderr,"genDataPointerSet %s, %d\n",
12043 AOP(result)->aopu.pcop->name,
12044 (AOP(result)->aopu.pcop->type == PO_DIR)?
12045 PCOR(AOP(result)->aopu.pcop)->instance:
12046 PCOI(AOP(result)->aopu.pcop)->offset);
12050 if(AOP(result)->aopu.pcop->type == PO_DIR)
12051 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12054 if (AOP_TYPE(right) == AOP_LIT) {
12057 if(!IS_FLOAT(operandType( right )))
12058 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12061 unsigned long lit_int;
12065 /* take care if literal is a float */
12066 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
12067 lit = info.lit_int;
12070 lit = lit >> (8*offset);
12072 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
12073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
12075 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
12078 pic16_mov2w(AOP(right), offset);
12079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
12085 pic16_freeAsmop(right,NULL,ic,TRUE);
12090 /*-----------------------------------------------------------------*/
12091 /* genNearPointerSet - pic16_emitcode for near pointer put */
12092 /*-----------------------------------------------------------------*/
12093 static void genNearPointerSet (operand *right,
12100 sym_link *ptype = operandType(result);
12101 sym_link *resetype;
12103 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12104 retype= getSpec(operandType(right));
12105 resetype = getSpec(operandType(result));
12107 pic16_aopOp(result,ic,FALSE);
12109 /* if the result is rematerializable &
12110 * in data space & not a bit variable */
12112 /* and result is not a bit variable */
12113 if (AOP_TYPE(result) == AOP_PCODE
12114 // && AOP_TYPE(result) == AOP_IMMD
12115 && DCL_TYPE(ptype) == POINTER
12116 && !IS_BITFIELD(retype)
12117 && !IS_BITFIELD(resetype)) {
12119 genDataPointerSet (right,result,ic);
12120 pic16_freeAsmop(result,NULL,ic,TRUE);
12124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12125 pic16_aopOp(right,ic,FALSE);
12126 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12128 /* if the value is already in a pointer register
12129 * then don't need anything more */
12130 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12131 /* otherwise get a free pointer register */
12132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12134 // if( (AOP_TYPE(result) == AOP_PCODE)
12135 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12136 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12137 if(is_LitAOp( AOP(result) ))
12139 if(!IS_BITFIELD(resetype))
12140 pic16_loadFSR0( result ); // patch 10
12142 if(!IS_BITFIELD(resetype)) {
12143 // set up FSR0 with address of result
12144 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12151 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12153 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12155 // pic16_loadFSR0( result );
12157 /* if bitfield then unpack the bits */
12158 if (IS_BITFIELD(resetype)) {
12159 genPackBits (resetype, result, right, NULL, POINTER);
12161 /* we have can just get the values */
12162 int size = AOP_SIZE(right);
12165 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12167 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12170 //pic16_emitcode("mov","@%s,a",rname);
12171 pic16_emitcode("movf","indf0,w ;1");
12174 if (AOP_TYPE(right) == AOP_LIT) {
12175 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12177 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12179 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12181 } else { // no literal
12183 pic16_emitpcode(POC_MOVFF,
12184 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12185 pic16_popCopyReg(&pic16_pc_postinc0)));
12187 pic16_emitpcode(POC_MOVFF,
12188 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12189 pic16_popCopyReg(&pic16_pc_indf0)));
12197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12198 /* now some housekeeping stuff */
12200 /* we had to allocate for this iCode */
12201 pic16_freeAsmop(NULL,aop,ic,TRUE);
12203 /* we did not allocate which means left
12204 * already in a pointer register, then
12205 * if size > 0 && this could be used again
12206 * we have to point it back to where it
12208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12209 if (AOP_SIZE(right) > 1
12210 && !OP_SYMBOL(result)->remat
12211 && ( OP_SYMBOL(result)->liveTo > ic->seq
12214 int size = AOP_SIZE(right) - 1;
12217 pic16_emitcode("decf","fsr0,f");
12218 //pic16_emitcode("dec","%s",rname);
12222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12225 pic16_freeAsmop(right,NULL,ic,TRUE);
12226 pic16_freeAsmop(result,NULL,ic,TRUE);
12229 /*-----------------------------------------------------------------*/
12230 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12231 /*-----------------------------------------------------------------*/
12232 static void genPagedPointerSet (operand *right,
12237 regs *preg = NULL ;
12241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12243 retype= getSpec(operandType(right));
12245 pic16_aopOp(result,ic,FALSE);
12247 /* if the value is already in a pointer register
12248 then don't need anything more */
12249 if (!AOP_INPREG(AOP(result))) {
12250 /* otherwise get a free pointer register */
12252 preg = getFreePtr(ic,&aop,FALSE);
12253 pic16_emitcode("mov","%s,%s",
12255 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12256 rname = preg->name ;
12258 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12260 pic16_freeAsmop(result,NULL,ic,TRUE);
12261 pic16_aopOp (right,ic,FALSE);
12263 /* if bitfield then unpack the bits */
12264 if (IS_BITFIELD(retype))
12265 genPackBits (retype,result,right,rname,PPOINTER);
12267 /* we have can just get the values */
12268 int size = AOP_SIZE(right);
12272 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12275 pic16_emitcode("movx","@%s,a",rname);
12278 pic16_emitcode("inc","%s",rname);
12284 /* now some housekeeping stuff */
12286 /* we had to allocate for this iCode */
12287 pic16_freeAsmop(NULL,aop,ic,TRUE);
12289 /* we did not allocate which means left
12290 already in a pointer register, then
12291 if size > 0 && this could be used again
12292 we have to point it back to where it
12294 if (AOP_SIZE(right) > 1 &&
12295 !OP_SYMBOL(result)->remat &&
12296 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12298 int size = AOP_SIZE(right) - 1;
12300 pic16_emitcode("dec","%s",rname);
12305 pic16_freeAsmop(right,NULL,ic,TRUE);
12310 /*-----------------------------------------------------------------*/
12311 /* genFarPointerSet - set value from far space */
12312 /*-----------------------------------------------------------------*/
12313 static void genFarPointerSet (operand *right,
12314 operand *result, iCode *ic)
12317 sym_link *retype = getSpec(operandType(right));
12319 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12320 pic16_aopOp(result,ic,FALSE);
12322 /* if the operand is already in dptr
12323 then we do nothing else we move the value to dptr */
12324 if (AOP_TYPE(result) != AOP_STR) {
12325 /* if this is remateriazable */
12326 if (AOP_TYPE(result) == AOP_IMMD)
12327 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12328 else { /* we need to get it byte by byte */
12329 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12330 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12331 if (options.model == MODEL_FLAT24)
12333 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12337 /* so dptr know contains the address */
12338 pic16_freeAsmop(result,NULL,ic,TRUE);
12339 pic16_aopOp(right,ic,FALSE);
12341 /* if bit then unpack */
12342 if (IS_BITFIELD(retype))
12343 genPackBits(retype,result,right,"dptr",FPOINTER);
12345 size = AOP_SIZE(right);
12349 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12351 pic16_emitcode("movx","@dptr,a");
12353 pic16_emitcode("inc","dptr");
12357 pic16_freeAsmop(right,NULL,ic,TRUE);
12360 /*-----------------------------------------------------------------*/
12361 /* genGenPointerSet - set value from generic pointer space */
12362 /*-----------------------------------------------------------------*/
12364 static void genGenPointerSet (operand *right,
12365 operand *result, iCode *ic)
12367 int i, size, offset, lit;
12368 sym_link *retype = getSpec(operandType(right));
12370 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12372 pic16_aopOp(result,ic,FALSE);
12373 pic16_aopOp(right,ic,FALSE);
12374 size = AOP_SIZE(right);
12377 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12379 /* if the operand is already in dptr
12380 then we do nothing else we move the value to dptr */
12381 if (AOP_TYPE(result) != AOP_STR) {
12382 /* if this is remateriazable */
12383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12384 // WARNING: anythig until "else" is untested!
12385 if (AOP_TYPE(result) == AOP_IMMD) {
12386 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12387 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12388 // load FSR0 from immediate
12389 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12393 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12401 else { /* we need to get it byte by byte */
12402 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12403 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12405 // set up FSR0 with address of result
12406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12407 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12409 /* hack hack! see if this the FSR. If so don't load W */
12410 if(AOP_TYPE(right) != AOP_ACC) {
12412 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12414 if(AOP_TYPE(right) == AOP_LIT)
12417 // note: pic16_popGet handles sign extension
12418 for(i=0;i<size;i++) {
12419 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12421 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12423 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12428 for(i=0;i<size;i++) {
12430 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12431 pic16_popCopyReg(&pic16_pc_postinc0)));
12433 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12434 pic16_popCopyReg(&pic16_pc_indf0)));
12440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12441 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12443 } // if (AOP_TYPE(result) != AOP_IMMD)
12445 } // if (AOP_TYPE(result) != AOP_STR)
12446 /* so dptr know contains the address */
12449 /* if bit then unpack */
12450 if (IS_BITFIELD(retype))
12451 genPackBits(retype,result,right,"dptr",GPOINTER);
12453 size = AOP_SIZE(right);
12456 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12458 // set up FSR0 with address of result
12459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12460 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12463 if (AOP_TYPE(right) == AOP_LIT) {
12464 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12466 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12468 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12470 } else { // no literal
12472 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12474 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12482 pic16_freeAsmop(right,NULL,ic,TRUE);
12483 pic16_freeAsmop(result,NULL,ic,TRUE);
12487 static void genGenPointerSet (operand *right,
12488 operand *result, iCode *ic)
12491 sym_link *retype = getSpec(operandType(right));
12494 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12496 pic16_aopOp(result,ic,FALSE);
12497 pic16_aopOp(right,ic,FALSE);
12498 size = AOP_SIZE(right);
12500 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12503 /* if bit then unpack */
12504 if (IS_BITFIELD(retype)) {
12505 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12506 genPackBits(retype,result,right,"dptr",GPOINTER);
12510 size = AOP_SIZE(right);
12512 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12516 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12518 /* value of right+0 is placed on stack, which will be retrieved
12519 * by the support function this restoring the stack. The important
12520 * thing is that there is no need to manually restore stack pointer
12522 pushaop(AOP(right), 0);
12523 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12524 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12525 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12526 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12528 /* load address to write to in WREG:FSR0H:FSR0L */
12529 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12530 pic16_popCopyReg(&pic16_pc_fsr0l)));
12531 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12532 pic16_popCopyReg(&pic16_pc_prodl)));
12533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12536 /* put code here */
12538 case 1: strcpy(fgptrput, "__gptrput1"); break;
12539 case 2: strcpy(fgptrput, "__gptrput2"); break;
12540 case 3: strcpy(fgptrput, "__gptrput3"); break;
12541 case 4: strcpy(fgptrput, "__gptrput4"); break;
12543 werror(W_POSSBUG2, __FILE__, __LINE__);
12547 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12552 sym = newSymbol( fgptrput, 0 );
12553 strcpy(sym->rname, fgptrput);
12554 checkAddSym(&externs, sym);
12558 pic16_freeAsmop(right,NULL,ic,TRUE);
12559 pic16_freeAsmop(result,NULL,ic,TRUE);
12562 /*-----------------------------------------------------------------*/
12563 /* genPointerSet - stores the value into a pointer location */
12564 /*-----------------------------------------------------------------*/
12565 static void genPointerSet (iCode *ic)
12567 operand *right, *result ;
12568 sym_link *type, *etype;
12573 right = IC_RIGHT(ic);
12574 result = IC_RESULT(ic) ;
12576 /* depending on the type of pointer we need to
12577 move it to the correct pointer register */
12578 type = operandType(result);
12579 etype = getSpec(type);
12580 /* if left is of type of pointer then it is simple */
12581 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12582 p_type = DCL_TYPE(type);
12585 /* we have to go by the storage class */
12586 p_type = PTR_TYPE(SPEC_OCLS(etype));
12588 /* if (SPEC_OCLS(etype)->codesp ) { */
12589 /* p_type = CPOINTER ; */
12592 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12593 /* p_type = FPOINTER ; */
12595 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12596 /* p_type = PPOINTER ; */
12598 /* if (SPEC_OCLS(etype) == idata ) */
12599 /* p_type = IPOINTER ; */
12601 /* p_type = POINTER ; */
12604 /* now that we have the pointer type we assign
12605 the pointer values */
12609 genNearPointerSet (right,result,ic);
12613 genPagedPointerSet (right,result,ic);
12617 genFarPointerSet (right,result,ic);
12621 genGenPointerSet (right,result,ic);
12625 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12626 "genPointerSet: illegal pointer type");
12630 /*-----------------------------------------------------------------*/
12631 /* genIfx - generate code for Ifx statement */
12632 /*-----------------------------------------------------------------*/
12633 static void genIfx (iCode *ic, iCode *popIc)
12635 operand *cond = IC_COND(ic);
12640 pic16_aopOp(cond,ic,FALSE);
12642 /* get the value into acc */
12643 if (AOP_TYPE(cond) != AOP_CRY)
12644 pic16_toBoolean(cond);
12647 /* the result is now in the accumulator */
12648 pic16_freeAsmop(cond,NULL,ic,TRUE);
12650 /* if there was something to be popped then do it */
12654 /* if the condition is a bit variable */
12655 if (isbit && IS_ITEMP(cond) &&
12657 genIfxJump(ic,"c");
12658 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12660 if (isbit && !IS_ITEMP(cond))
12661 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12663 genIfxJump(ic,"a");
12668 /*-----------------------------------------------------------------*/
12669 /* genAddrOf - generates code for address of */
12670 /*-----------------------------------------------------------------*/
12671 static void genAddrOf (iCode *ic)
12673 operand *result, *left;
12675 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12676 pCodeOp *pcop0, *pcop1, *pcop2;
12680 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12682 sym = OP_SYMBOL( IC_LEFT(ic) );
12685 /* get address of symbol on stack */
12686 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12688 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12689 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12692 // operands on stack are accessible via "FSR2 + index" with index
12693 // starting at 2 for arguments and growing from 0 downwards for
12694 // local variables (index == 0 is not assigned so we add one here)
12696 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12698 assert (soffs < 0);
12701 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12702 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12703 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12704 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12705 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12706 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12707 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12713 // if(pic16_debug_verbose) {
12714 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12715 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12718 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12719 size = AOP_SIZE(IC_RESULT(ic));
12721 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12722 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12723 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12726 pic16_emitpcode(POC_MOVLW, pcop0);
12727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12728 pic16_emitpcode(POC_MOVLW, pcop1);
12729 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12730 pic16_emitpcode(POC_MOVLW, pcop2);
12731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12734 pic16_emitpcode(POC_MOVLW, pcop0);
12735 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12736 pic16_emitpcode(POC_MOVLW, pcop1);
12737 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12739 pic16_emitpcode(POC_MOVLW, pcop0);
12740 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12743 pic16_freeAsmop(left, NULL, ic, FALSE);
12745 pic16_freeAsmop(result,NULL,ic,TRUE);
12750 /*-----------------------------------------------------------------*/
12751 /* genFarFarAssign - assignment when both are in far space */
12752 /*-----------------------------------------------------------------*/
12753 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12755 int size = AOP_SIZE(right);
12758 /* first push the right side on to the stack */
12760 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12762 pic16_emitcode ("push","acc");
12765 pic16_freeAsmop(right,NULL,ic,FALSE);
12766 /* now assign DPTR to result */
12767 pic16_aopOp(result,ic,FALSE);
12768 size = AOP_SIZE(result);
12770 pic16_emitcode ("pop","acc");
12771 pic16_aopPut(AOP(result),"a",--offset);
12773 pic16_freeAsmop(result,NULL,ic,FALSE);
12778 /*-----------------------------------------------------------------*/
12779 /* genAssign - generate code for assignment */
12780 /*-----------------------------------------------------------------*/
12781 static void genAssign (iCode *ic)
12783 operand *result, *right;
12784 int size, offset,know_W;
12785 unsigned long lit = 0L;
12787 result = IC_RESULT(ic);
12788 right = IC_RIGHT(ic) ;
12792 /* if they are the same */
12793 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12796 /* reversed order operands are aopOp'ed so that result operand
12797 * is effective in case right is a stack symbol. This maneauver
12798 * allows to use the _G.resDirect flag later */
12799 pic16_aopOp(result,ic,TRUE);
12800 pic16_aopOp(right,ic,FALSE);
12802 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12804 /* if they are the same registers */
12805 if (pic16_sameRegs(AOP(right),AOP(result)))
12808 /* if the result is a bit */
12809 if (AOP_TYPE(result) == AOP_CRY) {
12810 /* if the right size is a literal then
12811 we know what the value is */
12812 if (AOP_TYPE(right) == AOP_LIT) {
12814 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12815 pic16_popGet(AOP(result),0));
12817 if (((int) operandLitValue(right)))
12818 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12819 AOP(result)->aopu.aop_dir,
12820 AOP(result)->aopu.aop_dir);
12822 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12823 AOP(result)->aopu.aop_dir,
12824 AOP(result)->aopu.aop_dir);
12828 /* the right is also a bit variable */
12829 if (AOP_TYPE(right) == AOP_CRY) {
12830 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12831 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12832 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12834 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12835 AOP(result)->aopu.aop_dir,
12836 AOP(result)->aopu.aop_dir);
12837 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12838 AOP(right)->aopu.aop_dir,
12839 AOP(right)->aopu.aop_dir);
12840 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12841 AOP(result)->aopu.aop_dir,
12842 AOP(result)->aopu.aop_dir);
12846 /* we need to or */
12847 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12848 pic16_toBoolean(right);
12850 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12851 //pic16_aopPut(AOP(result),"a",0);
12855 /* bit variables done */
12857 size = AOP_SIZE(result);
12860 if(AOP_TYPE(right) == AOP_LIT) {
12861 if(!IS_FLOAT(operandType( right )))
12862 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12865 unsigned long lit_int;
12869 /* take care if literal is a float */
12870 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12871 lit = info.lit_int;
12875 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12876 // sizeof(unsigned long int), sizeof(float));
12879 if (AOP_TYPE(right) == AOP_REG) {
12880 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12883 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12888 if(AOP_TYPE(right) != AOP_LIT
12889 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12890 && !IS_FUNC(OP_SYM_TYPE(right))
12892 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12893 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12895 // set up table pointer
12896 if(is_LitOp(right)) {
12897 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12898 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12899 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12900 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12901 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12902 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12903 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12905 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12906 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12907 pic16_popCopyReg(&pic16_pc_tblptrl)));
12908 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12909 pic16_popCopyReg(&pic16_pc_tblptrh)));
12910 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12911 pic16_popCopyReg(&pic16_pc_tblptru)));
12914 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12916 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12917 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12918 pic16_popGet(AOP(result),offset)));
12922 size = getSize(OP_SYM_ETYPE(right));
12923 if(AOP_SIZE(result) > size) {
12924 size = AOP_SIZE(result) - size;
12926 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12936 /* VR - What is this?! */
12937 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12939 if(aopIdx(AOP(result),0) == 4) {
12941 /* this is a workaround to save value of right into wreg too,
12942 * value of wreg is going to be used later */
12943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12944 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12949 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12955 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12956 if(AOP_TYPE(right) == AOP_LIT) {
12958 if(know_W != (lit&0xff))
12959 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12963 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12967 } else if (AOP_TYPE(right) == AOP_CRY) {
12968 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12970 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12971 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12972 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12974 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12975 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12978 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12980 if(!_G.resDirect) /* use this aopForSym feature */
12981 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12988 pic16_freeAsmop (right,NULL,ic,FALSE);
12989 pic16_freeAsmop (result,NULL,ic,TRUE);
12992 /*-----------------------------------------------------------------*/
12993 /* genJumpTab - generates code for jump table */
12994 /*-----------------------------------------------------------------*/
12995 static void genJumpTab (iCode *ic)
13000 pCodeOp *jt_offs_hi;
13005 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
13006 /* get the condition into accumulator */
13007 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
13009 /* multiply by three */
13010 pic16_emitcode("add","a,acc");
13011 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
13013 jtab = newiTempLabel(NULL);
13014 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
13015 pic16_emitcode("jmp","@a+dptr");
13016 pic16_emitcode("","%05d_DS_:",jtab->key+100);
13019 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
13020 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
13022 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
13023 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
13024 pic16_emitpLabel(jtab->key);
13028 jt_offs = pic16_popGetTempReg(0);
13029 jt_offs_hi = pic16_popGetTempReg(1);
13030 jt_label = pic16_popGetLabel (jtab->key);
13031 //fprintf (stderr, "Creating jump table...\n");
13033 // calculate offset into jump table (idx * sizeof (GOTO))
13034 pic16_emitpcode(POC_CLRF , jt_offs_hi);
13035 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
13036 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13037 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
13038 pic16_emitpcode(POC_RLCF , jt_offs_hi);
13039 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
13040 pic16_emitpcode(POC_MOVWF , jt_offs);
13042 // prepare PCLATx (set to first entry in jump table)
13043 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
13044 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
13045 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
13046 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
13047 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
13049 // set PCLATx to selected entry (new PCL is stored in jt_offs)
13050 pic16_emitpcode(POC_ADDWF , jt_offs);
13051 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
13052 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
13054 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
13056 // release temporaries and prepare jump into table (new PCL --> WREG)
13057 pic16_emitpcode(POC_MOVFW , jt_offs);
13058 pic16_popReleaseTempReg (jt_offs_hi, 1);
13059 pic16_popReleaseTempReg (jt_offs, 0);
13061 // jump into the table
13062 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13064 pic16_emitpLabelFORCE(jtab->key);
13067 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13069 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13070 /* now generate the jump labels */
13071 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13072 jtab = setNextItem(IC_JTLABELS(ic))) {
13073 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13074 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13077 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13081 /*-----------------------------------------------------------------*/
13082 /* genMixedOperation - gen code for operators between mixed types */
13083 /*-----------------------------------------------------------------*/
13085 TSD - Written for the PIC port - but this unfortunately is buggy.
13086 This routine is good in that it is able to efficiently promote
13087 types to different (larger) sizes. Unfortunately, the temporary
13088 variables that are optimized out by this routine are sometimes
13089 used in other places. So until I know how to really parse the
13090 iCode tree, I'm going to not be using this routine :(.
13092 static int genMixedOperation (iCode *ic)
13095 operand *result = IC_RESULT(ic);
13096 sym_link *ctype = operandType(IC_LEFT(ic));
13097 operand *right = IC_RIGHT(ic);
13103 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13105 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13111 nextright = IC_RIGHT(nextic);
13112 nextleft = IC_LEFT(nextic);
13113 nextresult = IC_RESULT(nextic);
13115 pic16_aopOp(right,ic,FALSE);
13116 pic16_aopOp(result,ic,FALSE);
13117 pic16_aopOp(nextright, nextic, FALSE);
13118 pic16_aopOp(nextleft, nextic, FALSE);
13119 pic16_aopOp(nextresult, nextic, FALSE);
13121 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13123 operand *t = right;
13127 pic16_emitcode(";remove right +","");
13129 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13131 operand *t = right;
13135 pic16_emitcode(";remove left +","");
13139 big = AOP_SIZE(nextleft);
13140 small = AOP_SIZE(nextright);
13142 switch(nextic->op) {
13145 pic16_emitcode(";optimize a +","");
13146 /* if unsigned or not an integral type */
13147 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13148 pic16_emitcode(";add a bit to something","");
13151 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13153 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13154 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13155 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13157 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13165 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13166 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13167 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13170 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13172 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13173 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13174 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13175 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13176 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13179 pic16_emitcode("rlf","known_zero,w");
13186 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13187 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13188 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13190 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13200 pic16_freeAsmop(right,NULL,ic,TRUE);
13201 pic16_freeAsmop(result,NULL,ic,TRUE);
13202 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13203 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13205 nextic->generated = 1;
13212 /*-----------------------------------------------------------------*/
13213 /* genCast - gen code for casting */
13214 /*-----------------------------------------------------------------*/
13215 static void genCast (iCode *ic)
13217 operand *result = IC_RESULT(ic);
13218 sym_link *ctype = operandType(IC_LEFT(ic));
13219 sym_link *rtype = operandType(IC_RIGHT(ic));
13220 sym_link *restype = operandType(IC_RESULT(ic));
13221 operand *right = IC_RIGHT(ic);
13227 /* if they are equivalent then do nothing */
13228 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13231 pic16_aopOp(right,ic,FALSE) ;
13232 pic16_aopOp(result,ic,FALSE);
13234 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13237 /* if the result is a bit */
13238 if (AOP_TYPE(result) == AOP_CRY) {
13240 /* if the right size is a literal then
13241 * we know what the value is */
13242 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13244 if (AOP_TYPE(right) == AOP_LIT) {
13245 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13246 pic16_popGet(AOP(result),0));
13248 if (((int) operandLitValue(right)))
13249 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13250 AOP(result)->aopu.aop_dir,
13251 AOP(result)->aopu.aop_dir);
13253 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13254 AOP(result)->aopu.aop_dir,
13255 AOP(result)->aopu.aop_dir);
13259 /* the right is also a bit variable */
13260 if (AOP_TYPE(right) == AOP_CRY) {
13262 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13264 pic16_emitcode("clrc","");
13265 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13266 AOP(right)->aopu.aop_dir,
13267 AOP(right)->aopu.aop_dir);
13268 pic16_aopPut(AOP(result),"c",0);
13272 /* we need to or */
13273 if (AOP_TYPE(right) == AOP_REG) {
13274 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13275 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13276 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13278 pic16_toBoolean(right);
13279 pic16_aopPut(AOP(result),"a",0);
13283 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13286 size = AOP_SIZE(result);
13288 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13290 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13291 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13292 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13295 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13300 if(IS_BITFIELD(getSpec(restype))
13301 && IS_BITFIELD(getSpec(rtype))) {
13302 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13305 /* if they are the same size : or less */
13306 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13308 /* if they are in the same place */
13309 if (pic16_sameRegs(AOP(right),AOP(result)))
13312 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13314 if (IS_PTR_CONST(rtype))
13316 if (IS_CODEPTR(rtype))
13318 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13321 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13323 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13325 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13328 if(AOP_TYPE(right) == AOP_IMMD) {
13329 pCodeOp *pcop0, *pcop1, *pcop2;
13330 symbol *sym = OP_SYMBOL( right );
13332 size = AOP_SIZE(result);
13334 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13336 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13338 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13341 pic16_emitpcode(POC_MOVLW, pcop0);
13342 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13343 pic16_emitpcode(POC_MOVLW, pcop1);
13344 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13345 pic16_emitpcode(POC_MOVLW, pcop2);
13346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13349 pic16_emitpcode(POC_MOVLW, pcop0);
13350 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13351 pic16_emitpcode(POC_MOVLW, pcop1);
13352 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13354 pic16_emitpcode(POC_MOVLW, pcop0);
13355 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13359 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13360 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13361 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13362 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13364 if(AOP_SIZE(result) <2)
13365 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13367 /* if they in different places then copy */
13368 size = AOP_SIZE(result);
13371 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13372 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13379 /* if the result is of type pointer */
13380 if (IS_PTR(ctype)) {
13382 sym_link *type = operandType(right);
13383 sym_link *etype = getSpec(type);
13385 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13387 /* pointer to generic pointer */
13388 if (IS_GENPTR(ctype)) {
13392 p_type = DCL_TYPE(type);
13394 /* we have to go by the storage class */
13395 p_type = PTR_TYPE(SPEC_OCLS(etype));
13397 /* if (SPEC_OCLS(etype)->codesp ) */
13398 /* p_type = CPOINTER ; */
13400 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13401 /* p_type = FPOINTER ; */
13403 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13404 /* p_type = PPOINTER; */
13406 /* if (SPEC_OCLS(etype) == idata ) */
13407 /* p_type = IPOINTER ; */
13409 /* p_type = POINTER ; */
13412 /* the first two bytes are known */
13413 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13414 size = GPTRSIZE - 1;
13417 if(offset < AOP_SIZE(right)) {
13418 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13419 mov2f(AOP(result), AOP(right), offset);
13421 if ((AOP_TYPE(right) == AOP_PCODE) &&
13422 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13423 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13424 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13427 pic16_aopPut(AOP(result),
13428 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13433 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13436 /* the last byte depending on type */
13440 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13441 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13442 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13446 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13450 pic16_emitcode(";BUG!? ","%d",__LINE__);
13454 pic16_emitcode(";BUG!? ","%d",__LINE__);
13459 if (GPTRSIZE > AOP_SIZE(right)) {
13460 // assume data pointer... THIS MIGHT BE WRONG!
13461 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13462 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13464 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13469 /* this should never happen */
13470 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13471 "got unknown pointer type");
13474 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13478 /* just copy the pointers */
13479 size = AOP_SIZE(result);
13482 pic16_aopPut(AOP(result),
13483 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13492 /* so we now know that the size of destination is greater
13493 than the size of the source.
13494 Now, if the next iCode is an operator then we might be
13495 able to optimize the operation without performing a cast.
13497 if(genMixedOperation(ic))
13500 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13502 /* we move to result for the size of source */
13503 size = AOP_SIZE(right);
13506 mov2f(AOP(result), AOP(right), offset);
13510 /* now depending on the sign of the destination */
13511 size = AOP_SIZE(result) - AOP_SIZE(right);
13512 /* if unsigned or not an integral type */
13513 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13515 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13517 /* we need to extend the sign :( */
13520 /* Save one instruction of casting char to int */
13521 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13522 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13523 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13525 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13528 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13530 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13532 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13535 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13540 pic16_freeAsmop(right,NULL,ic,TRUE);
13541 pic16_freeAsmop(result,NULL,ic,TRUE);
13545 /*-----------------------------------------------------------------*/
13546 /* genDjnz - generate decrement & jump if not zero instrucion */
13547 /*-----------------------------------------------------------------*/
13548 static int genDjnz (iCode *ic, iCode *ifx)
13550 symbol *lbl, *lbl1;
13551 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13556 /* if the if condition has a false label
13557 then we cannot save */
13561 /* if the minus is not of the form
13563 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13564 !IS_OP_LITERAL(IC_RIGHT(ic)))
13567 if (operandLitValue(IC_RIGHT(ic)) != 1)
13570 /* if the size of this greater than one then no
13572 if (getSize(operandType(IC_RESULT(ic))) > 1)
13575 /* otherwise we can save BIG */
13576 lbl = newiTempLabel(NULL);
13577 lbl1= newiTempLabel(NULL);
13579 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13581 if (IS_AOP_PREG(IC_RESULT(ic))) {
13582 pic16_emitcode("dec","%s",
13583 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13584 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13585 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13589 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13590 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13592 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13593 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13597 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13598 ifx->generated = 1;
13602 /*-----------------------------------------------------------------*/
13603 /* genReceive - generate code for a receive iCode */
13604 /*-----------------------------------------------------------------*/
13605 static void genReceive (iCode *ic)
13611 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13612 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13614 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13616 if (isOperandInFarSpace(IC_RESULT(ic))
13617 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13618 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13620 int size = getSize(operandType(IC_RESULT(ic)));
13621 int offset = pic16_fReturnSizePic - size;
13625 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13626 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13630 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13632 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13633 size = AOP_SIZE(IC_RESULT(ic));
13636 pic16_emitcode ("pop","acc");
13637 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13640 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13642 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13645 /* set pseudo stack pointer to where it should be - dw*/
13646 GpsuedoStkPtr = ic->parmBytes;
13648 /* setting GpsuedoStkPtr has side effects here: */
13649 assignResultValue(IC_RESULT(ic), 0);
13652 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13655 /*-----------------------------------------------------------------*/
13656 /* genDummyRead - generate code for dummy read of volatiles */
13657 /*-----------------------------------------------------------------*/
13659 genDummyRead (iCode * ic)
13665 if (op && IS_SYMOP(op)) {
13666 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13667 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13670 pic16_aopOp (op, ic, FALSE);
13671 for (i=0; i < AOP_SIZE(op); i++) {
13672 // may need to protect this from the peepholer -- this is not nice but works...
13673 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13674 pic16_mov2w (AOP(op),i);
13675 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13677 pic16_freeAsmop (op, NULL, ic, TRUE);
13679 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13683 /*-----------------------------------------------------------------*/
13684 /* genpic16Code - generate code for pic16 based controllers */
13685 /*-----------------------------------------------------------------*/
13687 * At this point, ralloc.c has gone through the iCode and attempted
13688 * to optimize in a way suitable for a PIC. Now we've got to generate
13689 * PIC instructions that correspond to the iCode.
13691 * Once the instructions are generated, we'll pass through both the
13692 * peep hole optimizer and the pCode optimizer.
13693 *-----------------------------------------------------------------*/
13695 void genpic16Code (iCode *lic)
13700 lineHead = lineCurr = NULL;
13702 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13703 pic16_addpBlock(pb);
13706 /* if debug information required */
13707 if (options.debug && currFunc) {
13709 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13714 for (ic = lic ; ic ; ic = ic->next ) {
13716 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13717 if ( cln != ic->lineno ) {
13718 if ( options.debug ) {
13719 debugFile->writeCLine (ic);
13722 if(!options.noCcodeInAsm) {
13723 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13724 printCLine(ic->filename, ic->lineno)));
13730 if(options.iCodeInAsm) {
13733 /* insert here code to print iCode as comment */
13734 l = Safe_strdup(printILine(ic));
13735 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13738 /* if the result is marked as
13739 * spilt and rematerializable or code for
13740 * this has already been generated then
13742 if (resultRemat(ic) || ic->generated )
13745 /* depending on the operation */
13764 /* IPOP happens only when trying to restore a
13765 * spilt live range, if there is an ifx statement
13766 * following this pop then the if statement might
13767 * be using some of the registers being popped which
13768 * would destroy the contents of the register so
13769 * we need to check for this condition and handle it */
13771 && ic->next->op == IFX
13772 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13773 genIfx (ic->next,ic);
13791 genEndFunction (ic);
13807 pic16_genPlus (ic) ;
13811 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13812 pic16_genMinus (ic);
13828 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13832 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13838 /* note these two are xlated by algebraic equivalence
13839 * during parsing SDCC.y */
13840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13841 "got '>=' or '<=' shouldn't have come here");
13845 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13857 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13861 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13865 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13889 genRightShift (ic);
13892 case GET_VALUE_AT_ADDRESS:
13897 if (POINTER_SET(ic))
13924 addSet(&_G.sendSet,ic);
13927 case DUMMY_READ_VOLATILE:
13937 /* now we are ready to call the
13938 peep hole optimizer */
13939 if (!options.nopeep)
13940 peepHole (&lineHead);
13942 /* now do the actual printing */
13943 printLine (lineHead, codeOutFile);
13946 DFPRINTF((stderr,"printing pBlock\n\n"));
13947 pic16_printpBlock(stdout,pb);