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 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1259 sym->usl.spillLoc->offset, op);
1260 aop->size = getSize(sym->type);
1266 sym_link *type = operandType(op);
1268 if(IS_PTR_CONST(type))
1270 if(IS_CODEPTR(type))
1272 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1275 /* must be in a register */
1276 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1277 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1278 aop->size = sym->nRegs;
1279 for ( i = 0 ; i < sym->nRegs ;i++)
1280 aop->aopu.aop_reg[i] = sym->regs[i];
1283 /*-----------------------------------------------------------------*/
1284 /* pic16_freeAsmop - free up the asmop given to an operand */
1285 /*----------------------------------------------------------------*/
1286 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1303 /* depending on the asmop type only three cases need work AOP_RO
1304 , AOP_R1 && AOP_STK */
1306 switch (aop->type) {
1308 if (_G.fsr0Pushed ) {
1310 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1311 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1312 // pic16_emitcode ("pop","ar0");
1316 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1320 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1326 pic16_emitcode ("pop","ar0");
1330 bitVectUnSetBit(ic->rUsed,R0_IDX);
1336 pic16_emitcode ("pop","ar1");
1340 bitVectUnSetBit(ic->rUsed,R1_IDX);
1347 /* we must store the result on stack */
1348 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1349 // operands on stack are accessible via "FSR2 + index" with index
1350 // starting at 2 for arguments and growing from 0 downwards for
1351 // local variables (index == 0 is not assigned so we add one here)
1352 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1357 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1358 for(i=0;i<aop->size;i++) {
1359 /* initialise for stack access via frame pointer */
1360 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1361 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1362 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1365 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1369 for(i=0;i<aop->size;i++)
1370 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1379 int stk = aop->aopu.aop_stk + aop->size;
1380 bitVectUnSetBit(ic->rUsed,R0_IDX);
1381 bitVectUnSetBit(ic->rUsed,R1_IDX);
1383 getFreePtr(ic,&aop,FALSE);
1385 if (options.stack10bit)
1387 /* I'm not sure what to do here yet... */
1390 "*** Warning: probably generating bad code for "
1391 "10 bit stack mode.\n");
1395 pic16_emitcode ("mov","a,_bp");
1396 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1397 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1399 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1403 pic16_emitcode("pop","acc");
1404 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1406 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1409 pic16_freeAsmop(op,NULL,ic,TRUE);
1411 pic16_emitcode("pop","ar0");
1416 pic16_emitcode("pop","ar1");
1426 /* all other cases just dealloc */
1430 OP_SYMBOL(op)->aop = NULL;
1431 /* if the symbol has a spill */
1433 SPIL_LOC(op)->aop = NULL;
1438 /*-----------------------------------------------------------------*/
1439 /* pic16_aopGet - for fetching value of the aop */
1440 /*-----------------------------------------------------------------*/
1441 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1446 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1448 /* offset is greater than size then zero */
1449 if (offset > (aop->size - 1) &&
1450 aop->type != AOP_LIT)
1453 /* depending on type */
1454 switch (aop->type) {
1458 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1459 rs = Safe_calloc(1, strlen(s)+1);
1464 /* if we need to increment it */
1465 while (offset > aop->coff)
1467 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1471 while (offset < aop->coff)
1473 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1479 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1480 return (dname ? "acc" : "a");
1482 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1483 rs = Safe_calloc (1, strlen (s) + 1);
1491 sprintf (s,"%s",aop->aopu.aop_immd);
1494 sprintf(s,"(%s >> %d)",
1499 aop->aopu.aop_immd);
1500 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1501 rs = Safe_calloc(1,strlen(s)+1);
1507 sprintf(s,"(%s + %d)",
1510 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1512 sprintf(s,"%s",aop->aopu.aop_dir);
1513 rs = Safe_calloc(1,strlen(s)+1);
1519 // return aop->aopu.aop_reg[offset]->dname;
1521 return aop->aopu.aop_reg[offset]->name;
1524 //pic16_emitcode(";","%d",__LINE__);
1525 return aop->aopu.aop_dir;
1528 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1529 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1531 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1532 rs = Safe_strdup("WREG");
1536 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1537 rs = Safe_calloc(1,strlen(s)+1);
1542 aop->coff = offset ;
1543 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1546 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1548 return aop->aopu.aop_str[offset];
1552 pCodeOp *pcop = aop->aopu.pcop;
1553 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1555 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1556 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1558 sprintf(s,"(%s + %d)", pcop->name, offset);
1560 sprintf(s,"%s", pcop->name);
1563 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1566 rs = Safe_calloc(1,strlen(s)+1);
1572 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1574 sprintf(s,"(%s + %d)",
1578 sprintf(s,"%s",aop->aopu.aop_dir);
1579 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1580 rs = Safe_calloc(1,strlen(s)+1);
1586 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1590 // pCodeOp *pcop = aop->aop
1595 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1596 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1597 "aopget got unsupported aop->type");
1603 /* lock has the following meaning: When allocating temporary registers
1604 * for stack variables storage, the value of the temporary register is
1605 * saved on stack. Its value is restored at the end. This procedure is
1606 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1607 * a possibility that before a call to pic16_aopOp, a temporary register
1608 * is allocated for a while and it is freed after some time, this will
1609 * mess the stack and values will not be restored properly. So use lock=1
1610 * to allocate temporary registers used internally by the programmer, and
1611 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1612 * to inform the compiler developer about a possible bug. This is an internal
1613 * feature for developing the compiler -- VR */
1615 int _TempReg_lock = 0;
1616 /*-----------------------------------------------------------------*/
1617 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1618 /*-----------------------------------------------------------------*/
1619 pCodeOp *pic16_popGetTempReg(int lock)
1624 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1626 // werror(W_POSSBUG2, __FILE__, __LINE__);
1629 _TempReg_lock += lock;
1634 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1635 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1636 PCOR(pcop)->r->wasUsed=1;
1637 PCOR(pcop)->r->isFree=0;
1639 /* push value on stack */
1640 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1648 /*-----------------------------------------------------------------*/
1649 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1650 /* don't save if inside v */
1651 /*-----------------------------------------------------------------*/
1652 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1657 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1660 // werror(W_POSSBUG2, __FILE__, __LINE__);
1663 _TempReg_lock += lock;
1668 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1669 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1670 PCOR(pcop)->r->wasUsed=1;
1671 PCOR(pcop)->r->isFree=0;
1673 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1674 /* push value on stack */
1675 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1685 /*-----------------------------------------------------------------*/
1686 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1687 /*-----------------------------------------------------------------*/
1688 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1690 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1692 _TempReg_lock -= lock;
1694 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1695 PCOR(pcop)->r->isFree = 1;
1696 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1699 /*-----------------------------------------------------------------*/
1700 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1701 /*-----------------------------------------------------------------*/
1702 pCodeOp *pic16_popGetLabel(unsigned int key)
1705 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1710 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1713 /*-----------------------------------------------------------------*/
1714 /* pic16_popCopyReg - copy a pcode operator */
1715 /*-----------------------------------------------------------------*/
1716 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1720 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1721 pcor->pcop.type = pc->pcop.type;
1723 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1724 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1726 pcor->pcop.name = NULL;
1729 pcor->rIdx = pc->rIdx;
1731 pcor->instance = pc->instance;
1733 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1738 /*-----------------------------------------------------------------*/
1739 /* pic16_popGetLit - asm operator to pcode operator conversion */
1740 /*-----------------------------------------------------------------*/
1741 pCodeOp *pic16_popGetLit(int lit)
1743 return pic16_newpCodeOpLit(lit);
1746 /*-----------------------------------------------------------------*/
1747 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1748 /*-----------------------------------------------------------------*/
1749 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1751 return pic16_newpCodeOpLit2(lit, arg2);
1755 /*-----------------------------------------------------------------*/
1756 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1757 /*-----------------------------------------------------------------*/
1758 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1760 return pic16_newpCodeOpImmd(name, offset,index, 0);
1764 /*-----------------------------------------------------------------*/
1765 /* pic16_popGet - asm operator to pcode operator conversion */
1766 /*-----------------------------------------------------------------*/
1767 pCodeOp *pic16_popGetWithString(char *str)
1773 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1777 pcop = pic16_newpCodeOp(str,PO_STR);
1782 /*-----------------------------------------------------------------*/
1783 /* pic16_popRegFromString - */
1784 /*-----------------------------------------------------------------*/
1785 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1788 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1789 pcop->type = PO_DIR;
1791 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1792 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1797 pcop->name = Safe_calloc(1,strlen(str)+1);
1798 strcpy(pcop->name,str);
1800 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1802 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1804 /* make sure that register doesn't exist,
1805 * and operand isn't NULL
1806 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1807 if((PCOR(pcop)->r == NULL)
1809 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1810 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1811 // __FUNCTION__, __LINE__, str, size, offset);
1813 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1814 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1817 PCOR(pcop)->instance = offset;
1822 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1826 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1828 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1829 PCOR(pcop)->rIdx = rIdx;
1830 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1832 PCOR(pcop)->r->isFree = 0;
1833 PCOR(pcop)->r->wasUsed = 1;
1835 pcop->type = PCOR(pcop)->r->pc_type;
1840 /*---------------------------------------------------------------------------------*/
1841 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1843 /*---------------------------------------------------------------------------------*/
1844 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1849 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1851 /* comment the following check, so errors to throw up */
1852 // if(!pcop2)return NULL;
1854 temp = pic16_popGet(aop_dst, offset);
1855 pcop2->pcop2 = temp;
1862 /*--------------------------------------------------------------------------------.-*/
1863 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1864 /* VR 030601 , adapted by Hans Dorn */
1865 /*--------------------------------------------------------------------------------.-*/
1866 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1870 pcop2 = (pCodeOpReg2 *)src;
1878 /*---------------------------------------------------------------------------------*/
1879 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1880 /* movff instruction */
1881 /*---------------------------------------------------------------------------------*/
1882 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1887 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1888 pcop2->pcop2 = pic16_popCopyReg(dst);
1890 /* the pCodeOp may be already allocated */
1891 pcop2 = (pCodeOpReg2 *)(src);
1892 pcop2->pcop2 = (pCodeOp *)(dst);
1899 /*-----------------------------------------------------------------*/
1900 /* pic16_popGet - asm operator to pcode operator conversion */
1901 /*-----------------------------------------------------------------*/
1902 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1904 //char *s = buffer ;
1909 /* offset is greater than
1912 // if (offset > (aop->size - 1) &&
1913 // aop->type != AOP_LIT)
1914 // return NULL; //zero;
1916 /* depending on type */
1917 switch (aop->type) {
1923 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1924 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1931 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1932 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1933 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1934 PCOR(pcop)->r->wasUsed = 1;
1935 PCOR(pcop)->r->isFree = 0;
1937 PCOR(pcop)->instance = offset;
1938 pcop->type = PCOR(pcop)->r->pc_type;
1942 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1943 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1946 /* pCodeOp is already allocated from aopForSym */
1947 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1948 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1954 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1956 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1958 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1960 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1961 PCOR(pcop)->rIdx = rIdx;
1962 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1963 PCOR(pcop)->r->wasUsed=1;
1964 PCOR(pcop)->r->isFree=0;
1966 PCOR(pcop)->instance = offset;
1967 pcop->type = PCOR(pcop)->r->pc_type;
1968 // rs = aop->aopu.aop_reg[offset]->name;
1969 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1973 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1974 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1980 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1981 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1985 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1986 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1992 assert (aop && aop->aopu.aop_reg[offset] != NULL);
1993 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1995 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1997 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1998 // pcop->type = PO_GPR_REGISTER;
1999 PCOR(pcop)->rIdx = rIdx;
2000 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2001 PCOR(pcop)->r->wasUsed=1;
2002 PCOR(pcop)->r->isFree=0;
2004 PCOR(pcop)->instance = offset;
2005 pcop->type = PCOR(pcop)->r->pc_type;
2007 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2008 rs = aop->aopu.aop_reg[offset]->name;
2009 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2014 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2016 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2017 PCOR(pcop)->instance = offset;
2018 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2019 //if(PCOR(pcop)->r == NULL)
2020 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2024 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2025 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2028 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2029 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2032 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2033 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2034 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2035 pcop->type = PCOR(pcop)->r->pc_type;
2036 pcop->name = PCOR(pcop)->r->name;
2042 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2044 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2045 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2046 switch( aop->aopu.pcop->type ) {
2047 case PO_DIR: PCOR(pcop)->instance += offset; break;
2048 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2050 assert( 0 ); /* should never reach here */;
2055 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2056 "pic16_popGet got unsupported aop->type");
2059 /*-----------------------------------------------------------------*/
2060 /* pic16_aopPut - puts a string for a aop */
2061 /*-----------------------------------------------------------------*/
2062 void pic16_aopPut (asmop *aop, char *s, int offset)
2069 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2071 if (aop->size && offset > ( aop->size - 1)) {
2072 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2073 "pic16_aopPut got offset > aop->size");
2077 /* will assign value to value */
2078 /* depending on where it is ofcourse */
2079 switch (aop->type) {
2082 sprintf(d,"(%s + %d)",
2083 aop->aopu.aop_dir,offset);
2084 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2087 sprintf(d,"%s",aop->aopu.aop_dir);
2090 DEBUGpic16_emitcode(";","%d",__LINE__);
2092 pic16_emitcode("movf","%s,w",s);
2093 pic16_emitcode("movwf","%s",d);
2096 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2097 if(offset >= aop->size) {
2098 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2101 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2104 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2111 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2112 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2115 strcmp(s,"r0") == 0 ||
2116 strcmp(s,"r1") == 0 ||
2117 strcmp(s,"r2") == 0 ||
2118 strcmp(s,"r3") == 0 ||
2119 strcmp(s,"r4") == 0 ||
2120 strcmp(s,"r5") == 0 ||
2121 strcmp(s,"r6") == 0 ||
2122 strcmp(s,"r7") == 0 )
2123 pic16_emitcode("mov","%s,%s ; %d",
2124 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2128 if(strcmp(s,"W")==0 )
2129 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2131 pic16_emitcode("movwf","%s",
2132 aop->aopu.aop_reg[offset]->name);
2134 if(strcmp(s,zero)==0) {
2135 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2137 } else if(strcmp(s,"W")==0) {
2138 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2139 pcop->type = PO_GPR_REGISTER;
2141 PCOR(pcop)->rIdx = -1;
2142 PCOR(pcop)->r = NULL;
2144 DEBUGpic16_emitcode(";","%d",__LINE__);
2145 pcop->name = Safe_strdup(s);
2146 pic16_emitpcode(POC_MOVFW,pcop);
2147 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2148 } else if(strcmp(s,one)==0) {
2149 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2150 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2152 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2160 if (aop->type == AOP_DPTR2)
2166 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2167 "pic16_aopPut writting to code space");
2171 while (offset > aop->coff) {
2173 pic16_emitcode ("inc","dptr");
2176 while (offset < aop->coff) {
2178 pic16_emitcode("lcall","__decdptr");
2183 /* if not in accumulater */
2186 pic16_emitcode ("movx","@dptr,a");
2188 if (aop->type == AOP_DPTR2)
2196 while (offset > aop->coff) {
2198 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2200 while (offset < aop->coff) {
2202 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2208 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2213 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2215 if (strcmp(s,"r0") == 0 ||
2216 strcmp(s,"r1") == 0 ||
2217 strcmp(s,"r2") == 0 ||
2218 strcmp(s,"r3") == 0 ||
2219 strcmp(s,"r4") == 0 ||
2220 strcmp(s,"r5") == 0 ||
2221 strcmp(s,"r6") == 0 ||
2222 strcmp(s,"r7") == 0 ) {
2224 sprintf(buffer,"a%s",s);
2225 pic16_emitcode("mov","@%s,%s",
2226 aop->aopu.aop_ptr->name,buffer);
2228 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2233 if (strcmp(s,"a") == 0)
2234 pic16_emitcode("push","acc");
2236 pic16_emitcode("push","%s",s);
2241 /* if bit variable */
2242 if (!aop->aopu.aop_dir) {
2243 pic16_emitcode("clr","a");
2244 pic16_emitcode("rlc","a");
2247 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2250 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2253 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2255 lbl = newiTempLabel(NULL);
2257 if (strcmp(s,"a")) {
2260 pic16_emitcode("clr","c");
2261 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2262 pic16_emitcode("cpl","c");
2263 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2264 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2271 if (strcmp(aop->aopu.aop_str[offset],s))
2272 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2277 if (!offset && (strcmp(s,"acc") == 0))
2280 if (strcmp(aop->aopu.aop_str[offset],s))
2281 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2285 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2286 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2287 // "pic16_aopPut got unsupported aop->type");
2293 /*-----------------------------------------------------------------*/
2294 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2295 /*-----------------------------------------------------------------*/
2296 void pic16_mov2w (asmop *aop, int offset)
2298 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2301 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2303 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2306 static void mov2f(asmop *dst, asmop *src, int offset)
2308 if(is_LitAOp(src)) {
2309 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2310 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2312 if(pic16_sameRegsOfs(src, dst, offset))return;
2313 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2314 pic16_popGet(dst, offset)));
2318 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2320 if(is_LitAOp(src)) {
2321 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2322 pic16_emitpcode(POC_MOVWF, dst);
2324 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2328 void pic16_testStackOverflow(void)
2330 #define GSTACK_TEST_NAME "__gstack_test"
2332 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2337 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2338 strcpy(sym->rname, GSTACK_TEST_NAME);
2339 checkAddSym(&externs, sym);
2344 /* push pcop into stack */
2345 void pic16_pushpCodeOp(pCodeOp *pcop)
2347 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2348 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2349 if(pic16_options.gstack)
2350 pic16_testStackOverflow();
2354 /* pop pcop from stack */
2355 void pic16_poppCodeOp(pCodeOp *pcop)
2357 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2358 if(pic16_options.gstack)
2359 pic16_testStackOverflow();
2363 /*-----------------------------------------------------------------*/
2364 /* pushw - pushes wreg to stack */
2365 /*-----------------------------------------------------------------*/
2368 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2369 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2370 if(pic16_options.gstack)
2371 pic16_testStackOverflow();
2375 /*-----------------------------------------------------------------*/
2376 /* pushaop - pushes aop to stack */
2377 /*-----------------------------------------------------------------*/
2378 void pushaop(asmop *aop, int offset)
2380 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2382 if(is_LitAOp(aop)) {
2383 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2384 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2386 pic16_emitpcode(POC_MOVFF,
2387 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2390 if(pic16_options.gstack)
2391 pic16_testStackOverflow();
2394 /*-----------------------------------------------------------------*/
2395 /* popaop - pops aop from stack */
2396 /*-----------------------------------------------------------------*/
2397 void popaop(asmop *aop, int offset)
2399 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2400 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2401 if(pic16_options.gstack)
2402 pic16_testStackOverflow();
2405 void popaopidx(asmop *aop, int offset, int index)
2409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2411 if(STACK_MODEL_LARGE)ofs++;
2413 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2414 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2415 if(pic16_options.gstack)
2416 pic16_testStackOverflow();
2419 #if !(USE_GENERIC_SIGNED_SHIFT)
2420 /*-----------------------------------------------------------------*/
2421 /* reAdjustPreg - points a register back to where it should */
2422 /*-----------------------------------------------------------------*/
2423 static void reAdjustPreg (asmop *aop)
2427 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2429 if ((size = aop->size) <= 1)
2432 switch (aop->type) {
2436 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2440 if (aop->type == AOP_DPTR2)
2446 pic16_emitcode("lcall","__decdptr");
2449 if (aop->type == AOP_DPTR2)
2461 /*-----------------------------------------------------------------*/
2462 /* opIsGptr: returns non-zero if the passed operand is */
2463 /* a generic pointer type. */
2464 /*-----------------------------------------------------------------*/
2465 static int opIsGptr(operand *op)
2467 sym_link *type = operandType(op);
2469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2470 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2478 /*-----------------------------------------------------------------*/
2479 /* pic16_getDataSize - get the operand data size */
2480 /*-----------------------------------------------------------------*/
2481 int pic16_getDataSize(operand *op)
2483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2486 return AOP_SIZE(op);
2488 // tsd- in the pic port, the genptr size is 1, so this code here
2489 // fails. ( in the 8051 port, the size was 4).
2492 size = AOP_SIZE(op);
2493 if (size == GPTRSIZE)
2495 sym_link *type = operandType(op);
2496 if (IS_GENPTR(type))
2498 /* generic pointer; arithmetic operations
2499 * should ignore the high byte (pointer type).
2502 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2509 /*-----------------------------------------------------------------*/
2510 /* pic16_outAcc - output Acc */
2511 /*-----------------------------------------------------------------*/
2512 void pic16_outAcc(operand *result)
2515 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2516 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2519 size = pic16_getDataSize(result);
2521 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2524 /* unsigned or positive */
2526 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2531 /*-----------------------------------------------------------------*/
2532 /* pic16_outBitC - output a bit C */
2533 /* Move to result the value of Carry flag -- VR */
2534 /*-----------------------------------------------------------------*/
2535 void pic16_outBitC(operand *result)
2539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2541 /* if the result is bit */
2542 if (AOP_TYPE(result) == AOP_CRY) {
2543 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2544 pic16_aopPut(AOP(result),"c",0);
2547 i = AOP_SIZE(result);
2549 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2551 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2555 /*-----------------------------------------------------------------*/
2556 /* pic16_outBitOp - output a bit from Op */
2557 /* Move to result the value of set/clr op -- VR */
2558 /*-----------------------------------------------------------------*/
2559 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2565 /* if the result is bit */
2566 if (AOP_TYPE(result) == AOP_CRY) {
2567 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2568 pic16_aopPut(AOP(result),"c",0);
2571 i = AOP_SIZE(result);
2573 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2575 pic16_emitpcode(POC_RRCF, pcop);
2576 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2580 /*-----------------------------------------------------------------*/
2581 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2582 /*-----------------------------------------------------------------*/
2583 void pic16_toBoolean(operand *oper)
2585 int size = AOP_SIZE(oper) - 1;
2588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2590 if ( AOP_TYPE(oper) != AOP_ACC) {
2591 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2594 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2599 #if !defined(GEN_Not)
2600 /*-----------------------------------------------------------------*/
2601 /* genNot - generate code for ! operation */
2602 /*-----------------------------------------------------------------*/
2603 static void pic16_genNot (iCode *ic)
2609 /* assign asmOps to operand & result */
2610 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2611 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2613 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2614 /* if in bit space then a special case */
2615 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2616 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2617 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2618 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2620 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2621 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2622 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2627 size = AOP_SIZE(IC_LEFT(ic));
2629 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2630 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2631 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2634 pic16_toBoolean(IC_LEFT(ic));
2636 tlbl = newiTempLabel(NULL);
2637 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2638 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2639 pic16_outBitC(IC_RESULT(ic));
2642 /* release the aops */
2643 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2644 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2649 #if !defined(GEN_Cpl)
2650 /*-----------------------------------------------------------------*/
2651 /* genCpl - generate code for complement */
2652 /*-----------------------------------------------------------------*/
2653 static void pic16_genCpl (iCode *ic)
2659 /* assign asmOps to operand & result */
2660 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2661 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2663 /* if both are in bit space then
2665 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2666 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2668 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2669 pic16_emitcode("cpl","c");
2670 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2674 size = AOP_SIZE(IC_RESULT(ic));
2677 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2679 pic16_emitcode("cpl","a");
2680 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2682 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2683 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2685 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2694 /* release the aops */
2695 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2696 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2700 /*-----------------------------------------------------------------*/
2701 /* genUminusFloat - unary minus for floating points */
2702 /*-----------------------------------------------------------------*/
2703 static void genUminusFloat(operand *op,operand *result)
2705 int size ,offset =0 ;
2708 /* for this we just need to flip the
2709 first it then copy the rest in place */
2710 size = AOP_SIZE(op);
2713 mov2f(AOP(result), AOP(op), offset);
2717 /* toggle the MSB's highest bit */
2718 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2721 /*-----------------------------------------------------------------*/
2722 /* genUminus - unary minus code generation */
2723 /*-----------------------------------------------------------------*/
2724 static void genUminus (iCode *ic)
2727 sym_link *optype, *rtype;
2734 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2735 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2737 /* if both in bit space then special case */
2738 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2739 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2741 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2742 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2743 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2747 optype = operandType(IC_LEFT(ic));
2748 rtype = operandType(IC_RESULT(ic));
2750 /* if float then do float stuff */
2751 if (IS_FLOAT(optype)) {
2752 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2756 /* otherwise subtract from zero by taking the 2's complement */
2757 size = AOP_SIZE(IC_LEFT(ic));
2758 label = newiTempLabel ( NULL );
2760 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2761 for (i=size-1; i > 0; i--) {
2762 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2764 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2765 for (i=1; i < size; i++) {
2766 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2767 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2770 for (i=size-1; i >= 0; i--) {
2771 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2772 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2775 for (i=0; i < size-2; i++) {
2776 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2777 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2779 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2781 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2784 pic16_emitpLabel (label->key);
2787 /* release the aops */
2788 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2789 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2793 /*-----------------------------------------------------------------*/
2794 /* saveRegisters - will look for a call and save the registers */
2795 /*-----------------------------------------------------------------*/
2796 static void saveRegisters(iCode *lic)
2803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2805 for (ic = lic ; ic ; ic = ic->next)
2806 if (ic->op == CALL || ic->op == PCALL)
2810 fprintf(stderr,"found parameter push with no function call\n");
2814 /* if the registers have been saved already then
2816 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2819 /* find the registers in use at this time
2820 and push them away to safety */
2821 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2825 if (options.useXstack) {
2826 if (bitVectBitValue(rsave,R0_IDX))
2827 pic16_emitcode("mov","b,r0");
2828 pic16_emitcode("mov","r0,%s",spname);
2829 for (i = 0 ; i < pic16_nRegs ; i++) {
2830 if (bitVectBitValue(rsave,i)) {
2832 pic16_emitcode("mov","a,b");
2834 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2835 pic16_emitcode("movx","@r0,a");
2836 pic16_emitcode("inc","r0");
2839 pic16_emitcode("mov","%s,r0",spname);
2840 if (bitVectBitValue(rsave,R0_IDX))
2841 pic16_emitcode("mov","r0,b");
2843 //for (i = 0 ; i < pic16_nRegs ; i++) {
2844 // if (bitVectBitValue(rsave,i))
2845 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2848 dtype = operandType(IC_LEFT(ic));
2849 if (currFunc && dtype &&
2850 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2851 IFFUNC_ISISR(currFunc->type) &&
2854 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2857 /*-----------------------------------------------------------------*/
2858 /* unsaveRegisters - pop the pushed registers */
2859 /*-----------------------------------------------------------------*/
2860 static void unsaveRegisters (iCode *ic)
2865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2866 /* find the registers in use at this time
2867 and push them away to safety */
2868 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2871 if (options.useXstack) {
2872 pic16_emitcode("mov","r0,%s",spname);
2873 for (i = pic16_nRegs ; i >= 0 ; i--) {
2874 if (bitVectBitValue(rsave,i)) {
2875 pic16_emitcode("dec","r0");
2876 pic16_emitcode("movx","a,@r0");
2878 pic16_emitcode("mov","b,a");
2880 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2884 pic16_emitcode("mov","%s,r0",spname);
2885 if (bitVectBitValue(rsave,R0_IDX))
2886 pic16_emitcode("mov","r0,b");
2888 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2889 // if (bitVectBitValue(rsave,i))
2890 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2897 /*-----------------------------------------------------------------*/
2899 /*-----------------------------------------------------------------*/
2900 static void pushSide(operand * oper, int size)
2903 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2905 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2906 if (AOP_TYPE(oper) != AOP_REG &&
2907 AOP_TYPE(oper) != AOP_DIR &&
2909 pic16_emitcode("mov","a,%s",l);
2910 pic16_emitcode("push","acc");
2912 pic16_emitcode("push","%s",l);
2917 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2919 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2920 pic16_emitpcode(POC_MOVFW, src);
2921 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2923 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2924 src, pic16_popGet(AOP(op), offset)));
2929 /*-----------------------------------------------------------------*/
2930 /* assignResultValue - assign results to oper, rescall==1 is */
2931 /* called from genCall() or genPcall() */
2932 /*-----------------------------------------------------------------*/
2933 static void assignResultValue(operand * oper, int rescall)
2935 int size = AOP_SIZE(oper);
2939 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2940 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2943 /* assign result from a call/pcall function() */
2945 /* function results are stored in a special order,
2946 * see top of file with Function return policy, or manual */
2949 /* 8-bits, result in WREG */
2950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2953 /* 16-bits, result in PRODL:WREG */
2954 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2958 /* 24-bits, result in PRODH:PRODL:WREG */
2959 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2963 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2964 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2968 /* >32-bits, result on stack, and FSR0 points to beginning.
2969 * Fix stack when done */
2971 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2973 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2974 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2976 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2981 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2982 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2983 if(STACK_MODEL_LARGE) {
2985 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2989 int areg = 0; /* matching argument register */
2991 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2992 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2995 /* its called from genReceive (probably) -- VR */
2996 /* I hope this code will not be called from somewhere else in the future!
2997 * We manually set the pseudo stack pointer in genReceive. - dw
2999 if(!GpsuedoStkPtr && _G.useWreg) {
3000 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3002 /* The last byte in the assignment is in W */
3003 if(areg <= GpsuedoStkPtr) {
3005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3007 // debugf("receive from WREG\n", 0);
3009 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3012 _G.stack_lat = AOP_SIZE(oper)-1;
3017 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3018 // debugf("receive from STACK\n", 0);
3025 /*-----------------------------------------------------------------*/
3026 /* genIpush - generate code for pushing this gets a little complex */
3027 /*-----------------------------------------------------------------*/
3028 static void genIpush (iCode *ic)
3030 // int size, offset=0;
3033 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3036 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3038 /* send to stack as normal */
3039 addSet(&_G.sendSet,ic);
3040 // addSetHead(&_G.sendSet,ic);
3041 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3046 int size, offset = 0 ;
3050 /* if this is not a parm push : ie. it is spill push
3051 and spill push is always done on the local stack */
3052 if (!ic->parmPush) {
3054 /* and the item is spilt then do nothing */
3055 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3058 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3059 size = AOP_SIZE(IC_LEFT(ic));
3060 /* push it on the stack */
3062 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3067 pic16_emitcode("push","%s",l);
3072 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3076 /*-----------------------------------------------------------------*/
3077 /* genIpop - recover the registers: can happen only for spilling */
3078 /*-----------------------------------------------------------------*/
3079 static void genIpop (iCode *ic)
3082 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3087 /* if the temp was not pushed then */
3088 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3091 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3092 size = AOP_SIZE(IC_LEFT(ic));
3095 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3098 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3103 /*-----------------------------------------------------------------*/
3104 /* unsaverbank - restores the resgister bank from stack */
3105 /*-----------------------------------------------------------------*/
3106 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3108 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3116 if (options.useXstack) {
3118 r = getFreePtr(ic,&aop,FALSE);
3121 pic16_emitcode("mov","%s,_spx",r->name);
3122 pic16_emitcode("movx","a,@%s",r->name);
3123 pic16_emitcode("mov","psw,a");
3124 pic16_emitcode("dec","%s",r->name);
3127 pic16_emitcode ("pop","psw");
3130 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3131 if (options.useXstack) {
3132 pic16_emitcode("movx","a,@%s",r->name);
3133 //pic16_emitcode("mov","(%s+%d),a",
3134 // regspic16[i].base,8*bank+regspic16[i].offset);
3135 pic16_emitcode("dec","%s",r->name);
3138 pic16_emitcode("pop",""); //"(%s+%d)",
3139 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3142 if (options.useXstack) {
3144 pic16_emitcode("mov","_spx,%s",r->name);
3145 pic16_freeAsmop(NULL,aop,ic,TRUE);
3151 /*-----------------------------------------------------------------*/
3152 /* saverbank - saves an entire register bank on the stack */
3153 /*-----------------------------------------------------------------*/
3154 static void saverbank (int bank, iCode *ic, bool pushPsw)
3156 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3162 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3163 if (options.useXstack) {
3166 r = getFreePtr(ic,&aop,FALSE);
3167 pic16_emitcode("mov","%s,_spx",r->name);
3171 for (i = 0 ; i < pic16_nRegs ;i++) {
3172 if (options.useXstack) {
3173 pic16_emitcode("inc","%s",r->name);
3174 //pic16_emitcode("mov","a,(%s+%d)",
3175 // regspic16[i].base,8*bank+regspic16[i].offset);
3176 pic16_emitcode("movx","@%s,a",r->name);
3178 pic16_emitcode("push","");// "(%s+%d)",
3179 //regspic16[i].base,8*bank+regspic16[i].offset);
3183 if (options.useXstack) {
3184 pic16_emitcode("mov","a,psw");
3185 pic16_emitcode("movx","@%s,a",r->name);
3186 pic16_emitcode("inc","%s",r->name);
3187 pic16_emitcode("mov","_spx,%s",r->name);
3188 pic16_freeAsmop (NULL,aop,ic,TRUE);
3191 pic16_emitcode("push","psw");
3193 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3201 static int wparamCmp(void *p1, void *p2)
3203 return (!strcmp((char *)p1, (char *)p2));
3206 int inWparamList(char *s)
3208 return isinSetWith(wparamList, s, wparamCmp);
3212 /*-----------------------------------------------------------------*/
3213 /* genCall - generates a call statement */
3214 /*-----------------------------------------------------------------*/
3215 static void genCall (iCode *ic)
3225 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3226 /* if caller saves & we have not saved then */
3227 // if (!ic->regsSaved)
3228 // saveRegisters(ic);
3230 /* initialise stackParms for IPUSH pushes */
3231 // stackParms = psuedoStkPtr;
3232 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3233 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3234 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3237 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3240 /* if send set is not empty the assign */
3243 int psuedoStkPtr=-1;
3244 int firstTimeThruLoop = 1;
3247 /* reverse sendSet if function is not reentrant */
3248 if(!IFFUNC_ISREENT(ftype))
3249 _G.sendSet = reverseSet(_G.sendSet);
3251 /* First figure how many parameters are getting passed */
3255 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3259 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3260 size = AOP_SIZE(IC_LEFT(sic));
3264 /* pass the last byte through WREG */
3268 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3269 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3270 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3272 if(!firstTimeThruLoop) {
3273 /* If this is not the first time we've been through the loop
3274 * then we need to save the parameter in a temporary
3275 * register. The last byte of the last parameter is
3279 // --psuedoStkPtr; // sanity check
3283 firstTimeThruLoop=0;
3285 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3290 /* all arguments are passed via stack */
3294 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3295 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3296 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3298 // pushaop(AOP(IC_LEFT(sic)), size);
3299 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3304 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3308 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3309 pushw(); /* save last parameter to stack if functions has varargs */
3313 } else use_wreg = 0;
3315 _G.stackRegSet = _G.sendSet;
3320 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3324 /* if we need to assign a result value */
3325 if ((IS_ITEMP(IC_RESULT(ic))
3326 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3327 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3328 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3331 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3334 assignResultValue(IC_RESULT(ic), 1);
3336 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3337 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3339 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3342 if(!stackParms && ic->parmBytes) {
3343 stackParms = ic->parmBytes;
3346 stackParms -= use_wreg;
3349 if(stackParms == 1) {
3350 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3352 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3353 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3355 if(STACK_MODEL_LARGE) {
3357 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3362 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3365 /* adjust the stack for parameters if required */
3366 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3369 /* if register bank was saved then pop them */
3371 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3373 /* if we hade saved some registers then unsave them */
3374 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3375 unsaveRegisters (ic);
3381 /*-----------------------------------------------------------------*/
3382 /* genPcall - generates a call by pointer statement */
3383 /* new version, created from genCall - HJD */
3384 /*-----------------------------------------------------------------*/
3385 static void genPcall (iCode *ic)
3387 sym_link *ftype, *fntype;
3389 symbol *retlbl = newiTempLabel(NULL);
3390 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3394 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3395 fntype = operandType( IC_LEFT(ic) )->next;
3397 /* if send set is not empty the assign */
3400 int psuedoStkPtr=-1;
3402 /* reverse sendSet if function is not reentrant */
3403 if(!IFFUNC_ISREENT(fntype))
3404 _G.sendSet = reverseSet(_G.sendSet);
3408 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3411 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3412 size = AOP_SIZE(IC_LEFT(sic));
3415 /* all parameters are passed via stack, since WREG is clobbered
3416 * by the calling sequence */
3418 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3419 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3420 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3422 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3426 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3429 _G.stackRegSet = _G.sendSet;
3433 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3435 // push return address
3436 // push $ on return stack, then replace with retlbl
3438 /* Thanks to Thorsten Klose for pointing out that the following
3439 * snippet should be interrupt safe */
3440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3441 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3443 pic16_emitpcodeNULLop(POC_PUSH);
3445 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3446 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3447 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3448 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3449 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3450 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3453 /* restore interrupt control register */
3454 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3455 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3457 /* make the call by writing the pointer into pc */
3458 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3461 // note: MOVFF to PCL not allowed
3462 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3463 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3466 /* return address is here: (X) */
3467 pic16_emitpLabelFORCE(retlbl->key);
3469 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3472 /* if we need assign a result value */
3473 if ((IS_ITEMP(IC_RESULT(ic))
3474 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3475 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3476 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3479 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3482 assignResultValue(IC_RESULT(ic), 1);
3484 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3485 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3487 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3490 // stackParms -= use_wreg;
3493 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3494 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3495 if(STACK_MODEL_LARGE) {
3497 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3502 /*-----------------------------------------------------------------*/
3503 /* resultRemat - result is rematerializable */
3504 /*-----------------------------------------------------------------*/
3505 static int resultRemat (iCode *ic)
3507 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3508 if (SKIP_IC(ic) || ic->op == IFX)
3511 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3512 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3513 if (sym->remat && !POINTER_SET(ic))
3520 #if defined(__BORLANDC__) || defined(_MSC_VER)
3521 #define STRCASECMP stricmp
3523 #define STRCASECMP strcasecmp
3527 /*-----------------------------------------------------------------*/
3528 /* inExcludeList - return 1 if the string is in exclude Reg list */
3529 /*-----------------------------------------------------------------*/
3530 static bool inExcludeList(char *s)
3532 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3536 if (options.excludeRegs[i] &&
3537 STRCASECMP(options.excludeRegs[i],"none") == 0)
3540 for ( i = 0 ; options.excludeRegs[i]; i++) {
3541 if (options.excludeRegs[i] &&
3542 STRCASECMP(s,options.excludeRegs[i]) == 0)
3549 /*-----------------------------------------------------------------*/
3550 /* genFunction - generated code for function entry */
3551 /*-----------------------------------------------------------------*/
3552 static void genFunction (iCode *ic)
3558 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3560 pic16_labelOffset += (max_key+4);
3565 ftype = operandType(IC_LEFT(ic));
3566 sym = OP_SYMBOL(IC_LEFT(ic));
3568 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3569 /* create an absolute section at the interrupt vector:
3570 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3576 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3582 sym = OP_SYMBOL( IC_LEFT(ic));
3584 if(interrupts[i]->name
3585 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3592 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3593 __FILE__, __LINE__, sym->name);
3596 _G.interruptvector = found;
3600 if(FUNC_INTNO(sym->type) == 256)
3601 sprintf(asymname, "ivec_%s", sym->name);
3603 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3604 asym = newSymbol(asymname, 0);
3606 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3607 pic16_addpBlock( apb );
3609 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3610 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3611 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3613 /* mark the end of this tiny function */
3614 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3619 abSym = Safe_calloc(1, sizeof(absSym));
3620 strcpy(abSym->name, asymname);
3622 switch( FUNC_INTNO(sym->type) ) {
3623 case 0: abSym->address = 0x000000; break;
3624 case 1: abSym->address = 0x000008; break;
3625 case 2: abSym->address = 0x000018; break;
3628 abSym->address = -1; break;
3631 /* relocate interrupt vectors if needed */
3632 if(abSym->address != -1)
3633 abSym->address += pic16_options.ivt_loc;
3635 addSet(&absSymSet, abSym);
3639 /* create the function header */
3640 pic16_emitcode(";","-----------------------------------------");
3641 pic16_emitcode(";"," function %s",sym->name);
3642 pic16_emitcode(";","-----------------------------------------");
3644 pic16_emitcode("","%s:",sym->rname);
3645 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3651 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3652 if(!strcmp(ab->name, sym->rname)) {
3653 pic16_pBlockConvert2Absolute(pb);
3660 if(IFFUNC_ISNAKED(ftype)) {
3661 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3665 /* if critical function then turn interrupts off */
3666 if (IFFUNC_ISCRITICAL(ftype)) {
3667 //pic16_emitcode("clr","ea");
3670 _G.fregsUsed = sym->regsUsed;
3672 /* if this is an interrupt service routine then
3673 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3674 if (IFFUNC_ISISR(sym->type)) {
3675 _G.usefastretfie = 1; /* use shadow registers by default */
3677 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3678 if(!FUNC_ISSHADOWREGS(sym->type)) {
3679 /* do not save WREG,STATUS,BSR for high priority interrupts
3680 * because they are stored in the hardware shadow registers already */
3681 _G.usefastretfie = 0;
3682 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3683 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3684 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3687 /* these should really be optimized somehow, because not all
3688 * interrupt handlers modify them */
3689 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3690 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3691 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3692 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3694 // pic16_pBlockConvert2ISR(pb);
3698 /* emit code to setup stack frame if user enabled,
3699 * and function is not main() */
3701 //fprintf(stderr, "function name: %s\n", sym->name);
3702 if(strcmp(sym->name, "main")) {
3703 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3704 /* setup the stack frame */
3705 if(STACK_MODEL_LARGE)
3706 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3707 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3709 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3710 if(STACK_MODEL_LARGE)
3711 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3715 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3718 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3720 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3721 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3723 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3726 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3727 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3734 /* if callee-save to be used for this function
3735 * then save the registers being used in this function */
3736 // if (IFFUNC_CALLEESAVES(sym->type))
3740 /* if any registers used */
3741 if (sym->regsUsed) {
3742 /* save the registers used */
3743 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3744 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3745 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3746 if (bitVectBitValue(sym->regsUsed,i)) {
3747 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3750 if(!pic16_regWithIdx(i)->wasUsed) {
3751 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3752 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3753 pic16_regWithIdx(i)->wasUsed = 1;
3757 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3761 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3762 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3765 /*-----------------------------------------------------------------*/
3766 /* genEndFunction - generates epilogue for functions */
3767 /*-----------------------------------------------------------------*/
3768 static void genEndFunction (iCode *ic)
3770 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3774 if(IFFUNC_ISNAKED(sym->type)) {
3775 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3781 /* add code for ISCRITICAL */
3782 if(IFFUNC_ISCRITICAL(sym->type)) {
3783 /* if critical function, turn on interrupts */
3785 /* TODO: add code here -- VR */
3788 // sym->regsUsed = _G.fregsUsed;
3790 /* now we need to restore the registers */
3791 /* if any registers used */
3792 if (sym->regsUsed) {
3795 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3796 /* restore registers used */
3797 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3798 for ( i = sym->regsUsed->size; i >= 0; i--) {
3799 if (bitVectBitValue(sym->regsUsed,i)) {
3800 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3804 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3808 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3810 if (sym->stack == 1) {
3811 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3812 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3814 // we have to add more than one...
3815 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3816 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3817 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3819 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3820 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3821 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3825 if(strcmp(sym->name, "main")) {
3826 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3827 /* restore stack frame */
3828 if(STACK_MODEL_LARGE)
3829 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3830 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3836 if (IFFUNC_ISISR(sym->type)) {
3837 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3838 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3839 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3840 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3842 if(!FUNC_ISSHADOWREGS(sym->type)) {
3843 /* do not restore interrupt vector for WREG,STATUS,BSR
3844 * for high priority interrupt, see genFunction */
3845 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3846 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3847 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3849 // _G.interruptvector = 0; /* sanity check */
3852 /* if debug then send end of function */
3853 /* if (options.debug && currFunc) */
3855 debugFile->writeEndFunction (currFunc, ic, 1);
3858 if(_G.usefastretfie)
3859 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3861 pic16_emitpcodeNULLop(POC_RETFIE);
3863 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3865 _G.usefastretfie = 0;
3869 if (IFFUNC_ISCRITICAL(sym->type)) {
3870 pic16_emitcode("setb","ea");
3873 /* if debug then send end of function */
3875 debugFile->writeEndFunction (currFunc, ic, 1);
3878 /* insert code to restore stack frame, if user enabled it
3879 * and function is not main() */
3882 pic16_emitpcodeNULLop(POC_RETURN);
3884 /* Mark the end of a function */
3885 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3889 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3892 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3894 pic16_emitpcode(POC_CLRF, dest);
3896 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3897 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3900 if(dest->type == PO_WREG && (offset == 0)) {
3901 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3904 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3908 /*-----------------------------------------------------------------*/
3909 /* genRet - generate code for return statement */
3910 /*-----------------------------------------------------------------*/
3911 static void genRet (iCode *ic)
3917 /* if we have no return value then
3918 * just generate the "ret" */
3923 /* we have something to return then
3924 * move the return value into place */
3925 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3926 size = AOP_SIZE(IC_LEFT(ic));
3930 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3931 // pic16_emitpcode(POC_MOVFF,
3932 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3935 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3936 // pic16_emitpcode(POC_MOVFF,
3937 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3940 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3941 // pic16_emitpcode(POC_MOVFF,
3942 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3945 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3947 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3948 // pic16_emitpcode(POC_MOVFF,
3949 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3952 /* >32-bits, setup stack and FSR0 */
3954 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3955 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3957 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3959 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3964 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3965 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3967 if(STACK_MODEL_LARGE) {
3968 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3969 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3971 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3976 /* old code, left here for reference -- VR */
3980 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3982 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3983 pic16_emitpcomment("push %s",l);
3986 DEBUGpic16_emitcode(";", "%d", __LINE__);
3987 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3988 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3990 if (strcmp(fReturn[offset],l)) {
3991 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3992 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3993 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3995 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3999 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4009 if (strcmp(fReturn[pushed],"a"))
4010 pic16_emitcode("pop",fReturn[pushed]);
4012 pic16_emitcode("pop","acc");
4018 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4021 /* generate a jump to the return label
4022 * if the next is not the return statement */
4023 if (!(ic->next && ic->next->op == LABEL
4024 && IC_LABEL(ic->next) == returnLabel)) {
4026 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4027 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4031 /*-----------------------------------------------------------------*/
4032 /* genLabel - generates a label */
4033 /*-----------------------------------------------------------------*/
4034 static void genLabel (iCode *ic)
4038 /* special case never generate */
4039 if (IC_LABEL(ic) == entryLabel)
4042 pic16_emitpLabel(IC_LABEL(ic)->key);
4043 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4046 /*-----------------------------------------------------------------*/
4047 /* genGoto - generates a goto */
4048 /*-----------------------------------------------------------------*/
4050 static void genGoto (iCode *ic)
4053 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4054 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4058 /*-----------------------------------------------------------------*/
4059 /* genMultbits :- multiplication of bits */
4060 /*-----------------------------------------------------------------*/
4061 static void genMultbits (operand *left,
4067 if(!pic16_sameRegs(AOP(result),AOP(right)))
4068 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4070 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4071 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4072 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4077 /*-----------------------------------------------------------------*/
4078 /* genMultOneByte : 8 bit multiplication & division */
4079 /*-----------------------------------------------------------------*/
4080 static void genMultOneByte (operand *left,
4086 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4087 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4089 /* (if two literals, the value is computed before) */
4090 /* if one literal, literal on the right */
4091 if (AOP_TYPE(left) == AOP_LIT){
4097 /* size is already checked in genMult == 1 */
4098 // size = AOP_SIZE(result);
4100 if (AOP_TYPE(right) == AOP_LIT){
4101 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4102 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4103 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4104 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4106 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4107 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4108 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4109 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4112 pic16_genMult8X8_8 (left, right,result);
4115 /*-----------------------------------------------------------------*/
4116 /* genMultOneWord : 16 bit multiplication */
4117 /*-----------------------------------------------------------------*/
4118 static void genMultOneWord (operand *left,
4123 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4124 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4126 /* (if two literals, the value is computed before)
4127 * if one literal, literal on the right */
4128 if (AOP_TYPE(left) == AOP_LIT){
4134 /* size is checked already == 2 */
4135 // size = AOP_SIZE(result);
4137 if (AOP_TYPE(right) == AOP_LIT) {
4138 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4139 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4140 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4141 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4143 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4144 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4145 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4146 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4149 pic16_genMult16X16_16(left, right,result);
4152 /*-----------------------------------------------------------------*/
4153 /* genMultOneLong : 32 bit multiplication */
4154 /*-----------------------------------------------------------------*/
4155 static void genMultOneLong (operand *left,
4160 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4161 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4163 /* (if two literals, the value is computed before)
4164 * if one literal, literal on the right */
4165 if (AOP_TYPE(left) == AOP_LIT){
4171 /* size is checked already == 4 */
4172 // size = AOP_SIZE(result);
4174 if (AOP_TYPE(right) == AOP_LIT) {
4175 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4176 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4177 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4178 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4180 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4181 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4182 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4183 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4186 pic16_genMult32X32_32(left, right,result);
4191 /*-----------------------------------------------------------------*/
4192 /* genMult - generates code for multiplication */
4193 /*-----------------------------------------------------------------*/
4194 static void genMult (iCode *ic)
4196 operand *left = IC_LEFT(ic);
4197 operand *right = IC_RIGHT(ic);
4198 operand *result= IC_RESULT(ic);
4201 /* assign the amsops */
4202 pic16_aopOp (left,ic,FALSE);
4203 pic16_aopOp (right,ic,FALSE);
4204 pic16_aopOp (result,ic,TRUE);
4206 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4208 /* special cases first *
4210 if (AOP_TYPE(left) == AOP_CRY
4211 && AOP_TYPE(right)== AOP_CRY) {
4212 genMultbits(left,right,result);
4216 /* if both are of size == 1 */
4217 if(AOP_SIZE(left) == 1
4218 && AOP_SIZE(right) == 1) {
4219 genMultOneByte(left,right,result);
4223 /* if both are of size == 2 */
4224 if(AOP_SIZE(left) == 2
4225 && AOP_SIZE(right) == 2) {
4226 genMultOneWord(left, right, result);
4230 /* if both are of size == 4 */
4231 if(AOP_SIZE(left) == 4
4232 && AOP_SIZE(right) == 4) {
4233 genMultOneLong(left, right, result);
4237 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4240 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4241 /* should have been converted to function call */
4245 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4246 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4247 pic16_freeAsmop(result,NULL,ic,TRUE);
4250 /*-----------------------------------------------------------------*/
4251 /* genDivbits :- division of bits */
4252 /*-----------------------------------------------------------------*/
4253 static void genDivbits (operand *left,
4260 /* the result must be bit */
4261 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4262 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4266 pic16_emitcode("div","ab");
4267 pic16_emitcode("rrc","a");
4268 pic16_aopPut(AOP(result),"c",0);
4271 /*-----------------------------------------------------------------*/
4272 /* genDivOneByte : 8 bit division */
4273 /*-----------------------------------------------------------------*/
4274 static void genDivOneByte (operand *left,
4278 sym_link *opetype = operandType(result);
4283 /* result = divident / divisor
4284 * - divident may be a register or a literal,
4285 * - divisor may be a register or a literal,
4286 * so there are 3 cases (literal / literal is optimized
4287 * by the front-end) to handle.
4288 * In addition we must handle signed and unsigned, which
4289 * result in 6 final different cases -- VR */
4293 size = AOP_SIZE(result) - 1;
4295 /* signed or unsigned */
4296 if (SPEC_USIGN(opetype)) {
4297 pCodeOp *pct1, /* count */
4300 symbol *label1, *label2, *label3;;
4303 /* unsigned is easy */
4305 pct1 = pic16_popGetTempReg(1);
4306 pct2 = pic16_popGetTempReg(1);
4307 pct3 = pic16_popGetTempReg(1);
4309 label1 = newiTempLabel(NULL);
4310 label2 = newiTempLabel(NULL);
4311 label3 = newiTempLabel(NULL);
4313 /* the following algorithm is extracted from divuint.c */
4315 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4316 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4318 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4320 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4322 pic16_emitpLabel(label1->key);
4325 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4329 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4333 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4335 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4336 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4338 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4339 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4340 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4342 pic16_emitpLabel( label3->key );
4343 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4344 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4348 pic16_emitpLabel(label2->key);
4349 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4350 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4351 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4353 /* result is in wreg */
4354 if(AOP_TYPE(result) != AOP_ACC)
4355 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4357 pic16_popReleaseTempReg( pct3, 1);
4358 pic16_popReleaseTempReg( pct2, 1);
4359 pic16_popReleaseTempReg( pct1, 1);
4364 /* signed is a little bit more difficult */
4366 /* save the signs of the operands */
4367 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4369 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4370 pic16_emitcode("push","acc"); /* save it on the stack */
4372 /* now sign adjust for both left & right */
4373 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4375 lbl = newiTempLabel(NULL);
4376 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4377 pic16_emitcode("cpl","a");
4378 pic16_emitcode("inc","a");
4379 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4380 pic16_emitcode("mov","b,a");
4382 /* sign adjust left side */
4383 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4386 lbl = newiTempLabel(NULL);
4387 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4388 pic16_emitcode("cpl","a");
4389 pic16_emitcode("inc","a");
4390 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4392 /* now the division */
4393 pic16_emitcode("div","ab");
4394 /* we are interested in the lower order
4396 pic16_emitcode("mov","b,a");
4397 lbl = newiTempLabel(NULL);
4398 pic16_emitcode("pop","acc");
4399 /* if there was an over flow we don't
4400 adjust the sign of the result */
4401 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4402 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4404 pic16_emitcode("clr","a");
4405 pic16_emitcode("subb","a,b");
4406 pic16_emitcode("mov","b,a");
4407 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4409 /* now we are done */
4410 pic16_aopPut(AOP(result),"b",0);
4412 pic16_emitcode("mov","c,b.7");
4413 pic16_emitcode("subb","a,acc");
4416 pic16_aopPut(AOP(result),"a",offset++);
4420 /*-----------------------------------------------------------------*/
4421 /* genDiv - generates code for division */
4422 /*-----------------------------------------------------------------*/
4423 static void genDiv (iCode *ic)
4425 operand *left = IC_LEFT(ic);
4426 operand *right = IC_RIGHT(ic);
4427 operand *result= IC_RESULT(ic);
4430 /* Division is a very lengthy algorithm, so it is better
4431 * to call support routines than inlining algorithm.
4432 * Division functions written here just in case someone
4433 * wants to inline and not use the support libraries -- VR */
4437 /* assign the amsops */
4438 pic16_aopOp (left,ic,FALSE);
4439 pic16_aopOp (right,ic,FALSE);
4440 pic16_aopOp (result,ic,TRUE);
4442 /* special cases first */
4444 if (AOP_TYPE(left) == AOP_CRY &&
4445 AOP_TYPE(right)== AOP_CRY) {
4446 genDivbits(left,right,result);
4450 /* if both are of size == 1 */
4451 if (AOP_SIZE(left) == 1 &&
4452 AOP_SIZE(right) == 1 ) {
4453 genDivOneByte(left,right,result);
4457 /* should have been converted to function call */
4460 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4461 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4462 pic16_freeAsmop(result,NULL,ic,TRUE);
4465 /*-----------------------------------------------------------------*/
4466 /* genModbits :- modulus of bits */
4467 /*-----------------------------------------------------------------*/
4468 static void genModbits (operand *left,
4476 werror(W_POSSBUG2, __FILE__, __LINE__);
4477 /* the result must be bit */
4478 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4479 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4483 pic16_emitcode("div","ab");
4484 pic16_emitcode("mov","a,b");
4485 pic16_emitcode("rrc","a");
4486 pic16_aopPut(AOP(result),"c",0);
4489 /*-----------------------------------------------------------------*/
4490 /* genModOneByte : 8 bit modulus */
4491 /*-----------------------------------------------------------------*/
4492 static void genModOneByte (operand *left,
4496 sym_link *opetype = operandType(result);
4501 werror(W_POSSBUG2, __FILE__, __LINE__);
4503 /* signed or unsigned */
4504 if (SPEC_USIGN(opetype)) {
4505 /* unsigned is easy */
4506 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4507 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4509 pic16_emitcode("div","ab");
4510 pic16_aopPut(AOP(result),"b",0);
4514 /* signed is a little bit more difficult */
4516 /* save the signs of the operands */
4517 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4520 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4521 pic16_emitcode("push","acc"); /* save it on the stack */
4523 /* now sign adjust for both left & right */
4524 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4527 lbl = newiTempLabel(NULL);
4528 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4529 pic16_emitcode("cpl","a");
4530 pic16_emitcode("inc","a");
4531 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4532 pic16_emitcode("mov","b,a");
4534 /* sign adjust left side */
4535 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4538 lbl = newiTempLabel(NULL);
4539 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4540 pic16_emitcode("cpl","a");
4541 pic16_emitcode("inc","a");
4542 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4544 /* now the multiplication */
4545 pic16_emitcode("div","ab");
4546 /* we are interested in the lower order
4548 lbl = newiTempLabel(NULL);
4549 pic16_emitcode("pop","acc");
4550 /* if there was an over flow we don't
4551 adjust the sign of the result */
4552 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4553 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4555 pic16_emitcode("clr","a");
4556 pic16_emitcode("subb","a,b");
4557 pic16_emitcode("mov","b,a");
4558 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4560 /* now we are done */
4561 pic16_aopPut(AOP(result),"b",0);
4565 /*-----------------------------------------------------------------*/
4566 /* genMod - generates code for division */
4567 /*-----------------------------------------------------------------*/
4568 static void genMod (iCode *ic)
4570 operand *left = IC_LEFT(ic);
4571 operand *right = IC_RIGHT(ic);
4572 operand *result= IC_RESULT(ic);
4576 /* assign the amsops */
4577 pic16_aopOp (left,ic,FALSE);
4578 pic16_aopOp (right,ic,FALSE);
4579 pic16_aopOp (result,ic,TRUE);
4581 /* special cases first */
4583 if (AOP_TYPE(left) == AOP_CRY &&
4584 AOP_TYPE(right)== AOP_CRY) {
4585 genModbits(left,right,result);
4589 /* if both are of size == 1 */
4590 if (AOP_SIZE(left) == 1 &&
4591 AOP_SIZE(right) == 1 ) {
4592 genModOneByte(left,right,result);
4596 /* should have been converted to function call */
4600 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4601 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4602 pic16_freeAsmop(result,NULL,ic,TRUE);
4605 /*-----------------------------------------------------------------*/
4606 /* genIfxJump :- will create a jump depending on the ifx */
4607 /*-----------------------------------------------------------------*/
4609 note: May need to add parameter to indicate when a variable is in bit space.
4611 static void genIfxJump (iCode *ic, char *jval)
4615 /* if true label then we jump if condition
4617 if ( IC_TRUE(ic) ) {
4619 if(strcmp(jval,"a") == 0)
4621 else if (strcmp(jval,"c") == 0)
4624 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4625 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4628 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4629 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4633 /* false label is present */
4634 if(strcmp(jval,"a") == 0)
4636 else if (strcmp(jval,"c") == 0)
4639 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4640 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4643 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4644 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4649 /* mark the icode as generated */
4653 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4657 /* if true label then we jump if condition
4659 if ( IC_TRUE(ic) ) {
4660 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4661 pic16_emitpcode(POC_BTFSC, jop);
4663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4664 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4667 /* false label is present */
4668 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4669 pic16_emitpcode(POC_BTFSS, jop);
4671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4672 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4676 /* mark the icode as generated */
4683 /*-----------------------------------------------------------------*/
4685 /*-----------------------------------------------------------------*/
4686 static void genSkip(iCode *ifx,int status_bit)
4688 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4692 if ( IC_TRUE(ifx) ) {
4693 switch(status_bit) {
4708 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4709 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4713 switch(status_bit) {
4727 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4728 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4735 /*-----------------------------------------------------------------*/
4737 /*-----------------------------------------------------------------*/
4738 static void genSkipc(resolvedIfx *rifx)
4740 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4750 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4751 rifx->generated = 1;
4754 #if !(USE_SIMPLE_GENCMP)
4755 /*-----------------------------------------------------------------*/
4757 /*-----------------------------------------------------------------*/
4758 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4760 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4765 if( (rifx->condition ^ invert_condition) & 1)
4770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4771 rifx->generated = 1;
4776 /*-----------------------------------------------------------------*/
4778 /*-----------------------------------------------------------------*/
4779 static void genSkipz(iCode *ifx, int condition)
4790 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4792 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4795 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4797 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4802 #if !(USE_SIMPLE_GENCMP)
4803 /*-----------------------------------------------------------------*/
4805 /*-----------------------------------------------------------------*/
4806 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4812 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4814 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4817 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4818 rifx->generated = 1;
4823 /*-----------------------------------------------------------------*/
4824 /* genChkZeroes :- greater or less than comparison */
4825 /* For each byte in a literal that is zero, inclusive or the */
4826 /* the corresponding byte in the operand with W */
4827 /* returns true if any of the bytes are zero */
4828 /*-----------------------------------------------------------------*/
4829 static int genChkZeroes(operand *op, int lit, int size)
4836 i = (lit >> (size*8)) & 0xff;
4840 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4842 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4851 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4852 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4854 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4855 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4857 /*-----------------------------------------------------------------*/
4858 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4859 /* aop (if it's NOT a literal) or from lit (if */
4860 /* aop is a literal) */
4861 /*-----------------------------------------------------------------*/
4862 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4863 if (aop->type == AOP_LIT) {
4864 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4866 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4870 /*-----------------------------------------------------------------*/
4871 /* genCmp :- greater or less than comparison */
4872 /*-----------------------------------------------------------------*/
4874 #if USE_SIMPLE_GENCMP
4876 /* genCmp performs a left < right comparison, stores
4877 * the outcome in result (if != NULL) and generates
4878 * control flow code for the ifx (if != NULL).
4880 * This version leaves in sequences like
4881 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4882 * which should be optmized by the peephole
4883 * optimizer - RN 2005-01-01 */
4884 static void genCmp (operand *left,operand *right,
4885 operand *result, iCode *ifx, int sign)
4898 assert (AOP_SIZE(left) == AOP_SIZE(right));
4899 assert (left && right);
4901 size = AOP_SIZE(right) - 1;
4902 mask = (0x100UL << (size*8)) - 1;
4903 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4908 resolveIfx (&rIfx, ifx);
4910 /**********************************************************************
4911 * handle bits - bit compares are promoted to int compares seemingly! *
4912 **********************************************************************/
4914 // THIS IS COMPLETELY UNTESTED!
4915 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4916 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4917 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4918 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4921 // 1 < {0,1} is false --> clear C by skipping the next instruction
4922 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4923 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4924 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4925 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4926 emitCLRC; // only skipped for left=0 && right=1
4928 goto correct_result_in_carry;
4932 /*************************************************
4933 * make sure that left is register (or the like) *
4934 *************************************************/
4935 if (!isAOP_REGlike(left)) {
4936 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4937 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4939 assert (isAOP_LIT(left));
4940 assert (isAOP_REGlike(right));
4941 // swap left and right
4942 // left < right <==> right > left <==> (right >= left + 1)
4943 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4945 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4946 // MAXVALUE < right? always false
4947 if (performedLt) emitCLRC; else emitSETC;
4948 goto correct_result_in_carry;
4951 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4952 // that's we handled it above.
4959 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4960 } else if (isAOP_LIT(right)) {
4961 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4964 assert (isAOP_REGlike(left)); // left must be register or the like
4965 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4967 /*************************************************
4968 * special cases go here *
4969 *************************************************/
4971 if (isAOP_LIT(right)) {
4973 // unsigned comparison to a literal
4974 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4975 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4978 // unsigned left < 0? always false
4979 if (performedLt) emitCLRC; else emitSETC;
4980 goto correct_result_in_carry;
4983 // signed comparison to a literal
4984 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4985 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4987 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4988 // signed left < 0x80000000? always false
4989 if (performedLt) emitCLRC; else emitSETC;
4990 goto correct_result_in_carry;
4991 } else if (lit == 0) {
4992 // compare left < 0; set CARRY if SIGNBIT(left) is set
4993 if (performedLt) emitSETC; else emitCLRC;
4994 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4995 if (performedLt) emitCLRC; else emitSETC;
4996 goto correct_result_in_carry;
4999 } // right is literal
5001 /*************************************************
5002 * perform a general case comparison *
5003 * make sure we get CARRY==1 <==> left >= right *
5004 *************************************************/
5005 // compare most significant bytes
5006 //DEBUGpc ("comparing bytes at offset %d", size);
5008 // unsigned comparison
5009 mov2w_regOrLit (AOP(right), lit, size);
5010 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5012 // signed comparison
5013 // (add 2^n to both operands then perform an unsigned comparison)
5014 if (isAOP_LIT(right)) {
5015 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5016 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5018 if (litbyte == 0x80) {
5019 // left >= 0x80 -- always true, but more bytes to come
5020 pic16_mov2w (AOP(left), size);
5021 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5024 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5025 pic16_mov2w (AOP(left), size);
5026 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5027 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5030 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5031 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5032 pic16_mov2w (AOP(left), size);
5033 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5034 pic16_emitpcode (POC_MOVWF, pctemp);
5035 pic16_mov2w (AOP(right), size);
5036 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5037 pic16_emitpcode (POC_SUBFW, pctemp);
5038 //pic16_popReleaseTempReg(pctemp, 1);
5042 // compare remaining bytes (treat as unsigned case from above)
5043 templbl = newiTempLabel ( NULL );
5046 //DEBUGpc ("comparing bytes at offset %d", offs);
5047 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5048 mov2w_regOrLit (AOP(right), lit, offs);
5049 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5051 pic16_emitpLabel (templbl->key);
5052 goto result_in_carry;
5056 /****************************************************
5057 * now CARRY contains the result of the comparison: *
5058 * SUBWF sets CARRY iff *
5059 * F-W >= 0 <==> F >= W <==> !(F < W) *
5061 ****************************************************/
5064 if (result && AOP_TYPE(result) != AOP_CRY) {
5065 // value will be stored
5068 // value wil only be used in the following genSkipc()
5069 rIfx.condition ^= 1;
5073 correct_result_in_carry:
5075 // assign result to variable (if neccessary)
5076 if (result && AOP_TYPE(result) != AOP_CRY) {
5077 //DEBUGpc ("assign result");
5078 size = AOP_SIZE(result);
5080 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5082 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5085 // perform conditional jump
5086 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5088 //DEBUGpc ("generate control flow");
5089 rIfx.condition ^= 1;
5098 static void genCmp (operand *left,operand *right,
5099 operand *result, iCode *ifx, int sign)
5101 int size; //, offset = 0 ;
5102 unsigned long lit = 0L,i = 0;
5103 resolvedIfx rFalseIfx;
5104 // resolvedIfx rTrueIfx;
5106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5109 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5110 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5116 resolveIfx(&rFalseIfx,ifx);
5117 truelbl = newiTempLabel(NULL);
5118 size = max(AOP_SIZE(left),AOP_SIZE(right));
5120 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5124 /* if literal is on the right then swap with left */
5125 if ((AOP_TYPE(right) == AOP_LIT)) {
5126 operand *tmp = right ;
5127 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5128 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5131 lit = (lit - 1) & mask;
5134 rFalseIfx.condition ^= 1;
5137 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5138 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5142 //if(IC_TRUE(ifx) == NULL)
5143 /* if left & right are bit variables */
5144 if (AOP_TYPE(left) == AOP_CRY &&
5145 AOP_TYPE(right) == AOP_CRY ) {
5146 assert (0 && "bit variables used in genCmp");
5147 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5148 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5150 /* subtract right from left if at the
5151 end the carry flag is set then we know that
5152 left is greater than right */
5154 symbol *lbl = newiTempLabel(NULL);
5157 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5158 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5162 if(AOP_TYPE(right) == AOP_LIT) {
5164 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5166 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5173 genSkipCond(&rFalseIfx,left,size-1,7);
5175 /* no need to compare to 0...*/
5176 /* NOTE: this is a de-generate compare that most certainly
5177 * creates some dead code. */
5178 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5180 if(ifx) ifx->generated = 1;
5187 //i = (lit >> (size*8)) & 0xff;
5188 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5190 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5192 i = ((0-lit) & 0xff);
5195 /* lit is 0x7f, all signed chars are less than
5196 * this except for 0x7f itself */
5197 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5198 genSkipz2(&rFalseIfx,0);
5200 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5201 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5202 genSkipc(&rFalseIfx);
5207 genSkipz2(&rFalseIfx,1);
5209 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5210 genSkipc(&rFalseIfx);
5214 if(ifx) ifx->generated = 1;
5218 /* chars are out of the way. now do ints and longs */
5221 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5228 genSkipCond(&rFalseIfx,left,size,7);
5229 if(ifx) ifx->generated = 1;
5234 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5236 //rFalseIfx.condition ^= 1;
5237 //genSkipCond(&rFalseIfx,left,size,7);
5238 //rFalseIfx.condition ^= 1;
5240 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5241 if(rFalseIfx.condition)
5242 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5244 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5246 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5247 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5248 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5251 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5253 if(rFalseIfx.condition) {
5255 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5261 genSkipc(&rFalseIfx);
5262 pic16_emitpLabel(truelbl->key);
5263 if(ifx) ifx->generated = 1;
5270 if( (lit & 0xff) == 0) {
5271 /* lower byte is zero */
5272 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5273 i = ((lit >> 8) & 0xff) ^0x80;
5274 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5275 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5276 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5277 genSkipc(&rFalseIfx);
5280 if(ifx) ifx->generated = 1;
5285 /* Special cases for signed longs */
5286 if( (lit & 0xffffff) == 0) {
5287 /* lower byte is zero */
5288 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5289 i = ((lit >> 8*3) & 0xff) ^0x80;
5290 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5292 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5293 genSkipc(&rFalseIfx);
5296 if(ifx) ifx->generated = 1;
5304 if(lit & (0x80 << (size*8))) {
5305 /* lit is negative */
5306 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5308 //genSkipCond(&rFalseIfx,left,size,7);
5310 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5312 if(rFalseIfx.condition)
5313 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5315 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5319 /* lit is positive */
5320 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5321 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5322 if(rFalseIfx.condition)
5323 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5325 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5330 This works, but is only good for ints.
5331 It also requires a "known zero" register.
5332 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5333 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5334 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5336 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5337 genSkipc(&rFalseIfx);
5339 pic16_emitpLabel(truelbl->key);
5340 if(ifx) ifx->generated = 1;
5344 /* There are no more special cases, so perform a general compare */
5346 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5347 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5351 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5353 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5355 //rFalseIfx.condition ^= 1;
5356 genSkipc(&rFalseIfx);
5358 pic16_emitpLabel(truelbl->key);
5360 if(ifx) ifx->generated = 1;
5367 /* sign is out of the way. So now do an unsigned compare */
5368 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5371 /* General case - compare to an unsigned literal on the right.*/
5373 i = (lit >> (size*8)) & 0xff;
5374 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5375 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5377 i = (lit >> (size*8)) & 0xff;
5380 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5382 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5384 /* this byte of the lit is zero,
5385 *if it's not the last then OR in the variable */
5387 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5392 pic16_emitpLabel(lbl->key);
5393 // pic16_emitpLabel(truelbl->key);
5394 //if(emitFinalCheck)
5395 genSkipc(&rFalseIfx);
5397 pic16_emitpLabel(truelbl->key);
5399 if(ifx) ifx->generated = 1;
5406 if(AOP_TYPE(left) == AOP_LIT) {
5407 //symbol *lbl = newiTempLabel(NULL);
5409 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5412 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5415 if((lit == 0) && (sign == 0)){
5418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5420 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5422 genSkipz2(&rFalseIfx,0);
5423 if(ifx) ifx->generated = 1;
5430 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5431 /* degenerate compare can never be true */
5432 if(rFalseIfx.condition == 0)
5433 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5435 if(ifx) ifx->generated = 1;
5440 /* signed comparisons to a literal byte */
5442 int lp1 = (lit+1) & 0xff;
5444 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5447 rFalseIfx.condition ^= 1;
5448 genSkipCond(&rFalseIfx,right,0,7);
5451 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5452 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5453 genSkipz2(&rFalseIfx,1);
5456 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5457 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5458 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5459 rFalseIfx.condition ^= 1;
5460 genSkipc(&rFalseIfx);
5464 /* unsigned comparisons to a literal byte */
5466 switch(lit & 0xff ) {
5468 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5469 genSkipz2(&rFalseIfx,0);
5472 rFalseIfx.condition ^= 1;
5473 genSkipCond(&rFalseIfx,right,0,7);
5477 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5478 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5480 rFalseIfx.condition ^= 1;
5481 if (AOP_TYPE(result) == AOP_CRY)
5482 genSkipc(&rFalseIfx);
5484 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5485 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5491 if(ifx) ifx->generated = 1;
5492 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5498 /* Size is greater than 1 */
5506 /* this means lit = 0xffffffff, or -1 */
5509 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5510 rFalseIfx.condition ^= 1;
5511 genSkipCond(&rFalseIfx,right,size,7);
5512 if(ifx) ifx->generated = 1;
5514 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5523 if(rFalseIfx.condition) {
5524 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5525 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5528 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5530 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5534 if(rFalseIfx.condition) {
5535 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5536 pic16_emitpLabel(truelbl->key);
5538 rFalseIfx.condition ^= 1;
5539 genSkipCond(&rFalseIfx,right,s,7);
5542 if(ifx) ifx->generated = 1;
5544 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5550 if((size == 1) && (0 == (lp1&0xff))) {
5551 /* lower byte of signed word is zero */
5552 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5553 i = ((lp1 >> 8) & 0xff) ^0x80;
5554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5555 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5556 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5558 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5560 if(ifx) ifx->generated = 1;
5563 rFalseIfx.condition ^= 1;
5564 genSkipc(&rFalseIfx);
5565 if(ifx) ifx->generated = 1;
5571 if(lit & (0x80 << (size*8))) {
5572 /* Lit is less than zero */
5573 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5574 //rFalseIfx.condition ^= 1;
5575 //genSkipCond(&rFalseIfx,left,size,7);
5576 //rFalseIfx.condition ^= 1;
5577 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5578 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5580 if(rFalseIfx.condition)
5581 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5583 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5587 /* Lit is greater than or equal to zero */
5588 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5589 //rFalseIfx.condition ^= 1;
5590 //genSkipCond(&rFalseIfx,right,size,7);
5591 //rFalseIfx.condition ^= 1;
5593 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5594 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5596 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5597 if(rFalseIfx.condition)
5598 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5600 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5604 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5605 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5609 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5611 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5613 rFalseIfx.condition ^= 1;
5614 //rFalseIfx.condition = 1;
5615 genSkipc(&rFalseIfx);
5617 pic16_emitpLabel(truelbl->key);
5619 if(ifx) ifx->generated = 1;
5622 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5629 /* compare word or long to an unsigned literal on the right.*/
5634 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5637 break; /* handled above */
5640 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5642 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5643 genSkipz2(&rFalseIfx,0);
5647 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5649 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5652 if(rFalseIfx.condition)
5653 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5655 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5658 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5659 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5661 rFalseIfx.condition ^= 1;
5662 genSkipc(&rFalseIfx);
5665 pic16_emitpLabel(truelbl->key);
5667 if(ifx) ifx->generated = 1;
5669 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5677 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5678 i = (lit >> (size*8)) & 0xff;
5680 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5681 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5684 i = (lit >> (size*8)) & 0xff;
5687 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5689 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5691 /* this byte of the lit is zero,
5692 * if it's not the last then OR in the variable */
5694 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5699 pic16_emitpLabel(lbl->key);
5701 rFalseIfx.condition ^= 1;
5703 genSkipc(&rFalseIfx);
5707 pic16_emitpLabel(truelbl->key);
5708 if(ifx) ifx->generated = 1;
5710 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5716 /* Compare two variables */
5718 DEBUGpic16_emitcode(";sign","%d",sign);
5722 /* Sigh. thus sucks... */
5726 pctemp = pic16_popGetTempReg(1);
5727 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5728 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5729 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5730 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5731 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5732 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5733 pic16_popReleaseTempReg(pctemp, 1);
5735 /* Signed char comparison */
5736 /* Special thanks to Nikolai Golovchenko for this snippet */
5737 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5738 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5739 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5740 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5741 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5742 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5744 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5745 genSkipc(&rFalseIfx);
5747 if(ifx) ifx->generated = 1;
5749 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5762 /* The rest of the bytes of a multi-byte compare */
5766 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5769 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5770 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5775 pic16_emitpLabel(lbl->key);
5777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5778 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5779 (AOP_TYPE(result) == AOP_REG)) {
5780 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5781 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5783 genSkipc(&rFalseIfx);
5785 //genSkipc(&rFalseIfx);
5786 if(ifx) ifx->generated = 1;
5789 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5797 if ((AOP_TYPE(result) != AOP_CRY)
5798 && AOP_SIZE(result)) {
5799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5801 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5803 pic16_outBitC(result);
5805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5806 /* if the result is used in the next
5807 ifx conditional branch then generate
5808 code a little differently */
5810 genIfxJump (ifx,"c");
5812 pic16_outBitC(result);
5813 /* leave the result in acc */
5818 #else /* old version of genCmp() */ /* } else { */
5820 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5821 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5822 operand *result, int offset, int invert_op)
5826 /* check condition, > or < ?? */
5827 if(rIfx->condition != 0)invert_op ^= 1;
5829 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5831 if(!ifx)invert_op ^= 1;
5833 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5834 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5837 if(!invert_op)return POC_CPFSGT;
5838 else return POC_CPFSLT;
5841 static int compareAopfirstpass=1;
5843 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5844 operand *oper, int offset, operand *result,
5845 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5851 /* invert if there is a result to be loaded, in order to fit,
5852 * SETC/CLRC sequence */
5853 if(AOP_SIZE(result))invert_op ^= 1;
5855 // if(sign && !offset)invert_op ^= 1;
5857 // if(sign)invert_op ^= 1;
5859 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5861 if(AOP_SIZE(result) && compareAopfirstpass) {
5864 pic16_emitpcode(POC_SETF, pcop2);
5869 pic16_emitpcode(POC_CLRF, pcop2);
5875 compareAopfirstpass = 0;
5877 /* there is a bug when comparing operands with size > 1,
5878 * because higher bytes can be equal and test should be performed
5879 * to the next lower byte, current algorithm, considers operands
5880 * inequal in these cases! -- VR 20041107 */
5884 pic16_emitpcode(op, pcop);
5886 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5889 if((!sign || !offset) && AOP_SIZE(result)) {
5892 pic16_emitpcode(POC_CLRF, pcop2);
5897 pic16_emitpcode(POC_SETF, pcop2);
5902 /* don't emit final branch (offset == 0) */
5906 pic16_emitpcode(POC_RRCF, pcop2);
5908 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5911 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5912 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5913 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5915 truelbl = newiTempLabel( NULL );
5916 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5917 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5918 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5920 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5921 pic16_emitpLabel(truelbl->key);
5923 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5932 static void genCmp (operand *left, operand *right,
5933 operand *result, iCode *ifx, int sign)
5937 resolvedIfx rFalseIfx;
5938 symbol *falselbl, *tlbl;
5942 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5944 resolveIfx(&rFalseIfx, ifx);
5945 size = max(AOP_SIZE(left), AOP_SIZE(right));
5947 /* if left & right are bit variables */
5948 if(AOP_TYPE(left) == AOP_CRY
5949 && AOP_TYPE(right) == AOP_CRY ) {
5951 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5954 werror(W_POSSBUG2, __FILE__, __LINE__);
5958 /* if literal is on the right then swap with left */
5959 if((AOP_TYPE(right) == AOP_LIT)) {
5960 operand *tmp = right ;
5961 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5963 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5965 // lit = (lit - 1) & mask;
5968 rFalseIfx.condition ^= 1; /* reverse compare */
5970 if ((AOP_TYPE(left) == AOP_LIT)) {
5971 /* float compares are handled by support functions */
5972 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5975 /* actual comparing algorithm */
5976 // size = AOP_SIZE( right );
5978 falselbl = newiTempLabel( NULL );
5979 if(AOP_TYPE(left) == AOP_LIT) {
5980 /* compare to literal */
5981 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5984 pCodeOp *pct, *pct2;
5987 /* signed compare */
5988 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5990 pct = pic16_popCopyReg(&pic16_pc_prodl);
5991 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5992 tlbl = newiTempLabel( NULL );
5994 /* first compare signs:
5995 * a. if both are positive, compare just like unsigned
5996 * b. if both are negative, invert cmpop, compare just like unsigned
5997 * c. if different signs, determine the result directly */
6003 tlbl1 = newiTempLabel( NULL );
6004 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6008 /* literal is zero or positive:
6009 * a. if carry is zero, too, continue compare,
6010 * b. if carry is set, then continue depending on cmpop ^ condition:
6011 * 1. '<' return false (literal < variable),
6012 * 2. '>' return true (literal > variable) */
6013 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6014 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6017 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6018 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6022 /* literal is negative:
6023 * a. if carry is set, too, continue compare,
6024 * b. if carry is zero, then continue depending on cmpop ^ condition:
6025 * 1. '<' return true (literal < variable),
6026 * 2. '>' return false (literal > variable) */
6027 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6028 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6030 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6031 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6036 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6038 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6039 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6044 pic16_emitpLabel( tlbl1->key );
6047 compareAopfirstpass=1;
6048 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6049 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6050 // pic16_emitpcode(POC_MOVWF, pct);
6052 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6053 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6054 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6055 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6059 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6060 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6061 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6062 // pic16_emitpcode(POC_MOVWF, pct);
6064 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6066 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6067 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6068 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6072 if(ifx)ifx->generated = 1;
6074 if(AOP_SIZE(result)) {
6075 pic16_emitpLabel(tlbl->key);
6076 pic16_emitpLabel(falselbl->key);
6077 pic16_outBitOp( result, pct2 );
6079 pic16_emitpLabel(tlbl->key);
6084 /* unsigned compare */
6085 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6087 compareAopfirstpass=1;
6090 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6091 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6095 if(ifx)ifx->generated = 1;
6098 if(AOP_SIZE(result)) {
6099 pic16_emitpLabel(falselbl->key);
6100 pic16_outBitC( result );
6105 /* compare registers */
6106 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6110 pCodeOp *pct, *pct2;
6112 /* signed compare */
6113 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6115 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6116 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6117 tlbl = newiTempLabel( NULL );
6119 compareAopfirstpass=1;
6122 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6123 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6124 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6125 pic16_emitpcode(POC_MOVWF, pct);
6127 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6128 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6129 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6131 /* WREG already holds left + 0x80 */
6132 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6135 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6136 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6137 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6138 pic16_emitpcode(POC_MOVWF, pct);
6140 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6141 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6142 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6144 /* WREG already holds left + 0x80 */
6145 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6149 if(ifx)ifx->generated = 1;
6151 if(AOP_SIZE(result)) {
6152 pic16_emitpLabel(tlbl->key);
6153 pic16_emitpLabel(falselbl->key);
6154 pic16_outBitOp( result, pct2 );
6156 pic16_emitpLabel(tlbl->key);
6160 /* unsigned compare */
6161 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6163 compareAopfirstpass=1;
6166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6167 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6171 if(ifx)ifx->generated = 1;
6172 if(AOP_SIZE(result)) {
6174 pic16_emitpLabel(falselbl->key);
6175 pic16_outBitC( result );
6182 #else /* } else { */
6184 /* new version of genCmp -- VR 20041012 */
6185 static void genCmp (operand *left,operand *right,
6186 operand *result, iCode *ifx, int sign)
6188 int size; //, offset = 0 ;
6189 unsigned long lit = 0L,i = 0;
6190 resolvedIfx rFalseIfx;
6191 int willCheckCarry=0;
6192 // resolvedIfx rTrueIfx;
6198 * subtract right from left if at the end the carry flag is set then we
6199 * know that left is greater than right */
6201 resolveIfx(&rFalseIfx,ifx);
6202 truelbl = newiTempLabel(NULL);
6203 size = max(AOP_SIZE(left),AOP_SIZE(right));
6205 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6207 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6208 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6211 /* if literal is on the right then swap with left */
6212 if ((AOP_TYPE(right) == AOP_LIT)) {
6213 operand *tmp = right ;
6214 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6216 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6218 // lit = (lit - 1) & mask;
6221 rFalseIfx.condition ^= 1; /* reverse compare */
6223 if ((AOP_TYPE(left) == AOP_LIT)) {
6224 /* float compares are handled by support functions */
6225 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6229 //if(IC_TRUE(ifx) == NULL)
6230 /* if left & right are bit variables */
6231 if (AOP_TYPE(left) == AOP_CRY &&
6232 AOP_TYPE(right) == AOP_CRY ) {
6234 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6235 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6238 symbol *lbl = newiTempLabel(NULL);
6240 if(AOP_TYPE(left) == AOP_LIT) {
6241 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6243 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6245 else willCheckCarry = 0;
6248 if((lit == 0) && (sign == 0)) {
6249 /* unsigned compare to 0 */
6250 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6253 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6255 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6257 genSkipz2(&rFalseIfx,0);
6258 if(ifx)ifx->generated = 1;
6265 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6266 /* degenerate compare can never be true */
6267 if(rFalseIfx.condition == 0)
6268 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6270 if(ifx) ifx->generated = 1;
6275 /* signed comparisons to a literal byte */
6276 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6278 int lp1 = (lit+1) & 0xff;
6280 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6283 rFalseIfx.condition ^= 1;
6284 genSkipCond(&rFalseIfx,right,0,7);
6287 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6288 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6289 genSkipz2(&rFalseIfx,1);
6292 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6294 if(rFalseIfx.condition)
6295 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6297 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6299 if(willCheckCarry) {
6300 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6301 else { emitSETC; emitCLRC; }
6304 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6307 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6308 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6309 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6310 rFalseIfx.condition ^= 1;
6311 genSkipc(&rFalseIfx);
6316 /* unsigned comparisons to a literal byte */
6317 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6319 switch(lit & 0xff ) {
6322 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6323 genSkipz2(&rFalseIfx,0);
6326 rFalseIfx.condition ^= 1;
6327 genSkipCond(&rFalseIfx,right,0,7);
6330 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6331 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6333 rFalseIfx.condition ^= 1;
6334 if (AOP_TYPE(result) == AOP_CRY)
6335 genSkipc(&rFalseIfx);
6337 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6338 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6344 if(ifx) ifx->generated = 1;
6345 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6351 /* Size is greater than 1 */
6359 /* this means lit = 0xffffffff, or -1 */
6362 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6363 rFalseIfx.condition ^= 1;
6364 genSkipCond(&rFalseIfx,right,size,7);
6365 if(ifx) ifx->generated = 1;
6372 if(rFalseIfx.condition) {
6373 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6374 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6377 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6379 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6383 if(rFalseIfx.condition) {
6384 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6385 pic16_emitpLabel(truelbl->key);
6387 rFalseIfx.condition ^= 1;
6388 genSkipCond(&rFalseIfx,right,s,7);
6391 if(ifx) ifx->generated = 1;
6395 if((size == 1) && (0 == (lp1&0xff))) {
6396 /* lower byte of signed word is zero */
6397 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6398 i = ((lp1 >> 8) & 0xff) ^0x80;
6399 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6400 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6401 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6402 rFalseIfx.condition ^= 1;
6403 genSkipc(&rFalseIfx);
6406 if(ifx) ifx->generated = 1;
6410 if(lit & (0x80 << (size*8))) {
6411 /* Lit is less than zero */
6412 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6413 //rFalseIfx.condition ^= 1;
6414 //genSkipCond(&rFalseIfx,left,size,7);
6415 //rFalseIfx.condition ^= 1;
6416 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6417 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6419 if(rFalseIfx.condition)
6420 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6422 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6426 /* Lit is greater than or equal to zero */
6427 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6428 //rFalseIfx.condition ^= 1;
6429 //genSkipCond(&rFalseIfx,right,size,7);
6430 //rFalseIfx.condition ^= 1;
6432 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6433 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6435 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6436 if(rFalseIfx.condition)
6437 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6439 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6444 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6445 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6449 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6451 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6453 rFalseIfx.condition ^= 1;
6454 //rFalseIfx.condition = 1;
6455 genSkipc(&rFalseIfx);
6457 pic16_emitpLabel(truelbl->key);
6459 if(ifx) ifx->generated = 1;
6464 /* compare word or long to an unsigned literal on the right.*/
6469 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6472 break; /* handled above */
6475 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6477 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6478 genSkipz2(&rFalseIfx,0);
6482 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6484 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6487 if(rFalseIfx.condition)
6488 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6490 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6493 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6494 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6496 rFalseIfx.condition ^= 1;
6497 genSkipc(&rFalseIfx);
6500 pic16_emitpLabel(truelbl->key);
6502 if(ifx) ifx->generated = 1;
6508 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6509 i = (lit >> (size*8)) & 0xff;
6511 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6512 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6515 i = (lit >> (size*8)) & 0xff;
6518 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6520 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6522 /* this byte of the lit is zero,
6523 * if it's not the last then OR in the variable */
6525 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6530 pic16_emitpLabel(lbl->key);
6532 rFalseIfx.condition ^= 1;
6534 genSkipc(&rFalseIfx);
6538 pic16_emitpLabel(truelbl->key);
6539 if(ifx) ifx->generated = 1;
6543 /* Compare two variables */
6545 DEBUGpic16_emitcode(";sign","%d",sign);
6549 /* Sigh. thus sucks... */
6553 pctemp = pic16_popGetTempReg(1);
6554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6555 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6556 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6557 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6558 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6559 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6560 pic16_popReleaseTempReg(pctemp, 1);
6562 /* Signed char comparison */
6563 /* Special thanks to Nikolai Golovchenko for this snippet */
6564 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6565 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6566 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6567 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6568 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6569 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6572 genSkipc(&rFalseIfx);
6574 if(ifx) ifx->generated = 1;
6580 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6581 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6585 /* The rest of the bytes of a multi-byte compare */
6589 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6592 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6593 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6598 pic16_emitpLabel(lbl->key);
6600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6601 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6602 (AOP_TYPE(result) == AOP_REG)) {
6603 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6604 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6606 genSkipc(&rFalseIfx);
6608 //genSkipc(&rFalseIfx);
6609 if(ifx) ifx->generated = 1;
6616 if ((AOP_TYPE(result) != AOP_CRY)
6617 && AOP_SIZE(result)) {
6618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6620 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6622 pic16_outBitC(result);
6624 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6625 /* if the result is used in the next
6626 ifx conditional branch then generate
6627 code a little differently */
6629 genIfxJump (ifx,"c");
6631 pic16_outBitC(result);
6632 /* leave the result in acc */
6643 /*-----------------------------------------------------------------*/
6644 /* genCmpGt :- greater than comparison */
6645 /*-----------------------------------------------------------------*/
6646 static void genCmpGt (iCode *ic, iCode *ifx)
6648 operand *left, *right, *result;
6649 sym_link *letype , *retype;
6655 right= IC_RIGHT(ic);
6656 result = IC_RESULT(ic);
6658 letype = getSpec(operandType(left));
6659 retype =getSpec(operandType(right));
6660 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6661 /* assign the amsops */
6662 pic16_aopOp (left,ic,FALSE);
6663 pic16_aopOp (right,ic,FALSE);
6664 pic16_aopOp (result,ic,TRUE);
6666 genCmp(right, left, result, ifx, sign);
6668 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6669 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6670 pic16_freeAsmop(result,NULL,ic,TRUE);
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpLt - less than comparisons */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpLt (iCode *ic, iCode *ifx)
6678 operand *left, *right, *result;
6679 sym_link *letype , *retype;
6685 right= IC_RIGHT(ic);
6686 result = IC_RESULT(ic);
6688 letype = getSpec(operandType(left));
6689 retype =getSpec(operandType(right));
6690 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6692 /* assign the amsops */
6693 pic16_aopOp (left,ic,FALSE);
6694 pic16_aopOp (right,ic,FALSE);
6695 pic16_aopOp (result,ic,TRUE);
6697 genCmp(left, right, result, ifx, sign);
6699 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6700 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6701 pic16_freeAsmop(result,NULL,ic,TRUE);
6706 // FIXME reenable literal optimisation when the pic16 port is stable
6708 /*-----------------------------------------------------------------*/
6709 /* genc16bit2lit - compare a 16 bit value to a literal */
6710 /*-----------------------------------------------------------------*/
6711 static void genc16bit2lit(operand *op, int lit, int offset)
6715 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6716 if( (lit&0xff) == 0)
6721 switch( BYTEofLONG(lit,i)) {
6723 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6726 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6729 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6732 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6733 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6738 switch( BYTEofLONG(lit,i)) {
6740 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6744 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6748 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6751 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6753 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6762 /*-----------------------------------------------------------------*/
6763 /* gencjneshort - compare and jump if not equal */
6764 /*-----------------------------------------------------------------*/
6765 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6767 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6769 int res_offset = 0; /* the result may be a different size then left or right */
6770 int res_size = AOP_SIZE(result);
6772 symbol *lbl, *lbl_done;
6774 unsigned long lit = 0L;
6775 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6778 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6780 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6781 resolveIfx(&rIfx,ifx);
6782 lbl = newiTempLabel(NULL);
6783 lbl_done = newiTempLabel(NULL);
6786 /* if the left side is a literal or
6787 if the right is in a pointer register and left
6789 if ((AOP_TYPE(left) == AOP_LIT) ||
6790 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6795 if(AOP_TYPE(right) == AOP_LIT)
6796 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6798 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6799 preserve_result = 1;
6801 if(result && !preserve_result)
6804 for(i = 0; i < AOP_SIZE(result); i++)
6805 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6809 /* if the right side is a literal then anything goes */
6810 if (AOP_TYPE(right) == AOP_LIT &&
6811 AOP_TYPE(left) != AOP_DIR ) {
6814 genc16bit2lit(left, lit, 0);
6816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6822 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6823 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6825 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6829 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6831 if(res_offset < res_size-1)
6839 /* if the right side is in a register or in direct space or
6840 if the left is a pointer register & right is not */
6841 else if (AOP_TYPE(right) == AOP_REG ||
6842 AOP_TYPE(right) == AOP_DIR ||
6843 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6844 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6845 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6846 int lbl_key = lbl->key;
6849 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6850 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6852 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6853 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6854 __FUNCTION__,__LINE__);
6858 /* switch(size) { */
6860 /* genc16bit2lit(left, lit, 0); */
6862 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6867 if((AOP_TYPE(left) == AOP_DIR) &&
6868 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6870 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6871 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6873 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6875 switch (lit & 0xff) {
6877 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6880 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6881 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6882 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6886 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6887 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6888 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6893 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6894 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6899 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6902 if(AOP_TYPE(result) == AOP_CRY) {
6903 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6910 /* fix me. probably need to check result size too */
6911 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6916 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6917 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6924 if(res_offset < res_size-1)
6929 } else if(AOP_TYPE(right) == AOP_REG &&
6930 AOP_TYPE(left) != AOP_DIR){
6933 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6934 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6935 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6940 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6942 if(res_offset < res_size-1)
6947 /* right is a pointer reg need both a & b */
6949 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6951 pic16_emitcode("mov","b,%s",l);
6952 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6953 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6958 if(result && preserve_result)
6961 for(i = 0; i < AOP_SIZE(result); i++)
6962 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6965 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6967 if(result && preserve_result)
6968 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6971 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6973 pic16_emitpLabel(lbl->key);
6975 if(result && preserve_result)
6978 for(i = 0; i < AOP_SIZE(result); i++)
6979 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6981 pic16_emitpLabel(lbl_done->key);
6984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6992 /*-----------------------------------------------------------------*/
6993 /* gencjne - compare and jump if not equal */
6994 /*-----------------------------------------------------------------*/
6995 static void gencjne(operand *left, operand *right, iCode *ifx)
6997 symbol *tlbl = newiTempLabel(NULL);
6999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7000 gencjneshort(left, right, lbl);
7002 pic16_emitcode("mov","a,%s",one);
7003 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
7004 pic16_emitcode("","%05d_DS_:",lbl->key+100);
7005 pic16_emitcode("clr","a");
7006 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7008 pic16_emitpLabel(lbl->key);
7009 pic16_emitpLabel(tlbl->key);
7015 /*-----------------------------------------------------------------*/
7016 /* is_LitOp - check if operand has to be treated as literal */
7017 /*-----------------------------------------------------------------*/
7018 static bool is_LitOp(operand *op)
7020 return ((AOP_TYPE(op) == AOP_LIT)
7021 || ( (AOP_TYPE(op) == AOP_PCODE)
7022 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7023 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7026 /*-----------------------------------------------------------------*/
7027 /* is_LitAOp - check if operand has to be treated as literal */
7028 /*-----------------------------------------------------------------*/
7029 static bool is_LitAOp(asmop *aop)
7031 return ((aop->type == AOP_LIT)
7032 || ( (aop->type == AOP_PCODE)
7033 && ( (aop->aopu.pcop->type == PO_LITERAL)
7034 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7039 /*-----------------------------------------------------------------*/
7040 /* genCmpEq - generates code for equal to */
7041 /*-----------------------------------------------------------------*/
7042 static void genCmpEq (iCode *ic, iCode *ifx)
7044 operand *left, *right, *result;
7045 symbol *falselbl = newiTempLabel(NULL);
7046 symbol *donelbl = newiTempLabel(NULL);
7048 int preserve_result = 0;
7049 int generate_result = 0;
7054 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7055 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7056 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7058 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7060 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7062 werror(W_POSSBUG2, __FILE__, __LINE__);
7063 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7064 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7068 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7070 operand *tmp = right ;
7075 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7076 preserve_result = 1;
7078 if(result && AOP_SIZE(result))
7079 generate_result = 1;
7081 if(generate_result && !preserve_result)
7083 for(i = 0; i < AOP_SIZE(result); i++)
7084 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7087 for(i=0; i < AOP_SIZE(left); i++)
7089 if(AOP_TYPE(left) != AOP_ACC)
7092 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7094 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7097 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7099 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7101 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7106 if(generate_result && preserve_result)
7108 for(i = 0; i < AOP_SIZE(result); i++)
7109 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7113 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7115 if(generate_result && preserve_result)
7116 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7118 if(ifx && IC_TRUE(ifx))
7119 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7121 if(ifx && IC_FALSE(ifx))
7122 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7124 pic16_emitpLabel(falselbl->key);
7128 if(ifx && IC_FALSE(ifx))
7129 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7131 if(generate_result && preserve_result)
7133 for(i = 0; i < AOP_SIZE(result); i++)
7134 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7137 pic16_emitpLabel(donelbl->key);
7143 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7144 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7145 pic16_freeAsmop(result,NULL,ic,TRUE);
7151 // old version kept for reference
7153 /*-----------------------------------------------------------------*/
7154 /* genCmpEq - generates code for equal to */
7155 /*-----------------------------------------------------------------*/
7156 static void genCmpEq (iCode *ic, iCode *ifx)
7158 operand *left, *right, *result;
7159 unsigned long lit = 0L;
7161 symbol *falselbl = newiTempLabel(NULL);
7164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7167 DEBUGpic16_emitcode ("; ifx is non-null","");
7169 DEBUGpic16_emitcode ("; ifx is null","");
7171 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7172 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7173 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7175 size = max(AOP_SIZE(left),AOP_SIZE(right));
7177 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7179 /* if literal, literal on the right or
7180 if the right is in a pointer register and left
7182 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7183 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7184 operand *tmp = right ;
7190 if(ifx && !AOP_SIZE(result)){
7192 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7193 /* if they are both bit variables */
7194 if (AOP_TYPE(left) == AOP_CRY &&
7195 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7196 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7197 if(AOP_TYPE(right) == AOP_LIT){
7198 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7200 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7201 pic16_emitcode("cpl","c");
7202 } else if(lit == 1L) {
7203 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7205 pic16_emitcode("clr","c");
7207 /* AOP_TYPE(right) == AOP_CRY */
7209 symbol *lbl = newiTempLabel(NULL);
7210 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7211 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7212 pic16_emitcode("cpl","c");
7213 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7215 /* if true label then we jump if condition
7217 tlbl = newiTempLabel(NULL);
7218 if ( IC_TRUE(ifx) ) {
7219 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7220 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7222 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7223 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7225 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7228 /* left and right are both bit variables, result is carry */
7231 resolveIfx(&rIfx,ifx);
7233 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7234 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7235 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7236 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7241 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7243 /* They're not both bit variables. Is the right a literal? */
7244 if(AOP_TYPE(right) == AOP_LIT) {
7245 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7250 switch(lit & 0xff) {
7252 if ( IC_TRUE(ifx) ) {
7253 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7255 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7257 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7258 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7262 if ( IC_TRUE(ifx) ) {
7263 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7267 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7268 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7272 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7274 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7279 /* end of size == 1 */
7283 genc16bit2lit(left,lit,offset);
7286 /* end of size == 2 */
7291 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7292 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7293 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7294 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7297 /* search for patterns that can be optimized */
7299 genc16bit2lit(left,lit,0);
7303 emitSKPZ; // if hi word unequal
7305 emitSKPNZ; // if hi word equal
7307 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7308 genc16bit2lit(left,lit,2);
7311 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7312 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7316 pic16_emitpLabel(falselbl->key);
7325 } else if(AOP_TYPE(right) == AOP_CRY ) {
7326 /* we know the left is not a bit, but that the right is */
7327 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7328 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7329 pic16_popGet(AOP(right),offset));
7330 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7332 /* if the two are equal, then W will be 0 and the Z bit is set
7333 * we could test Z now, or go ahead and check the high order bytes if
7334 * the variable we're comparing is larger than a byte. */
7337 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7339 if ( IC_TRUE(ifx) ) {
7341 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7342 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7345 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7346 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7350 /* They're both variables that are larger than bits */
7353 tlbl = newiTempLabel(NULL);
7356 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7357 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7359 if ( IC_TRUE(ifx) ) {
7363 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7365 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7366 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7370 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7373 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7374 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7379 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7381 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7382 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7386 if(s>1 && IC_TRUE(ifx)) {
7387 pic16_emitpLabel(tlbl->key);
7388 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7392 /* mark the icode as generated */
7397 /* if they are both bit variables */
7398 if (AOP_TYPE(left) == AOP_CRY &&
7399 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7400 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7401 if(AOP_TYPE(right) == AOP_LIT){
7402 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7404 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7405 pic16_emitcode("cpl","c");
7406 } else if(lit == 1L) {
7407 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7409 pic16_emitcode("clr","c");
7411 /* AOP_TYPE(right) == AOP_CRY */
7413 symbol *lbl = newiTempLabel(NULL);
7414 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7415 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7416 pic16_emitcode("cpl","c");
7417 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7420 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7421 pic16_outBitC(result);
7425 genIfxJump (ifx,"c");
7428 /* if the result is used in an arithmetic operation
7429 then put the result in place */
7430 pic16_outBitC(result);
7433 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7434 gencjne(left,right,result,ifx);
7437 gencjne(left,right,newiTempLabel(NULL));
7439 if(IC_TRUE(ifx)->key)
7440 gencjne(left,right,IC_TRUE(ifx)->key);
7442 gencjne(left,right,IC_FALSE(ifx)->key);
7446 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7447 pic16_aopPut(AOP(result),"a",0);
7452 genIfxJump (ifx,"a");
7456 /* if the result is used in an arithmetic operation
7457 then put the result in place */
7459 if (AOP_TYPE(result) != AOP_CRY)
7460 pic16_outAcc(result);
7462 /* leave the result in acc */
7466 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7467 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7468 pic16_freeAsmop(result,NULL,ic,TRUE);
7472 /*-----------------------------------------------------------------*/
7473 /* ifxForOp - returns the icode containing the ifx for operand */
7474 /*-----------------------------------------------------------------*/
7475 static iCode *ifxForOp ( operand *op, iCode *ic )
7479 /* if true symbol then needs to be assigned */
7480 if (IS_TRUE_SYMOP(op))
7483 /* if this has register type condition and
7484 the next instruction is ifx with the same operand
7485 and live to of the operand is upto the ifx only then */
7487 && ic->next->op == IFX
7488 && IC_COND(ic->next)->key == op->key
7489 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7491 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7497 ic->next->op == IFX &&
7498 IC_COND(ic->next)->key == op->key) {
7499 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7504 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7506 ic->next->op == IFX)
7507 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7510 ic->next->op == IFX &&
7511 IC_COND(ic->next)->key == op->key) {
7512 DEBUGpic16_emitcode ("; "," key is okay");
7513 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7514 OP_SYMBOL(op)->liveTo,
7519 /* the code below is completely untested
7520 * it just allows ulong2fs.c compile -- VR */
7523 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7524 __FILE__, __FUNCTION__, __LINE__);
7526 /* if this has register type condition and
7527 the next instruction is ifx with the same operand
7528 and live to of the operand is upto the ifx only then */
7530 ic->next->op == IFX &&
7531 IC_COND(ic->next)->key == op->key &&
7532 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7536 ic->next->op == IFX &&
7537 IC_COND(ic->next)->key == op->key) {
7538 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7542 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7543 __FILE__, __FUNCTION__, __LINE__);
7545 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7550 /*-----------------------------------------------------------------*/
7551 /* genAndOp - for && operation */
7552 /*-----------------------------------------------------------------*/
7553 static void genAndOp (iCode *ic)
7555 operand *left,*right, *result;
7560 /* note here that && operations that are in an
7561 if statement are taken away by backPatchLabels
7562 only those used in arthmetic operations remain */
7563 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7564 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7565 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7567 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7569 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7570 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7571 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7573 /* if both are bit variables */
7574 /* if (AOP_TYPE(left) == AOP_CRY && */
7575 /* AOP_TYPE(right) == AOP_CRY ) { */
7576 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7577 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7578 /* pic16_outBitC(result); */
7580 /* tlbl = newiTempLabel(NULL); */
7581 /* pic16_toBoolean(left); */
7582 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7583 /* pic16_toBoolean(right); */
7584 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7585 /* pic16_outBitAcc(result); */
7588 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7589 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7590 pic16_freeAsmop(result,NULL,ic,TRUE);
7594 /*-----------------------------------------------------------------*/
7595 /* genOrOp - for || operation */
7596 /*-----------------------------------------------------------------*/
7599 modified this code, but it doesn't appear to ever get called
7602 static void genOrOp (iCode *ic)
7604 operand *left,*right, *result;
7609 /* note here that || operations that are in an
7610 if statement are taken away by backPatchLabels
7611 only those used in arthmetic operations remain */
7612 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7613 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7614 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7616 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7618 /* if both are bit variables */
7619 if (AOP_TYPE(left) == AOP_CRY &&
7620 AOP_TYPE(right) == AOP_CRY ) {
7621 pic16_emitcode("clrc","");
7622 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7623 AOP(left)->aopu.aop_dir,
7624 AOP(left)->aopu.aop_dir);
7625 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7626 AOP(right)->aopu.aop_dir,
7627 AOP(right)->aopu.aop_dir);
7628 pic16_emitcode("setc","");
7631 tlbl = newiTempLabel(NULL);
7632 pic16_toBoolean(left);
7634 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7635 pic16_toBoolean(right);
7636 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7638 pic16_outBitAcc(result);
7641 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7642 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7643 pic16_freeAsmop(result,NULL,ic,TRUE);
7646 /*-----------------------------------------------------------------*/
7647 /* isLiteralBit - test if lit == 2^n */
7648 /*-----------------------------------------------------------------*/
7649 static int isLiteralBit(unsigned long lit)
7651 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7652 0x100L,0x200L,0x400L,0x800L,
7653 0x1000L,0x2000L,0x4000L,0x8000L,
7654 0x10000L,0x20000L,0x40000L,0x80000L,
7655 0x100000L,0x200000L,0x400000L,0x800000L,
7656 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7657 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7660 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7661 for(idx = 0; idx < 32; idx++)
7667 /*-----------------------------------------------------------------*/
7668 /* continueIfTrue - */
7669 /*-----------------------------------------------------------------*/
7670 static void continueIfTrue (iCode *ic)
7674 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7678 /*-----------------------------------------------------------------*/
7680 /*-----------------------------------------------------------------*/
7681 static void jumpIfTrue (iCode *ic)
7685 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7689 /*-----------------------------------------------------------------*/
7690 /* jmpTrueOrFalse - */
7691 /*-----------------------------------------------------------------*/
7692 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7694 // ugly but optimized by peephole
7697 symbol *nlbl = newiTempLabel(NULL);
7698 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7699 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7700 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7701 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7703 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7704 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7709 /*-----------------------------------------------------------------*/
7710 /* genAnd - code for and */
7711 /*-----------------------------------------------------------------*/
7712 static void genAnd (iCode *ic, iCode *ifx)
7714 operand *left, *right, *result;
7716 unsigned long lit = 0L;
7722 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7723 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7724 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7726 resolveIfx(&rIfx,ifx);
7728 /* if left is a literal & right is not then exchange them */
7729 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7730 AOP_NEEDSACC(left)) {
7731 operand *tmp = right ;
7736 /* if result = right then exchange them */
7737 if(pic16_sameRegs(AOP(result),AOP(right))){
7738 operand *tmp = right ;
7743 /* if right is bit then exchange them */
7744 if (AOP_TYPE(right) == AOP_CRY &&
7745 AOP_TYPE(left) != AOP_CRY){
7746 operand *tmp = right ;
7750 if(AOP_TYPE(right) == AOP_LIT)
7751 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7753 size = AOP_SIZE(result);
7755 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7758 // result = bit & yy;
7759 if (AOP_TYPE(left) == AOP_CRY){
7760 // c = bit & literal;
7761 if(AOP_TYPE(right) == AOP_LIT){
7763 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7766 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7769 if(size && (AOP_TYPE(result) == AOP_CRY)){
7770 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7773 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7777 pic16_emitcode("clr","c");
7780 if (AOP_TYPE(right) == AOP_CRY){
7782 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7783 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7786 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7788 pic16_emitcode("rrc","a");
7789 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7795 pic16_outBitC(result);
7797 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7798 genIfxJump(ifx, "c");
7802 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7803 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7804 if((AOP_TYPE(right) == AOP_LIT) &&
7805 (AOP_TYPE(result) == AOP_CRY) &&
7806 (AOP_TYPE(left) != AOP_CRY)){
7807 int posbit = isLiteralBit(lit);
7811 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7814 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7820 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7821 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7823 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7824 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7827 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7828 size = AOP_SIZE(left);
7831 int bp = posbit, ofs=0;
7838 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7839 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7843 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7844 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7846 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7853 symbol *tlbl = newiTempLabel(NULL);
7854 int sizel = AOP_SIZE(left);
7860 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7862 /* patch provided by Aaron Colwell */
7863 if((posbit = isLiteralBit(bytelit)) != 0) {
7864 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7865 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7866 (posbit-1),0, PO_GPR_REGISTER));
7868 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7869 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7871 if (bytelit == 0xff) {
7872 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7873 * a peephole could optimize it out -- VR */
7874 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7876 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7877 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7880 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7881 pic16_popGetLabel(tlbl->key));
7885 /* old code, left here for reference -- VR 09/2004 */
7886 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7888 if((posbit = isLiteralBit(bytelit)) != 0)
7889 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7891 if(bytelit != 0x0FFL)
7892 pic16_emitcode("anl","a,%s",
7893 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7894 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7900 // bit = left & literal
7903 pic16_emitpLabel(tlbl->key);
7905 // if(left & literal)
7908 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7911 pic16_emitpLabel(tlbl->key);
7916 pic16_outBitC(result);
7920 /* if left is same as result */
7921 if(pic16_sameRegs(AOP(result),AOP(left))){
7923 for(;size--; offset++,lit>>=8) {
7924 if(AOP_TYPE(right) == AOP_LIT){
7925 switch(lit & 0xff) {
7927 /* and'ing with 0 has clears the result */
7928 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7929 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7932 /* and'ing with 0xff is a nop when the result and left are the same */
7937 int p = pic16_my_powof2( (~lit) & 0xff );
7939 /* only one bit is set in the literal, so use a bcf instruction */
7940 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7941 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7944 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7945 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7946 if(know_W != (lit&0xff))
7947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7949 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7954 if (AOP_TYPE(left) == AOP_ACC) {
7955 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7957 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7958 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7965 // left & result in different registers
7966 if(AOP_TYPE(result) == AOP_CRY){
7968 // if(size), result in bit
7969 // if(!size && ifx), conditional oper: if(left & right)
7970 symbol *tlbl = newiTempLabel(NULL);
7971 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7973 pic16_emitcode("setb","c");
7975 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7976 pic16_emitcode("anl","a,%s",
7977 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7978 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7983 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7984 pic16_outBitC(result);
7986 jmpTrueOrFalse(ifx, tlbl);
7988 for(;(size--);offset++) {
7990 // result = left & right
7991 if(AOP_TYPE(right) == AOP_LIT){
7992 int t = (lit >> (offset*8)) & 0x0FFL;
7995 pic16_emitcode("clrf","%s",
7996 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7997 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
8000 pic16_emitcode("movf","%s,w",
8001 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8002 pic16_emitcode("movwf","%s",
8003 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8004 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8005 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8008 pic16_emitcode("movlw","0x%x",t);
8009 pic16_emitcode("andwf","%s,w",
8010 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8011 pic16_emitcode("movwf","%s",
8012 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8014 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8015 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8016 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8021 if (AOP_TYPE(left) == AOP_ACC) {
8022 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8023 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8025 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8026 pic16_emitcode("andwf","%s,w",
8027 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8028 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8029 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8031 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8032 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8038 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8039 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8040 pic16_freeAsmop(result,NULL,ic,TRUE);
8043 /*-----------------------------------------------------------------*/
8044 /* genOr - code for or */
8045 /*-----------------------------------------------------------------*/
8046 static void genOr (iCode *ic, iCode *ifx)
8048 operand *left, *right, *result;
8050 unsigned long lit = 0L;
8052 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8054 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8055 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8056 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8058 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8060 /* if left is a literal & right is not then exchange them */
8061 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8062 AOP_NEEDSACC(left)) {
8063 operand *tmp = right ;
8068 /* if result = right then exchange them */
8069 if(pic16_sameRegs(AOP(result),AOP(right))){
8070 operand *tmp = right ;
8075 /* if right is bit then exchange them */
8076 if (AOP_TYPE(right) == AOP_CRY &&
8077 AOP_TYPE(left) != AOP_CRY){
8078 operand *tmp = right ;
8083 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8085 if(AOP_TYPE(right) == AOP_LIT)
8086 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8088 size = AOP_SIZE(result);
8092 if (AOP_TYPE(left) == AOP_CRY){
8093 if(AOP_TYPE(right) == AOP_LIT){
8094 // c = bit & literal;
8096 // lit != 0 => result = 1
8097 if(AOP_TYPE(result) == AOP_CRY){
8099 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8100 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8101 // AOP(result)->aopu.aop_dir,
8102 // AOP(result)->aopu.aop_dir);
8104 continueIfTrue(ifx);
8108 // lit == 0 => result = left
8109 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8111 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8114 if (AOP_TYPE(right) == AOP_CRY){
8115 if(pic16_sameRegs(AOP(result),AOP(left))){
8117 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8118 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8119 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8121 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8122 AOP(result)->aopu.aop_dir,
8123 AOP(result)->aopu.aop_dir);
8124 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8125 AOP(right)->aopu.aop_dir,
8126 AOP(right)->aopu.aop_dir);
8127 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8128 AOP(result)->aopu.aop_dir,
8129 AOP(result)->aopu.aop_dir);
8131 if( AOP_TYPE(result) == AOP_ACC) {
8132 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8133 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8134 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8135 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8139 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8140 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8141 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8142 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8144 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8145 AOP(result)->aopu.aop_dir,
8146 AOP(result)->aopu.aop_dir);
8147 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8148 AOP(right)->aopu.aop_dir,
8149 AOP(right)->aopu.aop_dir);
8150 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8151 AOP(left)->aopu.aop_dir,
8152 AOP(left)->aopu.aop_dir);
8153 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8154 AOP(result)->aopu.aop_dir,
8155 AOP(result)->aopu.aop_dir);
8160 symbol *tlbl = newiTempLabel(NULL);
8161 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8164 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8165 if( AOP_TYPE(right) == AOP_ACC) {
8166 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8168 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8169 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8174 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8175 pic16_emitcode(";XXX setb","c");
8176 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8177 AOP(left)->aopu.aop_dir,tlbl->key+100);
8178 pic16_toBoolean(right);
8179 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8180 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8181 jmpTrueOrFalse(ifx, tlbl);
8185 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8192 pic16_outBitC(result);
8194 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8195 genIfxJump(ifx, "c");
8199 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8200 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8201 if((AOP_TYPE(right) == AOP_LIT) &&
8202 (AOP_TYPE(result) == AOP_CRY) &&
8203 (AOP_TYPE(left) != AOP_CRY)){
8205 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8208 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8210 continueIfTrue(ifx);
8213 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8214 // lit = 0, result = boolean(left)
8216 pic16_emitcode(";XXX setb","c");
8217 pic16_toBoolean(right);
8219 symbol *tlbl = newiTempLabel(NULL);
8220 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8222 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8224 genIfxJump (ifx,"a");
8228 pic16_outBitC(result);
8232 /* if left is same as result */
8233 if(pic16_sameRegs(AOP(result),AOP(left))){
8235 for(;size--; offset++,lit>>=8) {
8236 if(AOP_TYPE(right) == AOP_LIT){
8237 if((lit & 0xff) == 0)
8238 /* or'ing with 0 has no effect */
8241 int p = pic16_my_powof2(lit & 0xff);
8243 /* only one bit is set in the literal, so use a bsf instruction */
8244 pic16_emitpcode(POC_BSF,
8245 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8247 if(know_W != (lit & 0xff))
8248 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8249 know_W = lit & 0xff;
8250 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8255 if (AOP_TYPE(left) == AOP_ACC) {
8256 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8257 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8259 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8260 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8262 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8263 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8269 // left & result in different registers
8270 if(AOP_TYPE(result) == AOP_CRY){
8272 // if(size), result in bit
8273 // if(!size && ifx), conditional oper: if(left | right)
8274 symbol *tlbl = newiTempLabel(NULL);
8275 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8276 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8280 pic16_emitcode(";XXX setb","c");
8282 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8283 pic16_emitcode(";XXX orl","a,%s",
8284 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8285 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8290 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8291 pic16_outBitC(result);
8293 jmpTrueOrFalse(ifx, tlbl);
8294 } else for(;(size--);offset++){
8296 // result = left & right
8297 if(AOP_TYPE(right) == AOP_LIT){
8298 int t = (lit >> (offset*8)) & 0x0FFL;
8301 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8302 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8304 pic16_emitcode("movf","%s,w",
8305 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8306 pic16_emitcode("movwf","%s",
8307 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8310 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8311 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8312 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8314 pic16_emitcode("movlw","0x%x",t);
8315 pic16_emitcode("iorwf","%s,w",
8316 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8317 pic16_emitcode("movwf","%s",
8318 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8324 // faster than result <- left, anl result,right
8325 // and better if result is SFR
8326 if (AOP_TYPE(left) == AOP_ACC) {
8327 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8328 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8330 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8331 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8333 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8334 pic16_emitcode("iorwf","%s,w",
8335 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8337 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8338 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8343 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8344 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8345 pic16_freeAsmop(result,NULL,ic,TRUE);
8348 /*-----------------------------------------------------------------*/
8349 /* genXor - code for xclusive or */
8350 /*-----------------------------------------------------------------*/
8351 static void genXor (iCode *ic, iCode *ifx)
8353 operand *left, *right, *result;
8355 unsigned long lit = 0L;
8357 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8359 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8360 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8361 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8363 /* if left is a literal & right is not ||
8364 if left needs acc & right does not */
8365 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8366 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8367 operand *tmp = right ;
8372 /* if result = right then exchange them */
8373 if(pic16_sameRegs(AOP(result),AOP(right))){
8374 operand *tmp = right ;
8379 /* if right is bit then exchange them */
8380 if (AOP_TYPE(right) == AOP_CRY &&
8381 AOP_TYPE(left) != AOP_CRY){
8382 operand *tmp = right ;
8386 if(AOP_TYPE(right) == AOP_LIT)
8387 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8389 size = AOP_SIZE(result);
8393 if (AOP_TYPE(left) == AOP_CRY){
8394 if(AOP_TYPE(right) == AOP_LIT){
8395 // c = bit & literal;
8397 // lit>>1 != 0 => result = 1
8398 if(AOP_TYPE(result) == AOP_CRY){
8400 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8401 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8403 continueIfTrue(ifx);
8406 pic16_emitcode("setb","c");
8410 // lit == 0, result = left
8411 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8413 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8415 // lit == 1, result = not(left)
8416 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8417 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8418 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8419 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8422 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8423 pic16_emitcode("cpl","c");
8430 symbol *tlbl = newiTempLabel(NULL);
8431 if (AOP_TYPE(right) == AOP_CRY){
8433 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8436 int sizer = AOP_SIZE(right);
8438 // if val>>1 != 0, result = 1
8439 pic16_emitcode("setb","c");
8441 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8443 // test the msb of the lsb
8444 pic16_emitcode("anl","a,#0xfe");
8445 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8449 pic16_emitcode("rrc","a");
8451 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8452 pic16_emitcode("cpl","c");
8453 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8458 pic16_outBitC(result);
8460 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8461 genIfxJump(ifx, "c");
8465 if(pic16_sameRegs(AOP(result),AOP(left))){
8466 /* if left is same as result */
8467 for(;size--; offset++) {
8468 if(AOP_TYPE(right) == AOP_LIT){
8469 int t = (lit >> (offset*8)) & 0x0FFL;
8473 if (IS_AOP_PREG(left)) {
8474 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8475 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8476 pic16_aopPut(AOP(result),"a",offset);
8478 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8479 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8480 pic16_emitcode("xrl","%s,%s",
8481 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8482 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8485 if (AOP_TYPE(left) == AOP_ACC)
8486 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8488 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8489 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8491 if (IS_AOP_PREG(left)) {
8492 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8493 pic16_aopPut(AOP(result),"a",offset);
8495 pic16_emitcode("xrl","%s,a",
8496 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8502 // left & result in different registers
8503 if(AOP_TYPE(result) == AOP_CRY){
8505 // if(size), result in bit
8506 // if(!size && ifx), conditional oper: if(left ^ right)
8507 symbol *tlbl = newiTempLabel(NULL);
8508 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8510 pic16_emitcode("setb","c");
8512 if((AOP_TYPE(right) == AOP_LIT) &&
8513 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8514 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8516 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8517 pic16_emitcode("xrl","a,%s",
8518 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8520 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8525 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8526 pic16_outBitC(result);
8528 jmpTrueOrFalse(ifx, tlbl);
8529 } else for(;(size--);offset++){
8531 // result = left & right
8532 if(AOP_TYPE(right) == AOP_LIT){
8533 int t = (lit >> (offset*8)) & 0x0FFL;
8536 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8537 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8538 pic16_emitcode("movf","%s,w",
8539 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8540 pic16_emitcode("movwf","%s",
8541 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8544 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8545 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8546 pic16_emitcode("comf","%s,w",
8547 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8548 pic16_emitcode("movwf","%s",
8549 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8552 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8553 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8554 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8555 pic16_emitcode("movlw","0x%x",t);
8556 pic16_emitcode("xorwf","%s,w",
8557 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8558 pic16_emitcode("movwf","%s",
8559 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8565 // faster than result <- left, anl result,right
8566 // and better if result is SFR
8567 if (AOP_TYPE(left) == AOP_ACC) {
8568 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8569 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8571 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8572 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8573 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8574 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8576 if ( AOP_TYPE(result) != AOP_ACC){
8577 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8578 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8584 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8585 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8586 pic16_freeAsmop(result,NULL,ic,TRUE);
8589 /*-----------------------------------------------------------------*/
8590 /* genInline - write the inline code out */
8591 /*-----------------------------------------------------------------*/
8592 static void genInline (iCode *ic)
8594 char *buffer, *bp, *bp1;
8596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8598 _G.inLine += (!options.asmpeep);
8600 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8601 strcpy(buffer,IC_INLINE(ic));
8603 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8605 /* emit each line as a code */
8611 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8619 /* print label, use this special format with NULL directive
8620 * to denote that the argument should not be indented with tab */
8621 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8628 if ((bp1 != bp) && *bp1)
8629 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8634 _G.inLine -= (!options.asmpeep);
8637 /*-----------------------------------------------------------------*/
8638 /* genRRC - rotate right with carry */
8639 /*-----------------------------------------------------------------*/
8640 static void genRRC (iCode *ic)
8642 operand *left , *result ;
8643 int size, offset = 0, same;
8645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8647 /* rotate right with carry */
8649 result=IC_RESULT(ic);
8650 pic16_aopOp (left,ic,FALSE);
8651 pic16_aopOp (result,ic,FALSE);
8653 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8655 same = pic16_sameRegs(AOP(result),AOP(left));
8657 size = AOP_SIZE(result);
8659 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8661 /* get the lsb and put it into the carry */
8662 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8669 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8671 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8678 pic16_freeAsmop(left,NULL,ic,TRUE);
8679 pic16_freeAsmop(result,NULL,ic,TRUE);
8682 /*-----------------------------------------------------------------*/
8683 /* genRLC - generate code for rotate left with carry */
8684 /*-----------------------------------------------------------------*/
8685 static void genRLC (iCode *ic)
8687 operand *left , *result ;
8688 int size, offset = 0;
8691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8692 /* rotate right with carry */
8694 result=IC_RESULT(ic);
8695 pic16_aopOp (left,ic,FALSE);
8696 pic16_aopOp (result,ic,FALSE);
8698 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8700 same = pic16_sameRegs(AOP(result),AOP(left));
8702 /* move it to the result */
8703 size = AOP_SIZE(result);
8705 /* get the msb and put it into the carry */
8706 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8713 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8715 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8716 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8723 pic16_freeAsmop(left,NULL,ic,TRUE);
8724 pic16_freeAsmop(result,NULL,ic,TRUE);
8728 /* gpasm can get the highest order bit with HIGH/UPPER
8729 * so the following probably is not needed -- VR */
8731 /*-----------------------------------------------------------------*/
8732 /* genGetHbit - generates code get highest order bit */
8733 /*-----------------------------------------------------------------*/
8734 static void genGetHbit (iCode *ic)
8736 operand *left, *result;
8738 result=IC_RESULT(ic);
8739 pic16_aopOp (left,ic,FALSE);
8740 pic16_aopOp (result,ic,FALSE);
8742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8743 /* get the highest order byte into a */
8744 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8745 if(AOP_TYPE(result) == AOP_CRY){
8746 pic16_emitcode("rlc","a");
8747 pic16_outBitC(result);
8750 pic16_emitcode("rl","a");
8751 pic16_emitcode("anl","a,#0x01");
8752 pic16_outAcc(result);
8756 pic16_freeAsmop(left,NULL,ic,TRUE);
8757 pic16_freeAsmop(result,NULL,ic,TRUE);
8761 /*-----------------------------------------------------------------*/
8762 /* AccRol - rotate left accumulator by known count */
8763 /*-----------------------------------------------------------------*/
8764 static void AccRol (int shCount)
8766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8767 shCount &= 0x0007; // shCount : 0..7
8772 pic16_emitcode("rl","a");
8775 pic16_emitcode("rl","a");
8776 pic16_emitcode("rl","a");
8779 pic16_emitcode("swap","a");
8780 pic16_emitcode("rr","a");
8783 pic16_emitcode("swap","a");
8786 pic16_emitcode("swap","a");
8787 pic16_emitcode("rl","a");
8790 pic16_emitcode("rr","a");
8791 pic16_emitcode("rr","a");
8794 pic16_emitcode("rr","a");
8800 /*-----------------------------------------------------------------*/
8801 /* AccLsh - left shift accumulator by known count */
8802 /*-----------------------------------------------------------------*/
8803 static void AccLsh (int shCount)
8805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8811 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8814 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8818 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8822 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8825 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8826 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8829 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8837 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8840 /*-----------------------------------------------------------------*/
8841 /* AccRsh - right shift accumulator by known count */
8842 /*-----------------------------------------------------------------*/
8843 static void AccRsh (int shCount, int andmask)
8845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8850 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8853 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8854 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8857 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8858 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8861 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8864 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8865 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8868 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8869 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8872 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8877 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8879 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8883 /*-----------------------------------------------------------------*/
8884 /* AccSRsh - signed right shift accumulator by known count */
8885 /*-----------------------------------------------------------------*/
8886 static void AccSRsh (int shCount)
8889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8892 pic16_emitcode("mov","c,acc.7");
8893 pic16_emitcode("rrc","a");
8894 } else if(shCount == 2){
8895 pic16_emitcode("mov","c,acc.7");
8896 pic16_emitcode("rrc","a");
8897 pic16_emitcode("mov","c,acc.7");
8898 pic16_emitcode("rrc","a");
8900 tlbl = newiTempLabel(NULL);
8901 /* rotate right accumulator */
8902 AccRol(8 - shCount);
8903 /* and kill the higher order bits */
8904 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8905 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8906 pic16_emitcode("orl","a,#0x%02x",
8907 (unsigned char)~SRMask[shCount]);
8908 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8914 /*-----------------------------------------------------------------*/
8915 /* shiftR1Left2Result - shift right one byte from left to result */
8916 /*-----------------------------------------------------------------*/
8917 static void shiftR1Left2ResultSigned (operand *left, int offl,
8918 operand *result, int offr,
8923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8925 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8929 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8931 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8934 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8942 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8957 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8961 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8964 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8965 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8972 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8973 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8974 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8975 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8982 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8984 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8985 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8986 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8987 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8988 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8994 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8995 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8996 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8997 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9002 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9004 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9010 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9011 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9012 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9015 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9017 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9025 /*-----------------------------------------------------------------*/
9026 /* shiftR1Left2Result - shift right one byte from left to result */
9027 /*-----------------------------------------------------------------*/
9028 static void shiftR1Left2Result (operand *left, int offl,
9029 operand *result, int offr,
9030 int shCount, int sign)
9034 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9036 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9038 /* Copy the msb into the carry if signed. */
9040 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9050 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9052 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9053 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
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));
9065 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9072 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9076 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9077 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9078 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9083 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9084 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9085 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9089 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9090 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9091 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9093 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9099 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9100 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9101 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9102 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9108 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9118 /*-----------------------------------------------------------------*/
9119 /* shiftL1Left2Result - shift left one byte from left to result */
9120 /*-----------------------------------------------------------------*/
9121 static void shiftL1Left2Result (operand *left, int offl,
9122 operand *result, int offr, int shCount)
9127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9129 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9130 DEBUGpic16_emitcode ("; ***","same = %d",same);
9131 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9133 /* shift left accumulator */
9134 //AccLsh(shCount); // don't comment out just yet...
9135 // pic16_aopPut(AOP(result),"a",offr);
9139 /* Shift left 1 bit position */
9140 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9142 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9144 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9149 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9150 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9151 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9156 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9157 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9158 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9162 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9163 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9168 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9169 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9170 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9173 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9174 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9175 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9177 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9181 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9182 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9186 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9191 /*-----------------------------------------------------------------*/
9192 /* movLeft2Result - move byte from left to result */
9193 /*-----------------------------------------------------------------*/
9194 static void movLeft2Result (operand *left, int offl,
9195 operand *result, int offr)
9198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9199 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9200 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9202 if (*l == '@' && (IS_AOP_PREG(result))) {
9203 pic16_emitcode("mov","a,%s",l);
9204 pic16_aopPut(AOP(result),"a",offr);
9206 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9212 /*-----------------------------------------------------------------*/
9213 /* shiftL2Left2Result - shift left two bytes from left to result */
9214 /*-----------------------------------------------------------------*/
9215 static void shiftL2Left2Result (operand *left, int offl,
9216 operand *result, int offr, int shCount)
9218 int same = pic16_sameRegs(AOP(result), AOP(left));
9221 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9223 if (same && (offl != offr)) { // shift bytes
9226 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9227 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9229 } else { // just treat as different later on
9242 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9243 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9244 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9248 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9249 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9255 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9256 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9257 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9258 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9259 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9260 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9261 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9263 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9264 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9268 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9269 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9270 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9271 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9272 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9273 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9274 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9275 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9276 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9277 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9280 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9281 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9282 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9283 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9284 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9294 /* note, use a mov/add for the shift since the mov has a
9295 chance of getting optimized out */
9296 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9297 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9298 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9299 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9300 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9304 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9305 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9311 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9312 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9313 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9314 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9315 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9316 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9317 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9318 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9322 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9323 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9327 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9328 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9329 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9332 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9333 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9334 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9335 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9336 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9337 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9338 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9339 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9342 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9343 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9344 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9345 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9346 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9351 /*-----------------------------------------------------------------*/
9352 /* shiftR2Left2Result - shift right two bytes from left to result */
9353 /*-----------------------------------------------------------------*/
9354 static void shiftR2Left2Result (operand *left, int offl,
9355 operand *result, int offr,
9356 int shCount, int sign)
9358 int same = pic16_sameRegs(AOP(result), AOP(left));
9360 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9362 if (same && (offl != offr)) { // shift right bytes
9365 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9366 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9368 } else { // just treat as different later on
9380 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9385 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9386 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9388 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9389 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9390 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9391 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9396 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9399 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9400 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9407 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9408 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9409 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9411 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9412 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9413 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9414 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9416 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9417 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9418 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9420 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9421 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9422 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9423 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9424 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9428 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9429 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9433 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9434 pic16_emitpcode(POC_BTFSC,
9435 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9436 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9444 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9445 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9447 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9448 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9449 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9450 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9452 pic16_emitpcode(POC_BTFSC,
9453 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9454 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9456 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9457 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9458 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9459 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9461 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9462 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9463 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9464 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9465 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9466 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9467 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9468 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9470 pic16_emitpcode(POC_BTFSC,
9471 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9472 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9474 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9475 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9482 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9483 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9484 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9485 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9488 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9490 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9495 /*-----------------------------------------------------------------*/
9496 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9497 /*-----------------------------------------------------------------*/
9498 static void shiftLLeftOrResult (operand *left, int offl,
9499 operand *result, int offr, int shCount)
9501 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9503 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9504 /* shift left accumulator */
9506 /* or with result */
9507 /* back to result */
9508 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9511 /*-----------------------------------------------------------------*/
9512 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9513 /*-----------------------------------------------------------------*/
9514 static void shiftRLeftOrResult (operand *left, int offl,
9515 operand *result, int offr, int shCount)
9517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9519 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9520 /* shift right accumulator */
9522 /* or with result */
9523 /* back to result */
9524 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9527 /*-----------------------------------------------------------------*/
9528 /* genlshOne - left shift a one byte quantity by known count */
9529 /*-----------------------------------------------------------------*/
9530 static void genlshOne (operand *result, operand *left, int shCount)
9532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9536 /*-----------------------------------------------------------------*/
9537 /* genlshTwo - left shift two bytes by known amount != 0 */
9538 /*-----------------------------------------------------------------*/
9539 static void genlshTwo (operand *result,operand *left, int shCount)
9543 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9544 size = pic16_getDataSize(result);
9546 /* if shCount >= 8 */
9552 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9554 movLeft2Result(left, LSB, result, MSB16);
9556 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9559 /* 1 <= shCount <= 7 */
9562 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9564 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9568 /*-----------------------------------------------------------------*/
9569 /* shiftLLong - shift left one long from left to result */
9570 /* offr = LSB or MSB16 */
9571 /*-----------------------------------------------------------------*/
9572 static void shiftLLong (operand *left, operand *result, int offr )
9574 int size = AOP_SIZE(result);
9575 int same = pic16_sameRegs(AOP(left),AOP(result));
9578 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9580 if (same && (offr == MSB16)) { //shift one byte
9581 for(i=size-1;i>=MSB16;i--) {
9582 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9583 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9586 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9589 if (size > LSB+offr ){
9591 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9593 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9594 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9598 if(size > MSB16+offr){
9600 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9602 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9603 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9607 if(size > MSB24+offr){
9609 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9611 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9612 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9616 if(size > MSB32+offr){
9618 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9620 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9621 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9625 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9629 /*-----------------------------------------------------------------*/
9630 /* genlshFour - shift four byte by a known amount != 0 */
9631 /*-----------------------------------------------------------------*/
9632 static void genlshFour (operand *result, operand *left, int shCount)
9636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9637 size = AOP_SIZE(result);
9639 /* if shifting more that 3 bytes */
9640 if (shCount >= 24 ) {
9643 /* lowest order of left goes to the highest
9644 order of the destination */
9645 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9647 movLeft2Result(left, LSB, result, MSB32);
9649 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9650 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9651 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9656 /* more than two bytes */
9657 else if ( shCount >= 16 ) {
9658 /* lower order two bytes goes to higher order two bytes */
9660 /* if some more remaining */
9662 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9664 movLeft2Result(left, MSB16, result, MSB32);
9665 movLeft2Result(left, LSB, result, MSB24);
9667 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9672 /* if more than 1 byte */
9673 else if ( shCount >= 8 ) {
9674 /* lower order three bytes goes to higher order three bytes */
9678 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9680 movLeft2Result(left, LSB, result, MSB16);
9682 else{ /* size = 4 */
9684 movLeft2Result(left, MSB24, result, MSB32);
9685 movLeft2Result(left, MSB16, result, MSB24);
9686 movLeft2Result(left, LSB, result, MSB16);
9687 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9689 else if(shCount == 1)
9690 shiftLLong(left, result, MSB16);
9692 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9693 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9694 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9695 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9700 /* 1 <= shCount <= 7 */
9701 else if(shCount <= 3)
9703 shiftLLong(left, result, LSB);
9704 while(--shCount >= 1)
9705 shiftLLong(result, result, LSB);
9707 /* 3 <= shCount <= 7, optimize */
9709 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9710 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9711 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9715 /*-----------------------------------------------------------------*/
9716 /* genLeftShiftLiteral - left shifting by known count */
9717 /*-----------------------------------------------------------------*/
9718 void pic16_genLeftShiftLiteral (operand *left,
9723 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9727 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9728 pic16_freeAsmop(right,NULL,ic,TRUE);
9730 pic16_aopOp(left,ic,FALSE);
9731 pic16_aopOp(result,ic,FALSE);
9733 size = getSize(operandType(result));
9736 pic16_emitcode("; shift left ","result %d, left %d",size,
9740 /* I suppose that the left size >= result size */
9743 movLeft2Result(left, size, result, size);
9747 else if(shCount >= (size * 8))
9749 pic16_aopPut(AOP(result),zero,size);
9753 genlshOne (result,left,shCount);
9758 genlshTwo (result,left,shCount);
9762 genlshFour (result,left,shCount);
9766 pic16_freeAsmop(left,NULL,ic,TRUE);
9767 pic16_freeAsmop(result,NULL,ic,TRUE);
9770 /*-----------------------------------------------------------------*
9771 * genMultiAsm - repeat assembly instruction for size of register.
9772 * if endian == 1, then the high byte (i.e base address + size of
9773 * register) is used first else the low byte is used first;
9774 *-----------------------------------------------------------------*/
9775 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9780 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9793 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9799 #if !(USE_GENERIC_SIGNED_SHIFT)
9800 /*-----------------------------------------------------------------*/
9801 /* genLeftShift - generates code for left shifting */
9802 /*-----------------------------------------------------------------*/
9803 static void genLeftShift (iCode *ic)
9805 operand *left,*right, *result;
9808 symbol *tlbl , *tlbl1;
9811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9813 right = IC_RIGHT(ic);
9815 result = IC_RESULT(ic);
9817 pic16_aopOp(right,ic,FALSE);
9819 /* if the shift count is known then do it
9820 as efficiently as possible */
9821 if (AOP_TYPE(right) == AOP_LIT) {
9822 pic16_genLeftShiftLiteral (left,right,result,ic);
9826 /* shift count is unknown then we have to form
9827 * a loop. Get the loop count in WREG : Note: we take
9828 * only the lower order byte since shifting
9829 * more than 32 bits make no sense anyway, ( the
9830 * largest size of an object can be only 32 bits ) */
9832 pic16_aopOp(left,ic,FALSE);
9833 pic16_aopOp(result,ic,FALSE);
9835 /* now move the left to the result if they are not the
9836 * same, and if size > 1,
9837 * and if right is not same to result (!!!) -- VR */
9838 if (!pic16_sameRegs(AOP(left),AOP(result))
9839 && (AOP_SIZE(result) > 1)) {
9841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9843 size = AOP_SIZE(result);
9848 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9849 if (*l == '@' && (IS_AOP_PREG(result))) {
9851 pic16_emitcode("mov","a,%s",l);
9852 pic16_aopPut(AOP(result),"a",offset);
9856 /* we don't know if left is a literal or a register, take care -- VR */
9857 mov2f(AOP(result), AOP(left), offset);
9863 size = AOP_SIZE(result);
9865 /* if it is only one byte then */
9867 if(optimized_for_speed) {
9868 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9869 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9870 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9871 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9873 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9874 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9875 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9876 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9877 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9878 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9879 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9884 tlbl = newiTempLabel(NULL);
9887 /* this is already done, why change it? */
9888 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9889 mov2f(AOP(result), AOP(left), 0);
9893 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9894 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9895 pic16_emitpLabel(tlbl->key);
9896 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9904 if (pic16_sameRegs(AOP(left),AOP(result))) {
9906 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9908 tlbl = newiTempLabel(NULL);
9909 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9910 genMultiAsm(POC_RRCF, result, size,1);
9911 pic16_emitpLabel(tlbl->key);
9912 genMultiAsm(POC_RLCF, result, size,0);
9913 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9915 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9919 //tlbl = newiTempLabel(NULL);
9921 //tlbl1 = newiTempLabel(NULL);
9923 //reAdjustPreg(AOP(result));
9925 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9926 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9927 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9929 //pic16_emitcode("add","a,acc");
9930 //pic16_aopPut(AOP(result),"a",offset++);
9932 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9934 // pic16_emitcode("rlc","a");
9935 // pic16_aopPut(AOP(result),"a",offset++);
9937 //reAdjustPreg(AOP(result));
9939 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9940 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9943 tlbl = newiTempLabel(NULL);
9944 tlbl1= newiTempLabel(NULL);
9946 size = AOP_SIZE(result);
9949 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9951 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9953 /* offset should be 0, 1 or 3 */
9955 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9957 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9959 pic16_emitpcode(POC_MOVWF, pctemp);
9962 pic16_emitpLabel(tlbl->key);
9965 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9967 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9969 pic16_emitpcode(POC_DECFSZ, pctemp);
9970 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9971 pic16_emitpLabel(tlbl1->key);
9973 pic16_popReleaseTempReg(pctemp,1);
9977 pic16_freeAsmop (right,NULL,ic,TRUE);
9978 pic16_freeAsmop(left,NULL,ic,TRUE);
9979 pic16_freeAsmop(result,NULL,ic,TRUE);
9985 #error old code (left here for reference)
9986 /*-----------------------------------------------------------------*/
9987 /* genLeftShift - generates code for left shifting */
9988 /*-----------------------------------------------------------------*/
9989 static void genLeftShift (iCode *ic)
9991 operand *left,*right, *result;
9994 symbol *tlbl , *tlbl1;
9997 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9999 right = IC_RIGHT(ic);
10000 left = IC_LEFT(ic);
10001 result = IC_RESULT(ic);
10003 pic16_aopOp(right,ic,FALSE);
10005 /* if the shift count is known then do it
10006 as efficiently as possible */
10007 if (AOP_TYPE(right) == AOP_LIT) {
10008 pic16_genLeftShiftLiteral (left,right,result,ic);
10012 /* shift count is unknown then we have to form
10013 a loop get the loop count in B : Note: we take
10014 only the lower order byte since shifting
10015 more that 32 bits make no sense anyway, ( the
10016 largest size of an object can be only 32 bits ) */
10019 pic16_aopOp(left,ic,FALSE);
10020 pic16_aopOp(result,ic,FALSE);
10022 /* now move the left to the result if they are not the
10024 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10025 AOP_SIZE(result) > 1) {
10027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10029 size = AOP_SIZE(result);
10032 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10033 if (*l == '@' && (IS_AOP_PREG(result))) {
10035 pic16_emitcode("mov","a,%s",l);
10036 pic16_aopPut(AOP(result),"a",offset);
10039 /* we don't know if left is a literal or a register, take care -- VR */
10040 mov2f(AOP(result), AOP(left), offset);
10046 size = AOP_SIZE(result);
10048 /* if it is only one byte then */
10050 if(optimized_for_speed) {
10051 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10052 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10053 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10054 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10056 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10057 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10058 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10059 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10060 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10061 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10062 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10067 tlbl = newiTempLabel(NULL);
10068 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10069 mov2f(AOP(result), AOP(left), 0);
10071 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10072 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10075 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10076 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10077 pic16_emitpLabel(tlbl->key);
10078 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10079 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10081 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10086 if (pic16_sameRegs(AOP(left),AOP(result))) {
10088 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10090 tlbl = newiTempLabel(NULL);
10091 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10092 genMultiAsm(POC_RRCF, result, size,1);
10093 pic16_emitpLabel(tlbl->key);
10094 genMultiAsm(POC_RLCF, result, size,0);
10095 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10097 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10101 //tlbl = newiTempLabel(NULL);
10103 //tlbl1 = newiTempLabel(NULL);
10105 //reAdjustPreg(AOP(result));
10107 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10108 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10109 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10111 //pic16_emitcode("add","a,acc");
10112 //pic16_aopPut(AOP(result),"a",offset++);
10114 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10116 // pic16_emitcode("rlc","a");
10117 // pic16_aopPut(AOP(result),"a",offset++);
10119 //reAdjustPreg(AOP(result));
10121 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10122 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10125 tlbl = newiTempLabel(NULL);
10126 tlbl1= newiTempLabel(NULL);
10128 size = AOP_SIZE(result);
10131 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10133 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10135 /* offset should be 0, 1 or 3 */
10137 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10139 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10141 pic16_emitpcode(POC_MOVWF, pctemp);
10144 pic16_emitpLabel(tlbl->key);
10147 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10149 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10151 pic16_emitpcode(POC_DECFSZ, pctemp);
10152 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10153 pic16_emitpLabel(tlbl1->key);
10155 pic16_popReleaseTempReg(pctemp,1);
10159 pic16_freeAsmop (right,NULL,ic,TRUE);
10160 pic16_freeAsmop(left,NULL,ic,TRUE);
10161 pic16_freeAsmop(result,NULL,ic,TRUE);
10165 /*-----------------------------------------------------------------*/
10166 /* genrshOne - right shift a one byte quantity by known count */
10167 /*-----------------------------------------------------------------*/
10168 static void genrshOne (operand *result, operand *left,
10169 int shCount, int sign)
10171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10172 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10175 /*-----------------------------------------------------------------*/
10176 /* genrshTwo - right shift two bytes by known amount != 0 */
10177 /*-----------------------------------------------------------------*/
10178 static void genrshTwo (operand *result,operand *left,
10179 int shCount, int sign)
10181 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10182 /* if shCount >= 8 */
10183 if (shCount >= 8) {
10186 shiftR1Left2Result(left, MSB16, result, LSB,
10189 movLeft2Result(left, MSB16, result, LSB);
10191 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10194 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10195 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10199 /* 1 <= shCount <= 7 */
10201 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10204 /*-----------------------------------------------------------------*/
10205 /* shiftRLong - shift right one long from left to result */
10206 /* offl = LSB or MSB16 */
10207 /*-----------------------------------------------------------------*/
10208 static void shiftRLong (operand *left, int offl,
10209 operand *result, int sign)
10211 int size = AOP_SIZE(result);
10212 int same = pic16_sameRegs(AOP(left),AOP(result));
10214 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10216 if (same && (offl == MSB16)) { //shift one byte right
10217 for(i=MSB16;i<size;i++) {
10218 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10219 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10224 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10230 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10232 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10236 if(offl == MSB16) {
10237 /* add sign of "a" */
10238 pic16_addSign(result, MSB32, sign);
10242 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10244 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10249 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10251 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10252 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10256 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10259 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10260 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10265 /*-----------------------------------------------------------------*/
10266 /* genrshFour - shift four byte by a known amount != 0 */
10267 /*-----------------------------------------------------------------*/
10268 static void genrshFour (operand *result, operand *left,
10269 int shCount, int sign)
10271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10272 /* if shifting more that 3 bytes */
10273 if(shCount >= 24 ) {
10276 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10278 movLeft2Result(left, MSB32, result, LSB);
10280 pic16_addSign(result, MSB16, sign);
10282 else if(shCount >= 16){
10285 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10287 movLeft2Result(left, MSB24, result, LSB);
10288 movLeft2Result(left, MSB32, result, MSB16);
10290 pic16_addSign(result, MSB24, sign);
10292 else if(shCount >= 8){
10295 shiftRLong(left, MSB16, result, sign);
10296 else if(shCount == 0){
10297 movLeft2Result(left, MSB16, result, LSB);
10298 movLeft2Result(left, MSB24, result, MSB16);
10299 movLeft2Result(left, MSB32, result, MSB24);
10300 pic16_addSign(result, MSB32, sign);
10302 else{ //shcount >= 2
10303 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10304 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10305 /* the last shift is signed */
10306 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10307 pic16_addSign(result, MSB32, sign);
10310 else{ /* 1 <= shCount <= 7 */
10312 shiftRLong(left, LSB, result, sign);
10314 shiftRLong(result, LSB, result, sign);
10317 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10318 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10319 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10324 /*-----------------------------------------------------------------*/
10325 /* genRightShiftLiteral - right shifting by known count */
10326 /*-----------------------------------------------------------------*/
10327 static void genRightShiftLiteral (operand *left,
10333 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10334 int lsize,res_size;
10336 pic16_freeAsmop(right,NULL,ic,TRUE);
10338 pic16_aopOp(left,ic,FALSE);
10339 pic16_aopOp(result,ic,FALSE);
10341 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10344 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10348 lsize = pic16_getDataSize(left);
10349 res_size = pic16_getDataSize(result);
10350 /* test the LEFT size !!! */
10352 /* I suppose that the left size >= result size */
10355 movLeft2Result(left, lsize, result, res_size);
10358 else if(shCount >= (lsize * 8)){
10360 if(res_size == 1) {
10361 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10363 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10364 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10369 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10370 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10371 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10373 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10378 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10383 switch (res_size) {
10385 genrshOne (result,left,shCount,sign);
10389 genrshTwo (result,left,shCount,sign);
10393 genrshFour (result,left,shCount,sign);
10401 pic16_freeAsmop(left,NULL,ic,TRUE);
10402 pic16_freeAsmop(result,NULL,ic,TRUE);
10405 #if !(USE_GENERIC_SIGNED_SHIFT)
10406 /*-----------------------------------------------------------------*/
10407 /* genSignedRightShift - right shift of signed number */
10408 /*-----------------------------------------------------------------*/
10409 static void genSignedRightShift (iCode *ic)
10411 operand *right, *left, *result;
10414 symbol *tlbl, *tlbl1 ;
10417 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10419 /* we do it the hard way put the shift count in b
10420 and loop thru preserving the sign */
10421 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10423 right = IC_RIGHT(ic);
10424 left = IC_LEFT(ic);
10425 result = IC_RESULT(ic);
10427 pic16_aopOp(right,ic,FALSE);
10428 pic16_aopOp(left,ic,FALSE);
10429 pic16_aopOp(result,ic,FALSE);
10432 if ( AOP_TYPE(right) == AOP_LIT) {
10433 genRightShiftLiteral (left,right,result,ic,1);
10436 /* shift count is unknown then we have to form
10437 a loop get the loop count in B : Note: we take
10438 only the lower order byte since shifting
10439 more that 32 bits make no sense anyway, ( the
10440 largest size of an object can be only 32 bits ) */
10442 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10443 //pic16_emitcode("inc","b");
10444 //pic16_freeAsmop (right,NULL,ic,TRUE);
10445 //pic16_aopOp(left,ic,FALSE);
10446 //pic16_aopOp(result,ic,FALSE);
10448 /* now move the left to the result if they are not the
10450 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10451 AOP_SIZE(result) > 1) {
10453 size = AOP_SIZE(result);
10457 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10458 if (*l == '@' && IS_AOP_PREG(result)) {
10460 pic16_emitcode("mov","a,%s",l);
10461 pic16_aopPut(AOP(result),"a",offset);
10463 pic16_aopPut(AOP(result),l,offset);
10465 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10466 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10472 /* mov the highest order bit to OVR */
10473 tlbl = newiTempLabel(NULL);
10474 tlbl1= newiTempLabel(NULL);
10476 size = AOP_SIZE(result);
10479 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10481 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10483 /* offset should be 0, 1 or 3 */
10484 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10486 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10488 pic16_emitpcode(POC_MOVWF, pctemp);
10491 pic16_emitpLabel(tlbl->key);
10493 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10494 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10497 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10500 pic16_emitpcode(POC_DECFSZ, pctemp);
10501 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10502 pic16_emitpLabel(tlbl1->key);
10504 pic16_popReleaseTempReg(pctemp,1);
10506 size = AOP_SIZE(result);
10508 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10509 pic16_emitcode("rlc","a");
10510 pic16_emitcode("mov","ov,c");
10511 /* if it is only one byte then */
10513 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10515 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10516 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10517 pic16_emitcode("mov","c,ov");
10518 pic16_emitcode("rrc","a");
10519 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10520 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10521 pic16_aopPut(AOP(result),"a",0);
10525 reAdjustPreg(AOP(result));
10526 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10527 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10528 pic16_emitcode("mov","c,ov");
10530 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10532 pic16_emitcode("rrc","a");
10533 pic16_aopPut(AOP(result),"a",offset--);
10535 reAdjustPreg(AOP(result));
10536 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10537 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10542 pic16_freeAsmop(left,NULL,ic,TRUE);
10543 pic16_freeAsmop(result,NULL,ic,TRUE);
10544 pic16_freeAsmop(right,NULL,ic,TRUE);
10548 #if !(USE_GENERIC_SIGNED_SHIFT)
10549 #warning This implementation of genRightShift() is incomplete!
10550 /*-----------------------------------------------------------------*/
10551 /* genRightShift - generate code for right shifting */
10552 /*-----------------------------------------------------------------*/
10553 static void genRightShift (iCode *ic)
10555 operand *right, *left, *result;
10559 symbol *tlbl, *tlbl1 ;
10561 /* if signed then we do it the hard way preserve the
10562 sign bit moving it inwards */
10563 letype = getSpec(operandType(IC_LEFT(ic)));
10564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10566 if (!SPEC_USIGN(letype)) {
10567 genSignedRightShift (ic);
10571 /* signed & unsigned types are treated the same : i.e. the
10572 signed is NOT propagated inwards : quoting from the
10573 ANSI - standard : "for E1 >> E2, is equivalent to division
10574 by 2**E2 if unsigned or if it has a non-negative value,
10575 otherwise the result is implementation defined ", MY definition
10576 is that the sign does not get propagated */
10578 right = IC_RIGHT(ic);
10579 left = IC_LEFT(ic);
10580 result = IC_RESULT(ic);
10582 pic16_aopOp(right,ic,FALSE);
10584 /* if the shift count is known then do it
10585 as efficiently as possible */
10586 if (AOP_TYPE(right) == AOP_LIT) {
10587 genRightShiftLiteral (left,right,result,ic, 0);
10591 /* shift count is unknown then we have to form
10592 a loop get the loop count in B : Note: we take
10593 only the lower order byte since shifting
10594 more that 32 bits make no sense anyway, ( the
10595 largest size of an object can be only 32 bits ) */
10597 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10598 pic16_emitcode("inc","b");
10599 pic16_aopOp(left,ic,FALSE);
10600 pic16_aopOp(result,ic,FALSE);
10602 /* now move the left to the result if they are not the
10604 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10605 AOP_SIZE(result) > 1) {
10607 size = AOP_SIZE(result);
10610 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10611 if (*l == '@' && IS_AOP_PREG(result)) {
10613 pic16_emitcode("mov","a,%s",l);
10614 pic16_aopPut(AOP(result),"a",offset);
10616 pic16_aopPut(AOP(result),l,offset);
10621 tlbl = newiTempLabel(NULL);
10622 tlbl1= newiTempLabel(NULL);
10623 size = AOP_SIZE(result);
10626 /* if it is only one byte then */
10629 tlbl = newiTempLabel(NULL);
10630 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10631 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10635 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10636 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10637 pic16_emitpLabel(tlbl->key);
10638 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10639 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10641 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10646 reAdjustPreg(AOP(result));
10647 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10648 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10651 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10653 pic16_emitcode("rrc","a");
10654 pic16_aopPut(AOP(result),"a",offset--);
10656 reAdjustPreg(AOP(result));
10658 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10659 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10662 pic16_freeAsmop(left,NULL,ic,TRUE);
10663 pic16_freeAsmop (right,NULL,ic,TRUE);
10664 pic16_freeAsmop(result,NULL,ic,TRUE);
10668 #if (USE_GENERIC_SIGNED_SHIFT)
10669 /*-----------------------------------------------------------------*/
10670 /* genGenericShift - generates code for left or right shifting */
10671 /*-----------------------------------------------------------------*/
10672 static void genGenericShift (iCode *ic, int isShiftLeft) {
10673 operand *left,*right, *result;
10675 int sign, signedCount;
10676 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10677 PIC_OPCODE pos_shift, neg_shift;
10681 right = IC_RIGHT(ic);
10682 left = IC_LEFT(ic);
10683 result = IC_RESULT(ic);
10685 pic16_aopOp(right,ic,FALSE);
10686 pic16_aopOp(left,ic,FALSE);
10687 pic16_aopOp(result,ic,FALSE);
10689 sign = !SPEC_USIGN(operandType (left));
10690 signedCount = !SPEC_USIGN(operandType (right));
10692 /* if the shift count is known then do it
10693 as efficiently as possible */
10694 if (AOP_TYPE(right) == AOP_LIT) {
10695 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10696 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10697 // we should modify right->aopu.aop_lit here!
10698 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10699 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10701 pic16_genLeftShiftLiteral (left,right,result,ic);
10703 genRightShiftLiteral (left,right,result,ic, sign);
10706 } // if (right is literal)
10708 /* shift count is unknown then we have to form a loop.
10709 * Note: we take only the lower order byte since shifting
10710 * more than 32 bits make no sense anyway, ( the
10711 * largest size of an object can be only 32 bits )
10712 * Note: we perform arithmetic shifts if the left operand is
10713 * signed and we do an (effective) right shift, i. e. we
10714 * shift in the sign bit from the left. */
10716 label_complete = newiTempLabel ( NULL );
10717 label_loop_pos = newiTempLabel ( NULL );
10718 label_loop_neg = NULL;
10719 label_negative = NULL;
10720 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10721 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10724 // additional labels needed
10725 label_loop_neg = newiTempLabel ( NULL );
10726 label_negative = newiTempLabel ( NULL );
10729 // copy source to result -- this will effectively truncate the left operand to the size of result!
10730 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10731 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10732 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10733 mov2f (AOP(result),AOP(left), offset);
10736 // if result is longer than left, fill with zeros (or sign)
10737 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10738 if (sign && AOP_SIZE(left) > 0) {
10739 // shift signed operand -- fill with sign
10740 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10741 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10742 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10743 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10744 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10747 // shift unsigned operand -- fill result with zeros
10748 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10749 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10752 } // if (size mismatch)
10754 pic16_mov2w (AOP(right), 0);
10755 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10756 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10759 // perform a shift by one (shift count is positive)
10760 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10761 // 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])
10762 pic16_emitpLabel (label_loop_pos->key);
10764 if (sign && (pos_shift == POC_RRCF)) {
10765 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10768 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10769 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10770 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10772 // perform a shift by one (shift count is positive)
10773 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10774 // 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])
10775 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10776 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10778 pic16_emitpLabel (label_loop_pos->key);
10779 if (sign && (pos_shift == POC_RRCF)) {
10780 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10783 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10784 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10785 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10786 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10790 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10792 pic16_emitpLabel (label_negative->key);
10793 // perform a shift by -1 (shift count is negative)
10794 // 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)
10796 pic16_emitpLabel (label_loop_neg->key);
10797 if (sign && (neg_shift == POC_RRCF)) {
10798 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10801 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10802 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10803 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10804 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10805 } // if (signedCount)
10807 pic16_emitpLabel (label_complete->key);
10810 pic16_freeAsmop (right,NULL,ic,TRUE);
10811 pic16_freeAsmop(left,NULL,ic,TRUE);
10812 pic16_freeAsmop(result,NULL,ic,TRUE);
10815 static void genLeftShift (iCode *ic) {
10816 genGenericShift (ic, 1);
10819 static void genRightShift (iCode *ic) {
10820 genGenericShift (ic, 0);
10825 void pic16_loadFSR0(operand *op)
10827 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10830 /*-----------------------------------------------------------------*/
10831 /* genUnpackBits - generates code for unpacking bits */
10832 /*-----------------------------------------------------------------*/
10833 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10837 sym_link *etype, *letype;
10838 int blen=0, bstr=0;
10842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10843 etype = getSpec(operandType(result));
10844 letype = getSpec(operandType(left));
10846 // if(IS_BITFIELD(etype)) {
10847 blen = SPEC_BLEN(etype);
10848 bstr = SPEC_BSTR(etype);
10851 lbstr = SPEC_BSTR( letype );
10854 if((blen == 1) && (bstr < 8)) {
10855 /* it is a single bit, so use the appropriate bit instructions */
10856 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10858 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10860 if((ptype == POINTER) && (result)) {
10861 /* workaround to reduce the extra lfsr instruction */
10862 pic16_emitpcode(POC_BTFSC,
10863 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10865 pic16_emitpcode(POC_BTFSC,
10866 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10869 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10871 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10877 /* the following call to pic16_loadFSR0 is temporary until
10878 * optimization to handle single bit assignments is added
10879 * to the function. Until then use the old safe way! -- VR */
10880 pic16_loadFSR0( left );
10882 /* read the first byte */
10889 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10892 pic16_emitcode("clr","a");
10893 pic16_emitcode("movc","a","@a+dptr");
10898 /* if we have bitdisplacement then it fits */
10899 /* into this byte completely or if length is */
10900 /* less than a byte */
10901 if ((shCnt = SPEC_BSTR(etype)) ||
10902 (SPEC_BLEN(etype) <= 8)) {
10904 /* shift right acc */
10907 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10908 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10910 /* VR -- normally I would use the following, but since we use the hack,
10911 * to avoid the masking from AccRsh, why not mask it right now? */
10914 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10923 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10924 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10927 /* bit field did not fit in a byte */
10928 rlen = SPEC_BLEN(etype) - 8;
10929 pic16_aopPut(AOP(result),"a",offset++);
10936 pic16_emitcode("inc","%s",rname);
10937 pic16_emitcode("mov","a,@%s",rname);
10941 pic16_emitcode("inc","%s",rname);
10942 pic16_emitcode("movx","a,@%s",rname);
10946 pic16_emitcode("inc","dptr");
10947 pic16_emitcode("movx","a,@dptr");
10951 pic16_emitcode("clr","a");
10952 pic16_emitcode("inc","dptr");
10953 pic16_emitcode("movc","a","@a+dptr");
10957 pic16_emitcode("inc","dptr");
10958 pic16_emitcode("lcall","__gptrget");
10963 /* if we are done */
10967 pic16_aopPut(AOP(result),"a",offset++);
10972 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10973 pic16_aopPut(AOP(result),"a",offset);
10980 static void genDataPointerGet(operand *left,
10984 int size, offset = 0, leoffset=0 ;
10986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10987 pic16_aopOp(result, ic, FALSE);
10989 size = AOP_SIZE(result);
10990 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10994 /* The following tests may save a redudant movff instruction when
10995 * accessing unions */
10997 /* if they are the same */
10998 if (operandsEqu (left, result)) {
10999 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
11005 /* if they are the same registers */
11006 if (pic16_sameRegs(AOP(left),AOP(result))) {
11007 DEBUGpic16_emitcode("; ***", "left and result registers are same");
11013 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11014 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11015 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11022 if ( AOP_TYPE(left) == AOP_PCODE) {
11023 fprintf(stderr,"genDataPointerGet %s, %d\n",
11024 AOP(left)->aopu.pcop->name,
11025 (AOP(left)->aopu.pcop->type == PO_DIR)?
11026 PCOR(AOP(left)->aopu.pcop)->instance:
11027 PCOI(AOP(left)->aopu.pcop)->offset);
11031 if(AOP(left)->aopu.pcop->type == PO_DIR)
11032 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11034 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11037 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11039 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11040 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11041 pic16_mov2w(AOP(left), offset); // patch 8
11042 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11045 pic16_popGet(AOP(left), offset), //patch 8
11046 pic16_popGet(AOP(result), offset)));
11054 pic16_freeAsmop(result,NULL,ic,TRUE);
11059 /*-----------------------------------------------------------------*/
11060 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11061 /*-----------------------------------------------------------------*/
11062 static void genNearPointerGet (operand *left,
11067 //regs *preg = NULL ;
11068 sym_link *rtype, *retype;
11069 sym_link *ltype = operandType(left);
11073 rtype = operandType(result);
11074 retype= getSpec(rtype);
11076 pic16_aopOp(left,ic,FALSE);
11078 // pic16_DumpOp("(left)",left);
11079 // pic16_DumpOp("(result)",result);
11081 /* if left is rematerialisable and
11082 * result is not bit variable type and
11083 * the left is pointer to data space i.e
11084 * lower 128 bytes of space */
11086 if (AOP_TYPE(left) == AOP_PCODE
11087 && !IS_BITFIELD(retype)
11088 && DCL_TYPE(ltype) == POINTER) {
11090 genDataPointerGet (left,result,ic);
11091 pic16_freeAsmop(left, NULL, ic, TRUE);
11095 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11096 pic16_aopOp (result,ic,FALSE);
11098 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11101 if(IS_BITFIELD( retype )
11102 && (SPEC_BLEN(operandType(result))==1)
11106 int bitstrt, bytestrt;
11108 /* if this is bitfield of size 1, see if we are checking the value
11109 * of a single bit in an if-statement,
11110 * if yes, then don't generate usual code, but execute the
11111 * genIfx directly -- VR */
11115 /* CHECK: if next iCode is IFX
11116 * and current result operand is nextic's conditional operand
11117 * and current result operand live ranges ends at nextic's key number
11119 if((nextic->op == IFX)
11120 && (result == IC_COND(nextic))
11121 && (OP_LIVETO(result) == nextic->seq)
11123 /* everything is ok then */
11124 /* find a way to optimize the genIfx iCode */
11126 bytestrt = SPEC_BSTR(operandType(result))/8;
11127 bitstrt = SPEC_BSTR(operandType(result))%8;
11129 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11131 genIfxpCOpJump(nextic, jop);
11133 pic16_freeAsmop(left, NULL, ic, TRUE);
11134 pic16_freeAsmop(result, NULL, ic, TRUE);
11141 /* if the value is already in a pointer register
11142 * then don't need anything more */
11143 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11144 /* otherwise get a free pointer register */
11145 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11147 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11148 /* bitfields will be handled by genUnpackBits */
11149 if(!IS_BITFIELD(retype)) {
11151 if(is_LitAOp( AOP(left) )) {
11152 pic16_loadFSR0( left );
11154 // set up FSR0 with address from left
11155 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11156 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11161 /* if bitfield then unpack the bits */
11162 if (IS_BITFIELD(retype))
11163 genUnpackBits (result, left, NULL, POINTER);
11165 /* we have can just get the values */
11166 int size = AOP_SIZE(result);
11169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11171 /* fsr0 is loaded already -- VR */
11172 // pic16_loadFSR0( left );
11174 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11175 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11178 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11179 pic16_popGet(AOP(result), offset++)));
11181 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11182 pic16_popGet(AOP(result), offset++)));
11186 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11187 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11189 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11193 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11195 pic16_emitcode("mov","a,@%s",rname);
11196 pic16_aopPut(AOP(result),"a",offset);
11198 sprintf(buffer,"@%s",rname);
11199 pic16_aopPut(AOP(result),buffer,offset);
11203 pic16_emitcode("inc","%s",rname);
11208 /* now some housekeeping stuff */
11210 /* we had to allocate for this iCode */
11211 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11212 pic16_freeAsmop(NULL,aop,ic,TRUE);
11214 /* we did not allocate which means left
11215 * already in a pointer register, then
11216 * if size > 0 && this could be used again
11217 * we have to point it back to where it
11219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11220 if (AOP_SIZE(result) > 1
11221 && !OP_SYMBOL(left)->remat
11222 && ( OP_SYMBOL(left)->liveTo > ic->seq
11224 // int size = AOP_SIZE(result) - 1;
11226 // pic16_emitcode("dec","%s",rname);
11231 pic16_freeAsmop(left,NULL,ic,TRUE);
11232 pic16_freeAsmop(result,NULL,ic,TRUE);
11235 /*-----------------------------------------------------------------*/
11236 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11237 /*-----------------------------------------------------------------*/
11238 static void genPagedPointerGet (operand *left,
11243 regs *preg = NULL ;
11245 sym_link *rtype, *retype;
11247 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11249 rtype = operandType(result);
11250 retype= getSpec(rtype);
11252 pic16_aopOp(left,ic,FALSE);
11254 /* if the value is already in a pointer register
11255 then don't need anything more */
11256 if (!AOP_INPREG(AOP(left))) {
11257 /* otherwise get a free pointer register */
11259 preg = getFreePtr(ic,&aop,FALSE);
11260 pic16_emitcode("mov","%s,%s",
11262 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11263 rname = preg->name ;
11265 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11267 pic16_freeAsmop(left,NULL,ic,TRUE);
11268 pic16_aopOp (result,ic,FALSE);
11270 /* if bitfield then unpack the bits */
11271 if (IS_BITFIELD(retype))
11272 genUnpackBits (result,left,rname,PPOINTER);
11274 /* we have can just get the values */
11275 int size = AOP_SIZE(result);
11280 pic16_emitcode("movx","a,@%s",rname);
11281 pic16_aopPut(AOP(result),"a",offset);
11286 pic16_emitcode("inc","%s",rname);
11290 /* now some housekeeping stuff */
11292 /* we had to allocate for this iCode */
11293 pic16_freeAsmop(NULL,aop,ic,TRUE);
11295 /* we did not allocate which means left
11296 already in a pointer register, then
11297 if size > 0 && this could be used again
11298 we have to point it back to where it
11300 if (AOP_SIZE(result) > 1 &&
11301 !OP_SYMBOL(left)->remat &&
11302 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11304 int size = AOP_SIZE(result) - 1;
11306 pic16_emitcode("dec","%s",rname);
11311 pic16_freeAsmop(result,NULL,ic,TRUE);
11316 /*-----------------------------------------------------------------*/
11317 /* genFarPointerGet - gget value from far space */
11318 /*-----------------------------------------------------------------*/
11319 static void genFarPointerGet (operand *left,
11320 operand *result, iCode *ic)
11323 sym_link *retype = getSpec(operandType(result));
11325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11327 pic16_aopOp(left,ic,FALSE);
11329 /* if the operand is already in dptr
11330 then we do nothing else we move the value to dptr */
11331 if (AOP_TYPE(left) != AOP_STR) {
11332 /* if this is remateriazable */
11333 if (AOP_TYPE(left) == AOP_IMMD)
11334 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11335 else { /* we need to get it byte by byte */
11336 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11337 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11338 if (options.model == MODEL_FLAT24)
11340 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11344 /* so dptr know contains the address */
11345 pic16_freeAsmop(left,NULL,ic,TRUE);
11346 pic16_aopOp(result,ic,FALSE);
11348 /* if bit then unpack */
11349 if (IS_BITFIELD(retype))
11350 genUnpackBits(result,left,"dptr",FPOINTER);
11352 size = AOP_SIZE(result);
11356 pic16_emitcode("movx","a,@dptr");
11357 pic16_aopPut(AOP(result),"a",offset++);
11359 pic16_emitcode("inc","dptr");
11363 pic16_freeAsmop(result,NULL,ic,TRUE);
11367 /*-----------------------------------------------------------------*/
11368 /* genCodePointerGet - get value from code space */
11369 /*-----------------------------------------------------------------*/
11370 static void genCodePointerGet (operand *left,
11371 operand *result, iCode *ic)
11374 sym_link *retype = getSpec(operandType(result));
11376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11378 pic16_aopOp(left,ic,FALSE);
11380 /* if the operand is already in dptr
11381 then we do nothing else we move the value to dptr */
11382 if (AOP_TYPE(left) != AOP_STR) {
11383 /* if this is remateriazable */
11384 if (AOP_TYPE(left) == AOP_IMMD)
11385 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11386 else { /* we need to get it byte by byte */
11387 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11388 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11389 if (options.model == MODEL_FLAT24)
11391 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11395 /* so dptr know contains the address */
11396 pic16_freeAsmop(left,NULL,ic,TRUE);
11397 pic16_aopOp(result,ic,FALSE);
11399 /* if bit then unpack */
11400 if (IS_BITFIELD(retype))
11401 genUnpackBits(result,left,"dptr",CPOINTER);
11403 size = AOP_SIZE(result);
11407 pic16_emitcode("clr","a");
11408 pic16_emitcode("movc","a,@a+dptr");
11409 pic16_aopPut(AOP(result),"a",offset++);
11411 pic16_emitcode("inc","dptr");
11415 pic16_freeAsmop(result,NULL,ic,TRUE);
11420 /*-----------------------------------------------------------------*/
11421 /* genGenPointerGet - gget value from generic pointer space */
11422 /*-----------------------------------------------------------------*/
11423 static void genGenPointerGet (operand *left,
11424 operand *result, iCode *ic)
11426 int size, offset, lit;
11427 sym_link *retype = getSpec(operandType(result));
11429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11430 pic16_aopOp(left,ic,FALSE);
11431 pic16_aopOp(result,ic,FALSE);
11432 size = AOP_SIZE(result);
11434 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11436 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11438 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11439 // load FSR0 from immediate
11440 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11442 // pic16_loadFSR0( left );
11447 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11456 else { /* we need to get it byte by byte */
11457 // set up FSR0 with address from left
11458 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11465 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11474 /* if bit then unpack */
11475 if (IS_BITFIELD(retype))
11476 genUnpackBits(result,left,"BAD",GPOINTER);
11479 pic16_freeAsmop(left,NULL,ic,TRUE);
11480 pic16_freeAsmop(result,NULL,ic,TRUE);
11486 /*-----------------------------------------------------------------*/
11487 /* genGenPointerGet - gget value from generic pointer space */
11488 /*-----------------------------------------------------------------*/
11489 static void genGenPointerGet (operand *left,
11490 operand *result, iCode *ic)
11492 int size, offset, lit;
11493 sym_link *retype = getSpec(operandType(result));
11496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11497 pic16_aopOp(left,ic,FALSE);
11498 pic16_aopOp(result,ic,FALSE);
11499 size = AOP_SIZE(result);
11501 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11503 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11505 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11506 // load FSR0 from immediate
11507 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11509 werror(W_POSSBUG2, __FILE__, __LINE__);
11514 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11516 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11523 } else { /* we need to get it byte by byte */
11525 /* set up WREG:PRODL:FSR0L with address from left */
11526 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11527 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11528 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11531 case 1: strcpy(fgptrget, "__gptrget1"); break;
11532 case 2: strcpy(fgptrget, "__gptrget2"); break;
11533 case 3: strcpy(fgptrget, "__gptrget3"); break;
11534 case 4: strcpy(fgptrget, "__gptrget4"); break;
11536 werror(W_POSSBUG2, __FILE__, __LINE__);
11540 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11542 assignResultValue(result, 1);
11547 sym = newSymbol( fgptrget, 0 );
11548 strcpy(sym->rname, fgptrget);
11549 checkAddSym(&externs, sym);
11551 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11557 /* if bit then unpack */
11558 if (IS_BITFIELD(retype))
11559 genUnpackBits(result,left,"BAD",GPOINTER);
11562 pic16_freeAsmop(left,NULL,ic,TRUE);
11563 pic16_freeAsmop(result,NULL,ic,TRUE);
11566 /*-----------------------------------------------------------------*/
11567 /* genConstPointerGet - get value from const generic pointer space */
11568 /*-----------------------------------------------------------------*/
11569 static void genConstPointerGet (operand *left,
11570 operand *result, iCode *ic)
11572 //sym_link *retype = getSpec(operandType(result));
11573 // symbol *albl = newiTempLabel(NULL); // patch 15
11574 // symbol *blbl = newiTempLabel(NULL); //
11575 // PIC_OPCODE poc; // patch 15
11579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11580 pic16_aopOp(left,ic,FALSE);
11581 pic16_aopOp(result,ic,TRUE);
11582 size = AOP_SIZE(result);
11584 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11586 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11588 // set up table pointer
11589 if( (AOP_TYPE(left) == AOP_PCODE)
11590 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11591 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11593 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11594 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11595 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11596 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11597 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11598 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11600 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11601 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11602 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11606 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11607 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11611 pic16_freeAsmop(left,NULL,ic,TRUE);
11612 pic16_freeAsmop(result,NULL,ic,TRUE);
11616 /*-----------------------------------------------------------------*/
11617 /* genPointerGet - generate code for pointer get */
11618 /*-----------------------------------------------------------------*/
11619 static void genPointerGet (iCode *ic)
11621 operand *left, *result ;
11622 sym_link *type, *etype;
11627 left = IC_LEFT(ic);
11628 result = IC_RESULT(ic) ;
11630 /* depending on the type of pointer we need to
11631 move it to the correct pointer register */
11632 type = operandType(left);
11633 etype = getSpec(type);
11636 if (IS_PTR_CONST(type))
11638 if (IS_CODEPTR(type))
11640 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11642 /* if left is of type of pointer then it is simple */
11643 if (IS_PTR(type) && !IS_FUNC(type->next))
11644 p_type = DCL_TYPE(type);
11646 /* we have to go by the storage class */
11647 p_type = PTR_TYPE(SPEC_OCLS(etype));
11649 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11651 if (SPEC_OCLS(etype)->codesp ) {
11652 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11653 //p_type = CPOINTER ;
11655 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11656 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11657 /*p_type = FPOINTER ;*/
11659 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11660 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11661 /* p_type = PPOINTER; */
11663 if (SPEC_OCLS(etype) == idata ) {
11664 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11665 /* p_type = IPOINTER; */
11667 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11668 /* p_type = POINTER ; */
11672 /* now that we have the pointer type we assign
11673 the pointer values */
11677 genNearPointerGet (left,result,ic);
11681 genPagedPointerGet(left,result,ic);
11685 genFarPointerGet (left,result,ic);
11689 genConstPointerGet (left,result,ic);
11690 //pic16_emitcodePointerGet (left,result,ic);
11695 if (IS_PTR_CONST(type))
11696 genConstPointerGet (left,result,ic);
11699 genGenPointerGet (left,result,ic);
11703 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11704 "genPointerGet: illegal pointer type");
11709 /*-----------------------------------------------------------------*/
11710 /* genPackBits - generates code for packed bit storage */
11711 /*-----------------------------------------------------------------*/
11712 static void genPackBits (sym_link *etype , operand *result,
11714 char *rname, int p_type)
11723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11724 blen = SPEC_BLEN(etype);
11725 bstr = SPEC_BSTR(etype);
11727 retype = getSpec(operandType(right));
11729 if(AOP_TYPE(right) == AOP_LIT) {
11730 if((blen == 1) && (bstr < 8)) {
11732 /* it is a single bit, so use the appropriate bit instructions */
11734 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11736 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11737 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11738 if((p_type == POINTER) && (result)) {
11739 /* workaround to reduce the extra lfsr instruction */
11741 pic16_emitpcode(POC_BSF,
11742 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11744 pic16_emitpcode(POC_BCF,
11745 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11748 pic16_loadFSR0( result );
11750 pic16_emitpcode(POC_BSF,
11751 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11753 pic16_emitpcode(POC_BCF,
11754 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11761 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11764 if(IS_BITFIELD(retype)
11765 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11769 rblen = SPEC_BLEN( retype );
11770 rbstr = SPEC_BSTR( retype );
11773 if(IS_BITFIELD(etype)) {
11774 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11775 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11777 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11780 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11782 if(IS_BITFIELD(etype)) {
11783 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11785 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11788 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11792 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11794 /* if the bit lenth is less than or */
11795 /* it exactly fits a byte then */
11796 if((shCnt=SPEC_BSTR(etype))
11797 || SPEC_BLEN(etype) <= 8 ) {
11799 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11801 /* shift left acc */
11804 /* using PRODL as a temporary register here */
11805 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11810 pic16_loadFSR0( result );
11811 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11812 // pic16_emitcode ("mov","b,a");
11813 // pic16_emitcode("mov","a,@%s",rname);
11817 werror(W_POSSBUG2, __FILE__, __LINE__);
11822 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11823 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11824 (unsigned char)(0xff >> (8-bstr))) ));
11825 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11826 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11833 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11834 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11839 if ( SPEC_BLEN(etype) <= 8 )
11842 pic16_emitcode("inc","%s",rname);
11843 rLen = SPEC_BLEN(etype) ;
11847 /* now generate for lengths greater than one byte */
11850 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11860 pic16_emitcode("mov","@%s,a",rname);
11862 pic16_emitcode("mov","@%s,%s",rname,l);
11867 pic16_emitcode("movx","@dptr,a");
11872 DEBUGpic16_emitcode(";lcall","__gptrput");
11875 pic16_emitcode ("inc","%s",rname);
11880 /* last last was not complete */
11882 /* save the byte & read byte */
11885 pic16_emitcode ("mov","b,a");
11886 pic16_emitcode("mov","a,@%s",rname);
11890 pic16_emitcode ("mov","b,a");
11891 pic16_emitcode("movx","a,@dptr");
11895 pic16_emitcode ("push","b");
11896 pic16_emitcode ("push","acc");
11897 pic16_emitcode ("lcall","__gptrget");
11898 pic16_emitcode ("pop","b");
11902 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11903 pic16_emitcode ("orl","a,b");
11906 if (p_type == GPOINTER)
11907 pic16_emitcode("pop","b");
11912 pic16_emitcode("mov","@%s,a",rname);
11916 pic16_emitcode("movx","@dptr,a");
11920 DEBUGpic16_emitcode(";lcall","__gptrput");
11924 /*-----------------------------------------------------------------*/
11925 /* genDataPointerSet - remat pointer to data space */
11926 /*-----------------------------------------------------------------*/
11927 static void genDataPointerSet(operand *right,
11931 int size, offset = 0, resoffset=0 ;
11933 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11934 pic16_aopOp(right,ic,FALSE);
11936 size = AOP_SIZE(right);
11938 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11941 if ( AOP_TYPE(result) == AOP_PCODE) {
11942 fprintf(stderr,"genDataPointerSet %s, %d\n",
11943 AOP(result)->aopu.pcop->name,
11944 (AOP(result)->aopu.pcop->type == PO_DIR)?
11945 PCOR(AOP(result)->aopu.pcop)->instance:
11946 PCOI(AOP(result)->aopu.pcop)->offset);
11950 if(AOP(result)->aopu.pcop->type == PO_DIR)
11951 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11954 if (AOP_TYPE(right) == AOP_LIT) {
11957 if(!IS_FLOAT(operandType( right )))
11958 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11961 unsigned long lit_int;
11965 /* take care if literal is a float */
11966 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11967 lit = info.lit_int;
11970 lit = lit >> (8*offset);
11972 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11973 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11975 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11978 pic16_mov2w(AOP(right), offset);
11979 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11985 pic16_freeAsmop(right,NULL,ic,TRUE);
11990 /*-----------------------------------------------------------------*/
11991 /* genNearPointerSet - pic16_emitcode for near pointer put */
11992 /*-----------------------------------------------------------------*/
11993 static void genNearPointerSet (operand *right,
12000 sym_link *ptype = operandType(result);
12001 sym_link *resetype;
12003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12004 retype= getSpec(operandType(right));
12005 resetype = getSpec(operandType(result));
12007 pic16_aopOp(result,ic,FALSE);
12009 /* if the result is rematerializable &
12010 * in data space & not a bit variable */
12012 /* and result is not a bit variable */
12013 if (AOP_TYPE(result) == AOP_PCODE
12014 // && AOP_TYPE(result) == AOP_IMMD
12015 && DCL_TYPE(ptype) == POINTER
12016 && !IS_BITFIELD(retype)
12017 && !IS_BITFIELD(resetype)) {
12019 genDataPointerSet (right,result,ic);
12020 pic16_freeAsmop(result,NULL,ic,TRUE);
12024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12025 pic16_aopOp(right,ic,FALSE);
12026 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12028 /* if the value is already in a pointer register
12029 * then don't need anything more */
12030 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12031 /* otherwise get a free pointer register */
12032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12034 // if( (AOP_TYPE(result) == AOP_PCODE)
12035 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12036 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12037 if(is_LitAOp( AOP(result) ))
12039 if(!IS_BITFIELD(resetype))
12040 pic16_loadFSR0( result ); // patch 10
12042 if(!IS_BITFIELD(resetype)) {
12043 // set up FSR0 with address of result
12044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12045 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12051 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12055 // pic16_loadFSR0( result );
12057 /* if bitfield then unpack the bits */
12058 if (IS_BITFIELD(resetype)) {
12059 genPackBits (resetype, result, right, NULL, POINTER);
12061 /* we have can just get the values */
12062 int size = AOP_SIZE(right);
12065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12067 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12070 //pic16_emitcode("mov","@%s,a",rname);
12071 pic16_emitcode("movf","indf0,w ;1");
12074 if (AOP_TYPE(right) == AOP_LIT) {
12075 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12077 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12079 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12081 } else { // no literal
12083 pic16_emitpcode(POC_MOVFF,
12084 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12085 pic16_popCopyReg(&pic16_pc_postinc0)));
12087 pic16_emitpcode(POC_MOVFF,
12088 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12089 pic16_popCopyReg(&pic16_pc_indf0)));
12097 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12098 /* now some housekeeping stuff */
12100 /* we had to allocate for this iCode */
12101 pic16_freeAsmop(NULL,aop,ic,TRUE);
12103 /* we did not allocate which means left
12104 * already in a pointer register, then
12105 * if size > 0 && this could be used again
12106 * we have to point it back to where it
12108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12109 if (AOP_SIZE(right) > 1
12110 && !OP_SYMBOL(result)->remat
12111 && ( OP_SYMBOL(result)->liveTo > ic->seq
12114 int size = AOP_SIZE(right) - 1;
12117 pic16_emitcode("decf","fsr0,f");
12118 //pic16_emitcode("dec","%s",rname);
12122 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12125 pic16_freeAsmop(right,NULL,ic,TRUE);
12126 pic16_freeAsmop(result,NULL,ic,TRUE);
12129 /*-----------------------------------------------------------------*/
12130 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12131 /*-----------------------------------------------------------------*/
12132 static void genPagedPointerSet (operand *right,
12137 regs *preg = NULL ;
12141 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12143 retype= getSpec(operandType(right));
12145 pic16_aopOp(result,ic,FALSE);
12147 /* if the value is already in a pointer register
12148 then don't need anything more */
12149 if (!AOP_INPREG(AOP(result))) {
12150 /* otherwise get a free pointer register */
12152 preg = getFreePtr(ic,&aop,FALSE);
12153 pic16_emitcode("mov","%s,%s",
12155 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12156 rname = preg->name ;
12158 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12160 pic16_freeAsmop(result,NULL,ic,TRUE);
12161 pic16_aopOp (right,ic,FALSE);
12163 /* if bitfield then unpack the bits */
12164 if (IS_BITFIELD(retype))
12165 genPackBits (retype,result,right,rname,PPOINTER);
12167 /* we have can just get the values */
12168 int size = AOP_SIZE(right);
12172 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12175 pic16_emitcode("movx","@%s,a",rname);
12178 pic16_emitcode("inc","%s",rname);
12184 /* now some housekeeping stuff */
12186 /* we had to allocate for this iCode */
12187 pic16_freeAsmop(NULL,aop,ic,TRUE);
12189 /* we did not allocate which means left
12190 already in a pointer register, then
12191 if size > 0 && this could be used again
12192 we have to point it back to where it
12194 if (AOP_SIZE(right) > 1 &&
12195 !OP_SYMBOL(result)->remat &&
12196 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12198 int size = AOP_SIZE(right) - 1;
12200 pic16_emitcode("dec","%s",rname);
12205 pic16_freeAsmop(right,NULL,ic,TRUE);
12210 /*-----------------------------------------------------------------*/
12211 /* genFarPointerSet - set value from far space */
12212 /*-----------------------------------------------------------------*/
12213 static void genFarPointerSet (operand *right,
12214 operand *result, iCode *ic)
12217 sym_link *retype = getSpec(operandType(right));
12219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12220 pic16_aopOp(result,ic,FALSE);
12222 /* if the operand is already in dptr
12223 then we do nothing else we move the value to dptr */
12224 if (AOP_TYPE(result) != AOP_STR) {
12225 /* if this is remateriazable */
12226 if (AOP_TYPE(result) == AOP_IMMD)
12227 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12228 else { /* we need to get it byte by byte */
12229 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12230 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12231 if (options.model == MODEL_FLAT24)
12233 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12237 /* so dptr know contains the address */
12238 pic16_freeAsmop(result,NULL,ic,TRUE);
12239 pic16_aopOp(right,ic,FALSE);
12241 /* if bit then unpack */
12242 if (IS_BITFIELD(retype))
12243 genPackBits(retype,result,right,"dptr",FPOINTER);
12245 size = AOP_SIZE(right);
12249 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12251 pic16_emitcode("movx","@dptr,a");
12253 pic16_emitcode("inc","dptr");
12257 pic16_freeAsmop(right,NULL,ic,TRUE);
12260 /*-----------------------------------------------------------------*/
12261 /* genGenPointerSet - set value from generic pointer space */
12262 /*-----------------------------------------------------------------*/
12264 static void genGenPointerSet (operand *right,
12265 operand *result, iCode *ic)
12267 int i, size, offset, lit;
12268 sym_link *retype = getSpec(operandType(right));
12270 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12272 pic16_aopOp(result,ic,FALSE);
12273 pic16_aopOp(right,ic,FALSE);
12274 size = AOP_SIZE(right);
12277 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12279 /* if the operand is already in dptr
12280 then we do nothing else we move the value to dptr */
12281 if (AOP_TYPE(result) != AOP_STR) {
12282 /* if this is remateriazable */
12283 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12284 // WARNING: anythig until "else" is untested!
12285 if (AOP_TYPE(result) == AOP_IMMD) {
12286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12287 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12288 // load FSR0 from immediate
12289 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12293 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12295 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12301 else { /* we need to get it byte by byte */
12302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12303 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12305 // set up FSR0 with address of result
12306 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12307 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12309 /* hack hack! see if this the FSR. If so don't load W */
12310 if(AOP_TYPE(right) != AOP_ACC) {
12312 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12314 if(AOP_TYPE(right) == AOP_LIT)
12317 // note: pic16_popGet handles sign extension
12318 for(i=0;i<size;i++) {
12319 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12321 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12323 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12328 for(i=0;i<size;i++) {
12330 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12331 pic16_popCopyReg(&pic16_pc_postinc0)));
12333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12334 pic16_popCopyReg(&pic16_pc_indf0)));
12340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12341 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12343 } // if (AOP_TYPE(result) != AOP_IMMD)
12345 } // if (AOP_TYPE(result) != AOP_STR)
12346 /* so dptr know contains the address */
12349 /* if bit then unpack */
12350 if (IS_BITFIELD(retype))
12351 genPackBits(retype,result,right,"dptr",GPOINTER);
12353 size = AOP_SIZE(right);
12356 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12358 // set up FSR0 with address of result
12359 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12360 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12363 if (AOP_TYPE(right) == AOP_LIT) {
12364 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12366 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12368 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12370 } else { // no literal
12372 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12374 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12382 pic16_freeAsmop(right,NULL,ic,TRUE);
12383 pic16_freeAsmop(result,NULL,ic,TRUE);
12387 static void genGenPointerSet (operand *right,
12388 operand *result, iCode *ic)
12391 sym_link *retype = getSpec(operandType(right));
12394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12396 pic16_aopOp(result,ic,FALSE);
12397 pic16_aopOp(right,ic,FALSE);
12398 size = AOP_SIZE(right);
12400 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12403 /* if bit then unpack */
12404 if (IS_BITFIELD(retype)) {
12405 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12406 genPackBits(retype,result,right,"dptr",GPOINTER);
12410 size = AOP_SIZE(right);
12412 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12416 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12418 /* value of right+0 is placed on stack, which will be retrieved
12419 * by the support function this restoring the stack. The important
12420 * thing is that there is no need to manually restore stack pointer
12422 pushaop(AOP(right), 0);
12423 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12424 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12425 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12426 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12428 /* load address to write to in WREG:FSR0H:FSR0L */
12429 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12430 pic16_popCopyReg(&pic16_pc_fsr0l)));
12431 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12432 pic16_popCopyReg(&pic16_pc_prodl)));
12433 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12436 /* put code here */
12438 case 1: strcpy(fgptrput, "__gptrput1"); break;
12439 case 2: strcpy(fgptrput, "__gptrput2"); break;
12440 case 3: strcpy(fgptrput, "__gptrput3"); break;
12441 case 4: strcpy(fgptrput, "__gptrput4"); break;
12443 werror(W_POSSBUG2, __FILE__, __LINE__);
12447 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12452 sym = newSymbol( fgptrput, 0 );
12453 strcpy(sym->rname, fgptrput);
12454 checkAddSym(&externs, sym);
12458 pic16_freeAsmop(right,NULL,ic,TRUE);
12459 pic16_freeAsmop(result,NULL,ic,TRUE);
12462 /*-----------------------------------------------------------------*/
12463 /* genPointerSet - stores the value into a pointer location */
12464 /*-----------------------------------------------------------------*/
12465 static void genPointerSet (iCode *ic)
12467 operand *right, *result ;
12468 sym_link *type, *etype;
12473 right = IC_RIGHT(ic);
12474 result = IC_RESULT(ic) ;
12476 /* depending on the type of pointer we need to
12477 move it to the correct pointer register */
12478 type = operandType(result);
12479 etype = getSpec(type);
12480 /* if left is of type of pointer then it is simple */
12481 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12482 p_type = DCL_TYPE(type);
12485 /* we have to go by the storage class */
12486 p_type = PTR_TYPE(SPEC_OCLS(etype));
12488 /* if (SPEC_OCLS(etype)->codesp ) { */
12489 /* p_type = CPOINTER ; */
12492 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12493 /* p_type = FPOINTER ; */
12495 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12496 /* p_type = PPOINTER ; */
12498 /* if (SPEC_OCLS(etype) == idata ) */
12499 /* p_type = IPOINTER ; */
12501 /* p_type = POINTER ; */
12504 /* now that we have the pointer type we assign
12505 the pointer values */
12509 genNearPointerSet (right,result,ic);
12513 genPagedPointerSet (right,result,ic);
12517 genFarPointerSet (right,result,ic);
12521 genGenPointerSet (right,result,ic);
12525 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12526 "genPointerSet: illegal pointer type");
12530 /*-----------------------------------------------------------------*/
12531 /* genIfx - generate code for Ifx statement */
12532 /*-----------------------------------------------------------------*/
12533 static void genIfx (iCode *ic, iCode *popIc)
12535 operand *cond = IC_COND(ic);
12540 pic16_aopOp(cond,ic,FALSE);
12542 /* get the value into acc */
12543 if (AOP_TYPE(cond) != AOP_CRY)
12544 pic16_toBoolean(cond);
12547 /* the result is now in the accumulator */
12548 pic16_freeAsmop(cond,NULL,ic,TRUE);
12550 /* if there was something to be popped then do it */
12554 /* if the condition is a bit variable */
12555 if (isbit && IS_ITEMP(cond) &&
12557 genIfxJump(ic,"c");
12558 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12560 if (isbit && !IS_ITEMP(cond))
12561 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12563 genIfxJump(ic,"a");
12568 /*-----------------------------------------------------------------*/
12569 /* genAddrOf - generates code for address of */
12570 /*-----------------------------------------------------------------*/
12571 static void genAddrOf (iCode *ic)
12573 operand *result, *left;
12575 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12576 pCodeOp *pcop0, *pcop1, *pcop2;
12580 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12582 sym = OP_SYMBOL( IC_LEFT(ic) );
12585 /* get address of symbol on stack */
12586 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12588 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12589 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12592 // operands on stack are accessible via "FSR2 + index" with index
12593 // starting at 2 for arguments and growing from 0 downwards for
12594 // local variables (index == 0 is not assigned so we add one here)
12596 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12598 assert (soffs < 0);
12601 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12602 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12603 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12604 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12605 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12606 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12607 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12613 // if(pic16_debug_verbose) {
12614 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12615 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12618 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12619 size = AOP_SIZE(IC_RESULT(ic));
12621 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12622 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12623 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12626 pic16_emitpcode(POC_MOVLW, pcop0);
12627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12628 pic16_emitpcode(POC_MOVLW, pcop1);
12629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12630 pic16_emitpcode(POC_MOVLW, pcop2);
12631 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12634 pic16_emitpcode(POC_MOVLW, pcop0);
12635 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12636 pic16_emitpcode(POC_MOVLW, pcop1);
12637 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12639 pic16_emitpcode(POC_MOVLW, pcop0);
12640 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12643 pic16_freeAsmop(left, NULL, ic, FALSE);
12645 pic16_freeAsmop(result,NULL,ic,TRUE);
12650 /*-----------------------------------------------------------------*/
12651 /* genFarFarAssign - assignment when both are in far space */
12652 /*-----------------------------------------------------------------*/
12653 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12655 int size = AOP_SIZE(right);
12658 /* first push the right side on to the stack */
12660 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12662 pic16_emitcode ("push","acc");
12665 pic16_freeAsmop(right,NULL,ic,FALSE);
12666 /* now assign DPTR to result */
12667 pic16_aopOp(result,ic,FALSE);
12668 size = AOP_SIZE(result);
12670 pic16_emitcode ("pop","acc");
12671 pic16_aopPut(AOP(result),"a",--offset);
12673 pic16_freeAsmop(result,NULL,ic,FALSE);
12678 /*-----------------------------------------------------------------*/
12679 /* genAssign - generate code for assignment */
12680 /*-----------------------------------------------------------------*/
12681 static void genAssign (iCode *ic)
12683 operand *result, *right;
12684 int size, offset,know_W;
12685 unsigned long lit = 0L;
12687 result = IC_RESULT(ic);
12688 right = IC_RIGHT(ic) ;
12692 /* if they are the same */
12693 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12696 /* reversed order operands are aopOp'ed so that result operand
12697 * is effective in case right is a stack symbol. This maneauver
12698 * allows to use the _G.resDirect flag later */
12699 pic16_aopOp(result,ic,TRUE);
12700 pic16_aopOp(right,ic,FALSE);
12702 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12704 /* if they are the same registers */
12705 if (pic16_sameRegs(AOP(right),AOP(result)))
12708 /* if the result is a bit */
12709 if (AOP_TYPE(result) == AOP_CRY) {
12710 /* if the right size is a literal then
12711 we know what the value is */
12712 if (AOP_TYPE(right) == AOP_LIT) {
12714 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12715 pic16_popGet(AOP(result),0));
12717 if (((int) operandLitValue(right)))
12718 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12719 AOP(result)->aopu.aop_dir,
12720 AOP(result)->aopu.aop_dir);
12722 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12723 AOP(result)->aopu.aop_dir,
12724 AOP(result)->aopu.aop_dir);
12728 /* the right is also a bit variable */
12729 if (AOP_TYPE(right) == AOP_CRY) {
12730 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12731 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12732 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12734 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12735 AOP(result)->aopu.aop_dir,
12736 AOP(result)->aopu.aop_dir);
12737 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12738 AOP(right)->aopu.aop_dir,
12739 AOP(right)->aopu.aop_dir);
12740 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12741 AOP(result)->aopu.aop_dir,
12742 AOP(result)->aopu.aop_dir);
12746 /* we need to or */
12747 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12748 pic16_toBoolean(right);
12750 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12751 //pic16_aopPut(AOP(result),"a",0);
12755 /* bit variables done */
12757 size = AOP_SIZE(result);
12760 if(AOP_TYPE(right) == AOP_LIT) {
12761 if(!IS_FLOAT(operandType( right )))
12762 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12765 unsigned long lit_int;
12769 /* take care if literal is a float */
12770 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12771 lit = info.lit_int;
12775 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12776 // sizeof(unsigned long int), sizeof(float));
12779 if (AOP_TYPE(right) == AOP_REG) {
12780 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12783 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12788 if(AOP_TYPE(right) != AOP_LIT
12789 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12790 && !IS_FUNC(OP_SYM_TYPE(right))
12792 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12793 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12795 // set up table pointer
12796 if(is_LitOp(right)) {
12797 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12798 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12799 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12800 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12801 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12802 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12803 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12805 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12806 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12807 pic16_popCopyReg(&pic16_pc_tblptrl)));
12808 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12809 pic16_popCopyReg(&pic16_pc_tblptrh)));
12810 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12811 pic16_popCopyReg(&pic16_pc_tblptru)));
12814 size = min(AOP_SIZE(right), AOP_SIZE(result));
12816 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12817 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12818 pic16_popGet(AOP(result),offset)));
12822 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12823 size = AOP_SIZE(result) - AOP_SIZE(right);
12825 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12835 /* VR - What is this?! */
12836 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12838 if(aopIdx(AOP(result),0) == 4) {
12840 /* this is a workaround to save value of right into wreg too,
12841 * value of wreg is going to be used later */
12842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12843 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12848 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12854 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12855 if(AOP_TYPE(right) == AOP_LIT) {
12857 if(know_W != (lit&0xff))
12858 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12862 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12866 } else if (AOP_TYPE(right) == AOP_CRY) {
12867 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12869 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12870 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12871 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12873 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12874 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12875 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12879 if(!_G.resDirect) /* use this aopForSym feature */
12880 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12887 pic16_freeAsmop (right,NULL,ic,FALSE);
12888 pic16_freeAsmop (result,NULL,ic,TRUE);
12891 /*-----------------------------------------------------------------*/
12892 /* genJumpTab - generates code for jump table */
12893 /*-----------------------------------------------------------------*/
12894 static void genJumpTab (iCode *ic)
12899 pCodeOp *jt_offs_hi;
12904 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12905 /* get the condition into accumulator */
12906 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12908 /* multiply by three */
12909 pic16_emitcode("add","a,acc");
12910 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12912 jtab = newiTempLabel(NULL);
12913 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12914 pic16_emitcode("jmp","@a+dptr");
12915 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12918 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12919 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12921 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12922 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12923 pic16_emitpLabel(jtab->key);
12927 jt_offs = pic16_popGetTempReg(0);
12928 jt_offs_hi = pic16_popGetTempReg(1);
12929 jt_label = pic16_popGetLabel (jtab->key);
12930 //fprintf (stderr, "Creating jump table...\n");
12932 // calculate offset into jump table (idx * sizeof (GOTO))
12933 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12934 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12935 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12936 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12937 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12938 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12939 pic16_emitpcode(POC_MOVWF , jt_offs);
12941 // prepare PCLATx (set to first entry in jump table)
12942 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12943 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12944 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12945 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12946 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12948 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12949 pic16_emitpcode(POC_ADDWF , jt_offs);
12950 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12951 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12953 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12955 // release temporaries and prepare jump into table (new PCL --> WREG)
12956 pic16_emitpcode(POC_MOVFW , jt_offs);
12957 pic16_popReleaseTempReg (jt_offs_hi, 1);
12958 pic16_popReleaseTempReg (jt_offs, 0);
12960 // jump into the table
12961 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12963 pic16_emitpLabelFORCE(jtab->key);
12966 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12968 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12969 /* now generate the jump labels */
12970 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12971 jtab = setNextItem(IC_JTLABELS(ic))) {
12972 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12973 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12976 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12980 /*-----------------------------------------------------------------*/
12981 /* genMixedOperation - gen code for operators between mixed types */
12982 /*-----------------------------------------------------------------*/
12984 TSD - Written for the PIC port - but this unfortunately is buggy.
12985 This routine is good in that it is able to efficiently promote
12986 types to different (larger) sizes. Unfortunately, the temporary
12987 variables that are optimized out by this routine are sometimes
12988 used in other places. So until I know how to really parse the
12989 iCode tree, I'm going to not be using this routine :(.
12991 static int genMixedOperation (iCode *ic)
12994 operand *result = IC_RESULT(ic);
12995 sym_link *ctype = operandType(IC_LEFT(ic));
12996 operand *right = IC_RIGHT(ic);
13002 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13004 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13010 nextright = IC_RIGHT(nextic);
13011 nextleft = IC_LEFT(nextic);
13012 nextresult = IC_RESULT(nextic);
13014 pic16_aopOp(right,ic,FALSE);
13015 pic16_aopOp(result,ic,FALSE);
13016 pic16_aopOp(nextright, nextic, FALSE);
13017 pic16_aopOp(nextleft, nextic, FALSE);
13018 pic16_aopOp(nextresult, nextic, FALSE);
13020 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13022 operand *t = right;
13026 pic16_emitcode(";remove right +","");
13028 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13030 operand *t = right;
13034 pic16_emitcode(";remove left +","");
13038 big = AOP_SIZE(nextleft);
13039 small = AOP_SIZE(nextright);
13041 switch(nextic->op) {
13044 pic16_emitcode(";optimize a +","");
13045 /* if unsigned or not an integral type */
13046 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13047 pic16_emitcode(";add a bit to something","");
13050 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13052 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13053 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13054 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13056 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13064 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13065 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13066 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13069 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13071 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13072 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13073 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13074 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13075 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13078 pic16_emitcode("rlf","known_zero,w");
13085 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13086 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13087 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13089 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13099 pic16_freeAsmop(right,NULL,ic,TRUE);
13100 pic16_freeAsmop(result,NULL,ic,TRUE);
13101 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13102 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13104 nextic->generated = 1;
13111 /*-----------------------------------------------------------------*/
13112 /* genCast - gen code for casting */
13113 /*-----------------------------------------------------------------*/
13114 static void genCast (iCode *ic)
13116 operand *result = IC_RESULT(ic);
13117 sym_link *ctype = operandType(IC_LEFT(ic));
13118 sym_link *rtype = operandType(IC_RIGHT(ic));
13119 sym_link *restype = operandType(IC_RESULT(ic));
13120 operand *right = IC_RIGHT(ic);
13126 /* if they are equivalent then do nothing */
13127 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13130 pic16_aopOp(right,ic,FALSE) ;
13131 pic16_aopOp(result,ic,FALSE);
13133 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13136 /* if the result is a bit */
13137 if (AOP_TYPE(result) == AOP_CRY) {
13139 /* if the right size is a literal then
13140 * we know what the value is */
13141 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13143 if (AOP_TYPE(right) == AOP_LIT) {
13144 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13145 pic16_popGet(AOP(result),0));
13147 if (((int) operandLitValue(right)))
13148 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13149 AOP(result)->aopu.aop_dir,
13150 AOP(result)->aopu.aop_dir);
13152 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13153 AOP(result)->aopu.aop_dir,
13154 AOP(result)->aopu.aop_dir);
13158 /* the right is also a bit variable */
13159 if (AOP_TYPE(right) == AOP_CRY) {
13161 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13163 pic16_emitcode("clrc","");
13164 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13165 AOP(right)->aopu.aop_dir,
13166 AOP(right)->aopu.aop_dir);
13167 pic16_aopPut(AOP(result),"c",0);
13171 /* we need to or */
13172 if (AOP_TYPE(right) == AOP_REG) {
13173 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13174 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13175 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13177 pic16_toBoolean(right);
13178 pic16_aopPut(AOP(result),"a",0);
13182 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13185 size = AOP_SIZE(result);
13187 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13189 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13190 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13191 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13194 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13199 if(IS_BITFIELD(getSpec(restype))
13200 && IS_BITFIELD(getSpec(rtype))) {
13201 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13204 /* if they are the same size : or less */
13205 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13207 /* if they are in the same place */
13208 if (pic16_sameRegs(AOP(right),AOP(result)))
13211 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13213 if (IS_PTR_CONST(rtype))
13215 if (IS_CODEPTR(rtype))
13217 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13220 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13222 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13224 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13227 if(AOP_TYPE(right) == AOP_IMMD) {
13228 pCodeOp *pcop0, *pcop1, *pcop2;
13229 symbol *sym = OP_SYMBOL( right );
13231 size = AOP_SIZE(result);
13233 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13235 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13237 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13240 pic16_emitpcode(POC_MOVLW, pcop0);
13241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13242 pic16_emitpcode(POC_MOVLW, pcop1);
13243 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13244 pic16_emitpcode(POC_MOVLW, pcop2);
13245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13248 pic16_emitpcode(POC_MOVLW, pcop0);
13249 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13250 pic16_emitpcode(POC_MOVLW, pcop1);
13251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13253 pic16_emitpcode(POC_MOVLW, pcop0);
13254 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13258 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13259 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13260 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13261 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13262 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13263 if(AOP_SIZE(result) <2)
13264 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13266 /* if they in different places then copy */
13267 size = AOP_SIZE(result);
13270 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13271 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13278 /* if the result is of type pointer */
13279 if (IS_PTR(ctype)) {
13281 sym_link *type = operandType(right);
13282 sym_link *etype = getSpec(type);
13284 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13286 /* pointer to generic pointer */
13287 if (IS_GENPTR(ctype)) {
13291 p_type = DCL_TYPE(type);
13293 /* we have to go by the storage class */
13294 p_type = PTR_TYPE(SPEC_OCLS(etype));
13296 /* if (SPEC_OCLS(etype)->codesp ) */
13297 /* p_type = CPOINTER ; */
13299 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13300 /* p_type = FPOINTER ; */
13302 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13303 /* p_type = PPOINTER; */
13305 /* if (SPEC_OCLS(etype) == idata ) */
13306 /* p_type = IPOINTER ; */
13308 /* p_type = POINTER ; */
13311 /* the first two bytes are known */
13312 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13313 size = GPTRSIZE - 1;
13316 if(offset < AOP_SIZE(right)) {
13317 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13318 mov2f(AOP(result), AOP(right), offset);
13320 if ((AOP_TYPE(right) == AOP_PCODE) &&
13321 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13322 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13326 pic16_aopPut(AOP(result),
13327 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13332 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13335 /* the last byte depending on type */
13339 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13340 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13341 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13345 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13349 pic16_emitcode(";BUG!? ","%d",__LINE__);
13353 pic16_emitcode(";BUG!? ","%d",__LINE__);
13358 if (GPTRSIZE > AOP_SIZE(right)) {
13359 // assume data pointer... THIS MIGHT BE WRONG!
13360 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13361 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13363 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13368 /* this should never happen */
13369 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13370 "got unknown pointer type");
13373 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13377 /* just copy the pointers */
13378 size = AOP_SIZE(result);
13381 pic16_aopPut(AOP(result),
13382 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13391 /* so we now know that the size of destination is greater
13392 than the size of the source.
13393 Now, if the next iCode is an operator then we might be
13394 able to optimize the operation without performing a cast.
13396 if(genMixedOperation(ic))
13399 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13401 /* we move to result for the size of source */
13402 size = AOP_SIZE(right);
13405 mov2f(AOP(result), AOP(right), offset);
13409 /* now depending on the sign of the destination */
13410 size = AOP_SIZE(result) - AOP_SIZE(right);
13411 /* if unsigned or not an integral type */
13412 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13414 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13416 /* we need to extend the sign :( */
13419 /* Save one instruction of casting char to int */
13420 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13421 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13422 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13424 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13427 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13429 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13431 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13434 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13439 pic16_freeAsmop(right,NULL,ic,TRUE);
13440 pic16_freeAsmop(result,NULL,ic,TRUE);
13444 /*-----------------------------------------------------------------*/
13445 /* genDjnz - generate decrement & jump if not zero instrucion */
13446 /*-----------------------------------------------------------------*/
13447 static int genDjnz (iCode *ic, iCode *ifx)
13449 symbol *lbl, *lbl1;
13450 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13455 /* if the if condition has a false label
13456 then we cannot save */
13460 /* if the minus is not of the form
13462 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13463 !IS_OP_LITERAL(IC_RIGHT(ic)))
13466 if (operandLitValue(IC_RIGHT(ic)) != 1)
13469 /* if the size of this greater than one then no
13471 if (getSize(operandType(IC_RESULT(ic))) > 1)
13474 /* otherwise we can save BIG */
13475 lbl = newiTempLabel(NULL);
13476 lbl1= newiTempLabel(NULL);
13478 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13480 if (IS_AOP_PREG(IC_RESULT(ic))) {
13481 pic16_emitcode("dec","%s",
13482 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13483 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13484 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13488 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13489 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13491 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13492 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13496 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13497 ifx->generated = 1;
13501 /*-----------------------------------------------------------------*/
13502 /* genReceive - generate code for a receive iCode */
13503 /*-----------------------------------------------------------------*/
13504 static void genReceive (iCode *ic)
13510 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13511 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13513 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13515 if (isOperandInFarSpace(IC_RESULT(ic))
13516 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13517 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13519 int size = getSize(operandType(IC_RESULT(ic)));
13520 int offset = pic16_fReturnSizePic - size;
13524 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13525 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13529 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13531 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13532 size = AOP_SIZE(IC_RESULT(ic));
13535 pic16_emitcode ("pop","acc");
13536 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13539 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13541 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13544 /* set pseudo stack pointer to where it should be - dw*/
13545 GpsuedoStkPtr = ic->parmBytes;
13547 /* setting GpsuedoStkPtr has side effects here: */
13548 assignResultValue(IC_RESULT(ic), 0);
13551 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13554 /*-----------------------------------------------------------------*/
13555 /* genDummyRead - generate code for dummy read of volatiles */
13556 /*-----------------------------------------------------------------*/
13558 genDummyRead (iCode * ic)
13560 pic16_emitcode ("; genDummyRead","");
13561 pic16_emitcode ("; not implemented","");
13566 /*-----------------------------------------------------------------*/
13567 /* genpic16Code - generate code for pic16 based controllers */
13568 /*-----------------------------------------------------------------*/
13570 * At this point, ralloc.c has gone through the iCode and attempted
13571 * to optimize in a way suitable for a PIC. Now we've got to generate
13572 * PIC instructions that correspond to the iCode.
13574 * Once the instructions are generated, we'll pass through both the
13575 * peep hole optimizer and the pCode optimizer.
13576 *-----------------------------------------------------------------*/
13578 void genpic16Code (iCode *lic)
13583 lineHead = lineCurr = NULL;
13585 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13586 pic16_addpBlock(pb);
13589 /* if debug information required */
13590 if (options.debug && currFunc) {
13592 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13597 for (ic = lic ; ic ; ic = ic->next ) {
13599 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13600 if ( cln != ic->lineno ) {
13601 if ( options.debug ) {
13602 debugFile->writeCLine (ic);
13605 if(!options.noCcodeInAsm) {
13606 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13607 printCLine(ic->filename, ic->lineno)));
13613 if(options.iCodeInAsm) {
13616 /* insert here code to print iCode as comment */
13617 l = Safe_strdup(printILine(ic));
13618 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13621 /* if the result is marked as
13622 * spilt and rematerializable or code for
13623 * this has already been generated then
13625 if (resultRemat(ic) || ic->generated )
13628 /* depending on the operation */
13647 /* IPOP happens only when trying to restore a
13648 * spilt live range, if there is an ifx statement
13649 * following this pop then the if statement might
13650 * be using some of the registers being popped which
13651 * would destroy the contents of the register so
13652 * we need to check for this condition and handle it */
13654 && ic->next->op == IFX
13655 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13656 genIfx (ic->next,ic);
13674 genEndFunction (ic);
13690 pic16_genPlus (ic) ;
13694 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13695 pic16_genMinus (ic);
13711 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13715 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13721 /* note these two are xlated by algebraic equivalence
13722 * during parsing SDCC.y */
13723 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13724 "got '>=' or '<=' shouldn't have come here");
13728 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13740 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13744 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13748 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13772 genRightShift (ic);
13775 case GET_VALUE_AT_ADDRESS:
13780 if (POINTER_SET(ic))
13807 addSet(&_G.sendSet,ic);
13810 case DUMMY_READ_VOLATILE:
13820 /* now we are ready to call the
13821 peep hole optimizer */
13822 if (!options.nopeep)
13823 peepHole (&lineHead);
13825 /* now do the actual printing */
13826 printLine (lineHead, codeOutFile);
13829 DFPRINTF((stderr,"printing pBlock\n\n"));
13830 pic16_printpBlock(stdout,pb);