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->size = AOP_SIZE( IC_LEFT(ic) );
873 else if(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)
3901 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3903 pic16_emitpcode(POC_CLRF, dest);
3905 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3906 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3909 if(dest->type == PO_WREG && (offset == 0)) {
3910 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3913 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3917 /*-----------------------------------------------------------------*/
3918 /* genRet - generate code for return statement */
3919 /*-----------------------------------------------------------------*/
3920 static void genRet (iCode *ic)
3926 /* if we have no return value then
3927 * just generate the "ret" */
3932 /* we have something to return then
3933 * move the return value into place */
3934 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3935 size = AOP_SIZE(IC_LEFT(ic));
3939 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3940 // pic16_emitpcode(POC_MOVFF,
3941 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3944 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3945 // pic16_emitpcode(POC_MOVFF,
3946 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3949 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3950 // pic16_emitpcode(POC_MOVFF,
3951 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3954 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3956 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3957 // pic16_emitpcode(POC_MOVFF,
3958 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3961 /* >32-bits, setup stack and FSR0 */
3963 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3964 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3966 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3968 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3973 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3974 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3976 if(STACK_MODEL_LARGE) {
3977 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3978 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3980 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3985 /* old code, left here for reference -- VR */
3989 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3991 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3992 pic16_emitpcomment("push %s",l);
3995 DEBUGpic16_emitcode(";", "%d", __LINE__);
3996 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3997 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3999 if (strcmp(fReturn[offset],l)) {
4000 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4001 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4002 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4004 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4008 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4018 if (strcmp(fReturn[pushed],"a"))
4019 pic16_emitcode("pop",fReturn[pushed]);
4021 pic16_emitcode("pop","acc");
4027 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4030 /* generate a jump to the return label
4031 * if the next is not the return statement */
4032 if (!(ic->next && ic->next->op == LABEL
4033 && IC_LABEL(ic->next) == returnLabel)) {
4035 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4036 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4040 /*-----------------------------------------------------------------*/
4041 /* genLabel - generates a label */
4042 /*-----------------------------------------------------------------*/
4043 static void genLabel (iCode *ic)
4047 /* special case never generate */
4048 if (IC_LABEL(ic) == entryLabel)
4051 pic16_emitpLabel(IC_LABEL(ic)->key);
4052 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4055 /*-----------------------------------------------------------------*/
4056 /* genGoto - generates a goto */
4057 /*-----------------------------------------------------------------*/
4059 static void genGoto (iCode *ic)
4062 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4063 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4067 /*-----------------------------------------------------------------*/
4068 /* genMultbits :- multiplication of bits */
4069 /*-----------------------------------------------------------------*/
4070 static void genMultbits (operand *left,
4076 if(!pic16_sameRegs(AOP(result),AOP(right)))
4077 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4079 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4080 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4081 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4086 /*-----------------------------------------------------------------*/
4087 /* genMultOneByte : 8 bit multiplication & division */
4088 /*-----------------------------------------------------------------*/
4089 static void genMultOneByte (operand *left,
4095 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4096 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4098 /* (if two literals, the value is computed before) */
4099 /* if one literal, literal on the right */
4100 if (AOP_TYPE(left) == AOP_LIT){
4106 /* size is already checked in genMult == 1 */
4107 // size = AOP_SIZE(result);
4109 if (AOP_TYPE(right) == AOP_LIT){
4110 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4111 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4112 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4113 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4115 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4116 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4117 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4118 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4121 pic16_genMult8X8_8 (left, right,result);
4124 /*-----------------------------------------------------------------*/
4125 /* genMultOneWord : 16 bit multiplication */
4126 /*-----------------------------------------------------------------*/
4127 static void genMultOneWord (operand *left,
4132 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4133 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4135 /* (if two literals, the value is computed before)
4136 * if one literal, literal on the right */
4137 if (AOP_TYPE(left) == AOP_LIT){
4143 /* size is checked already == 2 */
4144 // size = AOP_SIZE(result);
4146 if (AOP_TYPE(right) == AOP_LIT) {
4147 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4148 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4149 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4150 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4152 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4153 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4154 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4155 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4158 pic16_genMult16X16_16(left, right,result);
4161 /*-----------------------------------------------------------------*/
4162 /* genMultOneLong : 32 bit multiplication */
4163 /*-----------------------------------------------------------------*/
4164 static void genMultOneLong (operand *left,
4169 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4170 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4172 /* (if two literals, the value is computed before)
4173 * if one literal, literal on the right */
4174 if (AOP_TYPE(left) == AOP_LIT){
4180 /* size is checked already == 4 */
4181 // size = AOP_SIZE(result);
4183 if (AOP_TYPE(right) == AOP_LIT) {
4184 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4185 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4186 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4187 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4189 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4190 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4191 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4192 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4195 pic16_genMult32X32_32(left, right,result);
4200 /*-----------------------------------------------------------------*/
4201 /* genMult - generates code for multiplication */
4202 /*-----------------------------------------------------------------*/
4203 static void genMult (iCode *ic)
4205 operand *left = IC_LEFT(ic);
4206 operand *right = IC_RIGHT(ic);
4207 operand *result= IC_RESULT(ic);
4210 /* assign the amsops */
4211 pic16_aopOp (left,ic,FALSE);
4212 pic16_aopOp (right,ic,FALSE);
4213 pic16_aopOp (result,ic,TRUE);
4215 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4217 /* special cases first *
4219 if (AOP_TYPE(left) == AOP_CRY
4220 && AOP_TYPE(right)== AOP_CRY) {
4221 genMultbits(left,right,result);
4225 /* if both are of size == 1 */
4226 if(AOP_SIZE(left) == 1
4227 && AOP_SIZE(right) == 1) {
4228 genMultOneByte(left,right,result);
4232 /* if both are of size == 2 */
4233 if(AOP_SIZE(left) == 2
4234 && AOP_SIZE(right) == 2) {
4235 genMultOneWord(left, right, result);
4239 /* if both are of size == 4 */
4240 if(AOP_SIZE(left) == 4
4241 && AOP_SIZE(right) == 4) {
4242 genMultOneLong(left, right, result);
4246 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4249 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4250 /* should have been converted to function call */
4254 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4255 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4256 pic16_freeAsmop(result,NULL,ic,TRUE);
4259 /*-----------------------------------------------------------------*/
4260 /* genDivbits :- division of bits */
4261 /*-----------------------------------------------------------------*/
4262 static void genDivbits (operand *left,
4269 /* the result must be bit */
4270 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4271 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4275 pic16_emitcode("div","ab");
4276 pic16_emitcode("rrc","a");
4277 pic16_aopPut(AOP(result),"c",0);
4280 /*-----------------------------------------------------------------*/
4281 /* genDivOneByte : 8 bit division */
4282 /*-----------------------------------------------------------------*/
4283 static void genDivOneByte (operand *left,
4287 sym_link *opetype = operandType(result);
4292 /* result = divident / divisor
4293 * - divident may be a register or a literal,
4294 * - divisor may be a register or a literal,
4295 * so there are 3 cases (literal / literal is optimized
4296 * by the front-end) to handle.
4297 * In addition we must handle signed and unsigned, which
4298 * result in 6 final different cases -- VR */
4302 size = AOP_SIZE(result) - 1;
4304 /* signed or unsigned */
4305 if (SPEC_USIGN(opetype)) {
4306 pCodeOp *pct1, /* count */
4309 symbol *label1, *label2, *label3;;
4312 /* unsigned is easy */
4314 pct1 = pic16_popGetTempReg(1);
4315 pct2 = pic16_popGetTempReg(1);
4316 pct3 = pic16_popGetTempReg(1);
4318 label1 = newiTempLabel(NULL);
4319 label2 = newiTempLabel(NULL);
4320 label3 = newiTempLabel(NULL);
4322 /* the following algorithm is extracted from divuint.c */
4324 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4325 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4327 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4329 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4331 pic16_emitpLabel(label1->key);
4334 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4338 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4342 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4344 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4345 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4347 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4348 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4349 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4351 pic16_emitpLabel( label3->key );
4352 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4353 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4357 pic16_emitpLabel(label2->key);
4358 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4359 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4360 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4362 /* result is in wreg */
4363 if(AOP_TYPE(result) != AOP_ACC)
4364 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4366 pic16_popReleaseTempReg( pct3, 1);
4367 pic16_popReleaseTempReg( pct2, 1);
4368 pic16_popReleaseTempReg( pct1, 1);
4373 /* signed is a little bit more difficult */
4375 /* save the signs of the operands */
4376 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4378 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4379 pic16_emitcode("push","acc"); /* save it on the stack */
4381 /* now sign adjust for both left & right */
4382 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4384 lbl = newiTempLabel(NULL);
4385 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4386 pic16_emitcode("cpl","a");
4387 pic16_emitcode("inc","a");
4388 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4389 pic16_emitcode("mov","b,a");
4391 /* sign adjust left side */
4392 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4395 lbl = newiTempLabel(NULL);
4396 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4397 pic16_emitcode("cpl","a");
4398 pic16_emitcode("inc","a");
4399 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4401 /* now the division */
4402 pic16_emitcode("div","ab");
4403 /* we are interested in the lower order
4405 pic16_emitcode("mov","b,a");
4406 lbl = newiTempLabel(NULL);
4407 pic16_emitcode("pop","acc");
4408 /* if there was an over flow we don't
4409 adjust the sign of the result */
4410 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4411 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4413 pic16_emitcode("clr","a");
4414 pic16_emitcode("subb","a,b");
4415 pic16_emitcode("mov","b,a");
4416 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4418 /* now we are done */
4419 pic16_aopPut(AOP(result),"b",0);
4421 pic16_emitcode("mov","c,b.7");
4422 pic16_emitcode("subb","a,acc");
4425 pic16_aopPut(AOP(result),"a",offset++);
4429 /*-----------------------------------------------------------------*/
4430 /* genDiv - generates code for division */
4431 /*-----------------------------------------------------------------*/
4432 static void genDiv (iCode *ic)
4434 operand *left = IC_LEFT(ic);
4435 operand *right = IC_RIGHT(ic);
4436 operand *result= IC_RESULT(ic);
4439 /* Division is a very lengthy algorithm, so it is better
4440 * to call support routines than inlining algorithm.
4441 * Division functions written here just in case someone
4442 * wants to inline and not use the support libraries -- VR */
4446 /* assign the amsops */
4447 pic16_aopOp (left,ic,FALSE);
4448 pic16_aopOp (right,ic,FALSE);
4449 pic16_aopOp (result,ic,TRUE);
4451 /* special cases first */
4453 if (AOP_TYPE(left) == AOP_CRY &&
4454 AOP_TYPE(right)== AOP_CRY) {
4455 genDivbits(left,right,result);
4459 /* if both are of size == 1 */
4460 if (AOP_SIZE(left) == 1 &&
4461 AOP_SIZE(right) == 1 ) {
4462 genDivOneByte(left,right,result);
4466 /* should have been converted to function call */
4469 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4471 pic16_freeAsmop(result,NULL,ic,TRUE);
4474 /*-----------------------------------------------------------------*/
4475 /* genModbits :- modulus of bits */
4476 /*-----------------------------------------------------------------*/
4477 static void genModbits (operand *left,
4485 werror(W_POSSBUG2, __FILE__, __LINE__);
4486 /* the result must be bit */
4487 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4488 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4492 pic16_emitcode("div","ab");
4493 pic16_emitcode("mov","a,b");
4494 pic16_emitcode("rrc","a");
4495 pic16_aopPut(AOP(result),"c",0);
4498 /*-----------------------------------------------------------------*/
4499 /* genModOneByte : 8 bit modulus */
4500 /*-----------------------------------------------------------------*/
4501 static void genModOneByte (operand *left,
4505 sym_link *opetype = operandType(result);
4510 werror(W_POSSBUG2, __FILE__, __LINE__);
4512 /* signed or unsigned */
4513 if (SPEC_USIGN(opetype)) {
4514 /* unsigned is easy */
4515 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4516 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4518 pic16_emitcode("div","ab");
4519 pic16_aopPut(AOP(result),"b",0);
4523 /* signed is a little bit more difficult */
4525 /* save the signs of the operands */
4526 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4529 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4530 pic16_emitcode("push","acc"); /* save it on the stack */
4532 /* now sign adjust for both left & right */
4533 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4536 lbl = newiTempLabel(NULL);
4537 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4538 pic16_emitcode("cpl","a");
4539 pic16_emitcode("inc","a");
4540 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4541 pic16_emitcode("mov","b,a");
4543 /* sign adjust left side */
4544 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4547 lbl = newiTempLabel(NULL);
4548 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4549 pic16_emitcode("cpl","a");
4550 pic16_emitcode("inc","a");
4551 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4553 /* now the multiplication */
4554 pic16_emitcode("div","ab");
4555 /* we are interested in the lower order
4557 lbl = newiTempLabel(NULL);
4558 pic16_emitcode("pop","acc");
4559 /* if there was an over flow we don't
4560 adjust the sign of the result */
4561 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4562 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4564 pic16_emitcode("clr","a");
4565 pic16_emitcode("subb","a,b");
4566 pic16_emitcode("mov","b,a");
4567 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4569 /* now we are done */
4570 pic16_aopPut(AOP(result),"b",0);
4574 /*-----------------------------------------------------------------*/
4575 /* genMod - generates code for division */
4576 /*-----------------------------------------------------------------*/
4577 static void genMod (iCode *ic)
4579 operand *left = IC_LEFT(ic);
4580 operand *right = IC_RIGHT(ic);
4581 operand *result= IC_RESULT(ic);
4585 /* assign the amsops */
4586 pic16_aopOp (left,ic,FALSE);
4587 pic16_aopOp (right,ic,FALSE);
4588 pic16_aopOp (result,ic,TRUE);
4590 /* special cases first */
4592 if (AOP_TYPE(left) == AOP_CRY &&
4593 AOP_TYPE(right)== AOP_CRY) {
4594 genModbits(left,right,result);
4598 /* if both are of size == 1 */
4599 if (AOP_SIZE(left) == 1 &&
4600 AOP_SIZE(right) == 1 ) {
4601 genModOneByte(left,right,result);
4605 /* should have been converted to function call */
4609 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4610 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4611 pic16_freeAsmop(result,NULL,ic,TRUE);
4614 /*-----------------------------------------------------------------*/
4615 /* genIfxJump :- will create a jump depending on the ifx */
4616 /*-----------------------------------------------------------------*/
4618 note: May need to add parameter to indicate when a variable is in bit space.
4620 static void genIfxJump (iCode *ic, char *jval)
4624 /* if true label then we jump if condition
4626 if ( IC_TRUE(ic) ) {
4628 if(strcmp(jval,"a") == 0)
4630 else if (strcmp(jval,"c") == 0)
4633 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4634 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4637 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4638 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4642 /* false label is present */
4643 if(strcmp(jval,"a") == 0)
4645 else if (strcmp(jval,"c") == 0)
4648 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4649 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4652 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4653 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4658 /* mark the icode as generated */
4662 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4666 /* if true label then we jump if condition
4668 if ( IC_TRUE(ic) ) {
4669 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4670 pic16_emitpcode(POC_BTFSC, jop);
4672 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4673 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4676 /* false label is present */
4677 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4678 pic16_emitpcode(POC_BTFSS, jop);
4680 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4681 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4685 /* mark the icode as generated */
4692 /*-----------------------------------------------------------------*/
4694 /*-----------------------------------------------------------------*/
4695 static void genSkip(iCode *ifx,int status_bit)
4697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4701 if ( IC_TRUE(ifx) ) {
4702 switch(status_bit) {
4717 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4718 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4722 switch(status_bit) {
4736 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4737 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4744 /*-----------------------------------------------------------------*/
4746 /*-----------------------------------------------------------------*/
4747 static void genSkipc(resolvedIfx *rifx)
4749 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4759 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4760 rifx->generated = 1;
4763 #if !(USE_SIMPLE_GENCMP)
4764 /*-----------------------------------------------------------------*/
4766 /*-----------------------------------------------------------------*/
4767 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4769 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4774 if( (rifx->condition ^ invert_condition) & 1)
4779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4780 rifx->generated = 1;
4785 /*-----------------------------------------------------------------*/
4787 /*-----------------------------------------------------------------*/
4788 static void genSkipz(iCode *ifx, int condition)
4799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4801 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4804 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4806 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4811 #if !(USE_SIMPLE_GENCMP)
4812 /*-----------------------------------------------------------------*/
4814 /*-----------------------------------------------------------------*/
4815 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4821 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4823 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4826 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4827 rifx->generated = 1;
4832 /*-----------------------------------------------------------------*/
4833 /* genChkZeroes :- greater or less than comparison */
4834 /* For each byte in a literal that is zero, inclusive or the */
4835 /* the corresponding byte in the operand with W */
4836 /* returns true if any of the bytes are zero */
4837 /*-----------------------------------------------------------------*/
4838 static int genChkZeroes(operand *op, int lit, int size)
4845 i = (lit >> (size*8)) & 0xff;
4849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4851 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4860 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4861 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4863 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4864 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4866 /*-----------------------------------------------------------------*/
4867 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4868 /* aop (if it's NOT a literal) or from lit (if */
4869 /* aop is a literal) */
4870 /*-----------------------------------------------------------------*/
4871 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4872 if (aop->type == AOP_LIT) {
4873 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4875 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4879 /*-----------------------------------------------------------------*/
4880 /* genCmp :- greater or less than comparison */
4881 /*-----------------------------------------------------------------*/
4883 #if USE_SIMPLE_GENCMP
4885 /* genCmp performs a left < right comparison, stores
4886 * the outcome in result (if != NULL) and generates
4887 * control flow code for the ifx (if != NULL).
4889 * This version leaves in sequences like
4890 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4891 * which should be optmized by the peephole
4892 * optimizer - RN 2005-01-01 */
4893 static void genCmp (operand *left,operand *right,
4894 operand *result, iCode *ifx, int sign)
4907 assert (AOP_SIZE(left) == AOP_SIZE(right));
4908 assert (left && right);
4910 size = AOP_SIZE(right) - 1;
4911 mask = (0x100UL << (size*8)) - 1;
4912 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4917 resolveIfx (&rIfx, ifx);
4919 /**********************************************************************
4920 * handle bits - bit compares are promoted to int compares seemingly! *
4921 **********************************************************************/
4923 // THIS IS COMPLETELY UNTESTED!
4924 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4925 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4926 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4927 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4930 // 1 < {0,1} is false --> clear C by skipping the next instruction
4931 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4932 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4933 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4934 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4935 emitCLRC; // only skipped for left=0 && right=1
4937 goto correct_result_in_carry;
4941 /*************************************************
4942 * make sure that left is register (or the like) *
4943 *************************************************/
4944 if (!isAOP_REGlike(left)) {
4945 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4946 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4948 assert (isAOP_LIT(left));
4949 assert (isAOP_REGlike(right));
4950 // swap left and right
4951 // left < right <==> right > left <==> (right >= left + 1)
4952 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4954 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4955 // MAXVALUE < right? always false
4956 if (performedLt) emitCLRC; else emitSETC;
4957 goto correct_result_in_carry;
4960 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4961 // that's we handled it above.
4968 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4969 } else if (isAOP_LIT(right)) {
4970 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4973 assert (isAOP_REGlike(left)); // left must be register or the like
4974 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4976 /*************************************************
4977 * special cases go here *
4978 *************************************************/
4980 if (isAOP_LIT(right)) {
4982 // unsigned comparison to a literal
4983 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4984 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4987 // unsigned left < 0? always false
4988 if (performedLt) emitCLRC; else emitSETC;
4989 goto correct_result_in_carry;
4992 // signed comparison to a literal
4993 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4994 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4996 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4997 // signed left < 0x80000000? always false
4998 if (performedLt) emitCLRC; else emitSETC;
4999 goto correct_result_in_carry;
5000 } else if (lit == 0) {
5001 // compare left < 0; set CARRY if SIGNBIT(left) is set
5002 if (performedLt) emitSETC; else emitCLRC;
5003 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5004 if (performedLt) emitCLRC; else emitSETC;
5005 goto correct_result_in_carry;
5008 } // right is literal
5010 /*************************************************
5011 * perform a general case comparison *
5012 * make sure we get CARRY==1 <==> left >= right *
5013 *************************************************/
5014 // compare most significant bytes
5015 //DEBUGpc ("comparing bytes at offset %d", size);
5017 // unsigned comparison
5018 mov2w_regOrLit (AOP(right), lit, size);
5019 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5021 // signed comparison
5022 // (add 2^n to both operands then perform an unsigned comparison)
5023 if (isAOP_LIT(right)) {
5024 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5025 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5027 if (litbyte == 0x80) {
5028 // left >= 0x80 -- always true, but more bytes to come
5029 pic16_mov2w (AOP(left), size);
5030 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5033 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5034 pic16_mov2w (AOP(left), size);
5035 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5036 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5039 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5040 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5041 pic16_mov2w (AOP(left), size);
5042 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5043 pic16_emitpcode (POC_MOVWF, pctemp);
5044 pic16_mov2w (AOP(right), size);
5045 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5046 pic16_emitpcode (POC_SUBFW, pctemp);
5047 //pic16_popReleaseTempReg(pctemp, 1);
5051 // compare remaining bytes (treat as unsigned case from above)
5052 templbl = newiTempLabel ( NULL );
5055 //DEBUGpc ("comparing bytes at offset %d", offs);
5056 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5057 mov2w_regOrLit (AOP(right), lit, offs);
5058 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5060 pic16_emitpLabel (templbl->key);
5061 goto result_in_carry;
5065 /****************************************************
5066 * now CARRY contains the result of the comparison: *
5067 * SUBWF sets CARRY iff *
5068 * F-W >= 0 <==> F >= W <==> !(F < W) *
5070 ****************************************************/
5073 if (result && AOP_TYPE(result) != AOP_CRY) {
5074 // value will be stored
5077 // value wil only be used in the following genSkipc()
5078 rIfx.condition ^= 1;
5082 correct_result_in_carry:
5084 // assign result to variable (if neccessary)
5085 if (result && AOP_TYPE(result) != AOP_CRY) {
5086 //DEBUGpc ("assign result");
5087 size = AOP_SIZE(result);
5089 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5091 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5094 // perform conditional jump
5095 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5097 //DEBUGpc ("generate control flow");
5098 rIfx.condition ^= 1;
5107 static void genCmp (operand *left,operand *right,
5108 operand *result, iCode *ifx, int sign)
5110 int size; //, offset = 0 ;
5111 unsigned long lit = 0L,i = 0;
5112 resolvedIfx rFalseIfx;
5113 // resolvedIfx rTrueIfx;
5115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5118 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5119 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5125 resolveIfx(&rFalseIfx,ifx);
5126 truelbl = newiTempLabel(NULL);
5127 size = max(AOP_SIZE(left),AOP_SIZE(right));
5129 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5133 /* if literal is on the right then swap with left */
5134 if ((AOP_TYPE(right) == AOP_LIT)) {
5135 operand *tmp = right ;
5136 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5137 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5140 lit = (lit - 1) & mask;
5143 rFalseIfx.condition ^= 1;
5146 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5147 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5151 //if(IC_TRUE(ifx) == NULL)
5152 /* if left & right are bit variables */
5153 if (AOP_TYPE(left) == AOP_CRY &&
5154 AOP_TYPE(right) == AOP_CRY ) {
5155 assert (0 && "bit variables used in genCmp");
5156 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5157 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5159 /* subtract right from left if at the
5160 end the carry flag is set then we know that
5161 left is greater than right */
5163 symbol *lbl = newiTempLabel(NULL);
5166 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5167 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5171 if(AOP_TYPE(right) == AOP_LIT) {
5173 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5175 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5182 genSkipCond(&rFalseIfx,left,size-1,7);
5184 /* no need to compare to 0...*/
5185 /* NOTE: this is a de-generate compare that most certainly
5186 * creates some dead code. */
5187 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5189 if(ifx) ifx->generated = 1;
5196 //i = (lit >> (size*8)) & 0xff;
5197 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5199 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5201 i = ((0-lit) & 0xff);
5204 /* lit is 0x7f, all signed chars are less than
5205 * this except for 0x7f itself */
5206 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5207 genSkipz2(&rFalseIfx,0);
5209 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5210 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5211 genSkipc(&rFalseIfx);
5216 genSkipz2(&rFalseIfx,1);
5218 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5219 genSkipc(&rFalseIfx);
5223 if(ifx) ifx->generated = 1;
5227 /* chars are out of the way. now do ints and longs */
5230 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5237 genSkipCond(&rFalseIfx,left,size,7);
5238 if(ifx) ifx->generated = 1;
5243 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5245 //rFalseIfx.condition ^= 1;
5246 //genSkipCond(&rFalseIfx,left,size,7);
5247 //rFalseIfx.condition ^= 1;
5249 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5250 if(rFalseIfx.condition)
5251 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5253 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5255 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5256 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5257 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5260 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5262 if(rFalseIfx.condition) {
5264 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5270 genSkipc(&rFalseIfx);
5271 pic16_emitpLabel(truelbl->key);
5272 if(ifx) ifx->generated = 1;
5279 if( (lit & 0xff) == 0) {
5280 /* lower byte is zero */
5281 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5282 i = ((lit >> 8) & 0xff) ^0x80;
5283 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5284 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5285 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5286 genSkipc(&rFalseIfx);
5289 if(ifx) ifx->generated = 1;
5294 /* Special cases for signed longs */
5295 if( (lit & 0xffffff) == 0) {
5296 /* lower byte is zero */
5297 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5298 i = ((lit >> 8*3) & 0xff) ^0x80;
5299 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5300 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5301 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5302 genSkipc(&rFalseIfx);
5305 if(ifx) ifx->generated = 1;
5313 if(lit & (0x80 << (size*8))) {
5314 /* lit is negative */
5315 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5317 //genSkipCond(&rFalseIfx,left,size,7);
5319 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5321 if(rFalseIfx.condition)
5322 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5324 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5328 /* lit is positive */
5329 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5330 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5331 if(rFalseIfx.condition)
5332 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5334 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5339 This works, but is only good for ints.
5340 It also requires a "known zero" register.
5341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5342 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5344 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5345 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5346 genSkipc(&rFalseIfx);
5348 pic16_emitpLabel(truelbl->key);
5349 if(ifx) ifx->generated = 1;
5353 /* There are no more special cases, so perform a general compare */
5355 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5356 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5360 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5362 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5364 //rFalseIfx.condition ^= 1;
5365 genSkipc(&rFalseIfx);
5367 pic16_emitpLabel(truelbl->key);
5369 if(ifx) ifx->generated = 1;
5376 /* sign is out of the way. So now do an unsigned compare */
5377 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5380 /* General case - compare to an unsigned literal on the right.*/
5382 i = (lit >> (size*8)) & 0xff;
5383 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5384 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5386 i = (lit >> (size*8)) & 0xff;
5389 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5391 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5393 /* this byte of the lit is zero,
5394 *if it's not the last then OR in the variable */
5396 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5401 pic16_emitpLabel(lbl->key);
5402 // pic16_emitpLabel(truelbl->key);
5403 //if(emitFinalCheck)
5404 genSkipc(&rFalseIfx);
5406 pic16_emitpLabel(truelbl->key);
5408 if(ifx) ifx->generated = 1;
5415 if(AOP_TYPE(left) == AOP_LIT) {
5416 //symbol *lbl = newiTempLabel(NULL);
5418 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5421 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5424 if((lit == 0) && (sign == 0)){
5427 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5429 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5431 genSkipz2(&rFalseIfx,0);
5432 if(ifx) ifx->generated = 1;
5439 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5440 /* degenerate compare can never be true */
5441 if(rFalseIfx.condition == 0)
5442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5444 if(ifx) ifx->generated = 1;
5449 /* signed comparisons to a literal byte */
5451 int lp1 = (lit+1) & 0xff;
5453 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5456 rFalseIfx.condition ^= 1;
5457 genSkipCond(&rFalseIfx,right,0,7);
5460 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5461 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5462 genSkipz2(&rFalseIfx,1);
5465 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5466 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5467 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5468 rFalseIfx.condition ^= 1;
5469 genSkipc(&rFalseIfx);
5473 /* unsigned comparisons to a literal byte */
5475 switch(lit & 0xff ) {
5477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5478 genSkipz2(&rFalseIfx,0);
5481 rFalseIfx.condition ^= 1;
5482 genSkipCond(&rFalseIfx,right,0,7);
5486 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5487 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5489 rFalseIfx.condition ^= 1;
5490 if (AOP_TYPE(result) == AOP_CRY)
5491 genSkipc(&rFalseIfx);
5493 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5494 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5500 if(ifx) ifx->generated = 1;
5501 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5507 /* Size is greater than 1 */
5515 /* this means lit = 0xffffffff, or -1 */
5518 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5519 rFalseIfx.condition ^= 1;
5520 genSkipCond(&rFalseIfx,right,size,7);
5521 if(ifx) ifx->generated = 1;
5523 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5532 if(rFalseIfx.condition) {
5533 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5534 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5537 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5539 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5543 if(rFalseIfx.condition) {
5544 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5545 pic16_emitpLabel(truelbl->key);
5547 rFalseIfx.condition ^= 1;
5548 genSkipCond(&rFalseIfx,right,s,7);
5551 if(ifx) ifx->generated = 1;
5553 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5559 if((size == 1) && (0 == (lp1&0xff))) {
5560 /* lower byte of signed word is zero */
5561 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5562 i = ((lp1 >> 8) & 0xff) ^0x80;
5563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5564 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5565 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5567 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5569 if(ifx) ifx->generated = 1;
5572 rFalseIfx.condition ^= 1;
5573 genSkipc(&rFalseIfx);
5574 if(ifx) ifx->generated = 1;
5580 if(lit & (0x80 << (size*8))) {
5581 /* Lit is less than zero */
5582 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5583 //rFalseIfx.condition ^= 1;
5584 //genSkipCond(&rFalseIfx,left,size,7);
5585 //rFalseIfx.condition ^= 1;
5586 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5587 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5589 if(rFalseIfx.condition)
5590 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5592 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5596 /* Lit is greater than or equal to zero */
5597 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5598 //rFalseIfx.condition ^= 1;
5599 //genSkipCond(&rFalseIfx,right,size,7);
5600 //rFalseIfx.condition ^= 1;
5602 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5603 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5605 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5606 if(rFalseIfx.condition)
5607 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5609 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5613 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5614 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5618 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5620 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5622 rFalseIfx.condition ^= 1;
5623 //rFalseIfx.condition = 1;
5624 genSkipc(&rFalseIfx);
5626 pic16_emitpLabel(truelbl->key);
5628 if(ifx) ifx->generated = 1;
5631 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5638 /* compare word or long to an unsigned literal on the right.*/
5643 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5646 break; /* handled above */
5649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5651 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5652 genSkipz2(&rFalseIfx,0);
5656 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5658 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5661 if(rFalseIfx.condition)
5662 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5664 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5667 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5668 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5670 rFalseIfx.condition ^= 1;
5671 genSkipc(&rFalseIfx);
5674 pic16_emitpLabel(truelbl->key);
5676 if(ifx) ifx->generated = 1;
5678 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5686 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5687 i = (lit >> (size*8)) & 0xff;
5689 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5690 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5693 i = (lit >> (size*8)) & 0xff;
5696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5698 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5700 /* this byte of the lit is zero,
5701 * if it's not the last then OR in the variable */
5703 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5708 pic16_emitpLabel(lbl->key);
5710 rFalseIfx.condition ^= 1;
5712 genSkipc(&rFalseIfx);
5716 pic16_emitpLabel(truelbl->key);
5717 if(ifx) ifx->generated = 1;
5719 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5725 /* Compare two variables */
5727 DEBUGpic16_emitcode(";sign","%d",sign);
5731 /* Sigh. thus sucks... */
5735 pctemp = pic16_popGetTempReg(1);
5736 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5737 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5738 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5739 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5740 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5741 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5742 pic16_popReleaseTempReg(pctemp, 1);
5744 /* Signed char comparison */
5745 /* Special thanks to Nikolai Golovchenko for this snippet */
5746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5747 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5748 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5749 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5750 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5751 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5753 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5754 genSkipc(&rFalseIfx);
5756 if(ifx) ifx->generated = 1;
5758 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5766 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5767 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5771 /* The rest of the bytes of a multi-byte compare */
5775 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5778 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5779 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5784 pic16_emitpLabel(lbl->key);
5786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5787 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5788 (AOP_TYPE(result) == AOP_REG)) {
5789 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5790 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5792 genSkipc(&rFalseIfx);
5794 //genSkipc(&rFalseIfx);
5795 if(ifx) ifx->generated = 1;
5798 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5806 if ((AOP_TYPE(result) != AOP_CRY)
5807 && AOP_SIZE(result)) {
5808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5810 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5812 pic16_outBitC(result);
5814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5815 /* if the result is used in the next
5816 ifx conditional branch then generate
5817 code a little differently */
5819 genIfxJump (ifx,"c");
5821 pic16_outBitC(result);
5822 /* leave the result in acc */
5827 #else /* old version of genCmp() */ /* } else { */
5829 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5830 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5831 operand *result, int offset, int invert_op)
5835 /* check condition, > or < ?? */
5836 if(rIfx->condition != 0)invert_op ^= 1;
5838 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5840 if(!ifx)invert_op ^= 1;
5842 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5843 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5846 if(!invert_op)return POC_CPFSGT;
5847 else return POC_CPFSLT;
5850 static int compareAopfirstpass=1;
5852 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5853 operand *oper, int offset, operand *result,
5854 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5860 /* invert if there is a result to be loaded, in order to fit,
5861 * SETC/CLRC sequence */
5862 if(AOP_SIZE(result))invert_op ^= 1;
5864 // if(sign && !offset)invert_op ^= 1;
5866 // if(sign)invert_op ^= 1;
5868 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5870 if(AOP_SIZE(result) && compareAopfirstpass) {
5873 pic16_emitpcode(POC_SETF, pcop2);
5878 pic16_emitpcode(POC_CLRF, pcop2);
5884 compareAopfirstpass = 0;
5886 /* there is a bug when comparing operands with size > 1,
5887 * because higher bytes can be equal and test should be performed
5888 * to the next lower byte, current algorithm, considers operands
5889 * inequal in these cases! -- VR 20041107 */
5893 pic16_emitpcode(op, pcop);
5895 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5898 if((!sign || !offset) && AOP_SIZE(result)) {
5901 pic16_emitpcode(POC_CLRF, pcop2);
5906 pic16_emitpcode(POC_SETF, pcop2);
5911 /* don't emit final branch (offset == 0) */
5915 pic16_emitpcode(POC_RRCF, pcop2);
5917 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5920 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5921 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5922 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5924 truelbl = newiTempLabel( NULL );
5925 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5926 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5927 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5929 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5930 pic16_emitpLabel(truelbl->key);
5932 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5941 static void genCmp (operand *left, operand *right,
5942 operand *result, iCode *ifx, int sign)
5946 resolvedIfx rFalseIfx;
5947 symbol *falselbl, *tlbl;
5951 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5953 resolveIfx(&rFalseIfx, ifx);
5954 size = max(AOP_SIZE(left), AOP_SIZE(right));
5956 /* if left & right are bit variables */
5957 if(AOP_TYPE(left) == AOP_CRY
5958 && AOP_TYPE(right) == AOP_CRY ) {
5960 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5961 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5963 werror(W_POSSBUG2, __FILE__, __LINE__);
5967 /* if literal is on the right then swap with left */
5968 if((AOP_TYPE(right) == AOP_LIT)) {
5969 operand *tmp = right ;
5970 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5972 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5974 // lit = (lit - 1) & mask;
5977 rFalseIfx.condition ^= 1; /* reverse compare */
5979 if ((AOP_TYPE(left) == AOP_LIT)) {
5980 /* float compares are handled by support functions */
5981 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5984 /* actual comparing algorithm */
5985 // size = AOP_SIZE( right );
5987 falselbl = newiTempLabel( NULL );
5988 if(AOP_TYPE(left) == AOP_LIT) {
5989 /* compare to literal */
5990 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5993 pCodeOp *pct, *pct2;
5996 /* signed compare */
5997 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5999 pct = pic16_popCopyReg(&pic16_pc_prodl);
6000 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6001 tlbl = newiTempLabel( NULL );
6003 /* first compare signs:
6004 * a. if both are positive, compare just like unsigned
6005 * b. if both are negative, invert cmpop, compare just like unsigned
6006 * c. if different signs, determine the result directly */
6012 tlbl1 = newiTempLabel( NULL );
6013 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6017 /* literal is zero or positive:
6018 * a. if carry is zero, too, continue compare,
6019 * b. if carry is set, then continue depending on cmpop ^ condition:
6020 * 1. '<' return false (literal < variable),
6021 * 2. '>' return true (literal > variable) */
6022 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6023 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6026 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6027 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6031 /* literal is negative:
6032 * a. if carry is set, too, continue compare,
6033 * b. if carry is zero, then continue depending on cmpop ^ condition:
6034 * 1. '<' return true (literal < variable),
6035 * 2. '>' return false (literal > variable) */
6036 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6037 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6039 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6040 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6045 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6047 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6053 pic16_emitpLabel( tlbl1->key );
6056 compareAopfirstpass=1;
6057 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6058 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6059 // pic16_emitpcode(POC_MOVWF, pct);
6061 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6062 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6063 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6064 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6068 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6069 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6070 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6071 // pic16_emitpcode(POC_MOVWF, pct);
6073 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6074 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6075 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6076 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6077 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6081 if(ifx)ifx->generated = 1;
6083 if(AOP_SIZE(result)) {
6084 pic16_emitpLabel(tlbl->key);
6085 pic16_emitpLabel(falselbl->key);
6086 pic16_outBitOp( result, pct2 );
6088 pic16_emitpLabel(tlbl->key);
6093 /* unsigned compare */
6094 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6096 compareAopfirstpass=1;
6099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6100 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6104 if(ifx)ifx->generated = 1;
6107 if(AOP_SIZE(result)) {
6108 pic16_emitpLabel(falselbl->key);
6109 pic16_outBitC( result );
6114 /* compare registers */
6115 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6119 pCodeOp *pct, *pct2;
6121 /* signed compare */
6122 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6124 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6125 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6126 tlbl = newiTempLabel( NULL );
6128 compareAopfirstpass=1;
6131 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6132 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6133 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6134 pic16_emitpcode(POC_MOVWF, pct);
6136 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6137 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6138 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6140 /* WREG already holds left + 0x80 */
6141 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6144 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6145 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6146 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6147 pic16_emitpcode(POC_MOVWF, pct);
6149 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6150 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6151 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6153 /* WREG already holds left + 0x80 */
6154 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6155 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6158 if(ifx)ifx->generated = 1;
6160 if(AOP_SIZE(result)) {
6161 pic16_emitpLabel(tlbl->key);
6162 pic16_emitpLabel(falselbl->key);
6163 pic16_outBitOp( result, pct2 );
6165 pic16_emitpLabel(tlbl->key);
6169 /* unsigned compare */
6170 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6172 compareAopfirstpass=1;
6175 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6176 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6180 if(ifx)ifx->generated = 1;
6181 if(AOP_SIZE(result)) {
6183 pic16_emitpLabel(falselbl->key);
6184 pic16_outBitC( result );
6191 #else /* } else { */
6193 /* new version of genCmp -- VR 20041012 */
6194 static void genCmp (operand *left,operand *right,
6195 operand *result, iCode *ifx, int sign)
6197 int size; //, offset = 0 ;
6198 unsigned long lit = 0L,i = 0;
6199 resolvedIfx rFalseIfx;
6200 int willCheckCarry=0;
6201 // resolvedIfx rTrueIfx;
6207 * subtract right from left if at the end the carry flag is set then we
6208 * know that left is greater than right */
6210 resolveIfx(&rFalseIfx,ifx);
6211 truelbl = newiTempLabel(NULL);
6212 size = max(AOP_SIZE(left),AOP_SIZE(right));
6214 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6216 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6217 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6220 /* if literal is on the right then swap with left */
6221 if ((AOP_TYPE(right) == AOP_LIT)) {
6222 operand *tmp = right ;
6223 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6225 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6227 // lit = (lit - 1) & mask;
6230 rFalseIfx.condition ^= 1; /* reverse compare */
6232 if ((AOP_TYPE(left) == AOP_LIT)) {
6233 /* float compares are handled by support functions */
6234 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6238 //if(IC_TRUE(ifx) == NULL)
6239 /* if left & right are bit variables */
6240 if (AOP_TYPE(left) == AOP_CRY &&
6241 AOP_TYPE(right) == AOP_CRY ) {
6243 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6244 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6247 symbol *lbl = newiTempLabel(NULL);
6249 if(AOP_TYPE(left) == AOP_LIT) {
6250 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6252 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6254 else willCheckCarry = 0;
6257 if((lit == 0) && (sign == 0)) {
6258 /* unsigned compare to 0 */
6259 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6262 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6264 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6266 genSkipz2(&rFalseIfx,0);
6267 if(ifx)ifx->generated = 1;
6274 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6275 /* degenerate compare can never be true */
6276 if(rFalseIfx.condition == 0)
6277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6279 if(ifx) ifx->generated = 1;
6284 /* signed comparisons to a literal byte */
6285 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6287 int lp1 = (lit+1) & 0xff;
6289 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6292 rFalseIfx.condition ^= 1;
6293 genSkipCond(&rFalseIfx,right,0,7);
6296 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6297 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6298 genSkipz2(&rFalseIfx,1);
6301 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6303 if(rFalseIfx.condition)
6304 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6306 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6308 if(willCheckCarry) {
6309 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6310 else { emitSETC; emitCLRC; }
6313 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6316 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6317 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6318 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6319 rFalseIfx.condition ^= 1;
6320 genSkipc(&rFalseIfx);
6325 /* unsigned comparisons to a literal byte */
6326 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6328 switch(lit & 0xff ) {
6331 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6332 genSkipz2(&rFalseIfx,0);
6335 rFalseIfx.condition ^= 1;
6336 genSkipCond(&rFalseIfx,right,0,7);
6339 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6340 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6341 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6342 rFalseIfx.condition ^= 1;
6343 if (AOP_TYPE(result) == AOP_CRY)
6344 genSkipc(&rFalseIfx);
6346 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6347 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6353 if(ifx) ifx->generated = 1;
6354 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6360 /* Size is greater than 1 */
6368 /* this means lit = 0xffffffff, or -1 */
6371 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6372 rFalseIfx.condition ^= 1;
6373 genSkipCond(&rFalseIfx,right,size,7);
6374 if(ifx) ifx->generated = 1;
6381 if(rFalseIfx.condition) {
6382 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6383 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6386 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6388 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6392 if(rFalseIfx.condition) {
6393 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6394 pic16_emitpLabel(truelbl->key);
6396 rFalseIfx.condition ^= 1;
6397 genSkipCond(&rFalseIfx,right,s,7);
6400 if(ifx) ifx->generated = 1;
6404 if((size == 1) && (0 == (lp1&0xff))) {
6405 /* lower byte of signed word is zero */
6406 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6407 i = ((lp1 >> 8) & 0xff) ^0x80;
6408 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6409 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6410 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6411 rFalseIfx.condition ^= 1;
6412 genSkipc(&rFalseIfx);
6415 if(ifx) ifx->generated = 1;
6419 if(lit & (0x80 << (size*8))) {
6420 /* Lit is less than zero */
6421 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6422 //rFalseIfx.condition ^= 1;
6423 //genSkipCond(&rFalseIfx,left,size,7);
6424 //rFalseIfx.condition ^= 1;
6425 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6426 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6428 if(rFalseIfx.condition)
6429 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6431 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6435 /* Lit is greater than or equal to zero */
6436 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6437 //rFalseIfx.condition ^= 1;
6438 //genSkipCond(&rFalseIfx,right,size,7);
6439 //rFalseIfx.condition ^= 1;
6441 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6442 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6444 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6445 if(rFalseIfx.condition)
6446 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6448 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6453 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6454 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6458 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6460 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6462 rFalseIfx.condition ^= 1;
6463 //rFalseIfx.condition = 1;
6464 genSkipc(&rFalseIfx);
6466 pic16_emitpLabel(truelbl->key);
6468 if(ifx) ifx->generated = 1;
6473 /* compare word or long to an unsigned literal on the right.*/
6478 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6481 break; /* handled above */
6484 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6486 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6487 genSkipz2(&rFalseIfx,0);
6491 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6493 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6496 if(rFalseIfx.condition)
6497 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6499 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6502 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6503 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6505 rFalseIfx.condition ^= 1;
6506 genSkipc(&rFalseIfx);
6509 pic16_emitpLabel(truelbl->key);
6511 if(ifx) ifx->generated = 1;
6517 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6518 i = (lit >> (size*8)) & 0xff;
6520 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6521 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6524 i = (lit >> (size*8)) & 0xff;
6527 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6529 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6531 /* this byte of the lit is zero,
6532 * if it's not the last then OR in the variable */
6534 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6539 pic16_emitpLabel(lbl->key);
6541 rFalseIfx.condition ^= 1;
6543 genSkipc(&rFalseIfx);
6547 pic16_emitpLabel(truelbl->key);
6548 if(ifx) ifx->generated = 1;
6552 /* Compare two variables */
6554 DEBUGpic16_emitcode(";sign","%d",sign);
6558 /* Sigh. thus sucks... */
6562 pctemp = pic16_popGetTempReg(1);
6563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6564 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6565 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6566 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6567 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6568 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6569 pic16_popReleaseTempReg(pctemp, 1);
6571 /* Signed char comparison */
6572 /* Special thanks to Nikolai Golovchenko for this snippet */
6573 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6574 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6575 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6576 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6577 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6578 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6581 genSkipc(&rFalseIfx);
6583 if(ifx) ifx->generated = 1;
6589 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6590 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6594 /* The rest of the bytes of a multi-byte compare */
6598 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6601 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6602 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6607 pic16_emitpLabel(lbl->key);
6609 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6610 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6611 (AOP_TYPE(result) == AOP_REG)) {
6612 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6613 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6615 genSkipc(&rFalseIfx);
6617 //genSkipc(&rFalseIfx);
6618 if(ifx) ifx->generated = 1;
6625 if ((AOP_TYPE(result) != AOP_CRY)
6626 && AOP_SIZE(result)) {
6627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6629 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6631 pic16_outBitC(result);
6633 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6634 /* if the result is used in the next
6635 ifx conditional branch then generate
6636 code a little differently */
6638 genIfxJump (ifx,"c");
6640 pic16_outBitC(result);
6641 /* leave the result in acc */
6652 /*-----------------------------------------------------------------*/
6653 /* genCmpGt :- greater than comparison */
6654 /*-----------------------------------------------------------------*/
6655 static void genCmpGt (iCode *ic, iCode *ifx)
6657 operand *left, *right, *result;
6658 sym_link *letype , *retype;
6664 right= IC_RIGHT(ic);
6665 result = IC_RESULT(ic);
6667 letype = getSpec(operandType(left));
6668 retype =getSpec(operandType(right));
6669 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6670 /* assign the amsops */
6671 pic16_aopOp (left,ic,FALSE);
6672 pic16_aopOp (right,ic,FALSE);
6673 pic16_aopOp (result,ic,TRUE);
6675 genCmp(right, left, result, ifx, sign);
6677 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6678 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6679 pic16_freeAsmop(result,NULL,ic,TRUE);
6682 /*-----------------------------------------------------------------*/
6683 /* genCmpLt - less than comparisons */
6684 /*-----------------------------------------------------------------*/
6685 static void genCmpLt (iCode *ic, iCode *ifx)
6687 operand *left, *right, *result;
6688 sym_link *letype , *retype;
6694 right= IC_RIGHT(ic);
6695 result = IC_RESULT(ic);
6697 letype = getSpec(operandType(left));
6698 retype =getSpec(operandType(right));
6699 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6701 /* assign the amsops */
6702 pic16_aopOp (left,ic,FALSE);
6703 pic16_aopOp (right,ic,FALSE);
6704 pic16_aopOp (result,ic,TRUE);
6706 genCmp(left, right, result, ifx, sign);
6708 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6709 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6710 pic16_freeAsmop(result,NULL,ic,TRUE);
6715 // FIXME reenable literal optimisation when the pic16 port is stable
6717 /*-----------------------------------------------------------------*/
6718 /* genc16bit2lit - compare a 16 bit value to a literal */
6719 /*-----------------------------------------------------------------*/
6720 static void genc16bit2lit(operand *op, int lit, int offset)
6724 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6725 if( (lit&0xff) == 0)
6730 switch( BYTEofLONG(lit,i)) {
6732 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6735 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6738 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6741 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6742 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6747 switch( BYTEofLONG(lit,i)) {
6749 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6753 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6757 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6760 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6762 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6771 /*-----------------------------------------------------------------*/
6772 /* gencjneshort - compare and jump if not equal */
6773 /*-----------------------------------------------------------------*/
6774 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6776 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6778 int res_offset = 0; /* the result may be a different size then left or right */
6779 int res_size = AOP_SIZE(result);
6781 symbol *lbl, *lbl_done;
6783 unsigned long lit = 0L;
6784 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6787 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6789 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6790 resolveIfx(&rIfx,ifx);
6791 lbl = newiTempLabel(NULL);
6792 lbl_done = newiTempLabel(NULL);
6795 /* if the left side is a literal or
6796 if the right is in a pointer register and left
6798 if ((AOP_TYPE(left) == AOP_LIT) ||
6799 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6804 if(AOP_TYPE(right) == AOP_LIT)
6805 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6807 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6808 preserve_result = 1;
6810 if(result && !preserve_result)
6813 for(i = 0; i < AOP_SIZE(result); i++)
6814 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6818 /* if the right side is a literal then anything goes */
6819 if (AOP_TYPE(right) == AOP_LIT &&
6820 AOP_TYPE(left) != AOP_DIR ) {
6823 genc16bit2lit(left, lit, 0);
6825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6831 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6832 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6834 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6838 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6840 if(res_offset < res_size-1)
6848 /* if the right side is in a register or in direct space or
6849 if the left is a pointer register & right is not */
6850 else if (AOP_TYPE(right) == AOP_REG ||
6851 AOP_TYPE(right) == AOP_DIR ||
6852 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6853 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6854 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6855 int lbl_key = lbl->key;
6858 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6859 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6861 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6862 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6863 __FUNCTION__,__LINE__);
6867 /* switch(size) { */
6869 /* genc16bit2lit(left, lit, 0); */
6871 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6876 if((AOP_TYPE(left) == AOP_DIR) &&
6877 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6879 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6880 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6882 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6884 switch (lit & 0xff) {
6886 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6889 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6890 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6895 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6896 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6897 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6902 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6903 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6908 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6911 if(AOP_TYPE(result) == AOP_CRY) {
6912 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6917 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6919 /* fix me. probably need to check result size too */
6920 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6925 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6926 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6933 if(res_offset < res_size-1)
6938 } else if(AOP_TYPE(right) == AOP_REG &&
6939 AOP_TYPE(left) != AOP_DIR){
6942 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6943 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6944 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6949 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6951 if(res_offset < res_size-1)
6956 /* right is a pointer reg need both a & b */
6958 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6960 pic16_emitcode("mov","b,%s",l);
6961 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6962 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6967 if(result && preserve_result)
6970 for(i = 0; i < AOP_SIZE(result); i++)
6971 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6974 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6976 if(result && preserve_result)
6977 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6982 pic16_emitpLabel(lbl->key);
6984 if(result && preserve_result)
6987 for(i = 0; i < AOP_SIZE(result); i++)
6988 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6990 pic16_emitpLabel(lbl_done->key);
6993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7001 /*-----------------------------------------------------------------*/
7002 /* gencjne - compare and jump if not equal */
7003 /*-----------------------------------------------------------------*/
7004 static void gencjne(operand *left, operand *right, iCode *ifx)
7006 symbol *tlbl = newiTempLabel(NULL);
7008 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7009 gencjneshort(left, right, lbl);
7011 pic16_emitcode("mov","a,%s",one);
7012 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7013 pic16_emitcode("","%05d_DS_:",lbl->key+100);
7014 pic16_emitcode("clr","a");
7015 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7017 pic16_emitpLabel(lbl->key);
7018 pic16_emitpLabel(tlbl->key);
7024 /*-----------------------------------------------------------------*/
7025 /* is_LitOp - check if operand has to be treated as literal */
7026 /*-----------------------------------------------------------------*/
7027 static bool is_LitOp(operand *op)
7029 return ((AOP_TYPE(op) == AOP_LIT)
7030 || ( (AOP_TYPE(op) == AOP_PCODE)
7031 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7032 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7035 /*-----------------------------------------------------------------*/
7036 /* is_LitAOp - check if operand has to be treated as literal */
7037 /*-----------------------------------------------------------------*/
7038 static bool is_LitAOp(asmop *aop)
7040 return ((aop->type == AOP_LIT)
7041 || ( (aop->type == AOP_PCODE)
7042 && ( (aop->aopu.pcop->type == PO_LITERAL)
7043 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7048 /*-----------------------------------------------------------------*/
7049 /* genCmpEq - generates code for equal to */
7050 /*-----------------------------------------------------------------*/
7051 static void genCmpEq (iCode *ic, iCode *ifx)
7053 operand *left, *right, *result;
7054 symbol *falselbl = newiTempLabel(NULL);
7055 symbol *donelbl = newiTempLabel(NULL);
7057 int preserve_result = 0;
7058 int generate_result = 0;
7063 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7064 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7065 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7067 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7069 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7071 werror(W_POSSBUG2, __FILE__, __LINE__);
7072 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7073 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7077 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7079 operand *tmp = right ;
7084 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7085 preserve_result = 1;
7087 if(result && AOP_SIZE(result))
7088 generate_result = 1;
7090 if(generate_result && !preserve_result)
7092 for(i = 0; i < AOP_SIZE(result); i++)
7093 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7096 for(i=0; i < AOP_SIZE(left); i++)
7098 if(AOP_TYPE(left) != AOP_ACC)
7101 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7103 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7106 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7108 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7110 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7115 if(generate_result && preserve_result)
7117 for(i = 0; i < AOP_SIZE(result); i++)
7118 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7122 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7124 if(generate_result && preserve_result)
7125 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7127 if(ifx && IC_TRUE(ifx))
7128 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7130 if(ifx && IC_FALSE(ifx))
7131 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7133 pic16_emitpLabel(falselbl->key);
7137 if(ifx && IC_FALSE(ifx))
7138 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7140 if(generate_result && preserve_result)
7142 for(i = 0; i < AOP_SIZE(result); i++)
7143 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7146 pic16_emitpLabel(donelbl->key);
7152 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7153 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7154 pic16_freeAsmop(result,NULL,ic,TRUE);
7160 // old version kept for reference
7162 /*-----------------------------------------------------------------*/
7163 /* genCmpEq - generates code for equal to */
7164 /*-----------------------------------------------------------------*/
7165 static void genCmpEq (iCode *ic, iCode *ifx)
7167 operand *left, *right, *result;
7168 unsigned long lit = 0L;
7170 symbol *falselbl = newiTempLabel(NULL);
7173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7176 DEBUGpic16_emitcode ("; ifx is non-null","");
7178 DEBUGpic16_emitcode ("; ifx is null","");
7180 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7181 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7182 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7184 size = max(AOP_SIZE(left),AOP_SIZE(right));
7186 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7188 /* if literal, literal on the right or
7189 if the right is in a pointer register and left
7191 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7192 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7193 operand *tmp = right ;
7199 if(ifx && !AOP_SIZE(result)){
7201 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7202 /* if they are both bit variables */
7203 if (AOP_TYPE(left) == AOP_CRY &&
7204 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7205 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7206 if(AOP_TYPE(right) == AOP_LIT){
7207 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7209 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7210 pic16_emitcode("cpl","c");
7211 } else if(lit == 1L) {
7212 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7214 pic16_emitcode("clr","c");
7216 /* AOP_TYPE(right) == AOP_CRY */
7218 symbol *lbl = newiTempLabel(NULL);
7219 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7220 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7221 pic16_emitcode("cpl","c");
7222 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7224 /* if true label then we jump if condition
7226 tlbl = newiTempLabel(NULL);
7227 if ( IC_TRUE(ifx) ) {
7228 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7229 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7231 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7232 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7234 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7237 /* left and right are both bit variables, result is carry */
7240 resolveIfx(&rIfx,ifx);
7242 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7243 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7244 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7245 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7250 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7252 /* They're not both bit variables. Is the right a literal? */
7253 if(AOP_TYPE(right) == AOP_LIT) {
7254 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7259 switch(lit & 0xff) {
7261 if ( IC_TRUE(ifx) ) {
7262 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7264 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7266 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7267 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7271 if ( IC_TRUE(ifx) ) {
7272 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7274 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7276 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7281 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7283 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7288 /* end of size == 1 */
7292 genc16bit2lit(left,lit,offset);
7295 /* end of size == 2 */
7300 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7301 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7302 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7303 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7306 /* search for patterns that can be optimized */
7308 genc16bit2lit(left,lit,0);
7312 emitSKPZ; // if hi word unequal
7314 emitSKPNZ; // if hi word equal
7316 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7317 genc16bit2lit(left,lit,2);
7320 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7321 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7325 pic16_emitpLabel(falselbl->key);
7334 } else if(AOP_TYPE(right) == AOP_CRY ) {
7335 /* we know the left is not a bit, but that the right is */
7336 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7337 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7338 pic16_popGet(AOP(right),offset));
7339 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7341 /* if the two are equal, then W will be 0 and the Z bit is set
7342 * we could test Z now, or go ahead and check the high order bytes if
7343 * the variable we're comparing is larger than a byte. */
7346 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7348 if ( IC_TRUE(ifx) ) {
7350 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7351 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7354 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7355 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7359 /* They're both variables that are larger than bits */
7362 tlbl = newiTempLabel(NULL);
7365 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7366 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7368 if ( IC_TRUE(ifx) ) {
7372 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7374 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7375 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7379 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7382 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7383 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7388 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7390 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7391 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7395 if(s>1 && IC_TRUE(ifx)) {
7396 pic16_emitpLabel(tlbl->key);
7397 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7401 /* mark the icode as generated */
7406 /* if they are both bit variables */
7407 if (AOP_TYPE(left) == AOP_CRY &&
7408 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7409 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7410 if(AOP_TYPE(right) == AOP_LIT){
7411 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7413 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7414 pic16_emitcode("cpl","c");
7415 } else if(lit == 1L) {
7416 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7418 pic16_emitcode("clr","c");
7420 /* AOP_TYPE(right) == AOP_CRY */
7422 symbol *lbl = newiTempLabel(NULL);
7423 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7424 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7425 pic16_emitcode("cpl","c");
7426 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7429 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7430 pic16_outBitC(result);
7434 genIfxJump (ifx,"c");
7437 /* if the result is used in an arithmetic operation
7438 then put the result in place */
7439 pic16_outBitC(result);
7442 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7443 gencjne(left,right,result,ifx);
7446 gencjne(left,right,newiTempLabel(NULL));
7448 if(IC_TRUE(ifx)->key)
7449 gencjne(left,right,IC_TRUE(ifx)->key);
7451 gencjne(left,right,IC_FALSE(ifx)->key);
7455 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7456 pic16_aopPut(AOP(result),"a",0);
7461 genIfxJump (ifx,"a");
7465 /* if the result is used in an arithmetic operation
7466 then put the result in place */
7468 if (AOP_TYPE(result) != AOP_CRY)
7469 pic16_outAcc(result);
7471 /* leave the result in acc */
7475 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7476 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477 pic16_freeAsmop(result,NULL,ic,TRUE);
7481 /*-----------------------------------------------------------------*/
7482 /* ifxForOp - returns the icode containing the ifx for operand */
7483 /*-----------------------------------------------------------------*/
7484 static iCode *ifxForOp ( operand *op, iCode *ic )
7488 /* if true symbol then needs to be assigned */
7489 if (IS_TRUE_SYMOP(op))
7492 /* if this has register type condition and
7493 the next instruction is ifx with the same operand
7494 and live to of the operand is upto the ifx only then */
7496 && ic->next->op == IFX
7497 && IC_COND(ic->next)->key == op->key
7498 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7500 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7506 ic->next->op == IFX &&
7507 IC_COND(ic->next)->key == op->key) {
7508 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7513 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7515 ic->next->op == IFX)
7516 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7519 ic->next->op == IFX &&
7520 IC_COND(ic->next)->key == op->key) {
7521 DEBUGpic16_emitcode ("; "," key is okay");
7522 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7523 OP_SYMBOL(op)->liveTo,
7528 /* the code below is completely untested
7529 * it just allows ulong2fs.c compile -- VR */
7532 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7533 __FILE__, __FUNCTION__, __LINE__);
7535 /* if this has register type condition and
7536 the next instruction is ifx with the same operand
7537 and live to of the operand is upto the ifx only then */
7539 ic->next->op == IFX &&
7540 IC_COND(ic->next)->key == op->key &&
7541 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7545 ic->next->op == IFX &&
7546 IC_COND(ic->next)->key == op->key) {
7547 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7551 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7552 __FILE__, __FUNCTION__, __LINE__);
7554 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7559 /*-----------------------------------------------------------------*/
7560 /* genAndOp - for && operation */
7561 /*-----------------------------------------------------------------*/
7562 static void genAndOp (iCode *ic)
7564 operand *left,*right, *result;
7569 /* note here that && operations that are in an
7570 if statement are taken away by backPatchLabels
7571 only those used in arthmetic operations remain */
7572 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7573 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7574 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7576 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7578 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7579 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7580 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7582 /* if both are bit variables */
7583 /* if (AOP_TYPE(left) == AOP_CRY && */
7584 /* AOP_TYPE(right) == AOP_CRY ) { */
7585 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7586 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7587 /* pic16_outBitC(result); */
7589 /* tlbl = newiTempLabel(NULL); */
7590 /* pic16_toBoolean(left); */
7591 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7592 /* pic16_toBoolean(right); */
7593 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7594 /* pic16_outBitAcc(result); */
7597 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7598 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7599 pic16_freeAsmop(result,NULL,ic,TRUE);
7603 /*-----------------------------------------------------------------*/
7604 /* genOrOp - for || operation */
7605 /*-----------------------------------------------------------------*/
7608 modified this code, but it doesn't appear to ever get called
7611 static void genOrOp (iCode *ic)
7613 operand *left,*right, *result;
7618 /* note here that || operations that are in an
7619 if statement are taken away by backPatchLabels
7620 only those used in arthmetic operations remain */
7621 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7622 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7623 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7625 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7627 /* if both are bit variables */
7628 if (AOP_TYPE(left) == AOP_CRY &&
7629 AOP_TYPE(right) == AOP_CRY ) {
7630 pic16_emitcode("clrc","");
7631 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7632 AOP(left)->aopu.aop_dir,
7633 AOP(left)->aopu.aop_dir);
7634 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7635 AOP(right)->aopu.aop_dir,
7636 AOP(right)->aopu.aop_dir);
7637 pic16_emitcode("setc","");
7640 tlbl = newiTempLabel(NULL);
7641 pic16_toBoolean(left);
7643 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7644 pic16_toBoolean(right);
7645 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7647 pic16_outBitAcc(result);
7650 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7651 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7652 pic16_freeAsmop(result,NULL,ic,TRUE);
7655 /*-----------------------------------------------------------------*/
7656 /* isLiteralBit - test if lit == 2^n */
7657 /*-----------------------------------------------------------------*/
7658 static int isLiteralBit(unsigned long lit)
7660 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7661 0x100L,0x200L,0x400L,0x800L,
7662 0x1000L,0x2000L,0x4000L,0x8000L,
7663 0x10000L,0x20000L,0x40000L,0x80000L,
7664 0x100000L,0x200000L,0x400000L,0x800000L,
7665 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7666 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7670 for(idx = 0; idx < 32; idx++)
7676 /*-----------------------------------------------------------------*/
7677 /* continueIfTrue - */
7678 /*-----------------------------------------------------------------*/
7679 static void continueIfTrue (iCode *ic)
7683 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7687 /*-----------------------------------------------------------------*/
7689 /*-----------------------------------------------------------------*/
7690 static void jumpIfTrue (iCode *ic)
7694 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7698 /*-----------------------------------------------------------------*/
7699 /* jmpTrueOrFalse - */
7700 /*-----------------------------------------------------------------*/
7701 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7703 // ugly but optimized by peephole
7706 symbol *nlbl = newiTempLabel(NULL);
7707 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7708 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7709 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7710 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7712 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7713 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7718 /*-----------------------------------------------------------------*/
7719 /* genAnd - code for and */
7720 /*-----------------------------------------------------------------*/
7721 static void genAnd (iCode *ic, iCode *ifx)
7723 operand *left, *right, *result;
7725 unsigned long lit = 0L;
7731 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7732 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7733 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7735 resolveIfx(&rIfx,ifx);
7737 /* if left is a literal & right is not then exchange them */
7738 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7739 AOP_NEEDSACC(left)) {
7740 operand *tmp = right ;
7745 /* if result = right then exchange them */
7746 if(pic16_sameRegs(AOP(result),AOP(right))){
7747 operand *tmp = right ;
7752 /* if right is bit then exchange them */
7753 if (AOP_TYPE(right) == AOP_CRY &&
7754 AOP_TYPE(left) != AOP_CRY){
7755 operand *tmp = right ;
7759 if(AOP_TYPE(right) == AOP_LIT)
7760 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7762 size = AOP_SIZE(result);
7764 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7767 // result = bit & yy;
7768 if (AOP_TYPE(left) == AOP_CRY){
7769 // c = bit & literal;
7770 if(AOP_TYPE(right) == AOP_LIT){
7772 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7775 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7778 if(size && (AOP_TYPE(result) == AOP_CRY)){
7779 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7782 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7786 pic16_emitcode("clr","c");
7789 if (AOP_TYPE(right) == AOP_CRY){
7791 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7792 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7795 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7797 pic16_emitcode("rrc","a");
7798 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7804 pic16_outBitC(result);
7806 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7807 genIfxJump(ifx, "c");
7811 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7812 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7813 if((AOP_TYPE(right) == AOP_LIT) &&
7814 (AOP_TYPE(result) == AOP_CRY) &&
7815 (AOP_TYPE(left) != AOP_CRY)){
7816 int posbit = isLiteralBit(lit);
7820 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7823 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7829 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7830 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7832 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7833 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7836 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7837 size = AOP_SIZE(left);
7840 int bp = posbit, ofs=0;
7847 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7848 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7852 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7853 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7862 symbol *tlbl = newiTempLabel(NULL);
7863 int sizel = AOP_SIZE(left);
7869 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7871 /* patch provided by Aaron Colwell */
7872 if((posbit = isLiteralBit(bytelit)) != 0) {
7873 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7874 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7875 (posbit-1),0, PO_GPR_REGISTER));
7877 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7878 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7880 if (bytelit == 0xff) {
7881 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7882 * a peephole could optimize it out -- VR */
7883 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7885 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7886 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7889 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7890 pic16_popGetLabel(tlbl->key));
7894 /* old code, left here for reference -- VR 09/2004 */
7895 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7897 if((posbit = isLiteralBit(bytelit)) != 0)
7898 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7900 if(bytelit != 0x0FFL)
7901 pic16_emitcode("anl","a,%s",
7902 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7903 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7909 // bit = left & literal
7912 pic16_emitpLabel(tlbl->key);
7914 // if(left & literal)
7917 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7920 pic16_emitpLabel(tlbl->key);
7925 pic16_outBitC(result);
7929 /* if left is same as result */
7930 if(pic16_sameRegs(AOP(result),AOP(left))){
7932 for(;size--; offset++,lit>>=8) {
7933 if(AOP_TYPE(right) == AOP_LIT){
7934 switch(lit & 0xff) {
7936 /* and'ing with 0 has clears the result */
7937 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7938 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7941 /* and'ing with 0xff is a nop when the result and left are the same */
7946 int p = pic16_my_powof2( (~lit) & 0xff );
7948 /* only one bit is set in the literal, so use a bcf instruction */
7949 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7950 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7953 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7954 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7955 if(know_W != (lit&0xff))
7956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7958 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7963 if (AOP_TYPE(left) == AOP_ACC) {
7964 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7966 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7967 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7974 // left & result in different registers
7975 if(AOP_TYPE(result) == AOP_CRY){
7977 // if(size), result in bit
7978 // if(!size && ifx), conditional oper: if(left & right)
7979 symbol *tlbl = newiTempLabel(NULL);
7980 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7982 pic16_emitcode("setb","c");
7984 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7985 pic16_emitcode("anl","a,%s",
7986 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7987 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7992 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7993 pic16_outBitC(result);
7995 jmpTrueOrFalse(ifx, tlbl);
7997 for(;(size--);offset++) {
7999 // result = left & right
8000 if(AOP_TYPE(right) == AOP_LIT){
8001 int t = (lit >> (offset*8)) & 0x0FFL;
8004 pic16_emitcode("clrf","%s",
8005 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8006 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8009 pic16_emitcode("movf","%s,w",
8010 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8011 pic16_emitcode("movwf","%s",
8012 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8013 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8014 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8017 pic16_emitcode("movlw","0x%x",t);
8018 pic16_emitcode("andwf","%s,w",
8019 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8020 pic16_emitcode("movwf","%s",
8021 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8023 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8024 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8025 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8030 if (AOP_TYPE(left) == AOP_ACC) {
8031 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8032 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8034 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8035 pic16_emitcode("andwf","%s,w",
8036 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8037 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8038 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8040 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8041 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8047 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8048 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8049 pic16_freeAsmop(result,NULL,ic,TRUE);
8052 /*-----------------------------------------------------------------*/
8053 /* genOr - code for or */
8054 /*-----------------------------------------------------------------*/
8055 static void genOr (iCode *ic, iCode *ifx)
8057 operand *left, *right, *result;
8059 unsigned long lit = 0L;
8061 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8063 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8064 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8065 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8067 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8069 /* if left is a literal & right is not then exchange them */
8070 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8071 AOP_NEEDSACC(left)) {
8072 operand *tmp = right ;
8077 /* if result = right then exchange them */
8078 if(pic16_sameRegs(AOP(result),AOP(right))){
8079 operand *tmp = right ;
8084 /* if right is bit then exchange them */
8085 if (AOP_TYPE(right) == AOP_CRY &&
8086 AOP_TYPE(left) != AOP_CRY){
8087 operand *tmp = right ;
8092 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8094 if(AOP_TYPE(right) == AOP_LIT)
8095 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8097 size = AOP_SIZE(result);
8101 if (AOP_TYPE(left) == AOP_CRY){
8102 if(AOP_TYPE(right) == AOP_LIT){
8103 // c = bit & literal;
8105 // lit != 0 => result = 1
8106 if(AOP_TYPE(result) == AOP_CRY){
8108 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8109 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8110 // AOP(result)->aopu.aop_dir,
8111 // AOP(result)->aopu.aop_dir);
8113 continueIfTrue(ifx);
8117 // lit == 0 => result = left
8118 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8120 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8123 if (AOP_TYPE(right) == AOP_CRY){
8124 if(pic16_sameRegs(AOP(result),AOP(left))){
8126 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8127 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8128 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8130 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8131 AOP(result)->aopu.aop_dir,
8132 AOP(result)->aopu.aop_dir);
8133 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8134 AOP(right)->aopu.aop_dir,
8135 AOP(right)->aopu.aop_dir);
8136 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8137 AOP(result)->aopu.aop_dir,
8138 AOP(result)->aopu.aop_dir);
8140 if( AOP_TYPE(result) == AOP_ACC) {
8141 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8142 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8143 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8148 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8149 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8150 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8151 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8153 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8154 AOP(result)->aopu.aop_dir,
8155 AOP(result)->aopu.aop_dir);
8156 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8157 AOP(right)->aopu.aop_dir,
8158 AOP(right)->aopu.aop_dir);
8159 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8160 AOP(left)->aopu.aop_dir,
8161 AOP(left)->aopu.aop_dir);
8162 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8163 AOP(result)->aopu.aop_dir,
8164 AOP(result)->aopu.aop_dir);
8169 symbol *tlbl = newiTempLabel(NULL);
8170 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8173 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8174 if( AOP_TYPE(right) == AOP_ACC) {
8175 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8177 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8178 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8183 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8184 pic16_emitcode(";XXX setb","c");
8185 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8186 AOP(left)->aopu.aop_dir,tlbl->key+100);
8187 pic16_toBoolean(right);
8188 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8189 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8190 jmpTrueOrFalse(ifx, tlbl);
8194 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8201 pic16_outBitC(result);
8203 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8204 genIfxJump(ifx, "c");
8208 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8209 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8210 if((AOP_TYPE(right) == AOP_LIT) &&
8211 (AOP_TYPE(result) == AOP_CRY) &&
8212 (AOP_TYPE(left) != AOP_CRY)){
8214 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8217 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8219 continueIfTrue(ifx);
8222 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8223 // lit = 0, result = boolean(left)
8225 pic16_emitcode(";XXX setb","c");
8226 pic16_toBoolean(right);
8228 symbol *tlbl = newiTempLabel(NULL);
8229 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8231 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8233 genIfxJump (ifx,"a");
8237 pic16_outBitC(result);
8241 /* if left is same as result */
8242 if(pic16_sameRegs(AOP(result),AOP(left))){
8244 for(;size--; offset++,lit>>=8) {
8245 if(AOP_TYPE(right) == AOP_LIT){
8246 if((lit & 0xff) == 0)
8247 /* or'ing with 0 has no effect */
8250 int p = pic16_my_powof2(lit & 0xff);
8252 /* only one bit is set in the literal, so use a bsf instruction */
8253 pic16_emitpcode(POC_BSF,
8254 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8256 if(know_W != (lit & 0xff))
8257 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8258 know_W = lit & 0xff;
8259 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8264 if (AOP_TYPE(left) == AOP_ACC) {
8265 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8266 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8268 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8269 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8271 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8272 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8278 // left & result in different registers
8279 if(AOP_TYPE(result) == AOP_CRY){
8281 // if(size), result in bit
8282 // if(!size && ifx), conditional oper: if(left | right)
8283 symbol *tlbl = newiTempLabel(NULL);
8284 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8285 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8289 pic16_emitcode(";XXX setb","c");
8291 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8292 pic16_emitcode(";XXX orl","a,%s",
8293 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8294 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8299 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8300 pic16_outBitC(result);
8302 jmpTrueOrFalse(ifx, tlbl);
8303 } else for(;(size--);offset++){
8305 // result = left & right
8306 if(AOP_TYPE(right) == AOP_LIT){
8307 int t = (lit >> (offset*8)) & 0x0FFL;
8310 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8311 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8313 pic16_emitcode("movf","%s,w",
8314 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8315 pic16_emitcode("movwf","%s",
8316 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8319 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8320 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8321 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8323 pic16_emitcode("movlw","0x%x",t);
8324 pic16_emitcode("iorwf","%s,w",
8325 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8326 pic16_emitcode("movwf","%s",
8327 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8333 // faster than result <- left, anl result,right
8334 // and better if result is SFR
8335 if (AOP_TYPE(left) == AOP_ACC) {
8336 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8337 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8339 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8340 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8342 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8343 pic16_emitcode("iorwf","%s,w",
8344 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8347 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8352 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8353 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8354 pic16_freeAsmop(result,NULL,ic,TRUE);
8357 /*-----------------------------------------------------------------*/
8358 /* genXor - code for xclusive or */
8359 /*-----------------------------------------------------------------*/
8360 static void genXor (iCode *ic, iCode *ifx)
8362 operand *left, *right, *result;
8364 unsigned long lit = 0L;
8366 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8368 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8369 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8370 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8372 /* if left is a literal & right is not ||
8373 if left needs acc & right does not */
8374 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8375 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8376 operand *tmp = right ;
8381 /* if result = right then exchange them */
8382 if(pic16_sameRegs(AOP(result),AOP(right))){
8383 operand *tmp = right ;
8388 /* if right is bit then exchange them */
8389 if (AOP_TYPE(right) == AOP_CRY &&
8390 AOP_TYPE(left) != AOP_CRY){
8391 operand *tmp = right ;
8395 if(AOP_TYPE(right) == AOP_LIT)
8396 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8398 size = AOP_SIZE(result);
8402 if (AOP_TYPE(left) == AOP_CRY){
8403 if(AOP_TYPE(right) == AOP_LIT){
8404 // c = bit & literal;
8406 // lit>>1 != 0 => result = 1
8407 if(AOP_TYPE(result) == AOP_CRY){
8409 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8410 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8412 continueIfTrue(ifx);
8415 pic16_emitcode("setb","c");
8419 // lit == 0, result = left
8420 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8422 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8424 // lit == 1, result = not(left)
8425 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8426 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8427 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8428 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8431 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8432 pic16_emitcode("cpl","c");
8439 symbol *tlbl = newiTempLabel(NULL);
8440 if (AOP_TYPE(right) == AOP_CRY){
8442 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8445 int sizer = AOP_SIZE(right);
8447 // if val>>1 != 0, result = 1
8448 pic16_emitcode("setb","c");
8450 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8452 // test the msb of the lsb
8453 pic16_emitcode("anl","a,#0xfe");
8454 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8458 pic16_emitcode("rrc","a");
8460 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8461 pic16_emitcode("cpl","c");
8462 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8467 pic16_outBitC(result);
8469 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8470 genIfxJump(ifx, "c");
8474 if(pic16_sameRegs(AOP(result),AOP(left))){
8475 /* if left is same as result */
8476 for(;size--; offset++) {
8477 if(AOP_TYPE(right) == AOP_LIT){
8478 int t = (lit >> (offset*8)) & 0x0FFL;
8482 if (IS_AOP_PREG(left)) {
8483 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8484 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8485 pic16_aopPut(AOP(result),"a",offset);
8487 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8488 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8489 pic16_emitcode("xrl","%s,%s",
8490 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8491 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8494 if (AOP_TYPE(left) == AOP_ACC)
8495 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8497 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8498 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8500 if (IS_AOP_PREG(left)) {
8501 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8502 pic16_aopPut(AOP(result),"a",offset);
8504 pic16_emitcode("xrl","%s,a",
8505 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8511 // left & result in different registers
8512 if(AOP_TYPE(result) == AOP_CRY){
8514 // if(size), result in bit
8515 // if(!size && ifx), conditional oper: if(left ^ right)
8516 symbol *tlbl = newiTempLabel(NULL);
8517 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8519 pic16_emitcode("setb","c");
8521 if((AOP_TYPE(right) == AOP_LIT) &&
8522 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8523 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8525 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8526 pic16_emitcode("xrl","a,%s",
8527 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8529 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8534 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8535 pic16_outBitC(result);
8537 jmpTrueOrFalse(ifx, tlbl);
8538 } else for(;(size--);offset++){
8540 // result = left & right
8541 if(AOP_TYPE(right) == AOP_LIT){
8542 int t = (lit >> (offset*8)) & 0x0FFL;
8545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8546 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8547 pic16_emitcode("movf","%s,w",
8548 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8549 pic16_emitcode("movwf","%s",
8550 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8553 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8554 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8555 pic16_emitcode("comf","%s,w",
8556 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8557 pic16_emitcode("movwf","%s",
8558 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8561 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8562 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8563 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8564 pic16_emitcode("movlw","0x%x",t);
8565 pic16_emitcode("xorwf","%s,w",
8566 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8567 pic16_emitcode("movwf","%s",
8568 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8574 // faster than result <- left, anl result,right
8575 // and better if result is SFR
8576 if (AOP_TYPE(left) == AOP_ACC) {
8577 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8578 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8580 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8581 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8582 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8583 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8585 if ( AOP_TYPE(result) != AOP_ACC){
8586 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8587 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8593 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8594 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8595 pic16_freeAsmop(result,NULL,ic,TRUE);
8598 /*-----------------------------------------------------------------*/
8599 /* genInline - write the inline code out */
8600 /*-----------------------------------------------------------------*/
8601 static void genInline (iCode *ic)
8603 char *buffer, *bp, *bp1;
8605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8607 _G.inLine += (!options.asmpeep);
8609 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8610 strcpy(buffer,IC_INLINE(ic));
8612 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8614 /* emit each line as a code */
8620 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8628 /* print label, use this special format with NULL directive
8629 * to denote that the argument should not be indented with tab */
8630 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8637 if ((bp1 != bp) && *bp1)
8638 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8643 _G.inLine -= (!options.asmpeep);
8646 /*-----------------------------------------------------------------*/
8647 /* genRRC - rotate right with carry */
8648 /*-----------------------------------------------------------------*/
8649 static void genRRC (iCode *ic)
8651 operand *left , *result ;
8652 int size, offset = 0, same;
8654 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8656 /* rotate right with carry */
8658 result=IC_RESULT(ic);
8659 pic16_aopOp (left,ic,FALSE);
8660 pic16_aopOp (result,ic,FALSE);
8662 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8664 same = pic16_sameRegs(AOP(result),AOP(left));
8666 size = AOP_SIZE(result);
8668 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8670 /* get the lsb and put it into the carry */
8671 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8678 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8680 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8681 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8687 pic16_freeAsmop(left,NULL,ic,TRUE);
8688 pic16_freeAsmop(result,NULL,ic,TRUE);
8691 /*-----------------------------------------------------------------*/
8692 /* genRLC - generate code for rotate left with carry */
8693 /*-----------------------------------------------------------------*/
8694 static void genRLC (iCode *ic)
8696 operand *left , *result ;
8697 int size, offset = 0;
8700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8701 /* rotate right with carry */
8703 result=IC_RESULT(ic);
8704 pic16_aopOp (left,ic,FALSE);
8705 pic16_aopOp (result,ic,FALSE);
8707 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8709 same = pic16_sameRegs(AOP(result),AOP(left));
8711 /* move it to the result */
8712 size = AOP_SIZE(result);
8714 /* get the msb and put it into the carry */
8715 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8722 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8724 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8725 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8732 pic16_freeAsmop(left,NULL,ic,TRUE);
8733 pic16_freeAsmop(result,NULL,ic,TRUE);
8737 /* gpasm can get the highest order bit with HIGH/UPPER
8738 * so the following probably is not needed -- VR */
8740 /*-----------------------------------------------------------------*/
8741 /* genGetHbit - generates code get highest order bit */
8742 /*-----------------------------------------------------------------*/
8743 static void genGetHbit (iCode *ic)
8745 operand *left, *result;
8747 result=IC_RESULT(ic);
8748 pic16_aopOp (left,ic,FALSE);
8749 pic16_aopOp (result,ic,FALSE);
8751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8752 /* get the highest order byte into a */
8753 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8754 if(AOP_TYPE(result) == AOP_CRY){
8755 pic16_emitcode("rlc","a");
8756 pic16_outBitC(result);
8759 pic16_emitcode("rl","a");
8760 pic16_emitcode("anl","a,#0x01");
8761 pic16_outAcc(result);
8765 pic16_freeAsmop(left,NULL,ic,TRUE);
8766 pic16_freeAsmop(result,NULL,ic,TRUE);
8770 /*-----------------------------------------------------------------*/
8771 /* AccRol - rotate left accumulator by known count */
8772 /*-----------------------------------------------------------------*/
8773 static void AccRol (int shCount)
8775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8776 shCount &= 0x0007; // shCount : 0..7
8781 pic16_emitcode("rl","a");
8784 pic16_emitcode("rl","a");
8785 pic16_emitcode("rl","a");
8788 pic16_emitcode("swap","a");
8789 pic16_emitcode("rr","a");
8792 pic16_emitcode("swap","a");
8795 pic16_emitcode("swap","a");
8796 pic16_emitcode("rl","a");
8799 pic16_emitcode("rr","a");
8800 pic16_emitcode("rr","a");
8803 pic16_emitcode("rr","a");
8809 /*-----------------------------------------------------------------*/
8810 /* AccLsh - left shift accumulator by known count */
8811 /*-----------------------------------------------------------------*/
8812 static void AccLsh (int shCount)
8814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8820 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8823 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8824 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8828 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8831 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8834 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8835 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8838 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8839 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8842 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8846 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8849 /*-----------------------------------------------------------------*/
8850 /* AccRsh - right shift accumulator by known count */
8851 /*-----------------------------------------------------------------*/
8852 static void AccRsh (int shCount, int andmask)
8854 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8859 pic16_emitpcode(POC_RRNCFW,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_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8867 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8870 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8873 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8874 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8877 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8878 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8881 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8886 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8888 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8892 /*-----------------------------------------------------------------*/
8893 /* AccSRsh - signed right shift accumulator by known count */
8894 /*-----------------------------------------------------------------*/
8895 static void AccSRsh (int shCount)
8898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8901 pic16_emitcode("mov","c,acc.7");
8902 pic16_emitcode("rrc","a");
8903 } else if(shCount == 2){
8904 pic16_emitcode("mov","c,acc.7");
8905 pic16_emitcode("rrc","a");
8906 pic16_emitcode("mov","c,acc.7");
8907 pic16_emitcode("rrc","a");
8909 tlbl = newiTempLabel(NULL);
8910 /* rotate right accumulator */
8911 AccRol(8 - shCount);
8912 /* and kill the higher order bits */
8913 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8914 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8915 pic16_emitcode("orl","a,#0x%02x",
8916 (unsigned char)~SRMask[shCount]);
8917 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8923 /*-----------------------------------------------------------------*/
8924 /* shiftR1Left2Result - shift right one byte from left to result */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftR1Left2ResultSigned (operand *left, int offl,
8927 operand *result, int offr,
8932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8934 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8938 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8940 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8951 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8966 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8969 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8970 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8973 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8974 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8976 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8981 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8982 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8983 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8984 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8988 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8990 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8995 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8996 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9002 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9003 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9004 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9005 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9006 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9011 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9013 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9019 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9020 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9021 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9022 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9026 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9034 /*-----------------------------------------------------------------*/
9035 /* shiftR1Left2Result - shift right one byte from left to result */
9036 /*-----------------------------------------------------------------*/
9037 static void shiftR1Left2Result (operand *left, int offl,
9038 operand *result, int offr,
9039 int shCount, int sign)
9043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9045 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9047 /* Copy the msb into the carry if signed. */
9049 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9059 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9061 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9062 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9068 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9074 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9079 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9082 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9085 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9086 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9087 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9092 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9093 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9094 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9099 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9100 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9102 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9108 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9109 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9110 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9117 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9127 /*-----------------------------------------------------------------*/
9128 /* shiftL1Left2Result - shift left one byte from left to result */
9129 /*-----------------------------------------------------------------*/
9130 static void shiftL1Left2Result (operand *left, int offl,
9131 operand *result, int offr, int shCount)
9136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9138 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9139 DEBUGpic16_emitcode ("; ***","same = %d",same);
9140 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9142 /* shift left accumulator */
9143 //AccLsh(shCount); // don't comment out just yet...
9144 // pic16_aopPut(AOP(result),"a",offr);
9148 /* Shift left 1 bit position */
9149 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9151 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9153 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9154 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9158 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9159 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9164 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9165 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9171 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9172 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9177 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9179 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9182 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9183 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9184 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9185 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9186 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9189 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9190 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9195 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9200 /*-----------------------------------------------------------------*/
9201 /* movLeft2Result - move byte from left to result */
9202 /*-----------------------------------------------------------------*/
9203 static void movLeft2Result (operand *left, int offl,
9204 operand *result, int offr)
9207 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9208 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9209 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9211 if (*l == '@' && (IS_AOP_PREG(result))) {
9212 pic16_emitcode("mov","a,%s",l);
9213 pic16_aopPut(AOP(result),"a",offr);
9215 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9216 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9221 /*-----------------------------------------------------------------*/
9222 /* shiftL2Left2Result - shift left two bytes from left to result */
9223 /*-----------------------------------------------------------------*/
9224 static void shiftL2Left2Result (operand *left, int offl,
9225 operand *result, int offr, int shCount)
9227 int same = pic16_sameRegs(AOP(result), AOP(left));
9230 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9232 if (same && (offl != offr)) { // shift bytes
9235 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9236 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9238 } else { // just treat as different later on
9251 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9252 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9253 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9257 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9258 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9264 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9265 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9266 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9267 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9268 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9269 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9270 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9272 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9273 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9277 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9278 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9279 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9280 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9281 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9282 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9283 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9284 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9285 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9286 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9289 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9291 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9292 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9293 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9303 /* note, use a mov/add for the shift since the mov has a
9304 chance of getting optimized out */
9305 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9306 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9307 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9308 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9309 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9313 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9314 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9320 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9321 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9322 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9323 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9325 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9326 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9327 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9331 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9332 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9336 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9337 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9338 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9339 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9341 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9342 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9343 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9344 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9345 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9346 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9347 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9348 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9351 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9352 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9353 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9354 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9355 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9360 /*-----------------------------------------------------------------*/
9361 /* shiftR2Left2Result - shift right two bytes from left to result */
9362 /*-----------------------------------------------------------------*/
9363 static void shiftR2Left2Result (operand *left, int offl,
9364 operand *result, int offr,
9365 int shCount, int sign)
9367 int same = pic16_sameRegs(AOP(result), AOP(left));
9369 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9371 if (same && (offl != offr)) { // shift right bytes
9374 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9375 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9377 } else { // just treat as different later on
9389 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9394 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9395 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9397 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9398 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9399 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9400 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9405 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9408 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9409 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9416 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9417 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9418 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9420 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9421 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9422 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9425 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9426 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9427 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9429 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9430 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9431 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9432 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9433 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9437 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9438 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9442 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9443 pic16_emitpcode(POC_BTFSC,
9444 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9445 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9453 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9454 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9456 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9457 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9458 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9459 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9461 pic16_emitpcode(POC_BTFSC,
9462 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9463 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9465 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9466 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9467 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9468 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9470 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9471 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9472 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9473 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9474 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9475 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9476 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9477 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9479 pic16_emitpcode(POC_BTFSC,
9480 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9481 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9483 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9484 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9491 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9492 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9493 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9494 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9497 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9499 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9504 /*-----------------------------------------------------------------*/
9505 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9506 /*-----------------------------------------------------------------*/
9507 static void shiftLLeftOrResult (operand *left, int offl,
9508 operand *result, int offr, int shCount)
9510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9512 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9513 /* shift left accumulator */
9515 /* or with result */
9516 /* back to result */
9517 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9520 /*-----------------------------------------------------------------*/
9521 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9522 /*-----------------------------------------------------------------*/
9523 static void shiftRLeftOrResult (operand *left, int offl,
9524 operand *result, int offr, int shCount)
9526 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9528 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9529 /* shift right accumulator */
9531 /* or with result */
9532 /* back to result */
9533 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9536 /*-----------------------------------------------------------------*/
9537 /* genlshOne - left shift a one byte quantity by known count */
9538 /*-----------------------------------------------------------------*/
9539 static void genlshOne (operand *result, operand *left, int shCount)
9541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9542 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9545 /*-----------------------------------------------------------------*/
9546 /* genlshTwo - left shift two bytes by known amount != 0 */
9547 /*-----------------------------------------------------------------*/
9548 static void genlshTwo (operand *result,operand *left, int shCount)
9552 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9553 size = pic16_getDataSize(result);
9555 /* if shCount >= 8 */
9561 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9563 movLeft2Result(left, LSB, result, MSB16);
9565 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9568 /* 1 <= shCount <= 7 */
9571 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9573 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9577 /*-----------------------------------------------------------------*/
9578 /* shiftLLong - shift left one long from left to result */
9579 /* offr = LSB or MSB16 */
9580 /*-----------------------------------------------------------------*/
9581 static void shiftLLong (operand *left, operand *result, int offr )
9583 int size = AOP_SIZE(result);
9584 int same = pic16_sameRegs(AOP(left),AOP(result));
9587 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9589 if (same && (offr == MSB16)) { //shift one byte
9590 for(i=size-1;i>=MSB16;i--) {
9591 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9592 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9595 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9598 if (size > LSB+offr ){
9600 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9602 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9603 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9607 if(size > MSB16+offr){
9609 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9611 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9612 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9616 if(size > MSB24+offr){
9618 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9620 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9621 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9625 if(size > MSB32+offr){
9627 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9629 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9630 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9634 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9638 /*-----------------------------------------------------------------*/
9639 /* genlshFour - shift four byte by a known amount != 0 */
9640 /*-----------------------------------------------------------------*/
9641 static void genlshFour (operand *result, operand *left, int shCount)
9645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9646 size = AOP_SIZE(result);
9648 /* if shifting more that 3 bytes */
9649 if (shCount >= 24 ) {
9652 /* lowest order of left goes to the highest
9653 order of the destination */
9654 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9656 movLeft2Result(left, LSB, result, MSB32);
9658 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9659 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9660 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9665 /* more than two bytes */
9666 else if ( shCount >= 16 ) {
9667 /* lower order two bytes goes to higher order two bytes */
9669 /* if some more remaining */
9671 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9673 movLeft2Result(left, MSB16, result, MSB32);
9674 movLeft2Result(left, LSB, result, MSB24);
9676 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9677 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9681 /* if more than 1 byte */
9682 else if ( shCount >= 8 ) {
9683 /* lower order three bytes goes to higher order three bytes */
9687 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9689 movLeft2Result(left, LSB, result, MSB16);
9691 else{ /* size = 4 */
9693 movLeft2Result(left, MSB24, result, MSB32);
9694 movLeft2Result(left, MSB16, result, MSB24);
9695 movLeft2Result(left, LSB, result, MSB16);
9696 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9698 else if(shCount == 1)
9699 shiftLLong(left, result, MSB16);
9701 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9702 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9703 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9704 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9709 /* 1 <= shCount <= 7 */
9710 else if(shCount <= 3)
9712 shiftLLong(left, result, LSB);
9713 while(--shCount >= 1)
9714 shiftLLong(result, result, LSB);
9716 /* 3 <= shCount <= 7, optimize */
9718 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9719 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9720 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9724 /*-----------------------------------------------------------------*/
9725 /* genLeftShiftLiteral - left shifting by known count */
9726 /*-----------------------------------------------------------------*/
9727 void pic16_genLeftShiftLiteral (operand *left,
9732 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9736 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9737 pic16_freeAsmop(right,NULL,ic,TRUE);
9739 pic16_aopOp(left,ic,FALSE);
9740 pic16_aopOp(result,ic,FALSE);
9742 size = getSize(operandType(result));
9745 pic16_emitcode("; shift left ","result %d, left %d",size,
9749 /* I suppose that the left size >= result size */
9752 movLeft2Result(left, size, result, size);
9756 else if(shCount >= (size * 8))
9758 pic16_aopPut(AOP(result),zero,size);
9762 genlshOne (result,left,shCount);
9767 genlshTwo (result,left,shCount);
9771 genlshFour (result,left,shCount);
9775 pic16_freeAsmop(left,NULL,ic,TRUE);
9776 pic16_freeAsmop(result,NULL,ic,TRUE);
9779 /*-----------------------------------------------------------------*
9780 * genMultiAsm - repeat assembly instruction for size of register.
9781 * if endian == 1, then the high byte (i.e base address + size of
9782 * register) is used first else the low byte is used first;
9783 *-----------------------------------------------------------------*/
9784 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9802 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9808 #if !(USE_GENERIC_SIGNED_SHIFT)
9809 /*-----------------------------------------------------------------*/
9810 /* genLeftShift - generates code for left shifting */
9811 /*-----------------------------------------------------------------*/
9812 static void genLeftShift (iCode *ic)
9814 operand *left,*right, *result;
9817 symbol *tlbl , *tlbl1;
9820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9822 right = IC_RIGHT(ic);
9824 result = IC_RESULT(ic);
9826 pic16_aopOp(right,ic,FALSE);
9828 /* if the shift count is known then do it
9829 as efficiently as possible */
9830 if (AOP_TYPE(right) == AOP_LIT) {
9831 pic16_genLeftShiftLiteral (left,right,result,ic);
9835 /* shift count is unknown then we have to form
9836 * a loop. Get the loop count in WREG : Note: we take
9837 * only the lower order byte since shifting
9838 * more than 32 bits make no sense anyway, ( the
9839 * largest size of an object can be only 32 bits ) */
9841 pic16_aopOp(left,ic,FALSE);
9842 pic16_aopOp(result,ic,FALSE);
9844 /* now move the left to the result if they are not the
9845 * same, and if size > 1,
9846 * and if right is not same to result (!!!) -- VR */
9847 if (!pic16_sameRegs(AOP(left),AOP(result))
9848 && (AOP_SIZE(result) > 1)) {
9850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9852 size = AOP_SIZE(result);
9857 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9858 if (*l == '@' && (IS_AOP_PREG(result))) {
9860 pic16_emitcode("mov","a,%s",l);
9861 pic16_aopPut(AOP(result),"a",offset);
9865 /* we don't know if left is a literal or a register, take care -- VR */
9866 mov2f(AOP(result), AOP(left), offset);
9872 size = AOP_SIZE(result);
9874 /* if it is only one byte then */
9876 if(optimized_for_speed) {
9877 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9878 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9879 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9880 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9881 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9882 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9883 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9884 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9885 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9886 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9887 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9888 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9893 tlbl = newiTempLabel(NULL);
9896 /* this is already done, why change it? */
9897 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9898 mov2f(AOP(result), AOP(left), 0);
9902 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9903 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9904 pic16_emitpLabel(tlbl->key);
9905 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9906 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9913 if (pic16_sameRegs(AOP(left),AOP(result))) {
9915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9917 tlbl = newiTempLabel(NULL);
9918 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9919 genMultiAsm(POC_RRCF, result, size,1);
9920 pic16_emitpLabel(tlbl->key);
9921 genMultiAsm(POC_RLCF, result, size,0);
9922 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9928 //tlbl = newiTempLabel(NULL);
9930 //tlbl1 = newiTempLabel(NULL);
9932 //reAdjustPreg(AOP(result));
9934 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9935 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9936 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9938 //pic16_emitcode("add","a,acc");
9939 //pic16_aopPut(AOP(result),"a",offset++);
9941 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9943 // pic16_emitcode("rlc","a");
9944 // pic16_aopPut(AOP(result),"a",offset++);
9946 //reAdjustPreg(AOP(result));
9948 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9949 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9952 tlbl = newiTempLabel(NULL);
9953 tlbl1= newiTempLabel(NULL);
9955 size = AOP_SIZE(result);
9958 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9960 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9962 /* offset should be 0, 1 or 3 */
9964 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9966 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9968 pic16_emitpcode(POC_MOVWF, pctemp);
9971 pic16_emitpLabel(tlbl->key);
9974 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9976 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9978 pic16_emitpcode(POC_DECFSZ, pctemp);
9979 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9980 pic16_emitpLabel(tlbl1->key);
9982 pic16_popReleaseTempReg(pctemp,1);
9986 pic16_freeAsmop (right,NULL,ic,TRUE);
9987 pic16_freeAsmop(left,NULL,ic,TRUE);
9988 pic16_freeAsmop(result,NULL,ic,TRUE);
9994 #error old code (left here for reference)
9995 /*-----------------------------------------------------------------*/
9996 /* genLeftShift - generates code for left shifting */
9997 /*-----------------------------------------------------------------*/
9998 static void genLeftShift (iCode *ic)
10000 operand *left,*right, *result;
10003 symbol *tlbl , *tlbl1;
10006 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10008 right = IC_RIGHT(ic);
10009 left = IC_LEFT(ic);
10010 result = IC_RESULT(ic);
10012 pic16_aopOp(right,ic,FALSE);
10014 /* if the shift count is known then do it
10015 as efficiently as possible */
10016 if (AOP_TYPE(right) == AOP_LIT) {
10017 pic16_genLeftShiftLiteral (left,right,result,ic);
10021 /* shift count is unknown then we have to form
10022 a loop get the loop count in B : Note: we take
10023 only the lower order byte since shifting
10024 more that 32 bits make no sense anyway, ( the
10025 largest size of an object can be only 32 bits ) */
10028 pic16_aopOp(left,ic,FALSE);
10029 pic16_aopOp(result,ic,FALSE);
10031 /* now move the left to the result if they are not the
10033 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10034 AOP_SIZE(result) > 1) {
10036 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10038 size = AOP_SIZE(result);
10041 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10042 if (*l == '@' && (IS_AOP_PREG(result))) {
10044 pic16_emitcode("mov","a,%s",l);
10045 pic16_aopPut(AOP(result),"a",offset);
10048 /* we don't know if left is a literal or a register, take care -- VR */
10049 mov2f(AOP(result), AOP(left), offset);
10055 size = AOP_SIZE(result);
10057 /* if it is only one byte then */
10059 if(optimized_for_speed) {
10060 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10061 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10062 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10065 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10066 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10067 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10068 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10069 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10070 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10071 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10074 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10076 tlbl = newiTempLabel(NULL);
10077 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10078 mov2f(AOP(result), AOP(left), 0);
10080 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10081 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10084 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10085 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10086 pic16_emitpLabel(tlbl->key);
10087 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10088 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10090 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10095 if (pic16_sameRegs(AOP(left),AOP(result))) {
10097 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10099 tlbl = newiTempLabel(NULL);
10100 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10101 genMultiAsm(POC_RRCF, result, size,1);
10102 pic16_emitpLabel(tlbl->key);
10103 genMultiAsm(POC_RLCF, result, size,0);
10104 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10106 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10110 //tlbl = newiTempLabel(NULL);
10112 //tlbl1 = newiTempLabel(NULL);
10114 //reAdjustPreg(AOP(result));
10116 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10117 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10118 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10120 //pic16_emitcode("add","a,acc");
10121 //pic16_aopPut(AOP(result),"a",offset++);
10123 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10125 // pic16_emitcode("rlc","a");
10126 // pic16_aopPut(AOP(result),"a",offset++);
10128 //reAdjustPreg(AOP(result));
10130 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10131 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10134 tlbl = newiTempLabel(NULL);
10135 tlbl1= newiTempLabel(NULL);
10137 size = AOP_SIZE(result);
10140 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10142 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10144 /* offset should be 0, 1 or 3 */
10146 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10148 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10150 pic16_emitpcode(POC_MOVWF, pctemp);
10153 pic16_emitpLabel(tlbl->key);
10156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10158 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10160 pic16_emitpcode(POC_DECFSZ, pctemp);
10161 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10162 pic16_emitpLabel(tlbl1->key);
10164 pic16_popReleaseTempReg(pctemp,1);
10168 pic16_freeAsmop (right,NULL,ic,TRUE);
10169 pic16_freeAsmop(left,NULL,ic,TRUE);
10170 pic16_freeAsmop(result,NULL,ic,TRUE);
10174 /*-----------------------------------------------------------------*/
10175 /* genrshOne - right shift a one byte quantity by known count */
10176 /*-----------------------------------------------------------------*/
10177 static void genrshOne (operand *result, operand *left,
10178 int shCount, int sign)
10180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10181 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10184 /*-----------------------------------------------------------------*/
10185 /* genrshTwo - right shift two bytes by known amount != 0 */
10186 /*-----------------------------------------------------------------*/
10187 static void genrshTwo (operand *result,operand *left,
10188 int shCount, int sign)
10190 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10191 /* if shCount >= 8 */
10192 if (shCount >= 8) {
10195 shiftR1Left2Result(left, MSB16, result, LSB,
10198 movLeft2Result(left, MSB16, result, LSB);
10200 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10203 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10204 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10208 /* 1 <= shCount <= 7 */
10210 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10213 /*-----------------------------------------------------------------*/
10214 /* shiftRLong - shift right one long from left to result */
10215 /* offl = LSB or MSB16 */
10216 /*-----------------------------------------------------------------*/
10217 static void shiftRLong (operand *left, int offl,
10218 operand *result, int sign)
10220 int size = AOP_SIZE(result);
10221 int same = pic16_sameRegs(AOP(left),AOP(result));
10223 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10225 if (same && (offl == MSB16)) { //shift one byte right
10226 for(i=MSB16;i<size;i++) {
10227 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10228 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10233 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10239 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10241 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10242 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10245 if(offl == MSB16) {
10246 /* add sign of "a" */
10247 pic16_addSign(result, MSB32, sign);
10251 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10253 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10258 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10260 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10265 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10268 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10269 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10274 /*-----------------------------------------------------------------*/
10275 /* genrshFour - shift four byte by a known amount != 0 */
10276 /*-----------------------------------------------------------------*/
10277 static void genrshFour (operand *result, operand *left,
10278 int shCount, int sign)
10280 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10281 /* if shifting more that 3 bytes */
10282 if(shCount >= 24 ) {
10285 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10287 movLeft2Result(left, MSB32, result, LSB);
10289 pic16_addSign(result, MSB16, sign);
10291 else if(shCount >= 16){
10294 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10296 movLeft2Result(left, MSB24, result, LSB);
10297 movLeft2Result(left, MSB32, result, MSB16);
10299 pic16_addSign(result, MSB24, sign);
10301 else if(shCount >= 8){
10304 shiftRLong(left, MSB16, result, sign);
10305 else if(shCount == 0){
10306 movLeft2Result(left, MSB16, result, LSB);
10307 movLeft2Result(left, MSB24, result, MSB16);
10308 movLeft2Result(left, MSB32, result, MSB24);
10309 pic16_addSign(result, MSB32, sign);
10311 else{ //shcount >= 2
10312 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10313 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10314 /* the last shift is signed */
10315 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10316 pic16_addSign(result, MSB32, sign);
10319 else{ /* 1 <= shCount <= 7 */
10321 shiftRLong(left, LSB, result, sign);
10323 shiftRLong(result, LSB, result, sign);
10326 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10327 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10328 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10333 /*-----------------------------------------------------------------*/
10334 /* genRightShiftLiteral - right shifting by known count */
10335 /*-----------------------------------------------------------------*/
10336 static void genRightShiftLiteral (operand *left,
10342 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10343 int lsize,res_size;
10345 pic16_freeAsmop(right,NULL,ic,TRUE);
10347 pic16_aopOp(left,ic,FALSE);
10348 pic16_aopOp(result,ic,FALSE);
10350 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10353 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10357 lsize = pic16_getDataSize(left);
10358 res_size = pic16_getDataSize(result);
10359 /* test the LEFT size !!! */
10361 /* I suppose that the left size >= result size */
10364 movLeft2Result(left, lsize, result, res_size);
10367 else if(shCount >= (lsize * 8)){
10369 if(res_size == 1) {
10370 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10372 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10373 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10378 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10379 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10380 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10382 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10387 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10392 switch (res_size) {
10394 genrshOne (result,left,shCount,sign);
10398 genrshTwo (result,left,shCount,sign);
10402 genrshFour (result,left,shCount,sign);
10410 pic16_freeAsmop(left,NULL,ic,TRUE);
10411 pic16_freeAsmop(result,NULL,ic,TRUE);
10414 #if !(USE_GENERIC_SIGNED_SHIFT)
10415 /*-----------------------------------------------------------------*/
10416 /* genSignedRightShift - right shift of signed number */
10417 /*-----------------------------------------------------------------*/
10418 static void genSignedRightShift (iCode *ic)
10420 operand *right, *left, *result;
10423 symbol *tlbl, *tlbl1 ;
10426 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10428 /* we do it the hard way put the shift count in b
10429 and loop thru preserving the sign */
10430 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10432 right = IC_RIGHT(ic);
10433 left = IC_LEFT(ic);
10434 result = IC_RESULT(ic);
10436 pic16_aopOp(right,ic,FALSE);
10437 pic16_aopOp(left,ic,FALSE);
10438 pic16_aopOp(result,ic,FALSE);
10441 if ( AOP_TYPE(right) == AOP_LIT) {
10442 genRightShiftLiteral (left,right,result,ic,1);
10445 /* shift count is unknown then we have to form
10446 a loop get the loop count in B : Note: we take
10447 only the lower order byte since shifting
10448 more that 32 bits make no sense anyway, ( the
10449 largest size of an object can be only 32 bits ) */
10451 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10452 //pic16_emitcode("inc","b");
10453 //pic16_freeAsmop (right,NULL,ic,TRUE);
10454 //pic16_aopOp(left,ic,FALSE);
10455 //pic16_aopOp(result,ic,FALSE);
10457 /* now move the left to the result if they are not the
10459 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10460 AOP_SIZE(result) > 1) {
10462 size = AOP_SIZE(result);
10466 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10467 if (*l == '@' && IS_AOP_PREG(result)) {
10469 pic16_emitcode("mov","a,%s",l);
10470 pic16_aopPut(AOP(result),"a",offset);
10472 pic16_aopPut(AOP(result),l,offset);
10474 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10475 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10481 /* mov the highest order bit to OVR */
10482 tlbl = newiTempLabel(NULL);
10483 tlbl1= newiTempLabel(NULL);
10485 size = AOP_SIZE(result);
10488 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10490 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10492 /* offset should be 0, 1 or 3 */
10493 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10495 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10497 pic16_emitpcode(POC_MOVWF, pctemp);
10500 pic16_emitpLabel(tlbl->key);
10502 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10503 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10506 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10509 pic16_emitpcode(POC_DECFSZ, pctemp);
10510 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10511 pic16_emitpLabel(tlbl1->key);
10513 pic16_popReleaseTempReg(pctemp,1);
10515 size = AOP_SIZE(result);
10517 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10518 pic16_emitcode("rlc","a");
10519 pic16_emitcode("mov","ov,c");
10520 /* if it is only one byte then */
10522 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10524 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10525 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10526 pic16_emitcode("mov","c,ov");
10527 pic16_emitcode("rrc","a");
10528 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10529 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10530 pic16_aopPut(AOP(result),"a",0);
10534 reAdjustPreg(AOP(result));
10535 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10536 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10537 pic16_emitcode("mov","c,ov");
10539 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10541 pic16_emitcode("rrc","a");
10542 pic16_aopPut(AOP(result),"a",offset--);
10544 reAdjustPreg(AOP(result));
10545 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10546 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10551 pic16_freeAsmop(left,NULL,ic,TRUE);
10552 pic16_freeAsmop(result,NULL,ic,TRUE);
10553 pic16_freeAsmop(right,NULL,ic,TRUE);
10557 #if !(USE_GENERIC_SIGNED_SHIFT)
10558 #warning This implementation of genRightShift() is incomplete!
10559 /*-----------------------------------------------------------------*/
10560 /* genRightShift - generate code for right shifting */
10561 /*-----------------------------------------------------------------*/
10562 static void genRightShift (iCode *ic)
10564 operand *right, *left, *result;
10568 symbol *tlbl, *tlbl1 ;
10570 /* if signed then we do it the hard way preserve the
10571 sign bit moving it inwards */
10572 letype = getSpec(operandType(IC_LEFT(ic)));
10573 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10575 if (!SPEC_USIGN(letype)) {
10576 genSignedRightShift (ic);
10580 /* signed & unsigned types are treated the same : i.e. the
10581 signed is NOT propagated inwards : quoting from the
10582 ANSI - standard : "for E1 >> E2, is equivalent to division
10583 by 2**E2 if unsigned or if it has a non-negative value,
10584 otherwise the result is implementation defined ", MY definition
10585 is that the sign does not get propagated */
10587 right = IC_RIGHT(ic);
10588 left = IC_LEFT(ic);
10589 result = IC_RESULT(ic);
10591 pic16_aopOp(right,ic,FALSE);
10593 /* if the shift count is known then do it
10594 as efficiently as possible */
10595 if (AOP_TYPE(right) == AOP_LIT) {
10596 genRightShiftLiteral (left,right,result,ic, 0);
10600 /* shift count is unknown then we have to form
10601 a loop get the loop count in B : Note: we take
10602 only the lower order byte since shifting
10603 more that 32 bits make no sense anyway, ( the
10604 largest size of an object can be only 32 bits ) */
10606 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10607 pic16_emitcode("inc","b");
10608 pic16_aopOp(left,ic,FALSE);
10609 pic16_aopOp(result,ic,FALSE);
10611 /* now move the left to the result if they are not the
10613 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10614 AOP_SIZE(result) > 1) {
10616 size = AOP_SIZE(result);
10619 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10620 if (*l == '@' && IS_AOP_PREG(result)) {
10622 pic16_emitcode("mov","a,%s",l);
10623 pic16_aopPut(AOP(result),"a",offset);
10625 pic16_aopPut(AOP(result),l,offset);
10630 tlbl = newiTempLabel(NULL);
10631 tlbl1= newiTempLabel(NULL);
10632 size = AOP_SIZE(result);
10635 /* if it is only one byte then */
10638 tlbl = newiTempLabel(NULL);
10639 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10640 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10641 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10644 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10645 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10646 pic16_emitpLabel(tlbl->key);
10647 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10648 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10650 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10655 reAdjustPreg(AOP(result));
10656 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10657 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10660 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10662 pic16_emitcode("rrc","a");
10663 pic16_aopPut(AOP(result),"a",offset--);
10665 reAdjustPreg(AOP(result));
10667 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10668 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10671 pic16_freeAsmop(left,NULL,ic,TRUE);
10672 pic16_freeAsmop (right,NULL,ic,TRUE);
10673 pic16_freeAsmop(result,NULL,ic,TRUE);
10677 #if (USE_GENERIC_SIGNED_SHIFT)
10678 /*-----------------------------------------------------------------*/
10679 /* genGenericShift - generates code for left or right shifting */
10680 /*-----------------------------------------------------------------*/
10681 static void genGenericShift (iCode *ic, int isShiftLeft) {
10682 operand *left,*right, *result;
10684 int sign, signedCount;
10685 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10686 PIC_OPCODE pos_shift, neg_shift;
10690 right = IC_RIGHT(ic);
10691 left = IC_LEFT(ic);
10692 result = IC_RESULT(ic);
10694 pic16_aopOp(right,ic,FALSE);
10695 pic16_aopOp(left,ic,FALSE);
10696 pic16_aopOp(result,ic,FALSE);
10698 sign = !SPEC_USIGN(operandType (left));
10699 signedCount = !SPEC_USIGN(operandType (right));
10701 /* if the shift count is known then do it
10702 as efficiently as possible */
10703 if (AOP_TYPE(right) == AOP_LIT) {
10704 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10705 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10706 // we should modify right->aopu.aop_lit here!
10707 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10708 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10710 pic16_genLeftShiftLiteral (left,right,result,ic);
10712 genRightShiftLiteral (left,right,result,ic, sign);
10715 } // if (right is literal)
10717 /* shift count is unknown then we have to form a loop.
10718 * Note: we take only the lower order byte since shifting
10719 * more than 32 bits make no sense anyway, ( the
10720 * largest size of an object can be only 32 bits )
10721 * Note: we perform arithmetic shifts if the left operand is
10722 * signed and we do an (effective) right shift, i. e. we
10723 * shift in the sign bit from the left. */
10725 label_complete = newiTempLabel ( NULL );
10726 label_loop_pos = newiTempLabel ( NULL );
10727 label_loop_neg = NULL;
10728 label_negative = NULL;
10729 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10730 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10733 // additional labels needed
10734 label_loop_neg = newiTempLabel ( NULL );
10735 label_negative = newiTempLabel ( NULL );
10738 // copy source to result -- this will effectively truncate the left operand to the size of result!
10739 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10740 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10741 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10742 mov2f (AOP(result),AOP(left), offset);
10745 // if result is longer than left, fill with zeros (or sign)
10746 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10747 if (sign && AOP_SIZE(left) > 0) {
10748 // shift signed operand -- fill with sign
10749 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10750 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10751 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10752 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10753 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10756 // shift unsigned operand -- fill result with zeros
10757 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10758 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10761 } // if (size mismatch)
10763 pic16_mov2w (AOP(right), 0);
10764 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10765 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10768 // perform a shift by one (shift count is positive)
10769 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10770 // 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])
10771 pic16_emitpLabel (label_loop_pos->key);
10773 if (sign && (pos_shift == POC_RRCF)) {
10774 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10777 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10778 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10779 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10781 // perform a shift by one (shift count is positive)
10782 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10783 // 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])
10784 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10785 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10787 pic16_emitpLabel (label_loop_pos->key);
10788 if (sign && (pos_shift == POC_RRCF)) {
10789 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10792 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10793 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10794 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10795 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10799 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10801 pic16_emitpLabel (label_negative->key);
10802 // perform a shift by -1 (shift count is negative)
10803 // 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)
10805 pic16_emitpLabel (label_loop_neg->key);
10806 if (sign && (neg_shift == POC_RRCF)) {
10807 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10810 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10811 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10812 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10813 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10814 } // if (signedCount)
10816 pic16_emitpLabel (label_complete->key);
10819 pic16_freeAsmop (right,NULL,ic,TRUE);
10820 pic16_freeAsmop(left,NULL,ic,TRUE);
10821 pic16_freeAsmop(result,NULL,ic,TRUE);
10824 static void genLeftShift (iCode *ic) {
10825 genGenericShift (ic, 1);
10828 static void genRightShift (iCode *ic) {
10829 genGenericShift (ic, 0);
10834 void pic16_loadFSR0(operand *op)
10836 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10839 /*-----------------------------------------------------------------*/
10840 /* genUnpackBits - generates code for unpacking bits */
10841 /*-----------------------------------------------------------------*/
10842 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10846 sym_link *etype, *letype;
10847 int blen=0, bstr=0;
10851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10852 etype = getSpec(operandType(result));
10853 letype = getSpec(operandType(left));
10855 // if(IS_BITFIELD(etype)) {
10856 blen = SPEC_BLEN(etype);
10857 bstr = SPEC_BSTR(etype);
10860 lbstr = SPEC_BSTR( letype );
10863 if((blen == 1) && (bstr < 8)) {
10864 /* it is a single bit, so use the appropriate bit instructions */
10865 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10867 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10869 if((ptype == POINTER) && (result)) {
10870 /* workaround to reduce the extra lfsr instruction */
10871 pic16_emitpcode(POC_BTFSC,
10872 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10874 pic16_emitpcode(POC_BTFSC,
10875 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10878 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10880 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10886 /* the following call to pic16_loadFSR0 is temporary until
10887 * optimization to handle single bit assignments is added
10888 * to the function. Until then use the old safe way! -- VR */
10889 pic16_loadFSR0( left );
10891 /* read the first byte */
10898 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10901 pic16_emitcode("clr","a");
10902 pic16_emitcode("movc","a","@a+dptr");
10907 /* if we have bitdisplacement then it fits */
10908 /* into this byte completely or if length is */
10909 /* less than a byte */
10910 if ((shCnt = SPEC_BSTR(etype)) ||
10911 (SPEC_BLEN(etype) <= 8)) {
10913 /* shift right acc */
10916 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10917 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10919 /* VR -- normally I would use the following, but since we use the hack,
10920 * to avoid the masking from AccRsh, why not mask it right now? */
10923 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10932 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10933 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10936 /* bit field did not fit in a byte */
10937 rlen = SPEC_BLEN(etype) - 8;
10938 pic16_aopPut(AOP(result),"a",offset++);
10945 pic16_emitcode("inc","%s",rname);
10946 pic16_emitcode("mov","a,@%s",rname);
10950 pic16_emitcode("inc","%s",rname);
10951 pic16_emitcode("movx","a,@%s",rname);
10955 pic16_emitcode("inc","dptr");
10956 pic16_emitcode("movx","a,@dptr");
10960 pic16_emitcode("clr","a");
10961 pic16_emitcode("inc","dptr");
10962 pic16_emitcode("movc","a","@a+dptr");
10966 pic16_emitcode("inc","dptr");
10967 pic16_emitcode("lcall","__gptrget");
10972 /* if we are done */
10976 pic16_aopPut(AOP(result),"a",offset++);
10981 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10982 pic16_aopPut(AOP(result),"a",offset);
10989 static void genDataPointerGet(operand *left,
10993 int size, offset = 0, leoffset=0 ;
10995 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10996 pic16_aopOp(result, ic, FALSE);
10998 size = AOP_SIZE(result);
10999 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11003 /* The following tests may save a redudant movff instruction when
11004 * accessing unions */
11006 /* if they are the same */
11007 if (operandsEqu (left, result)) {
11008 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11014 /* if they are the same registers */
11015 if (pic16_sameRegs(AOP(left),AOP(result))) {
11016 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11022 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11023 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11024 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11031 if ( AOP_TYPE(left) == AOP_PCODE) {
11032 fprintf(stderr,"genDataPointerGet %s, %d\n",
11033 AOP(left)->aopu.pcop->name,
11034 (AOP(left)->aopu.pcop->type == PO_DIR)?
11035 PCOR(AOP(left)->aopu.pcop)->instance:
11036 PCOI(AOP(left)->aopu.pcop)->offset);
11040 if(AOP(left)->aopu.pcop->type == PO_DIR)
11041 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11043 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11046 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11048 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11049 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11050 pic16_mov2w(AOP(left), offset); // patch 8
11051 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11053 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11054 pic16_popGet(AOP(left), offset), //patch 8
11055 pic16_popGet(AOP(result), offset)));
11063 pic16_freeAsmop(result,NULL,ic,TRUE);
11068 /*-----------------------------------------------------------------*/
11069 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11070 /*-----------------------------------------------------------------*/
11071 static void genNearPointerGet (operand *left,
11076 //regs *preg = NULL ;
11077 sym_link *rtype, *retype;
11078 sym_link *ltype = operandType(left);
11082 rtype = operandType(result);
11083 retype= getSpec(rtype);
11085 pic16_aopOp(left,ic,FALSE);
11087 // pic16_DumpOp("(left)",left);
11088 // pic16_DumpOp("(result)",result);
11090 /* if left is rematerialisable and
11091 * result is not bit variable type and
11092 * the left is pointer to data space i.e
11093 * lower 128 bytes of space */
11095 if (AOP_TYPE(left) == AOP_PCODE
11096 && !IS_BITFIELD(retype)
11097 && DCL_TYPE(ltype) == POINTER) {
11099 genDataPointerGet (left,result,ic);
11100 pic16_freeAsmop(left, NULL, ic, TRUE);
11104 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11105 pic16_aopOp (result,ic,FALSE);
11107 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11110 if(IS_BITFIELD( retype )
11111 && (SPEC_BLEN(operandType(result))==1)
11115 int bitstrt, bytestrt;
11117 /* if this is bitfield of size 1, see if we are checking the value
11118 * of a single bit in an if-statement,
11119 * if yes, then don't generate usual code, but execute the
11120 * genIfx directly -- VR */
11124 /* CHECK: if next iCode is IFX
11125 * and current result operand is nextic's conditional operand
11126 * and current result operand live ranges ends at nextic's key number
11128 if((nextic->op == IFX)
11129 && (result == IC_COND(nextic))
11130 && (OP_LIVETO(result) == nextic->seq)
11132 /* everything is ok then */
11133 /* find a way to optimize the genIfx iCode */
11135 bytestrt = SPEC_BSTR(operandType(result))/8;
11136 bitstrt = SPEC_BSTR(operandType(result))%8;
11138 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11140 genIfxpCOpJump(nextic, jop);
11142 pic16_freeAsmop(left, NULL, ic, TRUE);
11143 pic16_freeAsmop(result, NULL, ic, TRUE);
11150 /* if the value is already in a pointer register
11151 * then don't need anything more */
11152 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11153 /* otherwise get a free pointer register */
11154 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11156 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11157 /* bitfields will be handled by genUnpackBits */
11158 if(!IS_BITFIELD(retype)) {
11160 if(is_LitAOp( AOP(left) )) {
11161 pic16_loadFSR0( left );
11163 // set up FSR0 with address from left
11164 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11165 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11170 /* if bitfield then unpack the bits */
11171 if (IS_BITFIELD(retype))
11172 genUnpackBits (result, left, NULL, POINTER);
11174 /* we have can just get the values */
11175 int size = AOP_SIZE(result);
11178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11180 /* fsr0 is loaded already -- VR */
11181 // pic16_loadFSR0( left );
11183 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11184 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11187 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11188 pic16_popGet(AOP(result), offset++)));
11190 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11191 pic16_popGet(AOP(result), offset++)));
11195 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11196 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11198 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11202 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11204 pic16_emitcode("mov","a,@%s",rname);
11205 pic16_aopPut(AOP(result),"a",offset);
11207 sprintf(buffer,"@%s",rname);
11208 pic16_aopPut(AOP(result),buffer,offset);
11212 pic16_emitcode("inc","%s",rname);
11217 /* now some housekeeping stuff */
11219 /* we had to allocate for this iCode */
11220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11221 pic16_freeAsmop(NULL,aop,ic,TRUE);
11223 /* we did not allocate which means left
11224 * already in a pointer register, then
11225 * if size > 0 && this could be used again
11226 * we have to point it back to where it
11228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11229 if (AOP_SIZE(result) > 1
11230 && !OP_SYMBOL(left)->remat
11231 && ( OP_SYMBOL(left)->liveTo > ic->seq
11233 // int size = AOP_SIZE(result) - 1;
11235 // pic16_emitcode("dec","%s",rname);
11240 pic16_freeAsmop(left,NULL,ic,TRUE);
11241 pic16_freeAsmop(result,NULL,ic,TRUE);
11244 /*-----------------------------------------------------------------*/
11245 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11246 /*-----------------------------------------------------------------*/
11247 static void genPagedPointerGet (operand *left,
11252 regs *preg = NULL ;
11254 sym_link *rtype, *retype;
11256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11258 rtype = operandType(result);
11259 retype= getSpec(rtype);
11261 pic16_aopOp(left,ic,FALSE);
11263 /* if the value is already in a pointer register
11264 then don't need anything more */
11265 if (!AOP_INPREG(AOP(left))) {
11266 /* otherwise get a free pointer register */
11268 preg = getFreePtr(ic,&aop,FALSE);
11269 pic16_emitcode("mov","%s,%s",
11271 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11272 rname = preg->name ;
11274 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11276 pic16_freeAsmop(left,NULL,ic,TRUE);
11277 pic16_aopOp (result,ic,FALSE);
11279 /* if bitfield then unpack the bits */
11280 if (IS_BITFIELD(retype))
11281 genUnpackBits (result,left,rname,PPOINTER);
11283 /* we have can just get the values */
11284 int size = AOP_SIZE(result);
11289 pic16_emitcode("movx","a,@%s",rname);
11290 pic16_aopPut(AOP(result),"a",offset);
11295 pic16_emitcode("inc","%s",rname);
11299 /* now some housekeeping stuff */
11301 /* we had to allocate for this iCode */
11302 pic16_freeAsmop(NULL,aop,ic,TRUE);
11304 /* we did not allocate which means left
11305 already in a pointer register, then
11306 if size > 0 && this could be used again
11307 we have to point it back to where it
11309 if (AOP_SIZE(result) > 1 &&
11310 !OP_SYMBOL(left)->remat &&
11311 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11313 int size = AOP_SIZE(result) - 1;
11315 pic16_emitcode("dec","%s",rname);
11320 pic16_freeAsmop(result,NULL,ic,TRUE);
11325 /*-----------------------------------------------------------------*/
11326 /* genFarPointerGet - gget value from far space */
11327 /*-----------------------------------------------------------------*/
11328 static void genFarPointerGet (operand *left,
11329 operand *result, iCode *ic)
11332 sym_link *retype = getSpec(operandType(result));
11334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11336 pic16_aopOp(left,ic,FALSE);
11338 /* if the operand is already in dptr
11339 then we do nothing else we move the value to dptr */
11340 if (AOP_TYPE(left) != AOP_STR) {
11341 /* if this is remateriazable */
11342 if (AOP_TYPE(left) == AOP_IMMD)
11343 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11344 else { /* we need to get it byte by byte */
11345 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11346 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11347 if (options.model == MODEL_FLAT24)
11349 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11353 /* so dptr know contains the address */
11354 pic16_freeAsmop(left,NULL,ic,TRUE);
11355 pic16_aopOp(result,ic,FALSE);
11357 /* if bit then unpack */
11358 if (IS_BITFIELD(retype))
11359 genUnpackBits(result,left,"dptr",FPOINTER);
11361 size = AOP_SIZE(result);
11365 pic16_emitcode("movx","a,@dptr");
11366 pic16_aopPut(AOP(result),"a",offset++);
11368 pic16_emitcode("inc","dptr");
11372 pic16_freeAsmop(result,NULL,ic,TRUE);
11376 /*-----------------------------------------------------------------*/
11377 /* genCodePointerGet - get value from code space */
11378 /*-----------------------------------------------------------------*/
11379 static void genCodePointerGet (operand *left,
11380 operand *result, iCode *ic)
11383 sym_link *retype = getSpec(operandType(result));
11385 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11387 pic16_aopOp(left,ic,FALSE);
11389 /* if the operand is already in dptr
11390 then we do nothing else we move the value to dptr */
11391 if (AOP_TYPE(left) != AOP_STR) {
11392 /* if this is remateriazable */
11393 if (AOP_TYPE(left) == AOP_IMMD)
11394 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11395 else { /* we need to get it byte by byte */
11396 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11397 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11398 if (options.model == MODEL_FLAT24)
11400 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11404 /* so dptr know contains the address */
11405 pic16_freeAsmop(left,NULL,ic,TRUE);
11406 pic16_aopOp(result,ic,FALSE);
11408 /* if bit then unpack */
11409 if (IS_BITFIELD(retype))
11410 genUnpackBits(result,left,"dptr",CPOINTER);
11412 size = AOP_SIZE(result);
11416 pic16_emitcode("clr","a");
11417 pic16_emitcode("movc","a,@a+dptr");
11418 pic16_aopPut(AOP(result),"a",offset++);
11420 pic16_emitcode("inc","dptr");
11424 pic16_freeAsmop(result,NULL,ic,TRUE);
11429 /*-----------------------------------------------------------------*/
11430 /* genGenPointerGet - gget value from generic pointer space */
11431 /*-----------------------------------------------------------------*/
11432 static void genGenPointerGet (operand *left,
11433 operand *result, iCode *ic)
11435 int size, offset, lit;
11436 sym_link *retype = getSpec(operandType(result));
11438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11439 pic16_aopOp(left,ic,FALSE);
11440 pic16_aopOp(result,ic,FALSE);
11441 size = AOP_SIZE(result);
11443 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11445 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11447 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11448 // load FSR0 from immediate
11449 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11451 // pic16_loadFSR0( left );
11456 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11458 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11465 else { /* we need to get it byte by byte */
11466 // set up FSR0 with address from left
11467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11474 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11476 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11483 /* if bit then unpack */
11484 if (IS_BITFIELD(retype))
11485 genUnpackBits(result,left,"BAD",GPOINTER);
11488 pic16_freeAsmop(left,NULL,ic,TRUE);
11489 pic16_freeAsmop(result,NULL,ic,TRUE);
11495 /*-----------------------------------------------------------------*/
11496 /* genGenPointerGet - gget value from generic pointer space */
11497 /*-----------------------------------------------------------------*/
11498 static void genGenPointerGet (operand *left,
11499 operand *result, iCode *ic)
11501 int size, offset, lit;
11502 sym_link *retype = getSpec(operandType(result));
11505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11506 pic16_aopOp(left,ic,FALSE);
11507 pic16_aopOp(result,ic,FALSE);
11508 size = AOP_SIZE(result);
11510 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11512 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11514 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11515 // load FSR0 from immediate
11516 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11518 werror(W_POSSBUG2, __FILE__, __LINE__);
11523 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11525 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11532 } else { /* we need to get it byte by byte */
11534 /* set up WREG:PRODL:FSR0L with address from left */
11535 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11536 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11537 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11540 case 1: strcpy(fgptrget, "__gptrget1"); break;
11541 case 2: strcpy(fgptrget, "__gptrget2"); break;
11542 case 3: strcpy(fgptrget, "__gptrget3"); break;
11543 case 4: strcpy(fgptrget, "__gptrget4"); break;
11545 werror(W_POSSBUG2, __FILE__, __LINE__);
11549 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11551 assignResultValue(result, 1);
11556 sym = newSymbol( fgptrget, 0 );
11557 strcpy(sym->rname, fgptrget);
11558 checkAddSym(&externs, sym);
11560 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11566 /* if bit then unpack */
11567 if (IS_BITFIELD(retype))
11568 genUnpackBits(result,left,"BAD",GPOINTER);
11571 pic16_freeAsmop(left,NULL,ic,TRUE);
11572 pic16_freeAsmop(result,NULL,ic,TRUE);
11575 /*-----------------------------------------------------------------*/
11576 /* genConstPointerGet - get value from const generic pointer space */
11577 /*-----------------------------------------------------------------*/
11578 static void genConstPointerGet (operand *left,
11579 operand *result, iCode *ic)
11581 //sym_link *retype = getSpec(operandType(result));
11582 // symbol *albl = newiTempLabel(NULL); // patch 15
11583 // symbol *blbl = newiTempLabel(NULL); //
11584 // PIC_OPCODE poc; // patch 15
11588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11589 pic16_aopOp(left,ic,FALSE);
11590 pic16_aopOp(result,ic,TRUE);
11591 size = AOP_SIZE(result);
11593 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11595 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11597 // set up table pointer
11598 if( (AOP_TYPE(left) == AOP_PCODE)
11599 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11600 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11602 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11603 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11604 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11605 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11606 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11607 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11609 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11610 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11611 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11615 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11616 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11620 pic16_freeAsmop(left,NULL,ic,TRUE);
11621 pic16_freeAsmop(result,NULL,ic,TRUE);
11625 /*-----------------------------------------------------------------*/
11626 /* genPointerGet - generate code for pointer get */
11627 /*-----------------------------------------------------------------*/
11628 static void genPointerGet (iCode *ic)
11630 operand *left, *result ;
11631 sym_link *type, *etype;
11636 left = IC_LEFT(ic);
11637 result = IC_RESULT(ic) ;
11639 /* depending on the type of pointer we need to
11640 move it to the correct pointer register */
11641 type = operandType(left);
11642 etype = getSpec(type);
11645 if (IS_PTR_CONST(type))
11647 if (IS_CODEPTR(type))
11649 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11651 /* if left is of type of pointer then it is simple */
11652 if (IS_PTR(type) && !IS_FUNC(type->next))
11653 p_type = DCL_TYPE(type);
11655 /* we have to go by the storage class */
11656 p_type = PTR_TYPE(SPEC_OCLS(etype));
11658 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11660 if (SPEC_OCLS(etype)->codesp ) {
11661 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11662 //p_type = CPOINTER ;
11664 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11665 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11666 /*p_type = FPOINTER ;*/
11668 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11669 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11670 /* p_type = PPOINTER; */
11672 if (SPEC_OCLS(etype) == idata ) {
11673 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11674 /* p_type = IPOINTER; */
11676 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11677 /* p_type = POINTER ; */
11681 /* now that we have the pointer type we assign
11682 the pointer values */
11686 genNearPointerGet (left,result,ic);
11690 genPagedPointerGet(left,result,ic);
11694 genFarPointerGet (left,result,ic);
11698 genConstPointerGet (left,result,ic);
11699 //pic16_emitcodePointerGet (left,result,ic);
11704 if (IS_PTR_CONST(type))
11705 genConstPointerGet (left,result,ic);
11708 genGenPointerGet (left,result,ic);
11712 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11713 "genPointerGet: illegal pointer type");
11718 /*-----------------------------------------------------------------*/
11719 /* genPackBits - generates code for packed bit storage */
11720 /*-----------------------------------------------------------------*/
11721 static void genPackBits (sym_link *etype , operand *result,
11723 char *rname, int p_type)
11732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11733 blen = SPEC_BLEN(etype);
11734 bstr = SPEC_BSTR(etype);
11736 retype = getSpec(operandType(right));
11738 if(AOP_TYPE(right) == AOP_LIT) {
11739 if((blen == 1) && (bstr < 8)) {
11741 /* it is a single bit, so use the appropriate bit instructions */
11743 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11745 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11746 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11747 if((p_type == POINTER) && (result)) {
11748 /* workaround to reduce the extra lfsr instruction */
11750 pic16_emitpcode(POC_BSF,
11751 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11753 pic16_emitpcode(POC_BCF,
11754 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11757 pic16_loadFSR0( result );
11759 pic16_emitpcode(POC_BSF,
11760 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11762 pic16_emitpcode(POC_BCF,
11763 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11770 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11773 if(IS_BITFIELD(retype)
11774 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11778 rblen = SPEC_BLEN( retype );
11779 rbstr = SPEC_BSTR( retype );
11782 if(IS_BITFIELD(etype)) {
11783 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11784 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11786 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11789 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11791 if(IS_BITFIELD(etype)) {
11792 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11794 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11797 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11801 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11803 /* if the bit lenth is less than or */
11804 /* it exactly fits a byte then */
11805 if((shCnt=SPEC_BSTR(etype))
11806 || SPEC_BLEN(etype) <= 8 ) {
11808 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11810 /* shift left acc */
11813 /* using PRODL as a temporary register here */
11814 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11819 pic16_loadFSR0( result );
11820 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11821 // pic16_emitcode ("mov","b,a");
11822 // pic16_emitcode("mov","a,@%s",rname);
11826 werror(W_POSSBUG2, __FILE__, __LINE__);
11831 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11832 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11833 (unsigned char)(0xff >> (8-bstr))) ));
11834 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11835 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11842 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11843 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11848 if ( SPEC_BLEN(etype) <= 8 )
11851 pic16_emitcode("inc","%s",rname);
11852 rLen = SPEC_BLEN(etype) ;
11856 /* now generate for lengths greater than one byte */
11859 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11869 pic16_emitcode("mov","@%s,a",rname);
11871 pic16_emitcode("mov","@%s,%s",rname,l);
11876 pic16_emitcode("movx","@dptr,a");
11881 DEBUGpic16_emitcode(";lcall","__gptrput");
11884 pic16_emitcode ("inc","%s",rname);
11889 /* last last was not complete */
11891 /* save the byte & read byte */
11894 pic16_emitcode ("mov","b,a");
11895 pic16_emitcode("mov","a,@%s",rname);
11899 pic16_emitcode ("mov","b,a");
11900 pic16_emitcode("movx","a,@dptr");
11904 pic16_emitcode ("push","b");
11905 pic16_emitcode ("push","acc");
11906 pic16_emitcode ("lcall","__gptrget");
11907 pic16_emitcode ("pop","b");
11911 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11912 pic16_emitcode ("orl","a,b");
11915 if (p_type == GPOINTER)
11916 pic16_emitcode("pop","b");
11921 pic16_emitcode("mov","@%s,a",rname);
11925 pic16_emitcode("movx","@dptr,a");
11929 DEBUGpic16_emitcode(";lcall","__gptrput");
11933 /*-----------------------------------------------------------------*/
11934 /* genDataPointerSet - remat pointer to data space */
11935 /*-----------------------------------------------------------------*/
11936 static void genDataPointerSet(operand *right,
11940 int size, offset = 0, resoffset=0 ;
11942 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11943 pic16_aopOp(right,ic,FALSE);
11945 size = AOP_SIZE(right);
11947 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11950 if ( AOP_TYPE(result) == AOP_PCODE) {
11951 fprintf(stderr,"genDataPointerSet %s, %d\n",
11952 AOP(result)->aopu.pcop->name,
11953 (AOP(result)->aopu.pcop->type == PO_DIR)?
11954 PCOR(AOP(result)->aopu.pcop)->instance:
11955 PCOI(AOP(result)->aopu.pcop)->offset);
11959 if(AOP(result)->aopu.pcop->type == PO_DIR)
11960 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11963 if (AOP_TYPE(right) == AOP_LIT) {
11966 if(!IS_FLOAT(operandType( right )))
11967 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11970 unsigned long lit_int;
11974 /* take care if literal is a float */
11975 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11976 lit = info.lit_int;
11979 lit = lit >> (8*offset);
11981 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11982 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11984 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11987 pic16_mov2w(AOP(right), offset);
11988 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11994 pic16_freeAsmop(right,NULL,ic,TRUE);
11999 /*-----------------------------------------------------------------*/
12000 /* genNearPointerSet - pic16_emitcode for near pointer put */
12001 /*-----------------------------------------------------------------*/
12002 static void genNearPointerSet (operand *right,
12009 sym_link *ptype = operandType(result);
12010 sym_link *resetype;
12012 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12013 retype= getSpec(operandType(right));
12014 resetype = getSpec(operandType(result));
12016 pic16_aopOp(result,ic,FALSE);
12018 /* if the result is rematerializable &
12019 * in data space & not a bit variable */
12021 /* and result is not a bit variable */
12022 if (AOP_TYPE(result) == AOP_PCODE
12023 // && AOP_TYPE(result) == AOP_IMMD
12024 && DCL_TYPE(ptype) == POINTER
12025 && !IS_BITFIELD(retype)
12026 && !IS_BITFIELD(resetype)) {
12028 genDataPointerSet (right,result,ic);
12029 pic16_freeAsmop(result,NULL,ic,TRUE);
12033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12034 pic16_aopOp(right,ic,FALSE);
12035 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12037 /* if the value is already in a pointer register
12038 * then don't need anything more */
12039 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12040 /* otherwise get a free pointer register */
12041 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12043 // if( (AOP_TYPE(result) == AOP_PCODE)
12044 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12045 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12046 if(is_LitAOp( AOP(result) ))
12048 if(!IS_BITFIELD(resetype))
12049 pic16_loadFSR0( result ); // patch 10
12051 if(!IS_BITFIELD(resetype)) {
12052 // set up FSR0 with address of result
12053 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12054 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12060 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12064 // pic16_loadFSR0( result );
12066 /* if bitfield then unpack the bits */
12067 if (IS_BITFIELD(resetype)) {
12068 genPackBits (resetype, result, right, NULL, POINTER);
12070 /* we have can just get the values */
12071 int size = AOP_SIZE(right);
12074 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12076 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12079 //pic16_emitcode("mov","@%s,a",rname);
12080 pic16_emitcode("movf","indf0,w ;1");
12083 if (AOP_TYPE(right) == AOP_LIT) {
12084 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12086 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12088 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12090 } else { // no literal
12092 pic16_emitpcode(POC_MOVFF,
12093 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12094 pic16_popCopyReg(&pic16_pc_postinc0)));
12096 pic16_emitpcode(POC_MOVFF,
12097 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12098 pic16_popCopyReg(&pic16_pc_indf0)));
12106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12107 /* now some housekeeping stuff */
12109 /* we had to allocate for this iCode */
12110 pic16_freeAsmop(NULL,aop,ic,TRUE);
12112 /* we did not allocate which means left
12113 * already in a pointer register, then
12114 * if size > 0 && this could be used again
12115 * we have to point it back to where it
12117 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12118 if (AOP_SIZE(right) > 1
12119 && !OP_SYMBOL(result)->remat
12120 && ( OP_SYMBOL(result)->liveTo > ic->seq
12123 int size = AOP_SIZE(right) - 1;
12126 pic16_emitcode("decf","fsr0,f");
12127 //pic16_emitcode("dec","%s",rname);
12131 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12134 pic16_freeAsmop(right,NULL,ic,TRUE);
12135 pic16_freeAsmop(result,NULL,ic,TRUE);
12138 /*-----------------------------------------------------------------*/
12139 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12140 /*-----------------------------------------------------------------*/
12141 static void genPagedPointerSet (operand *right,
12146 regs *preg = NULL ;
12150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12152 retype= getSpec(operandType(right));
12154 pic16_aopOp(result,ic,FALSE);
12156 /* if the value is already in a pointer register
12157 then don't need anything more */
12158 if (!AOP_INPREG(AOP(result))) {
12159 /* otherwise get a free pointer register */
12161 preg = getFreePtr(ic,&aop,FALSE);
12162 pic16_emitcode("mov","%s,%s",
12164 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12165 rname = preg->name ;
12167 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12169 pic16_freeAsmop(result,NULL,ic,TRUE);
12170 pic16_aopOp (right,ic,FALSE);
12172 /* if bitfield then unpack the bits */
12173 if (IS_BITFIELD(retype))
12174 genPackBits (retype,result,right,rname,PPOINTER);
12176 /* we have can just get the values */
12177 int size = AOP_SIZE(right);
12181 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12184 pic16_emitcode("movx","@%s,a",rname);
12187 pic16_emitcode("inc","%s",rname);
12193 /* now some housekeeping stuff */
12195 /* we had to allocate for this iCode */
12196 pic16_freeAsmop(NULL,aop,ic,TRUE);
12198 /* we did not allocate which means left
12199 already in a pointer register, then
12200 if size > 0 && this could be used again
12201 we have to point it back to where it
12203 if (AOP_SIZE(right) > 1 &&
12204 !OP_SYMBOL(result)->remat &&
12205 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12207 int size = AOP_SIZE(right) - 1;
12209 pic16_emitcode("dec","%s",rname);
12214 pic16_freeAsmop(right,NULL,ic,TRUE);
12219 /*-----------------------------------------------------------------*/
12220 /* genFarPointerSet - set value from far space */
12221 /*-----------------------------------------------------------------*/
12222 static void genFarPointerSet (operand *right,
12223 operand *result, iCode *ic)
12226 sym_link *retype = getSpec(operandType(right));
12228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12229 pic16_aopOp(result,ic,FALSE);
12231 /* if the operand is already in dptr
12232 then we do nothing else we move the value to dptr */
12233 if (AOP_TYPE(result) != AOP_STR) {
12234 /* if this is remateriazable */
12235 if (AOP_TYPE(result) == AOP_IMMD)
12236 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12237 else { /* we need to get it byte by byte */
12238 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12239 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12240 if (options.model == MODEL_FLAT24)
12242 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12246 /* so dptr know contains the address */
12247 pic16_freeAsmop(result,NULL,ic,TRUE);
12248 pic16_aopOp(right,ic,FALSE);
12250 /* if bit then unpack */
12251 if (IS_BITFIELD(retype))
12252 genPackBits(retype,result,right,"dptr",FPOINTER);
12254 size = AOP_SIZE(right);
12258 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12260 pic16_emitcode("movx","@dptr,a");
12262 pic16_emitcode("inc","dptr");
12266 pic16_freeAsmop(right,NULL,ic,TRUE);
12269 /*-----------------------------------------------------------------*/
12270 /* genGenPointerSet - set value from generic pointer space */
12271 /*-----------------------------------------------------------------*/
12273 static void genGenPointerSet (operand *right,
12274 operand *result, iCode *ic)
12276 int i, size, offset, lit;
12277 sym_link *retype = getSpec(operandType(right));
12279 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12281 pic16_aopOp(result,ic,FALSE);
12282 pic16_aopOp(right,ic,FALSE);
12283 size = AOP_SIZE(right);
12286 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12288 /* if the operand is already in dptr
12289 then we do nothing else we move the value to dptr */
12290 if (AOP_TYPE(result) != AOP_STR) {
12291 /* if this is remateriazable */
12292 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12293 // WARNING: anythig until "else" is untested!
12294 if (AOP_TYPE(result) == AOP_IMMD) {
12295 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12296 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12297 // load FSR0 from immediate
12298 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12302 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12304 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12310 else { /* we need to get it byte by byte */
12311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12312 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12314 // set up FSR0 with address of result
12315 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12316 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12318 /* hack hack! see if this the FSR. If so don't load W */
12319 if(AOP_TYPE(right) != AOP_ACC) {
12321 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12323 if(AOP_TYPE(right) == AOP_LIT)
12326 // note: pic16_popGet handles sign extension
12327 for(i=0;i<size;i++) {
12328 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12330 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12332 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12337 for(i=0;i<size;i++) {
12339 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12340 pic16_popCopyReg(&pic16_pc_postinc0)));
12342 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12343 pic16_popCopyReg(&pic16_pc_indf0)));
12349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12350 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12352 } // if (AOP_TYPE(result) != AOP_IMMD)
12354 } // if (AOP_TYPE(result) != AOP_STR)
12355 /* so dptr know contains the address */
12358 /* if bit then unpack */
12359 if (IS_BITFIELD(retype))
12360 genPackBits(retype,result,right,"dptr",GPOINTER);
12362 size = AOP_SIZE(right);
12365 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12367 // set up FSR0 with address of result
12368 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12369 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12372 if (AOP_TYPE(right) == AOP_LIT) {
12373 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12375 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12377 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12379 } else { // no literal
12381 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12383 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12391 pic16_freeAsmop(right,NULL,ic,TRUE);
12392 pic16_freeAsmop(result,NULL,ic,TRUE);
12396 static void genGenPointerSet (operand *right,
12397 operand *result, iCode *ic)
12400 sym_link *retype = getSpec(operandType(right));
12403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12405 pic16_aopOp(result,ic,FALSE);
12406 pic16_aopOp(right,ic,FALSE);
12407 size = AOP_SIZE(right);
12409 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12412 /* if bit then unpack */
12413 if (IS_BITFIELD(retype)) {
12414 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12415 genPackBits(retype,result,right,"dptr",GPOINTER);
12419 size = AOP_SIZE(right);
12421 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12425 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12427 /* value of right+0 is placed on stack, which will be retrieved
12428 * by the support function this restoring the stack. The important
12429 * thing is that there is no need to manually restore stack pointer
12431 pushaop(AOP(right), 0);
12432 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12433 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12434 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12435 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12437 /* load address to write to in WREG:FSR0H:FSR0L */
12438 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12439 pic16_popCopyReg(&pic16_pc_fsr0l)));
12440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12441 pic16_popCopyReg(&pic16_pc_prodl)));
12442 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12445 /* put code here */
12447 case 1: strcpy(fgptrput, "__gptrput1"); break;
12448 case 2: strcpy(fgptrput, "__gptrput2"); break;
12449 case 3: strcpy(fgptrput, "__gptrput3"); break;
12450 case 4: strcpy(fgptrput, "__gptrput4"); break;
12452 werror(W_POSSBUG2, __FILE__, __LINE__);
12456 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12461 sym = newSymbol( fgptrput, 0 );
12462 strcpy(sym->rname, fgptrput);
12463 checkAddSym(&externs, sym);
12467 pic16_freeAsmop(right,NULL,ic,TRUE);
12468 pic16_freeAsmop(result,NULL,ic,TRUE);
12471 /*-----------------------------------------------------------------*/
12472 /* genPointerSet - stores the value into a pointer location */
12473 /*-----------------------------------------------------------------*/
12474 static void genPointerSet (iCode *ic)
12476 operand *right, *result ;
12477 sym_link *type, *etype;
12482 right = IC_RIGHT(ic);
12483 result = IC_RESULT(ic) ;
12485 /* depending on the type of pointer we need to
12486 move it to the correct pointer register */
12487 type = operandType(result);
12488 etype = getSpec(type);
12489 /* if left is of type of pointer then it is simple */
12490 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12491 p_type = DCL_TYPE(type);
12494 /* we have to go by the storage class */
12495 p_type = PTR_TYPE(SPEC_OCLS(etype));
12497 /* if (SPEC_OCLS(etype)->codesp ) { */
12498 /* p_type = CPOINTER ; */
12501 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12502 /* p_type = FPOINTER ; */
12504 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12505 /* p_type = PPOINTER ; */
12507 /* if (SPEC_OCLS(etype) == idata ) */
12508 /* p_type = IPOINTER ; */
12510 /* p_type = POINTER ; */
12513 /* now that we have the pointer type we assign
12514 the pointer values */
12518 genNearPointerSet (right,result,ic);
12522 genPagedPointerSet (right,result,ic);
12526 genFarPointerSet (right,result,ic);
12530 genGenPointerSet (right,result,ic);
12534 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12535 "genPointerSet: illegal pointer type");
12539 /*-----------------------------------------------------------------*/
12540 /* genIfx - generate code for Ifx statement */
12541 /*-----------------------------------------------------------------*/
12542 static void genIfx (iCode *ic, iCode *popIc)
12544 operand *cond = IC_COND(ic);
12549 pic16_aopOp(cond,ic,FALSE);
12551 /* get the value into acc */
12552 if (AOP_TYPE(cond) != AOP_CRY)
12553 pic16_toBoolean(cond);
12556 /* the result is now in the accumulator */
12557 pic16_freeAsmop(cond,NULL,ic,TRUE);
12559 /* if there was something to be popped then do it */
12563 /* if the condition is a bit variable */
12564 if (isbit && IS_ITEMP(cond) &&
12566 genIfxJump(ic,"c");
12567 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12569 if (isbit && !IS_ITEMP(cond))
12570 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12572 genIfxJump(ic,"a");
12577 /*-----------------------------------------------------------------*/
12578 /* genAddrOf - generates code for address of */
12579 /*-----------------------------------------------------------------*/
12580 static void genAddrOf (iCode *ic)
12582 operand *result, *left;
12584 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12585 pCodeOp *pcop0, *pcop1, *pcop2;
12589 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12591 sym = OP_SYMBOL( IC_LEFT(ic) );
12594 /* get address of symbol on stack */
12595 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12597 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12598 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12601 // operands on stack are accessible via "FSR2 + index" with index
12602 // starting at 2 for arguments and growing from 0 downwards for
12603 // local variables (index == 0 is not assigned so we add one here)
12605 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12607 assert (soffs < 0);
12610 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12611 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12612 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12613 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12614 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12615 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12616 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12622 // if(pic16_debug_verbose) {
12623 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12624 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12627 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12628 size = AOP_SIZE(IC_RESULT(ic));
12630 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12631 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12632 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12635 pic16_emitpcode(POC_MOVLW, pcop0);
12636 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12637 pic16_emitpcode(POC_MOVLW, pcop1);
12638 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12639 pic16_emitpcode(POC_MOVLW, pcop2);
12640 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12643 pic16_emitpcode(POC_MOVLW, pcop0);
12644 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12645 pic16_emitpcode(POC_MOVLW, pcop1);
12646 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12648 pic16_emitpcode(POC_MOVLW, pcop0);
12649 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12652 pic16_freeAsmop(left, NULL, ic, FALSE);
12654 pic16_freeAsmop(result,NULL,ic,TRUE);
12659 /*-----------------------------------------------------------------*/
12660 /* genFarFarAssign - assignment when both are in far space */
12661 /*-----------------------------------------------------------------*/
12662 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12664 int size = AOP_SIZE(right);
12667 /* first push the right side on to the stack */
12669 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12671 pic16_emitcode ("push","acc");
12674 pic16_freeAsmop(right,NULL,ic,FALSE);
12675 /* now assign DPTR to result */
12676 pic16_aopOp(result,ic,FALSE);
12677 size = AOP_SIZE(result);
12679 pic16_emitcode ("pop","acc");
12680 pic16_aopPut(AOP(result),"a",--offset);
12682 pic16_freeAsmop(result,NULL,ic,FALSE);
12687 /*-----------------------------------------------------------------*/
12688 /* genAssign - generate code for assignment */
12689 /*-----------------------------------------------------------------*/
12690 static void genAssign (iCode *ic)
12692 operand *result, *right;
12693 int size, offset,know_W;
12694 unsigned long lit = 0L;
12696 result = IC_RESULT(ic);
12697 right = IC_RIGHT(ic) ;
12701 /* if they are the same */
12702 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12705 /* reversed order operands are aopOp'ed so that result operand
12706 * is effective in case right is a stack symbol. This maneauver
12707 * allows to use the _G.resDirect flag later */
12708 pic16_aopOp(result,ic,TRUE);
12709 pic16_aopOp(right,ic,FALSE);
12711 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12713 /* if they are the same registers */
12714 if (pic16_sameRegs(AOP(right),AOP(result)))
12717 /* if the result is a bit */
12718 if (AOP_TYPE(result) == AOP_CRY) {
12719 /* if the right size is a literal then
12720 we know what the value is */
12721 if (AOP_TYPE(right) == AOP_LIT) {
12723 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12724 pic16_popGet(AOP(result),0));
12726 if (((int) operandLitValue(right)))
12727 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12728 AOP(result)->aopu.aop_dir,
12729 AOP(result)->aopu.aop_dir);
12731 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12732 AOP(result)->aopu.aop_dir,
12733 AOP(result)->aopu.aop_dir);
12737 /* the right is also a bit variable */
12738 if (AOP_TYPE(right) == AOP_CRY) {
12739 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12740 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12741 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12743 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12744 AOP(result)->aopu.aop_dir,
12745 AOP(result)->aopu.aop_dir);
12746 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12747 AOP(right)->aopu.aop_dir,
12748 AOP(right)->aopu.aop_dir);
12749 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12750 AOP(result)->aopu.aop_dir,
12751 AOP(result)->aopu.aop_dir);
12755 /* we need to or */
12756 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12757 pic16_toBoolean(right);
12759 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12760 //pic16_aopPut(AOP(result),"a",0);
12764 /* bit variables done */
12766 size = AOP_SIZE(result);
12769 if(AOP_TYPE(right) == AOP_LIT) {
12770 if(!IS_FLOAT(operandType( right )))
12771 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12774 unsigned long lit_int;
12778 /* take care if literal is a float */
12779 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12780 lit = info.lit_int;
12784 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12785 // sizeof(unsigned long int), sizeof(float));
12788 if (AOP_TYPE(right) == AOP_REG) {
12789 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12792 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12797 if(AOP_TYPE(right) != AOP_LIT
12798 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12799 && !IS_FUNC(OP_SYM_TYPE(right))
12801 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12802 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12804 // set up table pointer
12805 if(is_LitOp(right)) {
12806 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12807 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12808 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12809 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12810 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12811 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12812 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12814 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12815 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12816 pic16_popCopyReg(&pic16_pc_tblptrl)));
12817 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12818 pic16_popCopyReg(&pic16_pc_tblptrh)));
12819 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12820 pic16_popCopyReg(&pic16_pc_tblptru)));
12823 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12825 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12826 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12827 pic16_popGet(AOP(result),offset)));
12831 size = getSize(OP_SYM_ETYPE(right));
12832 if(AOP_SIZE(result) > size) {
12833 size = AOP_SIZE(result) - size;
12835 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12845 /* VR - What is this?! */
12846 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12847 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12848 if(aopIdx(AOP(result),0) == 4) {
12850 /* this is a workaround to save value of right into wreg too,
12851 * value of wreg is going to be used later */
12852 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12853 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12858 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12864 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12865 if(AOP_TYPE(right) == AOP_LIT) {
12867 if(know_W != (lit&0xff))
12868 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12870 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12872 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12876 } else if (AOP_TYPE(right) == AOP_CRY) {
12877 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12879 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12880 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12881 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12883 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12884 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12885 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12889 if(!_G.resDirect) /* use this aopForSym feature */
12890 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12897 pic16_freeAsmop (right,NULL,ic,FALSE);
12898 pic16_freeAsmop (result,NULL,ic,TRUE);
12901 /*-----------------------------------------------------------------*/
12902 /* genJumpTab - generates code for jump table */
12903 /*-----------------------------------------------------------------*/
12904 static void genJumpTab (iCode *ic)
12909 pCodeOp *jt_offs_hi;
12914 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12915 /* get the condition into accumulator */
12916 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12918 /* multiply by three */
12919 pic16_emitcode("add","a,acc");
12920 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12922 jtab = newiTempLabel(NULL);
12923 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12924 pic16_emitcode("jmp","@a+dptr");
12925 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12928 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12929 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12931 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12932 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12933 pic16_emitpLabel(jtab->key);
12937 jt_offs = pic16_popGetTempReg(0);
12938 jt_offs_hi = pic16_popGetTempReg(1);
12939 jt_label = pic16_popGetLabel (jtab->key);
12940 //fprintf (stderr, "Creating jump table...\n");
12942 // calculate offset into jump table (idx * sizeof (GOTO))
12943 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12944 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12945 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12946 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12947 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12948 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12949 pic16_emitpcode(POC_MOVWF , jt_offs);
12951 // prepare PCLATx (set to first entry in jump table)
12952 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12953 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12954 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12955 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12956 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12958 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12959 pic16_emitpcode(POC_ADDWF , jt_offs);
12960 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12961 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12963 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12965 // release temporaries and prepare jump into table (new PCL --> WREG)
12966 pic16_emitpcode(POC_MOVFW , jt_offs);
12967 pic16_popReleaseTempReg (jt_offs_hi, 1);
12968 pic16_popReleaseTempReg (jt_offs, 0);
12970 // jump into the table
12971 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12973 pic16_emitpLabelFORCE(jtab->key);
12976 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12978 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12979 /* now generate the jump labels */
12980 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12981 jtab = setNextItem(IC_JTLABELS(ic))) {
12982 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12983 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12986 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12990 /*-----------------------------------------------------------------*/
12991 /* genMixedOperation - gen code for operators between mixed types */
12992 /*-----------------------------------------------------------------*/
12994 TSD - Written for the PIC port - but this unfortunately is buggy.
12995 This routine is good in that it is able to efficiently promote
12996 types to different (larger) sizes. Unfortunately, the temporary
12997 variables that are optimized out by this routine are sometimes
12998 used in other places. So until I know how to really parse the
12999 iCode tree, I'm going to not be using this routine :(.
13001 static int genMixedOperation (iCode *ic)
13004 operand *result = IC_RESULT(ic);
13005 sym_link *ctype = operandType(IC_LEFT(ic));
13006 operand *right = IC_RIGHT(ic);
13012 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13014 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13020 nextright = IC_RIGHT(nextic);
13021 nextleft = IC_LEFT(nextic);
13022 nextresult = IC_RESULT(nextic);
13024 pic16_aopOp(right,ic,FALSE);
13025 pic16_aopOp(result,ic,FALSE);
13026 pic16_aopOp(nextright, nextic, FALSE);
13027 pic16_aopOp(nextleft, nextic, FALSE);
13028 pic16_aopOp(nextresult, nextic, FALSE);
13030 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13032 operand *t = right;
13036 pic16_emitcode(";remove right +","");
13038 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13040 operand *t = right;
13044 pic16_emitcode(";remove left +","");
13048 big = AOP_SIZE(nextleft);
13049 small = AOP_SIZE(nextright);
13051 switch(nextic->op) {
13054 pic16_emitcode(";optimize a +","");
13055 /* if unsigned or not an integral type */
13056 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13057 pic16_emitcode(";add a bit to something","");
13060 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13062 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13063 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13064 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13066 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13074 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13075 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13076 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13079 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13081 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13082 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13083 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13084 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13085 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13088 pic16_emitcode("rlf","known_zero,w");
13095 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13096 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13097 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13099 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13109 pic16_freeAsmop(right,NULL,ic,TRUE);
13110 pic16_freeAsmop(result,NULL,ic,TRUE);
13111 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13112 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13114 nextic->generated = 1;
13121 /*-----------------------------------------------------------------*/
13122 /* genCast - gen code for casting */
13123 /*-----------------------------------------------------------------*/
13124 static void genCast (iCode *ic)
13126 operand *result = IC_RESULT(ic);
13127 sym_link *ctype = operandType(IC_LEFT(ic));
13128 sym_link *rtype = operandType(IC_RIGHT(ic));
13129 sym_link *restype = operandType(IC_RESULT(ic));
13130 operand *right = IC_RIGHT(ic);
13136 /* if they are equivalent then do nothing */
13137 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13140 pic16_aopOp(right,ic,FALSE) ;
13141 pic16_aopOp(result,ic,FALSE);
13143 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13146 /* if the result is a bit */
13147 if (AOP_TYPE(result) == AOP_CRY) {
13149 /* if the right size is a literal then
13150 * we know what the value is */
13151 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13153 if (AOP_TYPE(right) == AOP_LIT) {
13154 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13155 pic16_popGet(AOP(result),0));
13157 if (((int) operandLitValue(right)))
13158 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13159 AOP(result)->aopu.aop_dir,
13160 AOP(result)->aopu.aop_dir);
13162 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13163 AOP(result)->aopu.aop_dir,
13164 AOP(result)->aopu.aop_dir);
13168 /* the right is also a bit variable */
13169 if (AOP_TYPE(right) == AOP_CRY) {
13171 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13173 pic16_emitcode("clrc","");
13174 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13175 AOP(right)->aopu.aop_dir,
13176 AOP(right)->aopu.aop_dir);
13177 pic16_aopPut(AOP(result),"c",0);
13181 /* we need to or */
13182 if (AOP_TYPE(right) == AOP_REG) {
13183 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13184 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13185 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13187 pic16_toBoolean(right);
13188 pic16_aopPut(AOP(result),"a",0);
13192 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13195 size = AOP_SIZE(result);
13197 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13199 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13200 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13201 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13204 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13209 if(IS_BITFIELD(getSpec(restype))
13210 && IS_BITFIELD(getSpec(rtype))) {
13211 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13214 /* if they are the same size : or less */
13215 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13217 /* if they are in the same place */
13218 if (pic16_sameRegs(AOP(right),AOP(result)))
13221 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13223 if (IS_PTR_CONST(rtype))
13225 if (IS_CODEPTR(rtype))
13227 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13230 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13232 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13234 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13237 if(AOP_TYPE(right) == AOP_IMMD) {
13238 pCodeOp *pcop0, *pcop1, *pcop2;
13239 symbol *sym = OP_SYMBOL( right );
13241 size = AOP_SIZE(result);
13243 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13245 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13247 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13250 pic16_emitpcode(POC_MOVLW, pcop0);
13251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13252 pic16_emitpcode(POC_MOVLW, pcop1);
13253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13254 pic16_emitpcode(POC_MOVLW, pcop2);
13255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13258 pic16_emitpcode(POC_MOVLW, pcop0);
13259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13260 pic16_emitpcode(POC_MOVLW, pcop1);
13261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13263 pic16_emitpcode(POC_MOVLW, pcop0);
13264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13268 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13269 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13271 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13272 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13273 if(AOP_SIZE(result) <2)
13274 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13276 /* if they in different places then copy */
13277 size = AOP_SIZE(result);
13280 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13288 /* if the result is of type pointer */
13289 if (IS_PTR(ctype)) {
13291 sym_link *type = operandType(right);
13292 sym_link *etype = getSpec(type);
13294 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13296 /* pointer to generic pointer */
13297 if (IS_GENPTR(ctype)) {
13301 p_type = DCL_TYPE(type);
13303 /* we have to go by the storage class */
13304 p_type = PTR_TYPE(SPEC_OCLS(etype));
13306 /* if (SPEC_OCLS(etype)->codesp ) */
13307 /* p_type = CPOINTER ; */
13309 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13310 /* p_type = FPOINTER ; */
13312 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13313 /* p_type = PPOINTER; */
13315 /* if (SPEC_OCLS(etype) == idata ) */
13316 /* p_type = IPOINTER ; */
13318 /* p_type = POINTER ; */
13321 /* the first two bytes are known */
13322 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13323 size = GPTRSIZE - 1;
13326 if(offset < AOP_SIZE(right)) {
13327 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13328 mov2f(AOP(result), AOP(right), offset);
13330 if ((AOP_TYPE(right) == AOP_PCODE) &&
13331 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13332 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13333 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13336 pic16_aopPut(AOP(result),
13337 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13342 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13345 /* the last byte depending on type */
13349 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13350 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13351 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13355 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13359 pic16_emitcode(";BUG!? ","%d",__LINE__);
13363 pic16_emitcode(";BUG!? ","%d",__LINE__);
13368 if (GPTRSIZE > AOP_SIZE(right)) {
13369 // assume data pointer... THIS MIGHT BE WRONG!
13370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13371 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13373 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13378 /* this should never happen */
13379 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13380 "got unknown pointer type");
13383 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13387 /* just copy the pointers */
13388 size = AOP_SIZE(result);
13391 pic16_aopPut(AOP(result),
13392 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13401 /* so we now know that the size of destination is greater
13402 than the size of the source.
13403 Now, if the next iCode is an operator then we might be
13404 able to optimize the operation without performing a cast.
13406 if(genMixedOperation(ic))
13409 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13411 /* we move to result for the size of source */
13412 size = AOP_SIZE(right);
13415 mov2f(AOP(result), AOP(right), offset);
13419 /* now depending on the sign of the destination */
13420 size = AOP_SIZE(result) - AOP_SIZE(right);
13421 /* if unsigned or not an integral type */
13422 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13424 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13426 /* we need to extend the sign :( */
13429 /* Save one instruction of casting char to int */
13430 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13431 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13432 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13434 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13437 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13439 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13444 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13449 pic16_freeAsmop(right,NULL,ic,TRUE);
13450 pic16_freeAsmop(result,NULL,ic,TRUE);
13454 /*-----------------------------------------------------------------*/
13455 /* genDjnz - generate decrement & jump if not zero instrucion */
13456 /*-----------------------------------------------------------------*/
13457 static int genDjnz (iCode *ic, iCode *ifx)
13459 symbol *lbl, *lbl1;
13460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13465 /* if the if condition has a false label
13466 then we cannot save */
13470 /* if the minus is not of the form
13472 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13473 !IS_OP_LITERAL(IC_RIGHT(ic)))
13476 if (operandLitValue(IC_RIGHT(ic)) != 1)
13479 /* if the size of this greater than one then no
13481 if (getSize(operandType(IC_RESULT(ic))) > 1)
13484 /* otherwise we can save BIG */
13485 lbl = newiTempLabel(NULL);
13486 lbl1= newiTempLabel(NULL);
13488 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13490 if (IS_AOP_PREG(IC_RESULT(ic))) {
13491 pic16_emitcode("dec","%s",
13492 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13493 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13494 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13498 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13499 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13501 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13502 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13506 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13507 ifx->generated = 1;
13511 /*-----------------------------------------------------------------*/
13512 /* genReceive - generate code for a receive iCode */
13513 /*-----------------------------------------------------------------*/
13514 static void genReceive (iCode *ic)
13520 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13521 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13523 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13525 if (isOperandInFarSpace(IC_RESULT(ic))
13526 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13527 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13529 int size = getSize(operandType(IC_RESULT(ic)));
13530 int offset = pic16_fReturnSizePic - size;
13534 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13535 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13539 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13541 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13542 size = AOP_SIZE(IC_RESULT(ic));
13545 pic16_emitcode ("pop","acc");
13546 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13549 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13551 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13554 /* set pseudo stack pointer to where it should be - dw*/
13555 GpsuedoStkPtr = ic->parmBytes;
13557 /* setting GpsuedoStkPtr has side effects here: */
13558 assignResultValue(IC_RESULT(ic), 0);
13561 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13564 /*-----------------------------------------------------------------*/
13565 /* genDummyRead - generate code for dummy read of volatiles */
13566 /*-----------------------------------------------------------------*/
13568 genDummyRead (iCode * ic)
13574 if (op && IS_SYMOP(op)) {
13575 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13576 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13579 pic16_aopOp (op, ic, FALSE);
13580 for (i=0; i < AOP_SIZE(op); i++) {
13581 // may need to protect this from the peepholer -- this is not nice but works...
13582 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13583 pic16_mov2w (AOP(op),i);
13584 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13586 pic16_freeAsmop (op, NULL, ic, TRUE);
13588 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13592 /*-----------------------------------------------------------------*/
13593 /* genpic16Code - generate code for pic16 based controllers */
13594 /*-----------------------------------------------------------------*/
13596 * At this point, ralloc.c has gone through the iCode and attempted
13597 * to optimize in a way suitable for a PIC. Now we've got to generate
13598 * PIC instructions that correspond to the iCode.
13600 * Once the instructions are generated, we'll pass through both the
13601 * peep hole optimizer and the pCode optimizer.
13602 *-----------------------------------------------------------------*/
13604 void genpic16Code (iCode *lic)
13609 lineHead = lineCurr = NULL;
13611 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13612 pic16_addpBlock(pb);
13615 /* if debug information required */
13616 if (options.debug && currFunc) {
13618 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13623 for (ic = lic ; ic ; ic = ic->next ) {
13625 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13626 if ( cln != ic->lineno ) {
13627 if ( options.debug ) {
13628 debugFile->writeCLine (ic);
13631 if(!options.noCcodeInAsm) {
13632 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13633 printCLine(ic->filename, ic->lineno)));
13639 if(options.iCodeInAsm) {
13642 /* insert here code to print iCode as comment */
13643 l = Safe_strdup(printILine(ic));
13644 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13647 /* if the result is marked as
13648 * spilt and rematerializable or code for
13649 * this has already been generated then
13651 if (resultRemat(ic) || ic->generated )
13654 /* depending on the operation */
13673 /* IPOP happens only when trying to restore a
13674 * spilt live range, if there is an ifx statement
13675 * following this pop then the if statement might
13676 * be using some of the registers being popped which
13677 * would destroy the contents of the register so
13678 * we need to check for this condition and handle it */
13680 && ic->next->op == IFX
13681 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13682 genIfx (ic->next,ic);
13700 genEndFunction (ic);
13716 pic16_genPlus (ic) ;
13720 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13721 pic16_genMinus (ic);
13737 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13741 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13747 /* note these two are xlated by algebraic equivalence
13748 * during parsing SDCC.y */
13749 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13750 "got '>=' or '<=' shouldn't have come here");
13754 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13766 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13770 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13774 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13798 genRightShift (ic);
13801 case GET_VALUE_AT_ADDRESS:
13806 if (POINTER_SET(ic))
13833 addSet(&_G.sendSet,ic);
13836 case DUMMY_READ_VOLATILE:
13846 /* now we are ready to call the
13847 peep hole optimizer */
13848 if (!options.nopeep)
13849 peepHole (&lineHead);
13851 /* now do the actual printing */
13852 printLine (lineHead, codeOutFile);
13855 DFPRINTF((stderr,"printing pBlock\n\n"));
13856 pic16_printpBlock(stdout,pb);