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)
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;
159 int stack_lat; /* stack offset latency */
161 int useWreg; /* flag when WREG is used to pass function parameter */
164 /* Resolved ifx structure. This structure stores information
165 about an iCode ifx that makes it easier to generate code.
167 typedef struct resolvedIfx {
168 symbol *lbl; /* pointer to a label */
169 int condition; /* true or false ifx */
170 int generated; /* set true when the code associated with the ifx
174 extern int pic16_ptrRegReq ;
175 extern int pic16_nRegs;
176 extern FILE *codeOutFile;
177 //static void saverbank (int, iCode *,bool);
179 static lineNode *lineHead = NULL;
180 static lineNode *lineCurr = NULL;
182 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
183 0xE0, 0xC0, 0x80, 0x00};
184 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
185 0x07, 0x03, 0x01, 0x00};
189 /*-----------------------------------------------------------------*/
190 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
191 /* exponent of 2 is returned, otherwise -1 is */
193 /* note that this is similar to the function `powof2' in SDCCsymt */
197 /*-----------------------------------------------------------------*/
198 int pic16_my_powof2 (unsigned long num)
201 if( (num & (num-1)) == 0) {
214 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
216 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
218 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
219 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
220 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
221 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
222 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
223 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
224 ((result) ? AOP_SIZE(result) : 0));
227 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
230 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
232 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
233 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
234 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
235 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
236 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
237 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
241 void pic16_emitpcomment (char *fmt, ...)
244 char lb[INITIAL_INLINEASM];
250 vsprintf(lb+1,fmt,ap);
252 while (isspace(*lbp)) lbp++;
255 lineCurr = (lineCurr ?
256 connectLine(lineCurr,newLineNode(lb)) :
257 (lineHead = newLineNode(lb)));
258 lineCurr->isInline = _G.inLine;
259 lineCurr->isDebug = _G.debugLine;
261 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
264 // fprintf(stderr, "%s\n", lb);
267 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
270 char lb[INITIAL_INLINEASM];
273 if(!pic16_debug_verbose)
280 sprintf(lb,"%s\t",inst);
282 sprintf(lb,"%s",inst);
283 vsprintf(lb+(strlen(lb)),fmt,ap);
287 while (isspace(*lbp)) lbp++;
290 lineCurr = (lineCurr ?
291 connectLine(lineCurr,newLineNode(lb)) :
292 (lineHead = newLineNode(lb)));
293 lineCurr->isInline = _G.inLine;
294 lineCurr->isDebug = _G.debugLine;
296 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
299 // fprintf(stderr, "%s\n", lb);
304 void pic16_emitpLabel(int key)
306 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
309 void pic16_emitpLabelFORCE(int key)
311 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
314 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
318 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
320 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
323 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
326 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
328 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
331 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
334 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
340 #define pic16_emitcode DEBUGpic16_emitcode
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitcode - writes the code into a file : for now it is simple */
344 /*-----------------------------------------------------------------*/
345 void pic16_emitcode (char *inst,char *fmt, ...)
348 char lb[INITIAL_INLINEASM];
355 sprintf(lb,"%s\t",inst);
357 sprintf(lb,"%s",inst);
358 vsprintf(lb+(strlen(lb)),fmt,ap);
362 while (isspace(*lbp)) lbp++;
365 lineCurr = (lineCurr ?
366 connectLine(lineCurr,newLineNode(lb)) :
367 (lineHead = newLineNode(lb)));
368 lineCurr->isInline = _G.inLine;
369 lineCurr->isDebug = _G.debugLine;
371 // VR fprintf(stderr, "lb = <%s>\n", lbp);
373 // if(pic16_debug_verbose)
374 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
381 /*-----------------------------------------------------------------*/
382 /* pic16_emitDebuggerSymbol - associate the current code location */
383 /* with a debugger symbol */
384 /*-----------------------------------------------------------------*/
386 pic16_emitDebuggerSymbol (char * debugSym)
389 pic16_emitcode (";", "%s ==.", debugSym);
394 /*-----------------------------------------------------------------*/
395 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
396 /*-----------------------------------------------------------------*/
397 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
399 // bool r0iu = FALSE , r1iu = FALSE;
400 // bool r0ou = FALSE , r1ou = FALSE;
401 bool fsr0iu = FALSE, fsr0ou;
402 bool fsr2iu = FALSE, fsr2ou;
404 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
407 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
408 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
410 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
411 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
413 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
414 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
415 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
418 if(!fsr0iu && !fsr0ou) {
419 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
420 (*aopp)->type = AOP_FSR0;
422 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
424 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
428 /* no usage of FSR2 */
429 if(!fsr2iu && !fsr2ou) {
430 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
431 (*aopp)->type = AOP_FSR2;
433 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
437 /* now we know they both have usage */
438 /* if fsr0 not used in this instruction */
440 if (!_G.fsr0Pushed) {
441 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
442 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
446 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
447 (*aopp)->type = AOP_FSR0;
449 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
451 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
455 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
460 /* the logic: if r0 & r1 used in the instruction
461 then we are in trouble otherwise */
463 /* first check if r0 & r1 are used by this
464 instruction, in which case we are in trouble */
465 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
466 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
471 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
472 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
474 /* if no usage of r0 then return it */
475 if (!r0iu && !r0ou) {
476 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
477 (*aopp)->type = AOP_R0;
479 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
482 /* if no usage of r1 then return it */
483 if (!r1iu && !r1ou) {
484 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
485 (*aopp)->type = AOP_R1;
487 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
490 /* now we know they both have usage */
491 /* if r0 not used in this instruction */
493 /* push it if not already pushed */
495 //pic16_emitcode ("push","%s",
496 // pic16_regWithIdx(R0_IDX)->dname);
500 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
501 (*aopp)->type = AOP_R0;
503 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
506 /* if r1 not used then */
509 /* push it if not already pushed */
511 //pic16_emitcode ("push","%s",
512 // pic16_regWithIdx(R1_IDX)->dname);
516 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
517 (*aopp)->type = AOP_R1;
518 return pic16_regWithIdx(R1_IDX);
522 /* I said end of world but not quite end of world yet */
523 /* if this is a result then we can push it on the stack*/
525 (*aopp)->type = AOP_STK;
529 /* other wise this is true end of the world */
530 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
531 "getFreePtr should never reach here");
536 /*-----------------------------------------------------------------*/
537 /* newAsmop - creates a new asmOp */
538 /*-----------------------------------------------------------------*/
539 static asmop *newAsmop (short type)
543 aop = Safe_calloc(1,sizeof(asmop));
548 static void genSetDPTR(int n)
552 pic16_emitcode(";", "Select standard DPTR");
553 pic16_emitcode("mov", "dps, #0x00");
557 pic16_emitcode(";", "Select alternate DPTR");
558 pic16_emitcode("mov", "dps, #0x01");
562 /*-----------------------------------------------------------------*/
563 /* resolveIfx - converts an iCode ifx into a form more useful for */
564 /* generating code */
565 /*-----------------------------------------------------------------*/
566 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
570 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
576 resIfx->condition = 1; /* assume that the ifx is true */
577 resIfx->generated = 0; /* indicate that the ifx has not been used */
580 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
583 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
584 __FUNCTION__,__LINE__,resIfx->lbl->key);
589 resIfx->lbl = IC_TRUE(ifx);
591 resIfx->lbl = IC_FALSE(ifx);
592 resIfx->condition = 0;
597 DEBUGpic16_emitcode("; +++","ifx true is non-null");
599 DEBUGpic16_emitcode("; +++","ifx true is null");
601 DEBUGpic16_emitcode("; +++","ifx false is non-null");
603 DEBUGpic16_emitcode("; +++","ifx false is null");
607 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
611 /*-----------------------------------------------------------------*/
612 /* pointerCode - returns the code for a pointer type */
613 /*-----------------------------------------------------------------*/
614 static int pointerCode (sym_link *etype)
617 return PTR_TYPE(SPEC_OCLS(etype));
622 /*-----------------------------------------------------------------*/
623 /* aopForSym - for a true symbol */
624 /*-----------------------------------------------------------------*/
625 static asmop *aopForSym (iCode *ic, operand *op, bool result)
627 symbol *sym=OP_SYMBOL(op);
629 memmap *space= SPEC_OCLS(sym->etype);
633 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
635 // sym = OP_SYMBOL(op);
637 /* if already has one */
639 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
644 /* if symbol was initially placed onStack then we must re-place it
645 * to direct memory, since pic16 does not have a specific stack */
647 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
652 /* assign depending on the storage class */
653 /* if it is on the stack or indirectly addressable */
654 /* space we need to assign either r0 or r1 to it */
655 if (sym->onStack || sym->iaccess) {
659 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
660 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
662 /* acquire a temporary register -- it is saved in function */
664 sym->aop = aop = newAsmop(AOP_STA);
665 aop->aopu.stk.stk = sym->stack;
666 aop->size = getSize(sym->type);
669 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
670 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
671 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
672 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
674 for(i=0;i<aop->size;i++)
675 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
676 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
678 for(i=0;i<aop->size;i++) {
679 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
680 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
684 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
687 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
690 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
693 for(i=0;i<aop->size;i++) {
695 /* initialise for stack access via frame pointer */
696 // operands on stack are accessible via "FSR2 + index" with index
697 // starting at 2 for arguments and growing from 0 downwards for
698 // local variables (index == 0 is not assigned so we add one here)
700 int soffs = sym->stack;
705 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
706 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
707 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
712 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
719 /* now assign the address of the variable to
720 the pointer register */
721 if (aop->type != AOP_STK) {
725 pic16_emitcode("push","acc");
727 pic16_emitcode("mov","a,_bp");
728 pic16_emitcode("add","a,#0x%02x",
730 ((char)(sym->stack - _G.nRegsSaved )) :
731 ((char)sym->stack)) & 0xff);
732 pic16_emitcode("mov","%s,a",
733 aop->aopu.aop_ptr->name);
736 pic16_emitcode("pop","acc");
738 pic16_emitcode("mov","%s,#%s",
739 aop->aopu.aop_ptr->name,
741 aop->paged = space->paged;
743 aop->aopu.aop_stk = sym->stack;
751 if (sym->onStack && options.stack10bit)
753 /* It's on the 10 bit stack, which is located in
757 //DEBUGpic16_emitcode(";","%d",__LINE__);
760 pic16_emitcode("push","acc");
762 pic16_emitcode("mov","a,_bp");
763 pic16_emitcode("add","a,#0x%02x",
765 ((char)(sym->stack - _G.nRegsSaved )) :
766 ((char)sym->stack)) & 0xff);
769 pic16_emitcode ("mov","dpx1,#0x40");
770 pic16_emitcode ("mov","dph1,#0x00");
771 pic16_emitcode ("mov","dpl1, a");
775 pic16_emitcode("pop","acc");
777 sym->aop = aop = newAsmop(AOP_DPTR2);
778 aop->size = getSize(sym->type);
784 /* special case for a function */
785 if (IS_FUNC(sym->type)) {
786 sym->aop = aop = newAsmop(AOP_PCODE);
787 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
788 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
789 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
790 PCOI(aop->aopu.pcop)->index = 0;
791 aop->size = FPTRSIZE;
792 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
799 //DEBUGpic16_emitcode(";","%d",__LINE__);
800 /* if in bit space */
801 if (IN_BITSPACE(space)) {
802 sym->aop = aop = newAsmop (AOP_CRY);
803 aop->aopu.aop_dir = sym->rname ;
804 aop->size = getSize(sym->type);
805 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
808 /* if it is in direct space */
809 if (IN_DIRSPACE(space)) {
810 sym->aop = aop = newAsmop (AOP_DIR);
811 aop->aopu.aop_dir = sym->rname ;
812 aop->size = getSize(sym->type);
813 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
814 pic16_allocDirReg( IC_LEFT(ic) );
819 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
820 sym->aop = aop = newAsmop (AOP_DIR);
821 aop->aopu.aop_dir = sym->rname ;
822 aop->size = getSize(sym->type);
823 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
824 pic16_allocDirReg( IC_LEFT(ic) );
829 /* only remaining is far space */
830 sym->aop = aop = newAsmop(AOP_PCODE);
832 /* change the next if to 1 to revert to good old immediate code */
833 if(IN_CODESPACE(space)) {
834 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
835 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
836 PCOI(aop->aopu.pcop)->index = 0;
838 /* try to allocate via direct register */
839 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
840 // aop->size = getSize( sym->type );
843 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
844 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
847 if(!pic16_allocDirReg (IC_LEFT(ic)))
851 if(IN_DIRSPACE( space ))
853 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
854 aop->size = FPTRSIZE;
855 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
856 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
857 else if(sym->onStack) {
863 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
865 /* if it is in code space */
866 if (IN_CODESPACE(space))
872 /*-----------------------------------------------------------------*/
873 /* aopForRemat - rematerialzes an object */
874 /*-----------------------------------------------------------------*/
875 static asmop *aopForRemat (operand *op) // x symbol *sym)
877 symbol *sym = OP_SYMBOL(op);
879 iCode *ic = NULL, *oldic;
880 asmop *aop = newAsmop(AOP_PCODE);
887 ic = sym->rematiCode;
889 if(IS_OP_POINTER(op)) {
890 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
896 // pic16_emitpcomment("ic: %s\n", printILine(ic));
899 val += (int) operandLitValue(IC_RIGHT(ic));
900 } else if (ic->op == '-') {
901 val -= (int) operandLitValue(IC_RIGHT(ic));
905 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
908 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
911 if(!op->isaddr)viaimmd++; else viaimmd=0;
913 /* set the following if to 1 to revert to good old immediate code */
914 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
917 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
919 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
922 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
924 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
927 PCOI(aop->aopu.pcop)->index = val;
929 aop->size = getSize( sym->type );
931 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
933 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
934 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
936 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
940 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
941 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
943 val, IS_PTR_CONST(operandType(op)));
945 val, IS_CODEPTR(operandType(op)));
948 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
950 pic16_allocDirReg (IC_LEFT(ic));
952 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
959 static int aopIdx (asmop *aop, int offset)
964 if(aop->type != AOP_REG)
967 return aop->aopu.aop_reg[offset]->rIdx;
972 /*-----------------------------------------------------------------*/
973 /* regsInCommon - two operands have some registers in common */
974 /*-----------------------------------------------------------------*/
975 static bool regsInCommon (operand *op1, operand *op2)
980 /* if they have registers in common */
981 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
984 sym1 = OP_SYMBOL(op1);
985 sym2 = OP_SYMBOL(op2);
987 if (sym1->nRegs == 0 || sym2->nRegs == 0)
990 for (i = 0 ; i < sym1->nRegs ; i++) {
995 for (j = 0 ; j < sym2->nRegs ;j++ ) {
999 if (sym2->regs[j] == sym1->regs[i])
1007 /*-----------------------------------------------------------------*/
1008 /* operandsEqu - equivalent */
1009 /*-----------------------------------------------------------------*/
1010 static bool operandsEqu ( operand *op1, operand *op2)
1012 symbol *sym1, *sym2;
1014 /* if they not symbols */
1015 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1018 sym1 = OP_SYMBOL(op1);
1019 sym2 = OP_SYMBOL(op2);
1021 /* if both are itemps & one is spilt
1022 and the other is not then false */
1023 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1024 sym1->isspilt != sym2->isspilt )
1027 /* if they are the same */
1031 if (sym1->rname[0] && sym2->rname[0]
1032 && strcmp (sym1->rname, sym2->rname) == 0)
1036 /* if left is a tmp & right is not */
1037 if (IS_ITEMP(op1) &&
1040 (sym1->usl.spillLoc == sym2))
1043 if (IS_ITEMP(op2) &&
1047 (sym2->usl.spillLoc == sym1))
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_sameRegs - two asmops have the same registers */
1055 /*-----------------------------------------------------------------*/
1056 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1063 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1064 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1066 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1068 if (aop1->type != AOP_REG ||
1069 aop2->type != AOP_REG )
1072 if (aop1->size != aop2->size )
1075 for (i = 0 ; i < aop1->size ; i++ ) {
1076 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1078 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1079 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1086 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1088 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1089 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1091 if(aop1 == aop2)return TRUE;
1092 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1094 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1100 /*-----------------------------------------------------------------*/
1101 /* pic16_aopOp - allocates an asmop for an operand : */
1102 /*-----------------------------------------------------------------*/
1103 void pic16_aopOp (operand *op, iCode *ic, bool result)
1112 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1114 /* if this a literal */
1115 if (IS_OP_LITERAL(op)) {
1116 op->aop = aop = newAsmop(AOP_LIT);
1117 aop->aopu.aop_lit = op->operand.valOperand;
1118 aop->size = getSize(operandType(op));
1123 sym_link *type = operandType(op);
1125 if(IS_PTR_CONST(type))
1127 if(IS_CODEPTR(type))
1129 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1132 /* if already has a asmop then continue */
1136 /* if the underlying symbol has a aop */
1137 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1138 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1139 op->aop = OP_SYMBOL(op)->aop;
1143 /* if this is a true symbol */
1144 if (IS_TRUE_SYMOP(op)) {
1145 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1146 op->aop = aopForSym(ic, op, result);
1150 /* this is a temporary : this has
1156 e) can be a return use only */
1158 sym = OP_SYMBOL(op);
1160 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1161 /* if the type is a conditional */
1162 if (sym->regType == REG_CND) {
1163 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1168 /* if it is spilt then two situations
1170 b) has a spill location */
1171 if (sym->isspilt || sym->nRegs == 0) {
1173 DEBUGpic16_emitcode(";","%d",__LINE__);
1174 /* rematerialize it NOW */
1177 sym->aop = op->aop = aop = aopForRemat (op);
1178 // aop->size = getSize(sym->type);
1179 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1186 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1187 aop->size = getSize(sym->type);
1188 for ( i = 0 ; i < 1 ; i++ ) {
1189 aop->aopu.aop_str[i] = accUse[i];
1190 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1192 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1193 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1201 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1202 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1203 //pic16_allocDirReg (IC_LEFT(ic));
1204 aop->size = getSize(sym->type);
1209 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1210 aop->size = getSize(sym->type);
1211 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1212 aop->aopu.aop_str[i] = fReturn[i];
1214 DEBUGpic16_emitcode(";","%d",__LINE__);
1218 /* else spill location */
1219 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1220 /* force a new aop if sizes differ */
1221 sym->usl.spillLoc->aop = NULL;
1225 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1226 __FUNCTION__,__LINE__,
1227 sym->usl.spillLoc->rname,
1228 sym->rname, sym->usl.spillLoc->offset);
1231 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1232 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1233 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1235 sym->usl.spillLoc->offset, op);
1236 aop->size = getSize(sym->type);
1242 sym_link *type = operandType(op);
1244 if(IS_PTR_CONST(type))
1246 if(IS_CODEPTR(type))
1248 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1251 /* must be in a register */
1252 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1253 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1254 aop->size = sym->nRegs;
1255 for ( i = 0 ; i < sym->nRegs ;i++)
1256 aop->aopu.aop_reg[i] = sym->regs[i];
1259 /*-----------------------------------------------------------------*/
1260 /* pic16_freeAsmop - free up the asmop given to an operand */
1261 /*----------------------------------------------------------------*/
1262 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1279 /* depending on the asmop type only three cases need work AOP_RO
1280 , AOP_R1 && AOP_STK */
1282 switch (aop->type) {
1284 if (_G.fsr0Pushed ) {
1286 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1287 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1288 // pic16_emitcode ("pop","ar0");
1292 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1296 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1302 pic16_emitcode ("pop","ar0");
1306 bitVectUnSetBit(ic->rUsed,R0_IDX);
1312 pic16_emitcode ("pop","ar1");
1316 bitVectUnSetBit(ic->rUsed,R1_IDX);
1323 /* we must store the result on stack */
1324 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1325 // operands on stack are accessible via "FSR2 + index" with index
1326 // starting at 2 for arguments and growing from 0 downwards for
1327 // local variables (index == 0 is not assigned so we add one here)
1328 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1333 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1334 for(i=0;i<aop->size;i++) {
1335 /* initialise for stack access via frame pointer */
1336 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1337 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1338 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1341 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1345 for(i=0;i<aop->size;i++)
1346 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1355 int stk = aop->aopu.aop_stk + aop->size;
1356 bitVectUnSetBit(ic->rUsed,R0_IDX);
1357 bitVectUnSetBit(ic->rUsed,R1_IDX);
1359 getFreePtr(ic,&aop,FALSE);
1361 if (options.stack10bit)
1363 /* I'm not sure what to do here yet... */
1366 "*** Warning: probably generating bad code for "
1367 "10 bit stack mode.\n");
1371 pic16_emitcode ("mov","a,_bp");
1372 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1373 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1375 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1379 pic16_emitcode("pop","acc");
1380 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1382 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1385 pic16_freeAsmop(op,NULL,ic,TRUE);
1387 pic16_emitcode("pop","ar0");
1392 pic16_emitcode("pop","ar1");
1402 /* all other cases just dealloc */
1406 OP_SYMBOL(op)->aop = NULL;
1407 /* if the symbol has a spill */
1409 SPIL_LOC(op)->aop = NULL;
1414 /*-----------------------------------------------------------------*/
1415 /* pic16_aopGet - for fetching value of the aop */
1416 /*-----------------------------------------------------------------*/
1417 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1422 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1424 /* offset is greater than size then zero */
1425 if (offset > (aop->size - 1) &&
1426 aop->type != AOP_LIT)
1429 /* depending on type */
1430 switch (aop->type) {
1434 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1435 rs = Safe_calloc(1, strlen(s)+1);
1440 /* if we need to increment it */
1441 while (offset > aop->coff)
1443 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1447 while (offset < aop->coff)
1449 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1455 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1456 return (dname ? "acc" : "a");
1458 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1459 rs = Safe_calloc (1, strlen (s) + 1);
1467 sprintf (s,"%s",aop->aopu.aop_immd);
1470 sprintf(s,"(%s >> %d)",
1475 aop->aopu.aop_immd);
1476 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1477 rs = Safe_calloc(1,strlen(s)+1);
1483 sprintf(s,"(%s + %d)",
1486 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1488 sprintf(s,"%s",aop->aopu.aop_dir);
1489 rs = Safe_calloc(1,strlen(s)+1);
1495 // return aop->aopu.aop_reg[offset]->dname;
1497 return aop->aopu.aop_reg[offset]->name;
1500 //pic16_emitcode(";","%d",__LINE__);
1501 return aop->aopu.aop_dir;
1504 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1505 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1507 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1508 rs = Safe_strdup("WREG");
1512 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1513 rs = Safe_calloc(1,strlen(s)+1);
1518 aop->coff = offset ;
1519 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1522 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1524 return aop->aopu.aop_str[offset];
1528 pCodeOp *pcop = aop->aopu.pcop;
1529 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1531 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1532 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1534 sprintf(s,"(%s + %d)", pcop->name, offset);
1536 sprintf(s,"%s", pcop->name);
1539 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1542 rs = Safe_calloc(1,strlen(s)+1);
1547 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1551 // pCodeOp *pcop = aop->aop
1556 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1557 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1558 "aopget got unsupported aop->type");
1564 /* lock has the following meaning: When allocating temporary registers
1565 * for stack variables storage, the value of the temporary register is
1566 * saved on stack. Its value is restored at the end. This procedure is
1567 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1568 * a possibility that before a call to pic16_aopOp, a temporary register
1569 * is allocated for a while and it is freed after some time, this will
1570 * mess the stack and values will not be restored properly. So use lock=1
1571 * to allocate temporary registers used internally by the programmer, and
1572 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1573 * to inform the compiler developer about a possible bug. This is an internal
1574 * feature for developing the compiler -- VR */
1576 int _TempReg_lock = 0;
1577 /*-----------------------------------------------------------------*/
1578 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1579 /*-----------------------------------------------------------------*/
1580 pCodeOp *pic16_popGetTempReg(int lock)
1585 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1587 // werror(W_POSSBUG2, __FILE__, __LINE__);
1590 _TempReg_lock += lock;
1595 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1596 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1597 PCOR(pcop)->r->wasUsed=1;
1598 PCOR(pcop)->r->isFree=0;
1600 /* push value on stack */
1601 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1609 /*-----------------------------------------------------------------*/
1610 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1611 /* don't save if inside v */
1612 /*-----------------------------------------------------------------*/
1613 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1618 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1621 // werror(W_POSSBUG2, __FILE__, __LINE__);
1624 _TempReg_lock += lock;
1629 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1630 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1631 PCOR(pcop)->r->wasUsed=1;
1632 PCOR(pcop)->r->isFree=0;
1634 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1635 /* push value on stack */
1636 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1646 /*-----------------------------------------------------------------*/
1647 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1648 /*-----------------------------------------------------------------*/
1649 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1653 _TempReg_lock -= lock;
1655 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1656 PCOR(pcop)->r->isFree = 1;
1657 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1660 /*-----------------------------------------------------------------*/
1661 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1662 /*-----------------------------------------------------------------*/
1663 pCodeOp *pic16_popGetLabel(unsigned int key)
1666 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1671 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popCopyReg - copy a pcode operator */
1676 /*-----------------------------------------------------------------*/
1677 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1681 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1682 pcor->pcop.type = pc->pcop.type;
1684 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1685 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1687 pcor->pcop.name = NULL;
1690 pcor->rIdx = pc->rIdx;
1692 pcor->instance = pc->instance;
1694 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1699 /*-----------------------------------------------------------------*/
1700 /* pic16_popGetLit - asm operator to pcode operator conversion */
1701 /*-----------------------------------------------------------------*/
1702 pCodeOp *pic16_popGetLit(int lit)
1704 return pic16_newpCodeOpLit(lit);
1707 /*-----------------------------------------------------------------*/
1708 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1709 /*-----------------------------------------------------------------*/
1710 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1712 return pic16_newpCodeOpLit2(lit, arg2);
1716 /*-----------------------------------------------------------------*/
1717 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1718 /*-----------------------------------------------------------------*/
1719 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1721 return pic16_newpCodeOpImmd(name, offset,index, 0);
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGet - asm operator to pcode operator conversion */
1727 /*-----------------------------------------------------------------*/
1728 pCodeOp *pic16_popGetWithString(char *str)
1734 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1738 pcop = pic16_newpCodeOp(str,PO_STR);
1743 /*-----------------------------------------------------------------*/
1744 /* pic16_popRegFromString - */
1745 /*-----------------------------------------------------------------*/
1746 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1749 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1750 pcop->type = PO_DIR;
1752 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1753 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1758 pcop->name = Safe_calloc(1,strlen(str)+1);
1759 strcpy(pcop->name,str);
1761 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1763 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1765 /* make sure that register doesn't exist,
1766 * and operand isn't NULL
1767 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1768 if((PCOR(pcop)->r == NULL)
1770 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1771 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1772 // __FUNCTION__, __LINE__, str, size, offset);
1774 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1775 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1778 PCOR(pcop)->instance = offset;
1783 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1787 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1789 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1790 PCOR(pcop)->rIdx = rIdx;
1791 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1793 PCOR(pcop)->r->isFree = 0;
1794 PCOR(pcop)->r->wasUsed = 1;
1796 pcop->type = PCOR(pcop)->r->pc_type;
1801 /*---------------------------------------------------------------------------------*/
1802 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1804 /*---------------------------------------------------------------------------------*/
1805 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1810 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1812 /* comment the following check, so errors to throw up */
1813 // if(!pcop2)return NULL;
1815 temp = pic16_popGet(aop_dst, offset);
1816 pcop2->pcop2 = temp;
1823 /*--------------------------------------------------------------------------------.-*/
1824 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1825 /* VR 030601 , adapted by Hans Dorn */
1826 /*--------------------------------------------------------------------------------.-*/
1827 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1831 pcop2 = (pCodeOpReg2 *)src;
1839 /*---------------------------------------------------------------------------------*/
1840 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1841 /* movff instruction */
1842 /*---------------------------------------------------------------------------------*/
1843 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1848 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1849 pcop2->pcop2 = pic16_popCopyReg(dst);
1851 /* the pCodeOp may be already allocated */
1852 pcop2 = (pCodeOpReg2 *)(src);
1853 pcop2->pcop2 = (pCodeOp *)(dst);
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popGet - asm operator to pcode operator conversion */
1862 /*-----------------------------------------------------------------*/
1863 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1865 //char *s = buffer ;
1870 /* offset is greater than
1873 // if (offset > (aop->size - 1) &&
1874 // aop->type != AOP_LIT)
1875 // return NULL; //zero;
1877 /* depending on type */
1878 switch (aop->type) {
1884 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1885 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1892 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1893 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1894 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1895 PCOR(pcop)->r->wasUsed = 1;
1896 PCOR(pcop)->r->isFree = 0;
1898 PCOR(pcop)->instance = offset;
1899 pcop->type = PCOR(pcop)->r->pc_type;
1903 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1904 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1907 /* pCodeOp is already allocated from aopForSym */
1908 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1909 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1915 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1917 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1919 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1921 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1922 PCOR(pcop)->rIdx = rIdx;
1923 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1924 PCOR(pcop)->r->wasUsed=1;
1925 PCOR(pcop)->r->isFree=0;
1927 PCOR(pcop)->instance = offset;
1928 pcop->type = PCOR(pcop)->r->pc_type;
1929 // rs = aop->aopu.aop_reg[offset]->name;
1930 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1934 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1935 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1941 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1942 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1947 assert (aop && aop->aopu.aop_reg[offset] != NULL);
1948 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1950 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1952 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1953 // pcop->type = PO_GPR_REGISTER;
1954 PCOR(pcop)->rIdx = rIdx;
1955 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1956 PCOR(pcop)->r->wasUsed=1;
1957 PCOR(pcop)->r->isFree=0;
1959 PCOR(pcop)->instance = offset;
1960 pcop->type = PCOR(pcop)->r->pc_type;
1962 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1963 rs = aop->aopu.aop_reg[offset]->name;
1964 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1969 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1971 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1972 PCOR(pcop)->instance = offset;
1973 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1974 //if(PCOR(pcop)->r == NULL)
1975 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1979 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1980 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1983 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1984 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1987 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1988 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1989 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1990 pcop->type = PCOR(pcop)->r->pc_type;
1991 pcop->name = PCOR(pcop)->r->name;
1997 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1999 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2000 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2002 switch( aop->aopu.pcop->type ) {
2003 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
2004 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2006 assert( 0 ); /* should never reach here */;
2009 PCOI(pcop)->offset = offset;
2014 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2015 "pic16_popGet got unsupported aop->type");
2018 /*-----------------------------------------------------------------*/
2019 /* pic16_aopPut - puts a string for a aop */
2020 /*-----------------------------------------------------------------*/
2021 void pic16_aopPut (asmop *aop, char *s, int offset)
2028 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2030 if (aop->size && offset > ( aop->size - 1)) {
2031 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2032 "pic16_aopPut got offset > aop->size");
2036 /* will assign value to value */
2037 /* depending on where it is ofcourse */
2038 switch (aop->type) {
2041 sprintf(d,"(%s + %d)",
2042 aop->aopu.aop_dir,offset);
2043 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2046 sprintf(d,"%s",aop->aopu.aop_dir);
2049 DEBUGpic16_emitcode(";","%d",__LINE__);
2051 pic16_emitcode("movf","%s,w",s);
2052 pic16_emitcode("movwf","%s",d);
2055 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2056 if(offset >= aop->size) {
2057 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2060 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2063 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2070 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2071 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2074 strcmp(s,"r0") == 0 ||
2075 strcmp(s,"r1") == 0 ||
2076 strcmp(s,"r2") == 0 ||
2077 strcmp(s,"r3") == 0 ||
2078 strcmp(s,"r4") == 0 ||
2079 strcmp(s,"r5") == 0 ||
2080 strcmp(s,"r6") == 0 ||
2081 strcmp(s,"r7") == 0 )
2082 pic16_emitcode("mov","%s,%s ; %d",
2083 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2087 if(strcmp(s,"W")==0 )
2088 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2090 pic16_emitcode("movwf","%s",
2091 aop->aopu.aop_reg[offset]->name);
2093 if(strcmp(s,zero)==0) {
2094 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2096 } else if(strcmp(s,"W")==0) {
2097 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2098 pcop->type = PO_GPR_REGISTER;
2100 PCOR(pcop)->rIdx = -1;
2101 PCOR(pcop)->r = NULL;
2103 DEBUGpic16_emitcode(";","%d",__LINE__);
2104 pcop->name = Safe_strdup(s);
2105 pic16_emitpcode(POC_MOVFW,pcop);
2106 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2107 } else if(strcmp(s,one)==0) {
2108 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2109 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2111 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2119 if (aop->type == AOP_DPTR2)
2125 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2126 "pic16_aopPut writting to code space");
2130 while (offset > aop->coff) {
2132 pic16_emitcode ("inc","dptr");
2135 while (offset < aop->coff) {
2137 pic16_emitcode("lcall","__decdptr");
2142 /* if not in accumulater */
2145 pic16_emitcode ("movx","@dptr,a");
2147 if (aop->type == AOP_DPTR2)
2155 while (offset > aop->coff) {
2157 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2159 while (offset < aop->coff) {
2161 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2167 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2172 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2174 if (strcmp(s,"r0") == 0 ||
2175 strcmp(s,"r1") == 0 ||
2176 strcmp(s,"r2") == 0 ||
2177 strcmp(s,"r3") == 0 ||
2178 strcmp(s,"r4") == 0 ||
2179 strcmp(s,"r5") == 0 ||
2180 strcmp(s,"r6") == 0 ||
2181 strcmp(s,"r7") == 0 ) {
2183 sprintf(buffer,"a%s",s);
2184 pic16_emitcode("mov","@%s,%s",
2185 aop->aopu.aop_ptr->name,buffer);
2187 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2192 if (strcmp(s,"a") == 0)
2193 pic16_emitcode("push","acc");
2195 pic16_emitcode("push","%s",s);
2200 /* if bit variable */
2201 if (!aop->aopu.aop_dir) {
2202 pic16_emitcode("clr","a");
2203 pic16_emitcode("rlc","a");
2206 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2209 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2212 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2214 lbl = newiTempLabel(NULL);
2216 if (strcmp(s,"a")) {
2219 pic16_emitcode("clr","c");
2220 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2221 pic16_emitcode("cpl","c");
2222 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2223 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2230 if (strcmp(aop->aopu.aop_str[offset],s))
2231 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2236 if (!offset && (strcmp(s,"acc") == 0))
2239 if (strcmp(aop->aopu.aop_str[offset],s))
2240 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2244 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2245 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2246 // "pic16_aopPut got unsupported aop->type");
2252 /*-----------------------------------------------------------------*/
2253 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2254 /*-----------------------------------------------------------------*/
2255 void pic16_mov2w (asmop *aop, int offset)
2257 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2260 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2262 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2265 static void mov2f(asmop *dst, asmop *src, int offset)
2267 if(is_LitAOp(src)) {
2268 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2269 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2271 if(pic16_sameRegsOfs(src, dst, offset))return;
2272 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2273 pic16_popGet(dst, offset)));
2277 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2279 if(is_LitAOp(src)) {
2280 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2281 pic16_emitpcode(POC_MOVWF, dst);
2283 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2287 void pic16_testStackOverflow(void)
2289 #define GSTACK_TEST_NAME "__gstack_test"
2291 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2296 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2297 strcpy(sym->rname, GSTACK_TEST_NAME);
2298 checkAddSym(&externs, sym);
2303 /* push pcop into stack */
2304 void pic16_pushpCodeOp(pCodeOp *pcop)
2306 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2307 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2308 if(pic16_options.gstack)
2309 pic16_testStackOverflow();
2313 /* pop pcop from stack */
2314 void pic16_poppCodeOp(pCodeOp *pcop)
2316 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2317 if(pic16_options.gstack)
2318 pic16_testStackOverflow();
2322 /*-----------------------------------------------------------------*/
2323 /* pushw - pushes wreg to stack */
2324 /*-----------------------------------------------------------------*/
2327 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2328 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2329 if(pic16_options.gstack)
2330 pic16_testStackOverflow();
2334 /*-----------------------------------------------------------------*/
2335 /* pushaop - pushes aop to stack */
2336 /*-----------------------------------------------------------------*/
2337 void pushaop(asmop *aop, int offset)
2339 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2341 if(is_LitAOp(aop)) {
2342 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2343 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2345 pic16_emitpcode(POC_MOVFF,
2346 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2349 if(pic16_options.gstack)
2350 pic16_testStackOverflow();
2353 /*-----------------------------------------------------------------*/
2354 /* popaop - pops aop from stack */
2355 /*-----------------------------------------------------------------*/
2356 void popaop(asmop *aop, int offset)
2358 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2359 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2360 if(pic16_options.gstack)
2361 pic16_testStackOverflow();
2364 void popaopidx(asmop *aop, int offset, int index)
2368 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2370 if(STACK_MODEL_LARGE)ofs++;
2372 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2373 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2374 if(pic16_options.gstack)
2375 pic16_testStackOverflow();
2378 #if !(USE_GENERIC_SIGNED_SHIFT)
2379 /*-----------------------------------------------------------------*/
2380 /* reAdjustPreg - points a register back to where it should */
2381 /*-----------------------------------------------------------------*/
2382 static void reAdjustPreg (asmop *aop)
2386 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2388 if ((size = aop->size) <= 1)
2391 switch (aop->type) {
2395 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2399 if (aop->type == AOP_DPTR2)
2405 pic16_emitcode("lcall","__decdptr");
2408 if (aop->type == AOP_DPTR2)
2420 /*-----------------------------------------------------------------*/
2421 /* opIsGptr: returns non-zero if the passed operand is */
2422 /* a generic pointer type. */
2423 /*-----------------------------------------------------------------*/
2424 static int opIsGptr(operand *op)
2426 sym_link *type = operandType(op);
2428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2429 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2437 /*-----------------------------------------------------------------*/
2438 /* pic16_getDataSize - get the operand data size */
2439 /*-----------------------------------------------------------------*/
2440 int pic16_getDataSize(operand *op)
2442 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2445 return AOP_SIZE(op);
2447 // tsd- in the pic port, the genptr size is 1, so this code here
2448 // fails. ( in the 8051 port, the size was 4).
2451 size = AOP_SIZE(op);
2452 if (size == GPTRSIZE)
2454 sym_link *type = operandType(op);
2455 if (IS_GENPTR(type))
2457 /* generic pointer; arithmetic operations
2458 * should ignore the high byte (pointer type).
2461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2468 /*-----------------------------------------------------------------*/
2469 /* pic16_outAcc - output Acc */
2470 /*-----------------------------------------------------------------*/
2471 void pic16_outAcc(operand *result)
2474 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2475 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2478 size = pic16_getDataSize(result);
2480 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2483 /* unsigned or positive */
2485 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2490 /*-----------------------------------------------------------------*/
2491 /* pic16_outBitC - output a bit C */
2492 /* Move to result the value of Carry flag -- VR */
2493 /*-----------------------------------------------------------------*/
2494 void pic16_outBitC(operand *result)
2498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2500 /* if the result is bit */
2501 if (AOP_TYPE(result) == AOP_CRY) {
2502 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2503 pic16_aopPut(AOP(result),"c",0);
2506 i = AOP_SIZE(result);
2508 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2510 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2514 /*-----------------------------------------------------------------*/
2515 /* pic16_outBitOp - output a bit from Op */
2516 /* Move to result the value of set/clr op -- VR */
2517 /*-----------------------------------------------------------------*/
2518 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2524 /* if the result is bit */
2525 if (AOP_TYPE(result) == AOP_CRY) {
2526 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2527 pic16_aopPut(AOP(result),"c",0);
2530 i = AOP_SIZE(result);
2532 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2534 pic16_emitpcode(POC_RRCF, pcop);
2535 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2539 /*-----------------------------------------------------------------*/
2540 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2541 /*-----------------------------------------------------------------*/
2542 void pic16_toBoolean(operand *oper)
2544 int size = AOP_SIZE(oper) - 1;
2547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2549 if ( AOP_TYPE(oper) != AOP_ACC) {
2550 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2553 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2558 #if !defined(GEN_Not)
2559 /*-----------------------------------------------------------------*/
2560 /* genNot - generate code for ! operation */
2561 /*-----------------------------------------------------------------*/
2562 static void pic16_genNot (iCode *ic)
2568 /* assign asmOps to operand & result */
2569 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2570 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2572 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2573 /* if in bit space then a special case */
2574 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2575 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2576 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2577 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2579 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2580 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2581 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2586 size = AOP_SIZE(IC_LEFT(ic));
2588 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2589 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2590 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2593 pic16_toBoolean(IC_LEFT(ic));
2595 tlbl = newiTempLabel(NULL);
2596 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2597 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2598 pic16_outBitC(IC_RESULT(ic));
2601 /* release the aops */
2602 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2603 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2608 #if !defined(GEN_Cpl)
2609 /*-----------------------------------------------------------------*/
2610 /* genCpl - generate code for complement */
2611 /*-----------------------------------------------------------------*/
2612 static void pic16_genCpl (iCode *ic)
2618 /* assign asmOps to operand & result */
2619 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2620 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2622 /* if both are in bit space then
2624 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2625 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2627 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2628 pic16_emitcode("cpl","c");
2629 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2633 size = AOP_SIZE(IC_RESULT(ic));
2636 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2638 pic16_emitcode("cpl","a");
2639 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2641 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2642 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2644 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2645 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2653 /* release the aops */
2654 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2655 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2659 /*-----------------------------------------------------------------*/
2660 /* genUminusFloat - unary minus for floating points */
2661 /*-----------------------------------------------------------------*/
2662 static void genUminusFloat(operand *op,operand *result)
2664 int size ,offset =0 ;
2667 /* for this we just need to flip the
2668 first it then copy the rest in place */
2669 size = AOP_SIZE(op);
2672 mov2f(AOP(result), AOP(op), offset);
2676 /* toggle the MSB's highest bit */
2677 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2680 /*-----------------------------------------------------------------*/
2681 /* genUminus - unary minus code generation */
2682 /*-----------------------------------------------------------------*/
2683 static void genUminus (iCode *ic)
2686 sym_link *optype, *rtype;
2691 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2692 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2694 /* if both in bit space then special case */
2695 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2696 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2698 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2699 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2700 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2704 optype = operandType(IC_LEFT(ic));
2705 rtype = operandType(IC_RESULT(ic));
2707 /* if float then do float stuff */
2708 if (IS_FLOAT(optype)) {
2709 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2713 /* otherwise subtract from zero by taking the 2's complement */
2714 size = AOP_SIZE(IC_LEFT(ic));
2716 for(i=0; i<size; i++) {
2717 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2718 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2720 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2721 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2725 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2726 for(i=1; i<size; i++) {
2728 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2732 /* release the aops */
2733 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2734 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2738 /*-----------------------------------------------------------------*/
2739 /* saveRegisters - will look for a call and save the registers */
2740 /*-----------------------------------------------------------------*/
2741 static void saveRegisters(iCode *lic)
2748 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2750 for (ic = lic ; ic ; ic = ic->next)
2751 if (ic->op == CALL || ic->op == PCALL)
2755 fprintf(stderr,"found parameter push with no function call\n");
2759 /* if the registers have been saved already then
2761 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2764 /* find the registers in use at this time
2765 and push them away to safety */
2766 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2770 if (options.useXstack) {
2771 if (bitVectBitValue(rsave,R0_IDX))
2772 pic16_emitcode("mov","b,r0");
2773 pic16_emitcode("mov","r0,%s",spname);
2774 for (i = 0 ; i < pic16_nRegs ; i++) {
2775 if (bitVectBitValue(rsave,i)) {
2777 pic16_emitcode("mov","a,b");
2779 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2780 pic16_emitcode("movx","@r0,a");
2781 pic16_emitcode("inc","r0");
2784 pic16_emitcode("mov","%s,r0",spname);
2785 if (bitVectBitValue(rsave,R0_IDX))
2786 pic16_emitcode("mov","r0,b");
2788 //for (i = 0 ; i < pic16_nRegs ; i++) {
2789 // if (bitVectBitValue(rsave,i))
2790 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2793 dtype = operandType(IC_LEFT(ic));
2794 if (currFunc && dtype &&
2795 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2796 IFFUNC_ISISR(currFunc->type) &&
2799 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2802 /*-----------------------------------------------------------------*/
2803 /* unsaveRegisters - pop the pushed registers */
2804 /*-----------------------------------------------------------------*/
2805 static void unsaveRegisters (iCode *ic)
2810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2811 /* find the registers in use at this time
2812 and push them away to safety */
2813 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2816 if (options.useXstack) {
2817 pic16_emitcode("mov","r0,%s",spname);
2818 for (i = pic16_nRegs ; i >= 0 ; i--) {
2819 if (bitVectBitValue(rsave,i)) {
2820 pic16_emitcode("dec","r0");
2821 pic16_emitcode("movx","a,@r0");
2823 pic16_emitcode("mov","b,a");
2825 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2829 pic16_emitcode("mov","%s,r0",spname);
2830 if (bitVectBitValue(rsave,R0_IDX))
2831 pic16_emitcode("mov","r0,b");
2833 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2834 // if (bitVectBitValue(rsave,i))
2835 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2842 /*-----------------------------------------------------------------*/
2844 /*-----------------------------------------------------------------*/
2845 static void pushSide(operand * oper, int size)
2848 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2850 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2851 if (AOP_TYPE(oper) != AOP_REG &&
2852 AOP_TYPE(oper) != AOP_DIR &&
2854 pic16_emitcode("mov","a,%s",l);
2855 pic16_emitcode("push","acc");
2857 pic16_emitcode("push","%s",l);
2862 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2864 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2865 pic16_emitpcode(POC_MOVFW, src);
2866 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2869 src, pic16_popGet(AOP(op), offset)));
2874 /*-----------------------------------------------------------------*/
2875 /* assignResultValue - assign results to oper, rescall==1 is */
2876 /* called from genCall() or genPcall() */
2877 /*-----------------------------------------------------------------*/
2878 static void assignResultValue(operand * oper, int rescall)
2880 int size = AOP_SIZE(oper);
2884 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2885 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2888 /* assign result from a call/pcall function() */
2890 /* function results are stored in a special order,
2891 * see top of file with Function return policy, or manual */
2894 /* 8-bits, result in WREG */
2895 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2898 /* 16-bits, result in PRODL:WREG */
2899 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2903 /* 24-bits, result in PRODH:PRODL:WREG */
2904 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2908 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2909 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2913 /* >32-bits, result on stack, and FSR0 points to beginning.
2914 * Fix stack when done */
2916 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2918 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2919 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2921 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2926 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2927 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2928 if(STACK_MODEL_LARGE) {
2930 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2934 int areg = 0; /* matching argument register */
2936 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2937 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2940 /* its called from genReceive (probably) -- VR */
2941 /* I hope this code will not be called from somewhere else in the future!
2942 * We manually set the pseudo stack pointer in genReceive. - dw
2944 if(!GpsuedoStkPtr && _G.useWreg) {
2945 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2947 /* The last byte in the assignment is in W */
2948 if(areg <= GpsuedoStkPtr) {
2950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2952 // debugf("receive from WREG\n", 0);
2954 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2957 _G.stack_lat = AOP_SIZE(oper)-1;
2962 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2963 // debugf("receive from STACK\n", 0);
2970 /*-----------------------------------------------------------------*/
2971 /* genIpush - generate code for pushing this gets a little complex */
2972 /*-----------------------------------------------------------------*/
2973 static void genIpush (iCode *ic)
2975 // int size, offset=0;
2978 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2981 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2983 /* send to stack as normal */
2984 addSet(&_G.sendSet,ic);
2985 // addSetHead(&_G.sendSet,ic);
2986 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2991 int size, offset = 0 ;
2995 /* if this is not a parm push : ie. it is spill push
2996 and spill push is always done on the local stack */
2997 if (!ic->parmPush) {
2999 /* and the item is spilt then do nothing */
3000 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3003 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3004 size = AOP_SIZE(IC_LEFT(ic));
3005 /* push it on the stack */
3007 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3012 pic16_emitcode("push","%s",l);
3017 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3021 /*-----------------------------------------------------------------*/
3022 /* genIpop - recover the registers: can happen only for spilling */
3023 /*-----------------------------------------------------------------*/
3024 static void genIpop (iCode *ic)
3027 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3032 /* if the temp was not pushed then */
3033 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3036 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3037 size = AOP_SIZE(IC_LEFT(ic));
3040 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3043 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3048 /*-----------------------------------------------------------------*/
3049 /* unsaverbank - restores the resgister bank from stack */
3050 /*-----------------------------------------------------------------*/
3051 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3053 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3059 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3061 if (options.useXstack) {
3063 r = getFreePtr(ic,&aop,FALSE);
3066 pic16_emitcode("mov","%s,_spx",r->name);
3067 pic16_emitcode("movx","a,@%s",r->name);
3068 pic16_emitcode("mov","psw,a");
3069 pic16_emitcode("dec","%s",r->name);
3072 pic16_emitcode ("pop","psw");
3075 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3076 if (options.useXstack) {
3077 pic16_emitcode("movx","a,@%s",r->name);
3078 //pic16_emitcode("mov","(%s+%d),a",
3079 // regspic16[i].base,8*bank+regspic16[i].offset);
3080 pic16_emitcode("dec","%s",r->name);
3083 pic16_emitcode("pop",""); //"(%s+%d)",
3084 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3087 if (options.useXstack) {
3089 pic16_emitcode("mov","_spx,%s",r->name);
3090 pic16_freeAsmop(NULL,aop,ic,TRUE);
3096 /*-----------------------------------------------------------------*/
3097 /* saverbank - saves an entire register bank on the stack */
3098 /*-----------------------------------------------------------------*/
3099 static void saverbank (int bank, iCode *ic, bool pushPsw)
3101 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3107 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3108 if (options.useXstack) {
3111 r = getFreePtr(ic,&aop,FALSE);
3112 pic16_emitcode("mov","%s,_spx",r->name);
3116 for (i = 0 ; i < pic16_nRegs ;i++) {
3117 if (options.useXstack) {
3118 pic16_emitcode("inc","%s",r->name);
3119 //pic16_emitcode("mov","a,(%s+%d)",
3120 // regspic16[i].base,8*bank+regspic16[i].offset);
3121 pic16_emitcode("movx","@%s,a",r->name);
3123 pic16_emitcode("push","");// "(%s+%d)",
3124 //regspic16[i].base,8*bank+regspic16[i].offset);
3128 if (options.useXstack) {
3129 pic16_emitcode("mov","a,psw");
3130 pic16_emitcode("movx","@%s,a",r->name);
3131 pic16_emitcode("inc","%s",r->name);
3132 pic16_emitcode("mov","_spx,%s",r->name);
3133 pic16_freeAsmop (NULL,aop,ic,TRUE);
3136 pic16_emitcode("push","psw");
3138 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3146 static int wparamCmp(void *p1, void *p2)
3148 return (!strcmp((char *)p1, (char *)p2));
3151 int inWparamList(char *s)
3153 return isinSetWith(wparamList, s, wparamCmp);
3157 /*-----------------------------------------------------------------*/
3158 /* genCall - generates a call statement */
3159 /*-----------------------------------------------------------------*/
3160 static void genCall (iCode *ic)
3170 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3171 /* if caller saves & we have not saved then */
3172 // if (!ic->regsSaved)
3173 // saveRegisters(ic);
3175 /* initialise stackParms for IPUSH pushes */
3176 // stackParms = psuedoStkPtr;
3177 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3178 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3179 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3182 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3185 /* if send set is not empty the assign */
3188 int psuedoStkPtr=-1;
3189 int firstTimeThruLoop = 1;
3192 /* reverse sendSet if function is not reentrant */
3193 if(!IFFUNC_ISREENT(ftype))
3194 _G.sendSet = reverseSet(_G.sendSet);
3196 /* First figure how many parameters are getting passed */
3200 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3204 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3205 size = AOP_SIZE(IC_LEFT(sic));
3209 /* pass the last byte through WREG */
3213 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3214 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3215 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3217 if(!firstTimeThruLoop) {
3218 /* If this is not the first time we've been through the loop
3219 * then we need to save the parameter in a temporary
3220 * register. The last byte of the last parameter is
3224 // --psuedoStkPtr; // sanity check
3228 firstTimeThruLoop=0;
3230 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3235 /* all arguments are passed via stack */
3239 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3240 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3241 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3243 // pushaop(AOP(IC_LEFT(sic)), size);
3244 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3249 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3253 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3254 pushw(); /* save last parameter to stack if functions has varargs */
3258 } else use_wreg = 0;
3260 _G.stackRegSet = _G.sendSet;
3265 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3269 /* if we need to assign a result value */
3270 if ((IS_ITEMP(IC_RESULT(ic))
3271 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3272 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3273 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3276 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3279 assignResultValue(IC_RESULT(ic), 1);
3281 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3282 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3284 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3287 if(!stackParms && ic->parmBytes) {
3288 stackParms = ic->parmBytes;
3291 stackParms -= use_wreg;
3294 if(stackParms == 1) {
3295 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3297 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3298 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3300 if(STACK_MODEL_LARGE) {
3302 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3307 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3310 /* adjust the stack for parameters if required */
3311 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3314 /* if register bank was saved then pop them */
3316 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3318 /* if we hade saved some registers then unsave them */
3319 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3320 unsaveRegisters (ic);
3326 /*-----------------------------------------------------------------*/
3327 /* genPcall - generates a call by pointer statement */
3328 /* new version, created from genCall - HJD */
3329 /*-----------------------------------------------------------------*/
3330 static void genPcall (iCode *ic)
3332 sym_link *ftype, *fntype;
3334 symbol *retlbl = newiTempLabel(NULL);
3335 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3339 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3340 fntype = operandType( IC_LEFT(ic) )->next;
3342 /* if send set is not empty the assign */
3345 int psuedoStkPtr=-1;
3347 /* reverse sendSet if function is not reentrant */
3348 if(!IFFUNC_ISREENT(fntype))
3349 _G.sendSet = reverseSet(_G.sendSet);
3353 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3356 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3357 size = AOP_SIZE(IC_LEFT(sic));
3360 /* all parameters are passed via stack, since WREG is clobbered
3361 * by the calling sequence */
3363 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3367 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3371 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3374 _G.stackRegSet = _G.sendSet;
3378 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3380 // push return address
3381 // push $ on return stack, then replace with retlbl
3383 pic16_emitpcodeNULLop(POC_PUSH);
3385 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3386 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3387 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3388 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3389 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3390 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3392 /* make the call by writing the pointer into pc */
3393 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3394 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3396 // note: MOVFF to PCL not allowed
3397 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3398 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3401 /* return address is here: (X) */
3402 pic16_emitpLabelFORCE(retlbl->key);
3404 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3407 /* if we need assign a result value */
3408 if ((IS_ITEMP(IC_RESULT(ic))
3409 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3410 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3411 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3414 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3417 assignResultValue(IC_RESULT(ic), 1);
3419 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3422 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3425 // stackParms -= use_wreg;
3428 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3429 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3430 if(STACK_MODEL_LARGE) {
3432 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3437 /*-----------------------------------------------------------------*/
3438 /* resultRemat - result is rematerializable */
3439 /*-----------------------------------------------------------------*/
3440 static int resultRemat (iCode *ic)
3442 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3443 if (SKIP_IC(ic) || ic->op == IFX)
3446 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3447 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3448 if (sym->remat && !POINTER_SET(ic))
3455 #if defined(__BORLANDC__) || defined(_MSC_VER)
3456 #define STRCASECMP stricmp
3458 #define STRCASECMP strcasecmp
3462 /*-----------------------------------------------------------------*/
3463 /* inExcludeList - return 1 if the string is in exclude Reg list */
3464 /*-----------------------------------------------------------------*/
3465 static bool inExcludeList(char *s)
3467 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3471 if (options.excludeRegs[i] &&
3472 STRCASECMP(options.excludeRegs[i],"none") == 0)
3475 for ( i = 0 ; options.excludeRegs[i]; i++) {
3476 if (options.excludeRegs[i] &&
3477 STRCASECMP(s,options.excludeRegs[i]) == 0)
3484 /*-----------------------------------------------------------------*/
3485 /* genFunction - generated code for function entry */
3486 /*-----------------------------------------------------------------*/
3487 static void genFunction (iCode *ic)
3493 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3495 pic16_labelOffset += (max_key+4);
3500 ftype = operandType(IC_LEFT(ic));
3501 sym = OP_SYMBOL(IC_LEFT(ic));
3503 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3504 /* create an absolute section at the interrupt vector:
3505 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3513 sym = OP_SYMBOL( IC_LEFT(ic));
3515 if(interrupts[i]->name
3516 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3523 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3524 __FILE__, __LINE__, sym->name);
3527 _G.interruptvector = found;
3530 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3531 asym = newSymbol(asymname, 0);
3533 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3534 pic16_addpBlock( apb );
3536 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3537 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3538 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3540 /* mark the end of this tiny function */
3541 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3546 abSym = Safe_calloc(1, sizeof(absSym));
3547 strcpy(abSym->name, asymname);
3549 switch( _G.interruptvector ) {
3550 case 0: abSym->address = 0x000000; break;
3551 case 1: abSym->address = 0x000008; break;
3552 case 2: abSym->address = 0x000018; break;
3555 /* relocate interrupt vectors if needed */
3556 abSym->address += pic16_options.ivt_loc;
3558 addSet(&absSymSet, abSym);
3562 /* create the function header */
3563 pic16_emitcode(";","-----------------------------------------");
3564 pic16_emitcode(";"," function %s",sym->name);
3565 pic16_emitcode(";","-----------------------------------------");
3567 pic16_emitcode("","%s:",sym->rname);
3568 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3574 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3575 if(!strcmp(ab->name, sym->rname)) {
3576 pic16_pBlockConvert2Absolute(pb);
3583 if(IFFUNC_ISNAKED(ftype)) {
3584 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3588 /* if critical function then turn interrupts off */
3589 if (IFFUNC_ISCRITICAL(ftype)) {
3590 //pic16_emitcode("clr","ea");
3593 _G.fregsUsed = sym->regsUsed;
3595 /* if this is an interrupt service routine then
3596 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3597 if (IFFUNC_ISISR(sym->type)) {
3598 _G.usefastretfie = 1; /* use shadow registers by default */
3600 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3601 if(!(_G.interruptvector == 1)) {
3602 /* do not save WREG,STATUS,BSR for high priority interrupts
3603 * because they are stored in the hardware shadow registers already */
3604 _G.usefastretfie = 0;
3605 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3606 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3607 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3610 /* these should really be optimized somehow, because not all
3611 * interrupt handlers modify them */
3612 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3613 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3614 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3615 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3617 // pic16_pBlockConvert2ISR(pb);
3621 /* emit code to setup stack frame if user enabled,
3622 * and function is not main() */
3624 //fprintf(stderr, "function name: %s\n", sym->name);
3625 if(strcmp(sym->name, "main")) {
3626 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3627 /* setup the stack frame */
3628 if(STACK_MODEL_LARGE)
3629 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3630 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3632 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3633 if(STACK_MODEL_LARGE)
3634 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3638 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3641 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3643 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3644 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3646 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3649 if(inWparamList(sym->name)) {
3650 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3657 /* if callee-save to be used for this function
3658 * then save the registers being used in this function */
3659 // if (IFFUNC_CALLEESAVES(sym->type))
3663 /* if any registers used */
3664 if (sym->regsUsed) {
3665 /* save the registers used */
3666 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3667 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3668 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3669 if (bitVectBitValue(sym->regsUsed,i)) {
3670 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3673 if(!pic16_regWithIdx(i)->wasUsed) {
3674 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3675 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3676 pic16_regWithIdx(i)->wasUsed = 1;
3680 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3684 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3685 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3688 /*-----------------------------------------------------------------*/
3689 /* genEndFunction - generates epilogue for functions */
3690 /*-----------------------------------------------------------------*/
3691 static void genEndFunction (iCode *ic)
3693 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3697 if(IFFUNC_ISNAKED(sym->type)) {
3698 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3704 /* add code for ISCRITICAL */
3705 if(IFFUNC_ISCRITICAL(sym->type)) {
3706 /* if critical function, turn on interrupts */
3708 /* TODO: add code here -- VR */
3711 // sym->regsUsed = _G.fregsUsed;
3713 /* now we need to restore the registers */
3714 /* if any registers used */
3715 if (sym->regsUsed) {
3718 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3719 /* restore registers used */
3720 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3721 for ( i = sym->regsUsed->size; i >= 0; i--) {
3722 if (bitVectBitValue(sym->regsUsed,i)) {
3723 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3727 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3731 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3733 if (sym->stack == 1) {
3734 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3735 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3737 // we have to add more than one...
3738 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3739 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3740 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3742 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3743 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3744 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3748 if(strcmp(sym->name, "main")) {
3749 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3750 /* restore stack frame */
3751 if(STACK_MODEL_LARGE)
3752 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3753 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3759 if (IFFUNC_ISISR(sym->type)) {
3760 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3762 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3763 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3765 if(!(_G.interruptvector == 1)) {
3766 /* do not restore interrupt vector for WREG,STATUS,BSR
3767 * for high priority interrupt, see genFunction */
3768 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3769 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3770 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3772 _G.interruptvector = 0; /* sanity check */
3775 /* if debug then send end of function */
3776 /* if (options.debug && currFunc) */
3778 debugFile->writeEndFunction (currFunc, ic, 1);
3781 if(_G.usefastretfie)
3782 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3784 pic16_emitpcodeNULLop(POC_RETFIE);
3786 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3788 _G.usefastretfie = 0;
3792 if (IFFUNC_ISCRITICAL(sym->type)) {
3793 pic16_emitcode("setb","ea");
3796 /* if debug then send end of function */
3798 debugFile->writeEndFunction (currFunc, ic, 1);
3801 /* insert code to restore stack frame, if user enabled it
3802 * and function is not main() */
3805 pic16_emitpcodeNULLop(POC_RETURN);
3807 /* Mark the end of a function */
3808 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3812 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3815 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3817 pic16_emitpcode(POC_CLRF, dest);
3819 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3820 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3823 if(dest->type == PO_WREG && (offset == 0)) {
3824 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3827 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3831 /*-----------------------------------------------------------------*/
3832 /* genRet - generate code for return statement */
3833 /*-----------------------------------------------------------------*/
3834 static void genRet (iCode *ic)
3840 /* if we have no return value then
3841 * just generate the "ret" */
3846 /* we have something to return then
3847 * move the return value into place */
3848 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3849 size = AOP_SIZE(IC_LEFT(ic));
3853 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3854 // pic16_emitpcode(POC_MOVFF,
3855 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3858 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3859 // pic16_emitpcode(POC_MOVFF,
3860 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3863 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3864 // pic16_emitpcode(POC_MOVFF,
3865 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3868 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3870 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3871 // pic16_emitpcode(POC_MOVFF,
3872 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3875 /* >32-bits, setup stack and FSR0 */
3877 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3878 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3880 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3882 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3887 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3888 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3890 if(STACK_MODEL_LARGE) {
3891 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3892 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3894 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3899 /* old code, left here for reference -- VR */
3903 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3905 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3906 pic16_emitpcomment("push %s",l);
3909 DEBUGpic16_emitcode(";", "%d", __LINE__);
3910 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3911 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3913 if (strcmp(fReturn[offset],l)) {
3914 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3915 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3916 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3918 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3922 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3932 if (strcmp(fReturn[pushed],"a"))
3933 pic16_emitcode("pop",fReturn[pushed]);
3935 pic16_emitcode("pop","acc");
3941 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3944 /* generate a jump to the return label
3945 * if the next is not the return statement */
3946 if (!(ic->next && ic->next->op == LABEL
3947 && IC_LABEL(ic->next) == returnLabel)) {
3949 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3950 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3954 /*-----------------------------------------------------------------*/
3955 /* genLabel - generates a label */
3956 /*-----------------------------------------------------------------*/
3957 static void genLabel (iCode *ic)
3961 /* special case never generate */
3962 if (IC_LABEL(ic) == entryLabel)
3965 pic16_emitpLabel(IC_LABEL(ic)->key);
3966 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3969 /*-----------------------------------------------------------------*/
3970 /* genGoto - generates a goto */
3971 /*-----------------------------------------------------------------*/
3973 static void genGoto (iCode *ic)
3976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3977 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3981 /*-----------------------------------------------------------------*/
3982 /* genMultbits :- multiplication of bits */
3983 /*-----------------------------------------------------------------*/
3984 static void genMultbits (operand *left,
3990 if(!pic16_sameRegs(AOP(result),AOP(right)))
3991 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3993 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3994 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3995 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4000 /*-----------------------------------------------------------------*/
4001 /* genMultOneByte : 8 bit multiplication & division */
4002 /*-----------------------------------------------------------------*/
4003 static void genMultOneByte (operand *left,
4009 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4010 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4012 /* (if two literals, the value is computed before) */
4013 /* if one literal, literal on the right */
4014 if (AOP_TYPE(left) == AOP_LIT){
4020 /* size is already checked in genMult == 1 */
4021 // size = AOP_SIZE(result);
4023 if (AOP_TYPE(right) == AOP_LIT){
4024 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4025 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4026 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4027 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4029 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4030 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4031 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4032 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4035 pic16_genMult8X8_8 (left, right,result);
4038 /*-----------------------------------------------------------------*/
4039 /* genMultOneWord : 16 bit multiplication */
4040 /*-----------------------------------------------------------------*/
4041 static void genMultOneWord (operand *left,
4046 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4047 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4049 /* (if two literals, the value is computed before)
4050 * if one literal, literal on the right */
4051 if (AOP_TYPE(left) == AOP_LIT){
4057 /* size is checked already == 2 */
4058 // size = AOP_SIZE(result);
4060 if (AOP_TYPE(right) == AOP_LIT) {
4061 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4062 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4063 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4064 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4066 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4067 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4068 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4069 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4072 pic16_genMult16X16_16(left, right,result);
4075 /*-----------------------------------------------------------------*/
4076 /* genMultOneLong : 32 bit multiplication */
4077 /*-----------------------------------------------------------------*/
4078 static void genMultOneLong (operand *left,
4083 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4084 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4086 /* (if two literals, the value is computed before)
4087 * if one literal, literal on the right */
4088 if (AOP_TYPE(left) == AOP_LIT){
4094 /* size is checked already == 4 */
4095 // size = AOP_SIZE(result);
4097 if (AOP_TYPE(right) == AOP_LIT) {
4098 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4099 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4100 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4101 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4103 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4104 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4105 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4106 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4109 pic16_genMult32X32_32(left, right,result);
4114 /*-----------------------------------------------------------------*/
4115 /* genMult - generates code for multiplication */
4116 /*-----------------------------------------------------------------*/
4117 static void genMult (iCode *ic)
4119 operand *left = IC_LEFT(ic);
4120 operand *right = IC_RIGHT(ic);
4121 operand *result= IC_RESULT(ic);
4124 /* assign the amsops */
4125 pic16_aopOp (left,ic,FALSE);
4126 pic16_aopOp (right,ic,FALSE);
4127 pic16_aopOp (result,ic,TRUE);
4129 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4131 /* special cases first *
4133 if (AOP_TYPE(left) == AOP_CRY
4134 && AOP_TYPE(right)== AOP_CRY) {
4135 genMultbits(left,right,result);
4139 /* if both are of size == 1 */
4140 if(AOP_SIZE(left) == 1
4141 && AOP_SIZE(right) == 1) {
4142 genMultOneByte(left,right,result);
4146 /* if both are of size == 2 */
4147 if(AOP_SIZE(left) == 2
4148 && AOP_SIZE(right) == 2) {
4149 genMultOneWord(left, right, result);
4153 /* if both are of size == 4 */
4154 if(AOP_SIZE(left) == 4
4155 && AOP_SIZE(right) == 4) {
4156 genMultOneLong(left, right, result);
4160 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4163 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4164 /* should have been converted to function call */
4168 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4169 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4170 pic16_freeAsmop(result,NULL,ic,TRUE);
4173 /*-----------------------------------------------------------------*/
4174 /* genDivbits :- division of bits */
4175 /*-----------------------------------------------------------------*/
4176 static void genDivbits (operand *left,
4183 /* the result must be bit */
4184 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4185 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4189 pic16_emitcode("div","ab");
4190 pic16_emitcode("rrc","a");
4191 pic16_aopPut(AOP(result),"c",0);
4194 /*-----------------------------------------------------------------*/
4195 /* genDivOneByte : 8 bit division */
4196 /*-----------------------------------------------------------------*/
4197 static void genDivOneByte (operand *left,
4201 sym_link *opetype = operandType(result);
4206 /* result = divident / divisor
4207 * - divident may be a register or a literal,
4208 * - divisor may be a register or a literal,
4209 * so there are 3 cases (literal / literal is optimized
4210 * by the front-end) to handle.
4211 * In addition we must handle signed and unsigned, which
4212 * result in 6 final different cases -- VR */
4216 size = AOP_SIZE(result) - 1;
4218 /* signed or unsigned */
4219 if (SPEC_USIGN(opetype)) {
4220 pCodeOp *pct1, /* count */
4223 symbol *label1, *label2, *label3;;
4226 /* unsigned is easy */
4228 pct1 = pic16_popGetTempReg(1);
4229 pct2 = pic16_popGetTempReg(1);
4230 pct3 = pic16_popGetTempReg(1);
4232 label1 = newiTempLabel(NULL);
4233 label2 = newiTempLabel(NULL);
4234 label3 = newiTempLabel(NULL);
4236 /* the following algorithm is extracted from divuint.c */
4238 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4239 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4241 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4243 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4245 pic16_emitpLabel(label1->key);
4248 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4252 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4256 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4258 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4259 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4261 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4262 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4263 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4265 pic16_emitpLabel( label3->key );
4266 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4267 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4271 pic16_emitpLabel(label2->key);
4272 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4273 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4274 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4276 /* result is in wreg */
4277 if(AOP_TYPE(result) != AOP_ACC)
4278 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4280 pic16_popReleaseTempReg( pct3, 1);
4281 pic16_popReleaseTempReg( pct2, 1);
4282 pic16_popReleaseTempReg( pct1, 1);
4287 /* signed is a little bit more difficult */
4289 /* save the signs of the operands */
4290 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4292 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4293 pic16_emitcode("push","acc"); /* save it on the stack */
4295 /* now sign adjust for both left & right */
4296 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4298 lbl = newiTempLabel(NULL);
4299 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4300 pic16_emitcode("cpl","a");
4301 pic16_emitcode("inc","a");
4302 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4303 pic16_emitcode("mov","b,a");
4305 /* sign adjust left side */
4306 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4309 lbl = newiTempLabel(NULL);
4310 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4311 pic16_emitcode("cpl","a");
4312 pic16_emitcode("inc","a");
4313 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4315 /* now the division */
4316 pic16_emitcode("div","ab");
4317 /* we are interested in the lower order
4319 pic16_emitcode("mov","b,a");
4320 lbl = newiTempLabel(NULL);
4321 pic16_emitcode("pop","acc");
4322 /* if there was an over flow we don't
4323 adjust the sign of the result */
4324 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4325 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4327 pic16_emitcode("clr","a");
4328 pic16_emitcode("subb","a,b");
4329 pic16_emitcode("mov","b,a");
4330 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4332 /* now we are done */
4333 pic16_aopPut(AOP(result),"b",0);
4335 pic16_emitcode("mov","c,b.7");
4336 pic16_emitcode("subb","a,acc");
4339 pic16_aopPut(AOP(result),"a",offset++);
4343 /*-----------------------------------------------------------------*/
4344 /* genDiv - generates code for division */
4345 /*-----------------------------------------------------------------*/
4346 static void genDiv (iCode *ic)
4348 operand *left = IC_LEFT(ic);
4349 operand *right = IC_RIGHT(ic);
4350 operand *result= IC_RESULT(ic);
4353 /* Division is a very lengthy algorithm, so it is better
4354 * to call support routines than inlining algorithm.
4355 * Division functions written here just in case someone
4356 * wants to inline and not use the support libraries -- VR */
4360 /* assign the amsops */
4361 pic16_aopOp (left,ic,FALSE);
4362 pic16_aopOp (right,ic,FALSE);
4363 pic16_aopOp (result,ic,TRUE);
4365 /* special cases first */
4367 if (AOP_TYPE(left) == AOP_CRY &&
4368 AOP_TYPE(right)== AOP_CRY) {
4369 genDivbits(left,right,result);
4373 /* if both are of size == 1 */
4374 if (AOP_SIZE(left) == 1 &&
4375 AOP_SIZE(right) == 1 ) {
4376 genDivOneByte(left,right,result);
4380 /* should have been converted to function call */
4383 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4385 pic16_freeAsmop(result,NULL,ic,TRUE);
4388 /*-----------------------------------------------------------------*/
4389 /* genModbits :- modulus of bits */
4390 /*-----------------------------------------------------------------*/
4391 static void genModbits (operand *left,
4399 werror(W_POSSBUG2, __FILE__, __LINE__);
4400 /* the result must be bit */
4401 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4402 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4406 pic16_emitcode("div","ab");
4407 pic16_emitcode("mov","a,b");
4408 pic16_emitcode("rrc","a");
4409 pic16_aopPut(AOP(result),"c",0);
4412 /*-----------------------------------------------------------------*/
4413 /* genModOneByte : 8 bit modulus */
4414 /*-----------------------------------------------------------------*/
4415 static void genModOneByte (operand *left,
4419 sym_link *opetype = operandType(result);
4424 werror(W_POSSBUG2, __FILE__, __LINE__);
4426 /* signed or unsigned */
4427 if (SPEC_USIGN(opetype)) {
4428 /* unsigned is easy */
4429 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4430 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4432 pic16_emitcode("div","ab");
4433 pic16_aopPut(AOP(result),"b",0);
4437 /* signed is a little bit more difficult */
4439 /* save the signs of the operands */
4440 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4443 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4444 pic16_emitcode("push","acc"); /* save it on the stack */
4446 /* now sign adjust for both left & right */
4447 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4450 lbl = newiTempLabel(NULL);
4451 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4452 pic16_emitcode("cpl","a");
4453 pic16_emitcode("inc","a");
4454 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4455 pic16_emitcode("mov","b,a");
4457 /* sign adjust left side */
4458 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4461 lbl = newiTempLabel(NULL);
4462 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4463 pic16_emitcode("cpl","a");
4464 pic16_emitcode("inc","a");
4465 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4467 /* now the multiplication */
4468 pic16_emitcode("div","ab");
4469 /* we are interested in the lower order
4471 lbl = newiTempLabel(NULL);
4472 pic16_emitcode("pop","acc");
4473 /* if there was an over flow we don't
4474 adjust the sign of the result */
4475 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4476 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4478 pic16_emitcode("clr","a");
4479 pic16_emitcode("subb","a,b");
4480 pic16_emitcode("mov","b,a");
4481 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4483 /* now we are done */
4484 pic16_aopPut(AOP(result),"b",0);
4488 /*-----------------------------------------------------------------*/
4489 /* genMod - generates code for division */
4490 /*-----------------------------------------------------------------*/
4491 static void genMod (iCode *ic)
4493 operand *left = IC_LEFT(ic);
4494 operand *right = IC_RIGHT(ic);
4495 operand *result= IC_RESULT(ic);
4499 /* assign the amsops */
4500 pic16_aopOp (left,ic,FALSE);
4501 pic16_aopOp (right,ic,FALSE);
4502 pic16_aopOp (result,ic,TRUE);
4504 /* special cases first */
4506 if (AOP_TYPE(left) == AOP_CRY &&
4507 AOP_TYPE(right)== AOP_CRY) {
4508 genModbits(left,right,result);
4512 /* if both are of size == 1 */
4513 if (AOP_SIZE(left) == 1 &&
4514 AOP_SIZE(right) == 1 ) {
4515 genModOneByte(left,right,result);
4519 /* should have been converted to function call */
4523 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4524 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4525 pic16_freeAsmop(result,NULL,ic,TRUE);
4528 /*-----------------------------------------------------------------*/
4529 /* genIfxJump :- will create a jump depending on the ifx */
4530 /*-----------------------------------------------------------------*/
4532 note: May need to add parameter to indicate when a variable is in bit space.
4534 static void genIfxJump (iCode *ic, char *jval)
4538 /* if true label then we jump if condition
4540 if ( IC_TRUE(ic) ) {
4542 if(strcmp(jval,"a") == 0)
4544 else if (strcmp(jval,"c") == 0)
4547 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4548 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4551 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4552 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4556 /* false label is present */
4557 if(strcmp(jval,"a") == 0)
4559 else if (strcmp(jval,"c") == 0)
4562 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4563 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4566 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4567 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4572 /* mark the icode as generated */
4579 /*-----------------------------------------------------------------*/
4581 /*-----------------------------------------------------------------*/
4582 static void genSkip(iCode *ifx,int status_bit)
4584 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4588 if ( IC_TRUE(ifx) ) {
4589 switch(status_bit) {
4604 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4605 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4609 switch(status_bit) {
4623 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4624 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4631 /*-----------------------------------------------------------------*/
4633 /*-----------------------------------------------------------------*/
4634 static void genSkipc(resolvedIfx *rifx)
4636 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4646 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4647 rifx->generated = 1;
4650 #if !(USE_SIMPLE_GENCMP)
4651 /*-----------------------------------------------------------------*/
4653 /*-----------------------------------------------------------------*/
4654 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4656 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4661 if( (rifx->condition ^ invert_condition) & 1)
4666 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4667 rifx->generated = 1;
4672 /*-----------------------------------------------------------------*/
4674 /*-----------------------------------------------------------------*/
4675 static void genSkipz(iCode *ifx, int condition)
4686 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4688 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4691 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4693 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4698 #if !(USE_SIMPLE_GENCMP)
4699 /*-----------------------------------------------------------------*/
4701 /*-----------------------------------------------------------------*/
4702 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4708 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4710 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4713 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4714 rifx->generated = 1;
4719 /*-----------------------------------------------------------------*/
4720 /* genChkZeroes :- greater or less than comparison */
4721 /* For each byte in a literal that is zero, inclusive or the */
4722 /* the corresponding byte in the operand with W */
4723 /* returns true if any of the bytes are zero */
4724 /*-----------------------------------------------------------------*/
4725 static int genChkZeroes(operand *op, int lit, int size)
4732 i = (lit >> (size*8)) & 0xff;
4736 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4738 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4747 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4748 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4750 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4751 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4753 /*-----------------------------------------------------------------*/
4754 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4755 /* aop (if it's NOT a literal) or from lit (if */
4756 /* aop is a literal) */
4757 /*-----------------------------------------------------------------*/
4758 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4759 if (aop->type == AOP_LIT) {
4760 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4762 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4766 /*-----------------------------------------------------------------*/
4767 /* genCmp :- greater or less than comparison */
4768 /*-----------------------------------------------------------------*/
4770 #if USE_SIMPLE_GENCMP
4772 /* genCmp performs a left < right comparison, stores
4773 * the outcome in result (if != NULL) and generates
4774 * control flow code for the ifx (if != NULL).
4776 * This version leaves in sequences like
4777 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4778 * which should be optmized by the peephole
4779 * optimizer - RN 2005-01-01 */
4780 static void genCmp (operand *left,operand *right,
4781 operand *result, iCode *ifx, int sign)
4794 assert (AOP_SIZE(left) == AOP_SIZE(right));
4795 assert (left && right);
4797 size = AOP_SIZE(right) - 1;
4798 mask = (0x100UL << (size*8)) - 1;
4799 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4804 resolveIfx (&rIfx, ifx);
4806 /**********************************************************************
4807 * handle bits - bit compares are promoted to int compares seemingly! *
4808 **********************************************************************/
4810 // THIS IS COMPLETELY UNTESTED!
4811 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4812 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4813 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4814 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4817 // 1 < {0,1} is false --> clear C by skipping the next instruction
4818 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4819 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4820 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4821 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4822 emitCLRC; // only skipped for left=0 && right=1
4824 goto correct_result_in_carry;
4828 /*************************************************
4829 * make sure that left is register (or the like) *
4830 *************************************************/
4831 if (!isAOP_REGlike(left)) {
4832 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4833 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4835 assert (isAOP_LIT(left));
4836 assert (isAOP_REGlike(right));
4837 // swap left and right
4838 // left < right <==> right > left <==> (right >= left + 1)
4839 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4841 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4842 // MAXVALUE < right? always false
4843 if (performedLt) emitCLRC; else emitSETC;
4844 goto correct_result_in_carry;
4847 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4848 // that's we handled it above.
4855 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4856 } else if (isAOP_LIT(right)) {
4857 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4860 assert (isAOP_REGlike(left)); // left must be register or the like
4861 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4863 /*************************************************
4864 * special cases go here *
4865 *************************************************/
4867 if (isAOP_LIT(right)) {
4869 // unsigned comparison to a literal
4870 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4871 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4874 // unsigned left < 0? always false
4875 if (performedLt) emitCLRC; else emitSETC;
4876 goto correct_result_in_carry;
4879 // signed comparison to a literal
4880 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4881 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4883 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4884 // signed left < 0x80000000? always false
4885 if (performedLt) emitCLRC; else emitSETC;
4886 goto correct_result_in_carry;
4887 } else if (lit == 0) {
4888 // compare left < 0; set CARRY if SIGNBIT(left) is set
4889 if (performedLt) emitSETC; else emitCLRC;
4890 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4891 if (performedLt) emitCLRC; else emitSETC;
4892 goto correct_result_in_carry;
4895 } // right is literal
4897 /*************************************************
4898 * perform a general case comparison *
4899 * make sure we get CARRY==1 <==> left >= right *
4900 *************************************************/
4901 // compare most significant bytes
4902 //DEBUGpc ("comparing bytes at offset %d", size);
4904 // unsigned comparison
4905 mov2w_regOrLit (AOP(right), lit, size);
4906 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4908 // signed comparison
4909 // (add 2^n to both operands then perform an unsigned comparison)
4910 if (isAOP_LIT(right)) {
4911 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4912 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4914 if (litbyte == 0x80) {
4915 // left >= 0x80 -- always true, but more bytes to come
4916 pic16_mov2w (AOP(left), size);
4917 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4920 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4921 pic16_mov2w (AOP(left), size);
4922 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4923 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4926 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4927 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4928 pic16_mov2w (AOP(left), size);
4929 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4930 pic16_emitpcode (POC_MOVWF, pctemp);
4931 pic16_mov2w (AOP(right), size);
4932 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4933 pic16_emitpcode (POC_SUBFW, pctemp);
4934 //pic16_popReleaseTempReg(pctemp, 1);
4938 // compare remaining bytes (treat as unsigned case from above)
4939 templbl = newiTempLabel ( NULL );
4942 //DEBUGpc ("comparing bytes at offset %d", offs);
4943 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4944 mov2w_regOrLit (AOP(right), lit, offs);
4945 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4947 pic16_emitpLabel (templbl->key);
4948 goto result_in_carry;
4952 /****************************************************
4953 * now CARRY contains the result of the comparison: *
4954 * SUBWF sets CARRY iff *
4955 * F-W >= 0 <==> F >= W <==> !(F < W) *
4957 ****************************************************/
4960 if (result && AOP_TYPE(result) != AOP_CRY) {
4961 // value will be stored
4964 // value wil only be used in the following genSkipc()
4965 rIfx.condition ^= 1;
4969 correct_result_in_carry:
4971 // assign result to variable (if neccessary)
4972 if (result && AOP_TYPE(result) != AOP_CRY) {
4973 //DEBUGpc ("assign result");
4974 size = AOP_SIZE(result);
4976 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4978 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4981 // perform conditional jump
4982 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
4984 //DEBUGpc ("generate control flow");
4985 rIfx.condition ^= 1;
4994 static void genCmp (operand *left,operand *right,
4995 operand *result, iCode *ifx, int sign)
4997 int size; //, offset = 0 ;
4998 unsigned long lit = 0L,i = 0;
4999 resolvedIfx rFalseIfx;
5000 // resolvedIfx rTrueIfx;
5002 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5005 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5006 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5012 resolveIfx(&rFalseIfx,ifx);
5013 truelbl = newiTempLabel(NULL);
5014 size = max(AOP_SIZE(left),AOP_SIZE(right));
5016 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5020 /* if literal is on the right then swap with left */
5021 if ((AOP_TYPE(right) == AOP_LIT)) {
5022 operand *tmp = right ;
5023 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5024 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5027 lit = (lit - 1) & mask;
5030 rFalseIfx.condition ^= 1;
5033 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5034 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5038 //if(IC_TRUE(ifx) == NULL)
5039 /* if left & right are bit variables */
5040 if (AOP_TYPE(left) == AOP_CRY &&
5041 AOP_TYPE(right) == AOP_CRY ) {
5042 assert (0 && "bit variables used in genCmp");
5043 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5044 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5046 /* subtract right from left if at the
5047 end the carry flag is set then we know that
5048 left is greater than right */
5050 symbol *lbl = newiTempLabel(NULL);
5053 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5054 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5058 if(AOP_TYPE(right) == AOP_LIT) {
5060 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5062 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5069 genSkipCond(&rFalseIfx,left,size-1,7);
5071 /* no need to compare to 0...*/
5072 /* NOTE: this is a de-generate compare that most certainly
5073 * creates some dead code. */
5074 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5076 if(ifx) ifx->generated = 1;
5083 //i = (lit >> (size*8)) & 0xff;
5084 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5086 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5088 i = ((0-lit) & 0xff);
5091 /* lit is 0x7f, all signed chars are less than
5092 * this except for 0x7f itself */
5093 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5094 genSkipz2(&rFalseIfx,0);
5096 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5097 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5098 genSkipc(&rFalseIfx);
5103 genSkipz2(&rFalseIfx,1);
5105 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5106 genSkipc(&rFalseIfx);
5110 if(ifx) ifx->generated = 1;
5114 /* chars are out of the way. now do ints and longs */
5117 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5124 genSkipCond(&rFalseIfx,left,size,7);
5125 if(ifx) ifx->generated = 1;
5130 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5132 //rFalseIfx.condition ^= 1;
5133 //genSkipCond(&rFalseIfx,left,size,7);
5134 //rFalseIfx.condition ^= 1;
5136 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5137 if(rFalseIfx.condition)
5138 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5140 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5142 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5143 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5144 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5147 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5149 if(rFalseIfx.condition) {
5151 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5157 genSkipc(&rFalseIfx);
5158 pic16_emitpLabel(truelbl->key);
5159 if(ifx) ifx->generated = 1;
5166 if( (lit & 0xff) == 0) {
5167 /* lower byte is zero */
5168 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5169 i = ((lit >> 8) & 0xff) ^0x80;
5170 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5171 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5172 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5173 genSkipc(&rFalseIfx);
5176 if(ifx) ifx->generated = 1;
5181 /* Special cases for signed longs */
5182 if( (lit & 0xffffff) == 0) {
5183 /* lower byte is zero */
5184 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5185 i = ((lit >> 8*3) & 0xff) ^0x80;
5186 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5187 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5188 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5189 genSkipc(&rFalseIfx);
5192 if(ifx) ifx->generated = 1;
5200 if(lit & (0x80 << (size*8))) {
5201 /* lit is negative */
5202 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5204 //genSkipCond(&rFalseIfx,left,size,7);
5206 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5208 if(rFalseIfx.condition)
5209 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5211 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5215 /* lit is positive */
5216 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5217 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5218 if(rFalseIfx.condition)
5219 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5221 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5226 This works, but is only good for ints.
5227 It also requires a "known zero" register.
5228 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5229 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5230 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5231 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5232 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5233 genSkipc(&rFalseIfx);
5235 pic16_emitpLabel(truelbl->key);
5236 if(ifx) ifx->generated = 1;
5240 /* There are no more special cases, so perform a general compare */
5242 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5243 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5247 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5249 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5251 //rFalseIfx.condition ^= 1;
5252 genSkipc(&rFalseIfx);
5254 pic16_emitpLabel(truelbl->key);
5256 if(ifx) ifx->generated = 1;
5263 /* sign is out of the way. So now do an unsigned compare */
5264 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5267 /* General case - compare to an unsigned literal on the right.*/
5269 i = (lit >> (size*8)) & 0xff;
5270 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5271 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5273 i = (lit >> (size*8)) & 0xff;
5276 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5278 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5280 /* this byte of the lit is zero,
5281 *if it's not the last then OR in the variable */
5283 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5288 pic16_emitpLabel(lbl->key);
5289 // pic16_emitpLabel(truelbl->key);
5290 //if(emitFinalCheck)
5291 genSkipc(&rFalseIfx);
5293 pic16_emitpLabel(truelbl->key);
5295 if(ifx) ifx->generated = 1;
5302 if(AOP_TYPE(left) == AOP_LIT) {
5303 //symbol *lbl = newiTempLabel(NULL);
5305 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5308 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5311 if((lit == 0) && (sign == 0)){
5314 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5316 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5318 genSkipz2(&rFalseIfx,0);
5319 if(ifx) ifx->generated = 1;
5326 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5327 /* degenerate compare can never be true */
5328 if(rFalseIfx.condition == 0)
5329 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5331 if(ifx) ifx->generated = 1;
5336 /* signed comparisons to a literal byte */
5338 int lp1 = (lit+1) & 0xff;
5340 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5343 rFalseIfx.condition ^= 1;
5344 genSkipCond(&rFalseIfx,right,0,7);
5347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5348 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5349 genSkipz2(&rFalseIfx,1);
5352 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5353 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5354 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5355 rFalseIfx.condition ^= 1;
5356 genSkipc(&rFalseIfx);
5360 /* unsigned comparisons to a literal byte */
5362 switch(lit & 0xff ) {
5364 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5365 genSkipz2(&rFalseIfx,0);
5368 rFalseIfx.condition ^= 1;
5369 genSkipCond(&rFalseIfx,right,0,7);
5373 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5374 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5375 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5376 rFalseIfx.condition ^= 1;
5377 if (AOP_TYPE(result) == AOP_CRY)
5378 genSkipc(&rFalseIfx);
5380 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5381 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5387 if(ifx) ifx->generated = 1;
5388 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5394 /* Size is greater than 1 */
5402 /* this means lit = 0xffffffff, or -1 */
5405 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5406 rFalseIfx.condition ^= 1;
5407 genSkipCond(&rFalseIfx,right,size,7);
5408 if(ifx) ifx->generated = 1;
5410 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5419 if(rFalseIfx.condition) {
5420 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5424 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5426 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5430 if(rFalseIfx.condition) {
5431 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5432 pic16_emitpLabel(truelbl->key);
5434 rFalseIfx.condition ^= 1;
5435 genSkipCond(&rFalseIfx,right,s,7);
5438 if(ifx) ifx->generated = 1;
5440 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5446 if((size == 1) && (0 == (lp1&0xff))) {
5447 /* lower byte of signed word is zero */
5448 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5449 i = ((lp1 >> 8) & 0xff) ^0x80;
5450 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5451 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5452 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5454 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5456 if(ifx) ifx->generated = 1;
5459 rFalseIfx.condition ^= 1;
5460 genSkipc(&rFalseIfx);
5461 if(ifx) ifx->generated = 1;
5467 if(lit & (0x80 << (size*8))) {
5468 /* Lit is less than zero */
5469 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5470 //rFalseIfx.condition ^= 1;
5471 //genSkipCond(&rFalseIfx,left,size,7);
5472 //rFalseIfx.condition ^= 1;
5473 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5474 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5476 if(rFalseIfx.condition)
5477 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5479 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5483 /* Lit is greater than or equal to zero */
5484 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5485 //rFalseIfx.condition ^= 1;
5486 //genSkipCond(&rFalseIfx,right,size,7);
5487 //rFalseIfx.condition ^= 1;
5489 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5490 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5492 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5493 if(rFalseIfx.condition)
5494 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5496 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5500 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5501 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5505 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5507 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5509 rFalseIfx.condition ^= 1;
5510 //rFalseIfx.condition = 1;
5511 genSkipc(&rFalseIfx);
5513 pic16_emitpLabel(truelbl->key);
5515 if(ifx) ifx->generated = 1;
5518 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5525 /* compare word or long to an unsigned literal on the right.*/
5530 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5533 break; /* handled above */
5536 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5538 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5539 genSkipz2(&rFalseIfx,0);
5543 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5545 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5548 if(rFalseIfx.condition)
5549 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5551 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5555 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5557 rFalseIfx.condition ^= 1;
5558 genSkipc(&rFalseIfx);
5561 pic16_emitpLabel(truelbl->key);
5563 if(ifx) ifx->generated = 1;
5565 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5573 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5574 i = (lit >> (size*8)) & 0xff;
5576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5577 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5580 i = (lit >> (size*8)) & 0xff;
5583 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5585 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5587 /* this byte of the lit is zero,
5588 * if it's not the last then OR in the variable */
5590 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5595 pic16_emitpLabel(lbl->key);
5597 rFalseIfx.condition ^= 1;
5599 genSkipc(&rFalseIfx);
5603 pic16_emitpLabel(truelbl->key);
5604 if(ifx) ifx->generated = 1;
5606 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5612 /* Compare two variables */
5614 DEBUGpic16_emitcode(";sign","%d",sign);
5618 /* Sigh. thus sucks... */
5622 pctemp = pic16_popGetTempReg(1);
5623 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5624 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5625 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5626 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5627 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5628 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5629 pic16_popReleaseTempReg(pctemp, 1);
5631 /* Signed char comparison */
5632 /* Special thanks to Nikolai Golovchenko for this snippet */
5633 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5634 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5635 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5636 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5637 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5638 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5640 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5641 genSkipc(&rFalseIfx);
5643 if(ifx) ifx->generated = 1;
5645 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5658 /* The rest of the bytes of a multi-byte compare */
5662 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5665 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5666 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5671 pic16_emitpLabel(lbl->key);
5673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5674 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5675 (AOP_TYPE(result) == AOP_REG)) {
5676 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5677 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5679 genSkipc(&rFalseIfx);
5681 //genSkipc(&rFalseIfx);
5682 if(ifx) ifx->generated = 1;
5685 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5693 if ((AOP_TYPE(result) != AOP_CRY)
5694 && AOP_SIZE(result)) {
5695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5697 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5699 pic16_outBitC(result);
5701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5702 /* if the result is used in the next
5703 ifx conditional branch then generate
5704 code a little differently */
5706 genIfxJump (ifx,"c");
5708 pic16_outBitC(result);
5709 /* leave the result in acc */
5714 #else /* old version of genCmp() */ /* } else { */
5716 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5717 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5718 operand *result, int offset, int invert_op)
5722 /* check condition, > or < ?? */
5723 if(rIfx->condition != 0)invert_op ^= 1;
5725 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5727 if(!ifx)invert_op ^= 1;
5729 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5730 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5733 if(!invert_op)return POC_CPFSGT;
5734 else return POC_CPFSLT;
5737 static int compareAopfirstpass=1;
5739 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5740 operand *oper, int offset, operand *result,
5741 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5747 /* invert if there is a result to be loaded, in order to fit,
5748 * SETC/CLRC sequence */
5749 if(AOP_SIZE(result))invert_op ^= 1;
5751 // if(sign && !offset)invert_op ^= 1;
5753 // if(sign)invert_op ^= 1;
5755 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5757 if(AOP_SIZE(result) && compareAopfirstpass) {
5760 pic16_emitpcode(POC_SETF, pcop2);
5765 pic16_emitpcode(POC_CLRF, pcop2);
5771 compareAopfirstpass = 0;
5773 /* there is a bug when comparing operands with size > 1,
5774 * because higher bytes can be equal and test should be performed
5775 * to the next lower byte, current algorithm, considers operands
5776 * inequal in these cases! -- VR 20041107 */
5780 pic16_emitpcode(op, pcop);
5782 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5785 if((!sign || !offset) && AOP_SIZE(result)) {
5788 pic16_emitpcode(POC_CLRF, pcop2);
5793 pic16_emitpcode(POC_SETF, pcop2);
5798 /* don't emit final branch (offset == 0) */
5802 pic16_emitpcode(POC_RRCF, pcop2);
5804 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5807 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5808 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5809 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5811 truelbl = newiTempLabel( NULL );
5812 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5813 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5814 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5816 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5817 pic16_emitpLabel(truelbl->key);
5819 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5828 static void genCmp (operand *left, operand *right,
5829 operand *result, iCode *ifx, int sign)
5833 resolvedIfx rFalseIfx;
5834 symbol *falselbl, *tlbl;
5838 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5840 resolveIfx(&rFalseIfx, ifx);
5841 size = max(AOP_SIZE(left), AOP_SIZE(right));
5843 /* if left & right are bit variables */
5844 if(AOP_TYPE(left) == AOP_CRY
5845 && AOP_TYPE(right) == AOP_CRY ) {
5847 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5848 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5850 werror(W_POSSBUG2, __FILE__, __LINE__);
5854 /* if literal is on the right then swap with left */
5855 if((AOP_TYPE(right) == AOP_LIT)) {
5856 operand *tmp = right ;
5857 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5859 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5861 // lit = (lit - 1) & mask;
5864 rFalseIfx.condition ^= 1; /* reverse compare */
5866 if ((AOP_TYPE(left) == AOP_LIT)) {
5867 /* float compares are handled by support functions */
5868 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5871 /* actual comparing algorithm */
5872 // size = AOP_SIZE( right );
5874 falselbl = newiTempLabel( NULL );
5875 if(AOP_TYPE(left) == AOP_LIT) {
5876 /* compare to literal */
5877 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5880 pCodeOp *pct, *pct2;
5883 /* signed compare */
5884 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5886 pct = pic16_popCopyReg(&pic16_pc_prodl);
5887 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5888 tlbl = newiTempLabel( NULL );
5890 /* first compare signs:
5891 * a. if both are positive, compare just like unsigned
5892 * b. if both are negative, invert cmpop, compare just like unsigned
5893 * c. if different signs, determine the result directly */
5899 tlbl1 = newiTempLabel( NULL );
5900 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5904 /* literal is zero or positive:
5905 * a. if carry is zero, too, continue compare,
5906 * b. if carry is set, then continue depending on cmpop ^ condition:
5907 * 1. '<' return false (literal < variable),
5908 * 2. '>' return true (literal > variable) */
5909 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5910 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5913 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5914 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5918 /* literal is negative:
5919 * a. if carry is set, too, continue compare,
5920 * b. if carry is zero, then continue depending on cmpop ^ condition:
5921 * 1. '<' return true (literal < variable),
5922 * 2. '>' return false (literal > variable) */
5923 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5924 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5926 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5927 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5932 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5934 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5935 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5940 pic16_emitpLabel( tlbl1->key );
5943 compareAopfirstpass=1;
5944 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5945 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5946 // pic16_emitpcode(POC_MOVWF, pct);
5948 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5950 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5951 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5955 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5956 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5957 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5958 // pic16_emitpcode(POC_MOVWF, pct);
5960 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5961 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5962 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5963 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5964 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5968 if(ifx)ifx->generated = 1;
5970 if(AOP_SIZE(result)) {
5971 pic16_emitpLabel(tlbl->key);
5972 pic16_emitpLabel(falselbl->key);
5973 pic16_outBitOp( result, pct2 );
5975 pic16_emitpLabel(tlbl->key);
5980 /* unsigned compare */
5981 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5983 compareAopfirstpass=1;
5986 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5987 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5991 if(ifx)ifx->generated = 1;
5994 if(AOP_SIZE(result)) {
5995 pic16_emitpLabel(falselbl->key);
5996 pic16_outBitC( result );
6001 /* compare registers */
6002 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6006 pCodeOp *pct, *pct2;
6008 /* signed compare */
6009 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6011 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6012 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6013 tlbl = newiTempLabel( NULL );
6015 compareAopfirstpass=1;
6018 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6019 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6020 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6021 pic16_emitpcode(POC_MOVWF, pct);
6023 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6024 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6025 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6027 /* WREG already holds left + 0x80 */
6028 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6031 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6032 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6033 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6034 pic16_emitpcode(POC_MOVWF, pct);
6036 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6037 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6038 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6040 /* WREG already holds left + 0x80 */
6041 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6042 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6045 if(ifx)ifx->generated = 1;
6047 if(AOP_SIZE(result)) {
6048 pic16_emitpLabel(tlbl->key);
6049 pic16_emitpLabel(falselbl->key);
6050 pic16_outBitOp( result, pct2 );
6052 pic16_emitpLabel(tlbl->key);
6056 /* unsigned compare */
6057 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6059 compareAopfirstpass=1;
6062 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6063 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6067 if(ifx)ifx->generated = 1;
6068 if(AOP_SIZE(result)) {
6070 pic16_emitpLabel(falselbl->key);
6071 pic16_outBitC( result );
6078 #else /* } else { */
6080 /* new version of genCmp -- VR 20041012 */
6081 static void genCmp (operand *left,operand *right,
6082 operand *result, iCode *ifx, int sign)
6084 int size; //, offset = 0 ;
6085 unsigned long lit = 0L,i = 0;
6086 resolvedIfx rFalseIfx;
6087 int willCheckCarry=0;
6088 // resolvedIfx rTrueIfx;
6094 * subtract right from left if at the end the carry flag is set then we
6095 * know that left is greater than right */
6097 resolveIfx(&rFalseIfx,ifx);
6098 truelbl = newiTempLabel(NULL);
6099 size = max(AOP_SIZE(left),AOP_SIZE(right));
6101 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6103 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6104 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6107 /* if literal is on the right then swap with left */
6108 if ((AOP_TYPE(right) == AOP_LIT)) {
6109 operand *tmp = right ;
6110 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6112 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6114 // lit = (lit - 1) & mask;
6117 rFalseIfx.condition ^= 1; /* reverse compare */
6119 if ((AOP_TYPE(left) == AOP_LIT)) {
6120 /* float compares are handled by support functions */
6121 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6125 //if(IC_TRUE(ifx) == NULL)
6126 /* if left & right are bit variables */
6127 if (AOP_TYPE(left) == AOP_CRY &&
6128 AOP_TYPE(right) == AOP_CRY ) {
6130 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6131 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6134 symbol *lbl = newiTempLabel(NULL);
6136 if(AOP_TYPE(left) == AOP_LIT) {
6137 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6139 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6141 else willCheckCarry = 0;
6144 if((lit == 0) && (sign == 0)) {
6145 /* unsigned compare to 0 */
6146 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6149 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6151 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6153 genSkipz2(&rFalseIfx,0);
6154 if(ifx)ifx->generated = 1;
6161 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6162 /* degenerate compare can never be true */
6163 if(rFalseIfx.condition == 0)
6164 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6166 if(ifx) ifx->generated = 1;
6171 /* signed comparisons to a literal byte */
6172 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6174 int lp1 = (lit+1) & 0xff;
6176 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6179 rFalseIfx.condition ^= 1;
6180 genSkipCond(&rFalseIfx,right,0,7);
6183 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6184 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6185 genSkipz2(&rFalseIfx,1);
6188 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6190 if(rFalseIfx.condition)
6191 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6193 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6195 if(willCheckCarry) {
6196 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6197 else { emitSETC; emitCLRC; }
6200 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6203 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6204 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6206 rFalseIfx.condition ^= 1;
6207 genSkipc(&rFalseIfx);
6212 /* unsigned comparisons to a literal byte */
6213 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6215 switch(lit & 0xff ) {
6218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6219 genSkipz2(&rFalseIfx,0);
6222 rFalseIfx.condition ^= 1;
6223 genSkipCond(&rFalseIfx,right,0,7);
6226 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6227 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6229 rFalseIfx.condition ^= 1;
6230 if (AOP_TYPE(result) == AOP_CRY)
6231 genSkipc(&rFalseIfx);
6233 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6234 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6240 if(ifx) ifx->generated = 1;
6241 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6247 /* Size is greater than 1 */
6255 /* this means lit = 0xffffffff, or -1 */
6258 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6259 rFalseIfx.condition ^= 1;
6260 genSkipCond(&rFalseIfx,right,size,7);
6261 if(ifx) ifx->generated = 1;
6268 if(rFalseIfx.condition) {
6269 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6270 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6273 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6275 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6279 if(rFalseIfx.condition) {
6280 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6281 pic16_emitpLabel(truelbl->key);
6283 rFalseIfx.condition ^= 1;
6284 genSkipCond(&rFalseIfx,right,s,7);
6287 if(ifx) ifx->generated = 1;
6291 if((size == 1) && (0 == (lp1&0xff))) {
6292 /* lower byte of signed word is zero */
6293 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6294 i = ((lp1 >> 8) & 0xff) ^0x80;
6295 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6297 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6298 rFalseIfx.condition ^= 1;
6299 genSkipc(&rFalseIfx);
6302 if(ifx) ifx->generated = 1;
6306 if(lit & (0x80 << (size*8))) {
6307 /* Lit is less than zero */
6308 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6309 //rFalseIfx.condition ^= 1;
6310 //genSkipCond(&rFalseIfx,left,size,7);
6311 //rFalseIfx.condition ^= 1;
6312 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6313 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6315 if(rFalseIfx.condition)
6316 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6318 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6322 /* Lit is greater than or equal to zero */
6323 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6324 //rFalseIfx.condition ^= 1;
6325 //genSkipCond(&rFalseIfx,right,size,7);
6326 //rFalseIfx.condition ^= 1;
6328 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6329 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6331 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6332 if(rFalseIfx.condition)
6333 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6335 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6340 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6341 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6347 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6349 rFalseIfx.condition ^= 1;
6350 //rFalseIfx.condition = 1;
6351 genSkipc(&rFalseIfx);
6353 pic16_emitpLabel(truelbl->key);
6355 if(ifx) ifx->generated = 1;
6360 /* compare word or long to an unsigned literal on the right.*/
6365 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6368 break; /* handled above */
6371 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6373 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6374 genSkipz2(&rFalseIfx,0);
6378 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6380 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6383 if(rFalseIfx.condition)
6384 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6386 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6389 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6390 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6392 rFalseIfx.condition ^= 1;
6393 genSkipc(&rFalseIfx);
6396 pic16_emitpLabel(truelbl->key);
6398 if(ifx) ifx->generated = 1;
6404 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6405 i = (lit >> (size*8)) & 0xff;
6407 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6408 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6411 i = (lit >> (size*8)) & 0xff;
6414 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6416 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6418 /* this byte of the lit is zero,
6419 * if it's not the last then OR in the variable */
6421 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6426 pic16_emitpLabel(lbl->key);
6428 rFalseIfx.condition ^= 1;
6430 genSkipc(&rFalseIfx);
6434 pic16_emitpLabel(truelbl->key);
6435 if(ifx) ifx->generated = 1;
6439 /* Compare two variables */
6441 DEBUGpic16_emitcode(";sign","%d",sign);
6445 /* Sigh. thus sucks... */
6449 pctemp = pic16_popGetTempReg(1);
6450 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6451 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6452 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6453 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6454 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6455 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6456 pic16_popReleaseTempReg(pctemp, 1);
6458 /* Signed char comparison */
6459 /* Special thanks to Nikolai Golovchenko for this snippet */
6460 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6461 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6462 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6463 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6464 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6465 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6467 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6468 genSkipc(&rFalseIfx);
6470 if(ifx) ifx->generated = 1;
6476 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6481 /* The rest of the bytes of a multi-byte compare */
6485 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6488 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6489 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6494 pic16_emitpLabel(lbl->key);
6496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6497 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6498 (AOP_TYPE(result) == AOP_REG)) {
6499 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6500 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6502 genSkipc(&rFalseIfx);
6504 //genSkipc(&rFalseIfx);
6505 if(ifx) ifx->generated = 1;
6512 if ((AOP_TYPE(result) != AOP_CRY)
6513 && AOP_SIZE(result)) {
6514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6516 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6518 pic16_outBitC(result);
6520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6521 /* if the result is used in the next
6522 ifx conditional branch then generate
6523 code a little differently */
6525 genIfxJump (ifx,"c");
6527 pic16_outBitC(result);
6528 /* leave the result in acc */
6539 /*-----------------------------------------------------------------*/
6540 /* genCmpGt :- greater than comparison */
6541 /*-----------------------------------------------------------------*/
6542 static void genCmpGt (iCode *ic, iCode *ifx)
6544 operand *left, *right, *result;
6545 sym_link *letype , *retype;
6551 right= IC_RIGHT(ic);
6552 result = IC_RESULT(ic);
6554 letype = getSpec(operandType(left));
6555 retype =getSpec(operandType(right));
6556 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6557 /* assign the amsops */
6558 pic16_aopOp (left,ic,FALSE);
6559 pic16_aopOp (right,ic,FALSE);
6560 pic16_aopOp (result,ic,TRUE);
6562 genCmp(right, left, result, ifx, sign);
6564 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6565 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6566 pic16_freeAsmop(result,NULL,ic,TRUE);
6569 /*-----------------------------------------------------------------*/
6570 /* genCmpLt - less than comparisons */
6571 /*-----------------------------------------------------------------*/
6572 static void genCmpLt (iCode *ic, iCode *ifx)
6574 operand *left, *right, *result;
6575 sym_link *letype , *retype;
6581 right= IC_RIGHT(ic);
6582 result = IC_RESULT(ic);
6584 letype = getSpec(operandType(left));
6585 retype =getSpec(operandType(right));
6586 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6588 /* assign the amsops */
6589 pic16_aopOp (left,ic,FALSE);
6590 pic16_aopOp (right,ic,FALSE);
6591 pic16_aopOp (result,ic,TRUE);
6593 genCmp(left, right, result, ifx, sign);
6595 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6596 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6597 pic16_freeAsmop(result,NULL,ic,TRUE);
6602 // FIXME reenable literal optimisation when the pic16 port is stable
6604 /*-----------------------------------------------------------------*/
6605 /* genc16bit2lit - compare a 16 bit value to a literal */
6606 /*-----------------------------------------------------------------*/
6607 static void genc16bit2lit(operand *op, int lit, int offset)
6611 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6612 if( (lit&0xff) == 0)
6617 switch( BYTEofLONG(lit,i)) {
6619 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6622 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6625 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6628 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6629 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6634 switch( BYTEofLONG(lit,i)) {
6636 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6640 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6644 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6647 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6649 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6658 /*-----------------------------------------------------------------*/
6659 /* gencjneshort - compare and jump if not equal */
6660 /*-----------------------------------------------------------------*/
6661 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6663 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6665 int res_offset = 0; /* the result may be a different size then left or right */
6666 int res_size = AOP_SIZE(result);
6668 symbol *lbl, *lbl_done;
6670 unsigned long lit = 0L;
6671 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6674 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6676 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6677 resolveIfx(&rIfx,ifx);
6678 lbl = newiTempLabel(NULL);
6679 lbl_done = newiTempLabel(NULL);
6682 /* if the left side is a literal or
6683 if the right is in a pointer register and left
6685 if ((AOP_TYPE(left) == AOP_LIT) ||
6686 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6691 if(AOP_TYPE(right) == AOP_LIT)
6692 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6694 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6695 preserve_result = 1;
6697 if(result && !preserve_result)
6700 for(i = 0; i < AOP_SIZE(result); i++)
6701 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6705 /* if the right side is a literal then anything goes */
6706 if (AOP_TYPE(right) == AOP_LIT &&
6707 AOP_TYPE(left) != AOP_DIR ) {
6710 genc16bit2lit(left, lit, 0);
6712 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6715 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6718 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6719 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6721 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6725 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6727 if(res_offset < res_size-1)
6735 /* if the right side is in a register or in direct space or
6736 if the left is a pointer register & right is not */
6737 else if (AOP_TYPE(right) == AOP_REG ||
6738 AOP_TYPE(right) == AOP_DIR ||
6739 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6740 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6741 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6742 int lbl_key = lbl->key;
6745 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6746 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6748 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6749 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6750 __FUNCTION__,__LINE__);
6754 /* switch(size) { */
6756 /* genc16bit2lit(left, lit, 0); */
6758 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6763 if((AOP_TYPE(left) == AOP_DIR) &&
6764 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6766 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6767 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6769 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6771 switch (lit & 0xff) {
6773 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6776 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6777 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6782 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6783 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6784 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6785 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6789 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6790 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6795 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6798 if(AOP_TYPE(result) == AOP_CRY) {
6799 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6804 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6806 /* fix me. probably need to check result size too */
6807 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6812 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6813 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6820 if(res_offset < res_size-1)
6825 } else if(AOP_TYPE(right) == AOP_REG &&
6826 AOP_TYPE(left) != AOP_DIR){
6829 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6830 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6831 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6836 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6838 if(res_offset < res_size-1)
6843 /* right is a pointer reg need both a & b */
6845 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6847 pic16_emitcode("mov","b,%s",l);
6848 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6849 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6854 if(result && preserve_result)
6857 for(i = 0; i < AOP_SIZE(result); i++)
6858 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6861 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6863 if(result && preserve_result)
6864 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6867 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6869 pic16_emitpLabel(lbl->key);
6871 if(result && preserve_result)
6874 for(i = 0; i < AOP_SIZE(result); i++)
6875 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6877 pic16_emitpLabel(lbl_done->key);
6880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6888 /*-----------------------------------------------------------------*/
6889 /* gencjne - compare and jump if not equal */
6890 /*-----------------------------------------------------------------*/
6891 static void gencjne(operand *left, operand *right, iCode *ifx)
6893 symbol *tlbl = newiTempLabel(NULL);
6895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6896 gencjneshort(left, right, lbl);
6898 pic16_emitcode("mov","a,%s",one);
6899 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6900 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6901 pic16_emitcode("clr","a");
6902 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6904 pic16_emitpLabel(lbl->key);
6905 pic16_emitpLabel(tlbl->key);
6911 /*-----------------------------------------------------------------*/
6912 /* is_LitOp - check if operand has to be treated as literal */
6913 /*-----------------------------------------------------------------*/
6914 static bool is_LitOp(operand *op)
6916 return ((AOP_TYPE(op) == AOP_LIT)
6917 || ( (AOP_TYPE(op) == AOP_PCODE)
6918 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6919 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6922 /*-----------------------------------------------------------------*/
6923 /* is_LitAOp - check if operand has to be treated as literal */
6924 /*-----------------------------------------------------------------*/
6925 static bool is_LitAOp(asmop *aop)
6927 return ((aop->type == AOP_LIT)
6928 || ( (aop->type == AOP_PCODE)
6929 && ( (aop->aopu.pcop->type == PO_LITERAL)
6930 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6935 /*-----------------------------------------------------------------*/
6936 /* genCmpEq - generates code for equal to */
6937 /*-----------------------------------------------------------------*/
6938 static void genCmpEq (iCode *ic, iCode *ifx)
6940 operand *left, *right, *result;
6941 symbol *falselbl = newiTempLabel(NULL);
6942 symbol *donelbl = newiTempLabel(NULL);
6944 int preserve_result = 0;
6945 int generate_result = 0;
6950 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6951 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6952 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6954 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6956 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6958 werror(W_POSSBUG2, __FILE__, __LINE__);
6959 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6960 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6964 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6966 operand *tmp = right ;
6971 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6972 preserve_result = 1;
6974 if(result && AOP_SIZE(result))
6975 generate_result = 1;
6977 if(generate_result && !preserve_result)
6979 for(i = 0; i < AOP_SIZE(result); i++)
6980 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6983 for(i=0; i < AOP_SIZE(left); i++)
6985 if(AOP_TYPE(left) != AOP_ACC)
6988 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6990 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6993 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6995 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6997 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7002 if(generate_result && preserve_result)
7004 for(i = 0; i < AOP_SIZE(result); i++)
7005 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7009 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7011 if(generate_result && preserve_result)
7012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7014 if(ifx && IC_TRUE(ifx))
7015 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7017 if(ifx && IC_FALSE(ifx))
7018 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7020 pic16_emitpLabel(falselbl->key);
7024 if(ifx && IC_FALSE(ifx))
7025 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7027 if(generate_result && preserve_result)
7029 for(i = 0; i < AOP_SIZE(result); i++)
7030 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7033 pic16_emitpLabel(donelbl->key);
7039 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7040 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7041 pic16_freeAsmop(result,NULL,ic,TRUE);
7047 // old version kept for reference
7049 /*-----------------------------------------------------------------*/
7050 /* genCmpEq - generates code for equal to */
7051 /*-----------------------------------------------------------------*/
7052 static void genCmpEq (iCode *ic, iCode *ifx)
7054 operand *left, *right, *result;
7055 unsigned long lit = 0L;
7057 symbol *falselbl = newiTempLabel(NULL);
7060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7063 DEBUGpic16_emitcode ("; ifx is non-null","");
7065 DEBUGpic16_emitcode ("; ifx is null","");
7067 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7068 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7069 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7071 size = max(AOP_SIZE(left),AOP_SIZE(right));
7073 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7075 /* if literal, literal on the right or
7076 if the right is in a pointer register and left
7078 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7079 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7080 operand *tmp = right ;
7086 if(ifx && !AOP_SIZE(result)){
7088 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7089 /* if they are both bit variables */
7090 if (AOP_TYPE(left) == AOP_CRY &&
7091 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7092 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7093 if(AOP_TYPE(right) == AOP_LIT){
7094 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7096 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7097 pic16_emitcode("cpl","c");
7098 } else if(lit == 1L) {
7099 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7101 pic16_emitcode("clr","c");
7103 /* AOP_TYPE(right) == AOP_CRY */
7105 symbol *lbl = newiTempLabel(NULL);
7106 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7107 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7108 pic16_emitcode("cpl","c");
7109 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7111 /* if true label then we jump if condition
7113 tlbl = newiTempLabel(NULL);
7114 if ( IC_TRUE(ifx) ) {
7115 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7116 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7118 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7119 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7121 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7124 /* left and right are both bit variables, result is carry */
7127 resolveIfx(&rIfx,ifx);
7129 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7130 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7131 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7132 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7137 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7139 /* They're not both bit variables. Is the right a literal? */
7140 if(AOP_TYPE(right) == AOP_LIT) {
7141 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7146 switch(lit & 0xff) {
7148 if ( IC_TRUE(ifx) ) {
7149 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7151 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7153 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7154 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7158 if ( IC_TRUE(ifx) ) {
7159 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7161 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7163 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7164 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7168 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7170 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7175 /* end of size == 1 */
7179 genc16bit2lit(left,lit,offset);
7182 /* end of size == 2 */
7187 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7188 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7189 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7190 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7193 /* search for patterns that can be optimized */
7195 genc16bit2lit(left,lit,0);
7199 emitSKPZ; // if hi word unequal
7201 emitSKPNZ; // if hi word equal
7203 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7204 genc16bit2lit(left,lit,2);
7207 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7208 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7212 pic16_emitpLabel(falselbl->key);
7221 } else if(AOP_TYPE(right) == AOP_CRY ) {
7222 /* we know the left is not a bit, but that the right is */
7223 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7224 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7225 pic16_popGet(AOP(right),offset));
7226 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7228 /* if the two are equal, then W will be 0 and the Z bit is set
7229 * we could test Z now, or go ahead and check the high order bytes if
7230 * the variable we're comparing is larger than a byte. */
7233 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7235 if ( IC_TRUE(ifx) ) {
7237 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7238 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7241 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7242 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7246 /* They're both variables that are larger than bits */
7249 tlbl = newiTempLabel(NULL);
7252 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7253 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7255 if ( IC_TRUE(ifx) ) {
7259 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7261 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7262 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7266 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7269 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7270 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7275 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7278 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7282 if(s>1 && IC_TRUE(ifx)) {
7283 pic16_emitpLabel(tlbl->key);
7284 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7288 /* mark the icode as generated */
7293 /* if they are both bit variables */
7294 if (AOP_TYPE(left) == AOP_CRY &&
7295 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7296 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7297 if(AOP_TYPE(right) == AOP_LIT){
7298 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7300 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7301 pic16_emitcode("cpl","c");
7302 } else if(lit == 1L) {
7303 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7305 pic16_emitcode("clr","c");
7307 /* AOP_TYPE(right) == AOP_CRY */
7309 symbol *lbl = newiTempLabel(NULL);
7310 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7311 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7312 pic16_emitcode("cpl","c");
7313 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7316 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7317 pic16_outBitC(result);
7321 genIfxJump (ifx,"c");
7324 /* if the result is used in an arithmetic operation
7325 then put the result in place */
7326 pic16_outBitC(result);
7329 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7330 gencjne(left,right,result,ifx);
7333 gencjne(left,right,newiTempLabel(NULL));
7335 if(IC_TRUE(ifx)->key)
7336 gencjne(left,right,IC_TRUE(ifx)->key);
7338 gencjne(left,right,IC_FALSE(ifx)->key);
7342 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7343 pic16_aopPut(AOP(result),"a",0);
7348 genIfxJump (ifx,"a");
7352 /* if the result is used in an arithmetic operation
7353 then put the result in place */
7355 if (AOP_TYPE(result) != AOP_CRY)
7356 pic16_outAcc(result);
7358 /* leave the result in acc */
7362 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7363 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7364 pic16_freeAsmop(result,NULL,ic,TRUE);
7368 /*-----------------------------------------------------------------*/
7369 /* ifxForOp - returns the icode containing the ifx for operand */
7370 /*-----------------------------------------------------------------*/
7371 static iCode *ifxForOp ( operand *op, iCode *ic )
7375 /* if true symbol then needs to be assigned */
7376 if (IS_TRUE_SYMOP(op))
7379 /* if this has register type condition and
7380 the next instruction is ifx with the same operand
7381 and live to of the operand is upto the ifx only then */
7383 && ic->next->op == IFX
7384 && IC_COND(ic->next)->key == op->key
7385 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7387 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7393 ic->next->op == IFX &&
7394 IC_COND(ic->next)->key == op->key) {
7395 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7400 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7402 ic->next->op == IFX)
7403 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7406 ic->next->op == IFX &&
7407 IC_COND(ic->next)->key == op->key) {
7408 DEBUGpic16_emitcode ("; "," key is okay");
7409 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7410 OP_SYMBOL(op)->liveTo,
7415 /* the code below is completely untested
7416 * it just allows ulong2fs.c compile -- VR */
7419 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7420 __FILE__, __FUNCTION__, __LINE__);
7422 /* if this has register type condition and
7423 the next instruction is ifx with the same operand
7424 and live to of the operand is upto the ifx only then */
7426 ic->next->op == IFX &&
7427 IC_COND(ic->next)->key == op->key &&
7428 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7432 ic->next->op == IFX &&
7433 IC_COND(ic->next)->key == op->key) {
7434 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7438 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7439 __FILE__, __FUNCTION__, __LINE__);
7441 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7446 /*-----------------------------------------------------------------*/
7447 /* genAndOp - for && operation */
7448 /*-----------------------------------------------------------------*/
7449 static void genAndOp (iCode *ic)
7451 operand *left,*right, *result;
7456 /* note here that && operations that are in an
7457 if statement are taken away by backPatchLabels
7458 only those used in arthmetic operations remain */
7459 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7460 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7461 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7463 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7465 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7466 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7467 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7469 /* if both are bit variables */
7470 /* if (AOP_TYPE(left) == AOP_CRY && */
7471 /* AOP_TYPE(right) == AOP_CRY ) { */
7472 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7473 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7474 /* pic16_outBitC(result); */
7476 /* tlbl = newiTempLabel(NULL); */
7477 /* pic16_toBoolean(left); */
7478 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7479 /* pic16_toBoolean(right); */
7480 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7481 /* pic16_outBitAcc(result); */
7484 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7485 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7486 pic16_freeAsmop(result,NULL,ic,TRUE);
7490 /*-----------------------------------------------------------------*/
7491 /* genOrOp - for || operation */
7492 /*-----------------------------------------------------------------*/
7495 modified this code, but it doesn't appear to ever get called
7498 static void genOrOp (iCode *ic)
7500 operand *left,*right, *result;
7505 /* note here that || operations that are in an
7506 if statement are taken away by backPatchLabels
7507 only those used in arthmetic operations remain */
7508 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7509 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7510 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7512 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7514 /* if both are bit variables */
7515 if (AOP_TYPE(left) == AOP_CRY &&
7516 AOP_TYPE(right) == AOP_CRY ) {
7517 pic16_emitcode("clrc","");
7518 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7519 AOP(left)->aopu.aop_dir,
7520 AOP(left)->aopu.aop_dir);
7521 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7522 AOP(right)->aopu.aop_dir,
7523 AOP(right)->aopu.aop_dir);
7524 pic16_emitcode("setc","");
7527 tlbl = newiTempLabel(NULL);
7528 pic16_toBoolean(left);
7530 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7531 pic16_toBoolean(right);
7532 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7534 pic16_outBitAcc(result);
7537 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7538 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7539 pic16_freeAsmop(result,NULL,ic,TRUE);
7542 /*-----------------------------------------------------------------*/
7543 /* isLiteralBit - test if lit == 2^n */
7544 /*-----------------------------------------------------------------*/
7545 static int isLiteralBit(unsigned long lit)
7547 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7548 0x100L,0x200L,0x400L,0x800L,
7549 0x1000L,0x2000L,0x4000L,0x8000L,
7550 0x10000L,0x20000L,0x40000L,0x80000L,
7551 0x100000L,0x200000L,0x400000L,0x800000L,
7552 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7553 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7557 for(idx = 0; idx < 32; idx++)
7563 /*-----------------------------------------------------------------*/
7564 /* continueIfTrue - */
7565 /*-----------------------------------------------------------------*/
7566 static void continueIfTrue (iCode *ic)
7570 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7574 /*-----------------------------------------------------------------*/
7576 /*-----------------------------------------------------------------*/
7577 static void jumpIfTrue (iCode *ic)
7581 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7585 /*-----------------------------------------------------------------*/
7586 /* jmpTrueOrFalse - */
7587 /*-----------------------------------------------------------------*/
7588 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7590 // ugly but optimized by peephole
7593 symbol *nlbl = newiTempLabel(NULL);
7594 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7595 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7596 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7597 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7599 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7600 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7605 /*-----------------------------------------------------------------*/
7606 /* genAnd - code for and */
7607 /*-----------------------------------------------------------------*/
7608 static void genAnd (iCode *ic, iCode *ifx)
7610 operand *left, *right, *result;
7612 unsigned long lit = 0L;
7618 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7619 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7620 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7622 resolveIfx(&rIfx,ifx);
7624 /* if left is a literal & right is not then exchange them */
7625 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7626 AOP_NEEDSACC(left)) {
7627 operand *tmp = right ;
7632 /* if result = right then exchange them */
7633 if(pic16_sameRegs(AOP(result),AOP(right))){
7634 operand *tmp = right ;
7639 /* if right is bit then exchange them */
7640 if (AOP_TYPE(right) == AOP_CRY &&
7641 AOP_TYPE(left) != AOP_CRY){
7642 operand *tmp = right ;
7646 if(AOP_TYPE(right) == AOP_LIT)
7647 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7649 size = AOP_SIZE(result);
7651 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7654 // result = bit & yy;
7655 if (AOP_TYPE(left) == AOP_CRY){
7656 // c = bit & literal;
7657 if(AOP_TYPE(right) == AOP_LIT){
7659 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7662 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7665 if(size && (AOP_TYPE(result) == AOP_CRY)){
7666 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7669 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7673 pic16_emitcode("clr","c");
7676 if (AOP_TYPE(right) == AOP_CRY){
7678 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7679 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7682 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7684 pic16_emitcode("rrc","a");
7685 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7691 pic16_outBitC(result);
7693 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7694 genIfxJump(ifx, "c");
7698 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7699 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7700 if((AOP_TYPE(right) == AOP_LIT) &&
7701 (AOP_TYPE(result) == AOP_CRY) &&
7702 (AOP_TYPE(left) != AOP_CRY)){
7703 int posbit = isLiteralBit(lit);
7707 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7710 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7716 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7717 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7719 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7720 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7723 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7724 size = AOP_SIZE(left);
7727 int bp = posbit, ofs=0;
7734 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7735 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7739 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7740 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7742 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7749 symbol *tlbl = newiTempLabel(NULL);
7750 int sizel = AOP_SIZE(left);
7756 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7758 /* patch provided by Aaron Colwell */
7759 if((posbit = isLiteralBit(bytelit)) != 0) {
7760 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7761 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7762 (posbit-1),0, PO_GPR_REGISTER));
7764 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7765 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7767 if (bytelit == 0xff) {
7768 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7769 * a peephole could optimize it out -- VR */
7770 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7772 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7773 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7776 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7777 pic16_popGetLabel(tlbl->key));
7781 /* old code, left here for reference -- VR 09/2004 */
7782 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7784 if((posbit = isLiteralBit(bytelit)) != 0)
7785 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7787 if(bytelit != 0x0FFL)
7788 pic16_emitcode("anl","a,%s",
7789 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7790 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7796 // bit = left & literal
7799 pic16_emitpLabel(tlbl->key);
7801 // if(left & literal)
7804 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7807 pic16_emitpLabel(tlbl->key);
7812 pic16_outBitC(result);
7816 /* if left is same as result */
7817 if(pic16_sameRegs(AOP(result),AOP(left))){
7819 for(;size--; offset++,lit>>=8) {
7820 if(AOP_TYPE(right) == AOP_LIT){
7821 switch(lit & 0xff) {
7823 /* and'ing with 0 has clears the result */
7824 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7825 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7828 /* and'ing with 0xff is a nop when the result and left are the same */
7833 int p = pic16_my_powof2( (~lit) & 0xff );
7835 /* only one bit is set in the literal, so use a bcf instruction */
7836 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7837 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7840 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7841 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7842 if(know_W != (lit&0xff))
7843 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7845 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7850 if (AOP_TYPE(left) == AOP_ACC) {
7851 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7853 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7854 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7861 // left & result in different registers
7862 if(AOP_TYPE(result) == AOP_CRY){
7864 // if(size), result in bit
7865 // if(!size && ifx), conditional oper: if(left & right)
7866 symbol *tlbl = newiTempLabel(NULL);
7867 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7869 pic16_emitcode("setb","c");
7871 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7872 pic16_emitcode("anl","a,%s",
7873 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7874 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7879 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7880 pic16_outBitC(result);
7882 jmpTrueOrFalse(ifx, tlbl);
7884 for(;(size--);offset++) {
7886 // result = left & right
7887 if(AOP_TYPE(right) == AOP_LIT){
7888 int t = (lit >> (offset*8)) & 0x0FFL;
7891 pic16_emitcode("clrf","%s",
7892 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7893 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7896 pic16_emitcode("movf","%s,w",
7897 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7898 pic16_emitcode("movwf","%s",
7899 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7900 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7901 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7904 pic16_emitcode("movlw","0x%x",t);
7905 pic16_emitcode("andwf","%s,w",
7906 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907 pic16_emitcode("movwf","%s",
7908 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7910 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7911 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7912 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7917 if (AOP_TYPE(left) == AOP_ACC) {
7918 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7921 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7922 pic16_emitcode("andwf","%s,w",
7923 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7925 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7927 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7928 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7934 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7935 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7936 pic16_freeAsmop(result,NULL,ic,TRUE);
7939 /*-----------------------------------------------------------------*/
7940 /* genOr - code for or */
7941 /*-----------------------------------------------------------------*/
7942 static void genOr (iCode *ic, iCode *ifx)
7944 operand *left, *right, *result;
7946 unsigned long lit = 0L;
7948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7950 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7951 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7952 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7954 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7956 /* if left is a literal & right is not then exchange them */
7957 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7958 AOP_NEEDSACC(left)) {
7959 operand *tmp = right ;
7964 /* if result = right then exchange them */
7965 if(pic16_sameRegs(AOP(result),AOP(right))){
7966 operand *tmp = right ;
7971 /* if right is bit then exchange them */
7972 if (AOP_TYPE(right) == AOP_CRY &&
7973 AOP_TYPE(left) != AOP_CRY){
7974 operand *tmp = right ;
7979 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7981 if(AOP_TYPE(right) == AOP_LIT)
7982 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7984 size = AOP_SIZE(result);
7988 if (AOP_TYPE(left) == AOP_CRY){
7989 if(AOP_TYPE(right) == AOP_LIT){
7990 // c = bit & literal;
7992 // lit != 0 => result = 1
7993 if(AOP_TYPE(result) == AOP_CRY){
7995 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7996 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7997 // AOP(result)->aopu.aop_dir,
7998 // AOP(result)->aopu.aop_dir);
8000 continueIfTrue(ifx);
8004 // lit == 0 => result = left
8005 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8007 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8010 if (AOP_TYPE(right) == AOP_CRY){
8011 if(pic16_sameRegs(AOP(result),AOP(left))){
8013 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8014 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8015 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8017 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8018 AOP(result)->aopu.aop_dir,
8019 AOP(result)->aopu.aop_dir);
8020 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8021 AOP(right)->aopu.aop_dir,
8022 AOP(right)->aopu.aop_dir);
8023 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8024 AOP(result)->aopu.aop_dir,
8025 AOP(result)->aopu.aop_dir);
8027 if( AOP_TYPE(result) == AOP_ACC) {
8028 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8029 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8030 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8031 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8035 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8036 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8037 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8038 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8040 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8041 AOP(result)->aopu.aop_dir,
8042 AOP(result)->aopu.aop_dir);
8043 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8044 AOP(right)->aopu.aop_dir,
8045 AOP(right)->aopu.aop_dir);
8046 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8047 AOP(left)->aopu.aop_dir,
8048 AOP(left)->aopu.aop_dir);
8049 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8050 AOP(result)->aopu.aop_dir,
8051 AOP(result)->aopu.aop_dir);
8056 symbol *tlbl = newiTempLabel(NULL);
8057 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8060 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8061 if( AOP_TYPE(right) == AOP_ACC) {
8062 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8064 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8065 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8070 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8071 pic16_emitcode(";XXX setb","c");
8072 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8073 AOP(left)->aopu.aop_dir,tlbl->key+100);
8074 pic16_toBoolean(right);
8075 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8076 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8077 jmpTrueOrFalse(ifx, tlbl);
8081 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8088 pic16_outBitC(result);
8090 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8091 genIfxJump(ifx, "c");
8095 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8096 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8097 if((AOP_TYPE(right) == AOP_LIT) &&
8098 (AOP_TYPE(result) == AOP_CRY) &&
8099 (AOP_TYPE(left) != AOP_CRY)){
8101 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8104 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8106 continueIfTrue(ifx);
8109 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8110 // lit = 0, result = boolean(left)
8112 pic16_emitcode(";XXX setb","c");
8113 pic16_toBoolean(right);
8115 symbol *tlbl = newiTempLabel(NULL);
8116 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8118 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8120 genIfxJump (ifx,"a");
8124 pic16_outBitC(result);
8128 /* if left is same as result */
8129 if(pic16_sameRegs(AOP(result),AOP(left))){
8131 for(;size--; offset++,lit>>=8) {
8132 if(AOP_TYPE(right) == AOP_LIT){
8133 if((lit & 0xff) == 0)
8134 /* or'ing with 0 has no effect */
8137 int p = pic16_my_powof2(lit & 0xff);
8139 /* only one bit is set in the literal, so use a bsf instruction */
8140 pic16_emitpcode(POC_BSF,
8141 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8143 if(know_W != (lit & 0xff))
8144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8145 know_W = lit & 0xff;
8146 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8151 if (AOP_TYPE(left) == AOP_ACC) {
8152 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8153 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8155 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8156 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8158 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8159 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8165 // left & result in different registers
8166 if(AOP_TYPE(result) == AOP_CRY){
8168 // if(size), result in bit
8169 // if(!size && ifx), conditional oper: if(left | right)
8170 symbol *tlbl = newiTempLabel(NULL);
8171 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8172 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8176 pic16_emitcode(";XXX setb","c");
8178 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8179 pic16_emitcode(";XXX orl","a,%s",
8180 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8186 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8187 pic16_outBitC(result);
8189 jmpTrueOrFalse(ifx, tlbl);
8190 } else for(;(size--);offset++){
8192 // result = left & right
8193 if(AOP_TYPE(right) == AOP_LIT){
8194 int t = (lit >> (offset*8)) & 0x0FFL;
8197 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8198 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8200 pic16_emitcode("movf","%s,w",
8201 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8202 pic16_emitcode("movwf","%s",
8203 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8206 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8207 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8208 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8210 pic16_emitcode("movlw","0x%x",t);
8211 pic16_emitcode("iorwf","%s,w",
8212 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8213 pic16_emitcode("movwf","%s",
8214 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8220 // faster than result <- left, anl result,right
8221 // and better if result is SFR
8222 if (AOP_TYPE(left) == AOP_ACC) {
8223 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8224 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8226 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8227 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8229 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8230 pic16_emitcode("iorwf","%s,w",
8231 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8234 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8239 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8240 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8241 pic16_freeAsmop(result,NULL,ic,TRUE);
8244 /*-----------------------------------------------------------------*/
8245 /* genXor - code for xclusive or */
8246 /*-----------------------------------------------------------------*/
8247 static void genXor (iCode *ic, iCode *ifx)
8249 operand *left, *right, *result;
8251 unsigned long lit = 0L;
8253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8255 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8256 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8257 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8259 /* if left is a literal & right is not ||
8260 if left needs acc & right does not */
8261 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8262 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8263 operand *tmp = right ;
8268 /* if result = right then exchange them */
8269 if(pic16_sameRegs(AOP(result),AOP(right))){
8270 operand *tmp = right ;
8275 /* if right is bit then exchange them */
8276 if (AOP_TYPE(right) == AOP_CRY &&
8277 AOP_TYPE(left) != AOP_CRY){
8278 operand *tmp = right ;
8282 if(AOP_TYPE(right) == AOP_LIT)
8283 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8285 size = AOP_SIZE(result);
8289 if (AOP_TYPE(left) == AOP_CRY){
8290 if(AOP_TYPE(right) == AOP_LIT){
8291 // c = bit & literal;
8293 // lit>>1 != 0 => result = 1
8294 if(AOP_TYPE(result) == AOP_CRY){
8296 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8297 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8299 continueIfTrue(ifx);
8302 pic16_emitcode("setb","c");
8306 // lit == 0, result = left
8307 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8309 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8311 // lit == 1, result = not(left)
8312 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8313 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8314 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8315 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8318 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8319 pic16_emitcode("cpl","c");
8326 symbol *tlbl = newiTempLabel(NULL);
8327 if (AOP_TYPE(right) == AOP_CRY){
8329 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8332 int sizer = AOP_SIZE(right);
8334 // if val>>1 != 0, result = 1
8335 pic16_emitcode("setb","c");
8337 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8339 // test the msb of the lsb
8340 pic16_emitcode("anl","a,#0xfe");
8341 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8345 pic16_emitcode("rrc","a");
8347 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8348 pic16_emitcode("cpl","c");
8349 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8354 pic16_outBitC(result);
8356 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8357 genIfxJump(ifx, "c");
8361 if(pic16_sameRegs(AOP(result),AOP(left))){
8362 /* if left is same as result */
8363 for(;size--; offset++) {
8364 if(AOP_TYPE(right) == AOP_LIT){
8365 int t = (lit >> (offset*8)) & 0x0FFL;
8369 if (IS_AOP_PREG(left)) {
8370 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8371 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8372 pic16_aopPut(AOP(result),"a",offset);
8374 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8375 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8376 pic16_emitcode("xrl","%s,%s",
8377 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8378 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8381 if (AOP_TYPE(left) == AOP_ACC)
8382 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8384 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8385 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8387 if (IS_AOP_PREG(left)) {
8388 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8389 pic16_aopPut(AOP(result),"a",offset);
8391 pic16_emitcode("xrl","%s,a",
8392 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8398 // left & result in different registers
8399 if(AOP_TYPE(result) == AOP_CRY){
8401 // if(size), result in bit
8402 // if(!size && ifx), conditional oper: if(left ^ right)
8403 symbol *tlbl = newiTempLabel(NULL);
8404 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8406 pic16_emitcode("setb","c");
8408 if((AOP_TYPE(right) == AOP_LIT) &&
8409 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8410 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8412 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8413 pic16_emitcode("xrl","a,%s",
8414 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8416 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8421 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8422 pic16_outBitC(result);
8424 jmpTrueOrFalse(ifx, tlbl);
8425 } else for(;(size--);offset++){
8427 // result = left & right
8428 if(AOP_TYPE(right) == AOP_LIT){
8429 int t = (lit >> (offset*8)) & 0x0FFL;
8432 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8433 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8434 pic16_emitcode("movf","%s,w",
8435 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8436 pic16_emitcode("movwf","%s",
8437 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8440 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8441 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8442 pic16_emitcode("comf","%s,w",
8443 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8444 pic16_emitcode("movwf","%s",
8445 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8448 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8449 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8450 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8451 pic16_emitcode("movlw","0x%x",t);
8452 pic16_emitcode("xorwf","%s,w",
8453 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8454 pic16_emitcode("movwf","%s",
8455 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8461 // faster than result <- left, anl result,right
8462 // and better if result is SFR
8463 if (AOP_TYPE(left) == AOP_ACC) {
8464 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8465 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8467 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8468 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8469 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8470 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8472 if ( AOP_TYPE(result) != AOP_ACC){
8473 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8474 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8480 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8481 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8482 pic16_freeAsmop(result,NULL,ic,TRUE);
8485 /*-----------------------------------------------------------------*/
8486 /* genInline - write the inline code out */
8487 /*-----------------------------------------------------------------*/
8488 static void genInline (iCode *ic)
8490 char *buffer, *bp, *bp1;
8492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8494 _G.inLine += (!options.asmpeep);
8496 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8497 strcpy(buffer,IC_INLINE(ic));
8499 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8501 /* emit each line as a code */
8507 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8515 /* print label, use this special format with NULL directive
8516 * to denote that the argument should not be indented with tab */
8517 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8524 if ((bp1 != bp) && *bp1)
8525 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8530 _G.inLine -= (!options.asmpeep);
8533 /*-----------------------------------------------------------------*/
8534 /* genRRC - rotate right with carry */
8535 /*-----------------------------------------------------------------*/
8536 static void genRRC (iCode *ic)
8538 operand *left , *result ;
8539 int size, offset = 0, same;
8541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8543 /* rotate right with carry */
8545 result=IC_RESULT(ic);
8546 pic16_aopOp (left,ic,FALSE);
8547 pic16_aopOp (result,ic,FALSE);
8549 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8551 same = pic16_sameRegs(AOP(result),AOP(left));
8553 size = AOP_SIZE(result);
8555 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8557 /* get the lsb and put it into the carry */
8558 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8565 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8567 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8568 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8574 pic16_freeAsmop(left,NULL,ic,TRUE);
8575 pic16_freeAsmop(result,NULL,ic,TRUE);
8578 /*-----------------------------------------------------------------*/
8579 /* genRLC - generate code for rotate left with carry */
8580 /*-----------------------------------------------------------------*/
8581 static void genRLC (iCode *ic)
8583 operand *left , *result ;
8584 int size, offset = 0;
8587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8588 /* rotate right with carry */
8590 result=IC_RESULT(ic);
8591 pic16_aopOp (left,ic,FALSE);
8592 pic16_aopOp (result,ic,FALSE);
8594 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8596 same = pic16_sameRegs(AOP(result),AOP(left));
8598 /* move it to the result */
8599 size = AOP_SIZE(result);
8601 /* get the msb and put it into the carry */
8602 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8609 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8611 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8612 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8619 pic16_freeAsmop(left,NULL,ic,TRUE);
8620 pic16_freeAsmop(result,NULL,ic,TRUE);
8624 /* gpasm can get the highest order bit with HIGH/UPPER
8625 * so the following probably is not needed -- VR */
8627 /*-----------------------------------------------------------------*/
8628 /* genGetHbit - generates code get highest order bit */
8629 /*-----------------------------------------------------------------*/
8630 static void genGetHbit (iCode *ic)
8632 operand *left, *result;
8634 result=IC_RESULT(ic);
8635 pic16_aopOp (left,ic,FALSE);
8636 pic16_aopOp (result,ic,FALSE);
8638 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8639 /* get the highest order byte into a */
8640 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8641 if(AOP_TYPE(result) == AOP_CRY){
8642 pic16_emitcode("rlc","a");
8643 pic16_outBitC(result);
8646 pic16_emitcode("rl","a");
8647 pic16_emitcode("anl","a,#0x01");
8648 pic16_outAcc(result);
8652 pic16_freeAsmop(left,NULL,ic,TRUE);
8653 pic16_freeAsmop(result,NULL,ic,TRUE);
8657 /*-----------------------------------------------------------------*/
8658 /* AccRol - rotate left accumulator by known count */
8659 /*-----------------------------------------------------------------*/
8660 static void AccRol (int shCount)
8662 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8663 shCount &= 0x0007; // shCount : 0..7
8668 pic16_emitcode("rl","a");
8671 pic16_emitcode("rl","a");
8672 pic16_emitcode("rl","a");
8675 pic16_emitcode("swap","a");
8676 pic16_emitcode("rr","a");
8679 pic16_emitcode("swap","a");
8682 pic16_emitcode("swap","a");
8683 pic16_emitcode("rl","a");
8686 pic16_emitcode("rr","a");
8687 pic16_emitcode("rr","a");
8690 pic16_emitcode("rr","a");
8696 /*-----------------------------------------------------------------*/
8697 /* AccLsh - left shift accumulator by known count */
8698 /*-----------------------------------------------------------------*/
8699 static void AccLsh (int shCount)
8701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8707 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8710 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8711 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8714 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8715 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8718 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8721 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8722 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8725 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8726 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8729 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8733 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8736 /*-----------------------------------------------------------------*/
8737 /* AccRsh - right shift accumulator by known count */
8738 /*-----------------------------------------------------------------*/
8739 static void AccRsh (int shCount, int andmask)
8741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8746 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8749 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8750 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8753 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8754 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8757 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8760 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8761 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8764 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8765 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8768 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8773 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8775 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8779 /*-----------------------------------------------------------------*/
8780 /* AccSRsh - signed right shift accumulator by known count */
8781 /*-----------------------------------------------------------------*/
8782 static void AccSRsh (int shCount)
8785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8788 pic16_emitcode("mov","c,acc.7");
8789 pic16_emitcode("rrc","a");
8790 } else if(shCount == 2){
8791 pic16_emitcode("mov","c,acc.7");
8792 pic16_emitcode("rrc","a");
8793 pic16_emitcode("mov","c,acc.7");
8794 pic16_emitcode("rrc","a");
8796 tlbl = newiTempLabel(NULL);
8797 /* rotate right accumulator */
8798 AccRol(8 - shCount);
8799 /* and kill the higher order bits */
8800 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8801 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8802 pic16_emitcode("orl","a,#0x%02x",
8803 (unsigned char)~SRMask[shCount]);
8804 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8810 /*-----------------------------------------------------------------*/
8811 /* shiftR1Left2Result - shift right one byte from left to result */
8812 /*-----------------------------------------------------------------*/
8813 static void shiftR1Left2ResultSigned (operand *left, int offl,
8814 operand *result, int offr,
8819 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8821 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8825 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8827 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8829 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8830 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8836 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8838 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8840 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8841 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8843 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8844 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8853 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8857 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8860 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8861 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8863 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8868 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8869 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8870 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8871 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8878 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8881 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8882 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8883 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8884 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8889 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8890 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8892 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8893 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8894 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8896 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8898 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8899 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8900 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8906 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8907 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8908 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8911 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8912 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8913 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8921 /*-----------------------------------------------------------------*/
8922 /* shiftR1Left2Result - shift right one byte from left to result */
8923 /*-----------------------------------------------------------------*/
8924 static void shiftR1Left2Result (operand *left, int offl,
8925 operand *result, int offr,
8926 int shCount, int sign)
8930 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8932 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8934 /* Copy the msb into the carry if signed. */
8936 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8969 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8973 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8975 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8980 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8981 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8985 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8986 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8987 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8995 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8996 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8997 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8998 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9004 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9005 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9014 /*-----------------------------------------------------------------*/
9015 /* shiftL1Left2Result - shift left one byte from left to result */
9016 /*-----------------------------------------------------------------*/
9017 static void shiftL1Left2Result (operand *left, int offl,
9018 operand *result, int offr, int shCount)
9023 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9025 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9026 DEBUGpic16_emitcode ("; ***","same = %d",same);
9027 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9029 /* shift left accumulator */
9030 //AccLsh(shCount); // don't comment out just yet...
9031 // pic16_aopPut(AOP(result),"a",offr);
9035 /* Shift left 1 bit position */
9036 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9038 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9040 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9041 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9045 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9046 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9047 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9052 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9053 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9054 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9059 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9060 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9063 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9064 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9065 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9066 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9069 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9070 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9071 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9072 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9073 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9076 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9077 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9078 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9082 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9087 /*-----------------------------------------------------------------*/
9088 /* movLeft2Result - move byte from left to result */
9089 /*-----------------------------------------------------------------*/
9090 static void movLeft2Result (operand *left, int offl,
9091 operand *result, int offr)
9094 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9095 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9096 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9098 if (*l == '@' && (IS_AOP_PREG(result))) {
9099 pic16_emitcode("mov","a,%s",l);
9100 pic16_aopPut(AOP(result),"a",offr);
9102 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9103 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9108 /*-----------------------------------------------------------------*/
9109 /* shiftL2Left2Result - shift left two bytes from left to result */
9110 /*-----------------------------------------------------------------*/
9111 static void shiftL2Left2Result (operand *left, int offl,
9112 operand *result, int offr, int shCount)
9114 int same = pic16_sameRegs(AOP(result), AOP(left));
9117 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9119 if (same && (offl != offr)) { // shift bytes
9122 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9123 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9125 } else { // just treat as different later on
9138 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9139 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9140 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9144 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9145 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9151 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9152 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9154 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9156 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9159 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9160 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9164 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9165 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9166 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9167 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9168 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9169 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9170 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9171 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9173 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9176 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9177 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9179 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9190 /* note, use a mov/add for the shift since the mov has a
9191 chance of getting optimized out */
9192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9194 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9195 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9196 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9200 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9207 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9208 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9209 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9210 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9211 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9212 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9213 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9214 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9218 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9219 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9223 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9224 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9225 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9226 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9228 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9229 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9230 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9231 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9232 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9234 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9235 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9238 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9239 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9240 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9241 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9242 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9247 /*-----------------------------------------------------------------*/
9248 /* shiftR2Left2Result - shift right two bytes from left to result */
9249 /*-----------------------------------------------------------------*/
9250 static void shiftR2Left2Result (operand *left, int offl,
9251 operand *result, int offr,
9252 int shCount, int sign)
9254 int same = pic16_sameRegs(AOP(result), AOP(left));
9256 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9258 if (same && (offl != offr)) { // shift right bytes
9261 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9262 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9264 } else { // just treat as different later on
9276 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9281 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9282 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9284 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9285 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9286 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9287 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9292 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9295 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9296 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9304 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9305 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9307 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9308 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9309 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9310 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9312 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9313 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9316 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9317 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9318 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9319 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9320 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9324 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9325 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9329 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9330 pic16_emitpcode(POC_BTFSC,
9331 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9332 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9340 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9341 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9343 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9344 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9345 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9346 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9348 pic16_emitpcode(POC_BTFSC,
9349 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9350 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9352 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9353 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9354 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9355 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9357 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9358 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9359 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9360 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9361 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9362 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9363 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9364 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9366 pic16_emitpcode(POC_BTFSC,
9367 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9368 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9370 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9371 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9378 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9379 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9380 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9381 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9384 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9386 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9391 /*-----------------------------------------------------------------*/
9392 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9393 /*-----------------------------------------------------------------*/
9394 static void shiftLLeftOrResult (operand *left, int offl,
9395 operand *result, int offr, int shCount)
9397 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9399 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9400 /* shift left accumulator */
9402 /* or with result */
9403 /* back to result */
9404 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9407 /*-----------------------------------------------------------------*/
9408 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9409 /*-----------------------------------------------------------------*/
9410 static void shiftRLeftOrResult (operand *left, int offl,
9411 operand *result, int offr, int shCount)
9413 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9415 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9416 /* shift right accumulator */
9418 /* or with result */
9419 /* back to result */
9420 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9423 /*-----------------------------------------------------------------*/
9424 /* genlshOne - left shift a one byte quantity by known count */
9425 /*-----------------------------------------------------------------*/
9426 static void genlshOne (operand *result, operand *left, int shCount)
9428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9429 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9432 /*-----------------------------------------------------------------*/
9433 /* genlshTwo - left shift two bytes by known amount != 0 */
9434 /*-----------------------------------------------------------------*/
9435 static void genlshTwo (operand *result,operand *left, int shCount)
9439 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9440 size = pic16_getDataSize(result);
9442 /* if shCount >= 8 */
9448 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9450 movLeft2Result(left, LSB, result, MSB16);
9452 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9455 /* 1 <= shCount <= 7 */
9458 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9460 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9464 /*-----------------------------------------------------------------*/
9465 /* shiftLLong - shift left one long from left to result */
9466 /* offr = LSB or MSB16 */
9467 /*-----------------------------------------------------------------*/
9468 static void shiftLLong (operand *left, operand *result, int offr )
9470 int size = AOP_SIZE(result);
9471 int same = pic16_sameRegs(AOP(left),AOP(result));
9474 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9476 if (same && (offr == MSB16)) { //shift one byte
9477 for(i=size-1;i>=MSB16;i--) {
9478 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9479 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9482 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9485 if (size > LSB+offr ){
9487 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9489 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9490 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9494 if(size > MSB16+offr){
9496 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9498 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9499 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9503 if(size > MSB24+offr){
9505 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9507 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9508 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9512 if(size > MSB32+offr){
9514 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9516 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9517 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9521 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9525 /*-----------------------------------------------------------------*/
9526 /* genlshFour - shift four byte by a known amount != 0 */
9527 /*-----------------------------------------------------------------*/
9528 static void genlshFour (operand *result, operand *left, int shCount)
9532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 size = AOP_SIZE(result);
9535 /* if shifting more that 3 bytes */
9536 if (shCount >= 24 ) {
9539 /* lowest order of left goes to the highest
9540 order of the destination */
9541 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9543 movLeft2Result(left, LSB, result, MSB32);
9545 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9546 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9547 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9552 /* more than two bytes */
9553 else if ( shCount >= 16 ) {
9554 /* lower order two bytes goes to higher order two bytes */
9556 /* if some more remaining */
9558 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9560 movLeft2Result(left, MSB16, result, MSB32);
9561 movLeft2Result(left, LSB, result, MSB24);
9563 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9564 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9568 /* if more than 1 byte */
9569 else if ( shCount >= 8 ) {
9570 /* lower order three bytes goes to higher order three bytes */
9574 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9576 movLeft2Result(left, LSB, result, MSB16);
9578 else{ /* size = 4 */
9580 movLeft2Result(left, MSB24, result, MSB32);
9581 movLeft2Result(left, MSB16, result, MSB24);
9582 movLeft2Result(left, LSB, result, MSB16);
9583 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9585 else if(shCount == 1)
9586 shiftLLong(left, result, MSB16);
9588 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9589 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9590 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9591 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9596 /* 1 <= shCount <= 7 */
9597 else if(shCount <= 3)
9599 shiftLLong(left, result, LSB);
9600 while(--shCount >= 1)
9601 shiftLLong(result, result, LSB);
9603 /* 3 <= shCount <= 7, optimize */
9605 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9606 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9607 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9611 /*-----------------------------------------------------------------*/
9612 /* genLeftShiftLiteral - left shifting by known count */
9613 /*-----------------------------------------------------------------*/
9614 void pic16_genLeftShiftLiteral (operand *left,
9619 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9623 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9624 pic16_freeAsmop(right,NULL,ic,TRUE);
9626 pic16_aopOp(left,ic,FALSE);
9627 pic16_aopOp(result,ic,FALSE);
9629 size = getSize(operandType(result));
9632 pic16_emitcode("; shift left ","result %d, left %d",size,
9636 /* I suppose that the left size >= result size */
9639 movLeft2Result(left, size, result, size);
9643 else if(shCount >= (size * 8))
9645 pic16_aopPut(AOP(result),zero,size);
9649 genlshOne (result,left,shCount);
9654 genlshTwo (result,left,shCount);
9658 genlshFour (result,left,shCount);
9662 pic16_freeAsmop(left,NULL,ic,TRUE);
9663 pic16_freeAsmop(result,NULL,ic,TRUE);
9666 /*-----------------------------------------------------------------*
9667 * genMultiAsm - repeat assembly instruction for size of register.
9668 * if endian == 1, then the high byte (i.e base address + size of
9669 * register) is used first else the low byte is used first;
9670 *-----------------------------------------------------------------*/
9671 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9676 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9689 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9695 #if !(USE_GENERIC_SIGNED_SHIFT)
9696 /*-----------------------------------------------------------------*/
9697 /* genLeftShift - generates code for left shifting */
9698 /*-----------------------------------------------------------------*/
9699 static void genLeftShift (iCode *ic)
9701 operand *left,*right, *result;
9704 symbol *tlbl , *tlbl1;
9707 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9709 right = IC_RIGHT(ic);
9711 result = IC_RESULT(ic);
9713 pic16_aopOp(right,ic,FALSE);
9715 /* if the shift count is known then do it
9716 as efficiently as possible */
9717 if (AOP_TYPE(right) == AOP_LIT) {
9718 pic16_genLeftShiftLiteral (left,right,result,ic);
9722 /* shift count is unknown then we have to form
9723 * a loop. Get the loop count in WREG : Note: we take
9724 * only the lower order byte since shifting
9725 * more than 32 bits make no sense anyway, ( the
9726 * largest size of an object can be only 32 bits ) */
9728 pic16_aopOp(left,ic,FALSE);
9729 pic16_aopOp(result,ic,FALSE);
9731 /* now move the left to the result if they are not the
9732 * same, and if size > 1,
9733 * and if right is not same to result (!!!) -- VR */
9734 if (!pic16_sameRegs(AOP(left),AOP(result))
9735 && (AOP_SIZE(result) > 1)) {
9737 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9739 size = AOP_SIZE(result);
9744 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9745 if (*l == '@' && (IS_AOP_PREG(result))) {
9747 pic16_emitcode("mov","a,%s",l);
9748 pic16_aopPut(AOP(result),"a",offset);
9752 /* we don't know if left is a literal or a register, take care -- VR */
9753 mov2f(AOP(result), AOP(left), offset);
9759 size = AOP_SIZE(result);
9761 /* if it is only one byte then */
9763 if(optimized_for_speed) {
9764 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9765 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9766 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9767 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9768 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9769 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9770 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9771 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9772 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9773 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9774 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9775 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9780 tlbl = newiTempLabel(NULL);
9783 /* this is already done, why change it? */
9784 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9785 mov2f(AOP(result), AOP(left), 0);
9789 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9790 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9791 pic16_emitpLabel(tlbl->key);
9792 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9793 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9795 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9800 if (pic16_sameRegs(AOP(left),AOP(result))) {
9802 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9804 tlbl = newiTempLabel(NULL);
9805 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9806 genMultiAsm(POC_RRCF, result, size,1);
9807 pic16_emitpLabel(tlbl->key);
9808 genMultiAsm(POC_RLCF, result, size,0);
9809 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9811 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9815 //tlbl = newiTempLabel(NULL);
9817 //tlbl1 = newiTempLabel(NULL);
9819 //reAdjustPreg(AOP(result));
9821 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9822 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9823 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9825 //pic16_emitcode("add","a,acc");
9826 //pic16_aopPut(AOP(result),"a",offset++);
9828 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9830 // pic16_emitcode("rlc","a");
9831 // pic16_aopPut(AOP(result),"a",offset++);
9833 //reAdjustPreg(AOP(result));
9835 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9836 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9839 tlbl = newiTempLabel(NULL);
9840 tlbl1= newiTempLabel(NULL);
9842 size = AOP_SIZE(result);
9845 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9847 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9849 /* offset should be 0, 1 or 3 */
9851 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9853 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9855 pic16_emitpcode(POC_MOVWF, pctemp);
9858 pic16_emitpLabel(tlbl->key);
9861 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9863 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9865 pic16_emitpcode(POC_DECFSZ, pctemp);
9866 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9867 pic16_emitpLabel(tlbl1->key);
9869 pic16_popReleaseTempReg(pctemp,1);
9873 pic16_freeAsmop (right,NULL,ic,TRUE);
9874 pic16_freeAsmop(left,NULL,ic,TRUE);
9875 pic16_freeAsmop(result,NULL,ic,TRUE);
9881 #error old code (left here for reference)
9882 /*-----------------------------------------------------------------*/
9883 /* genLeftShift - generates code for left shifting */
9884 /*-----------------------------------------------------------------*/
9885 static void genLeftShift (iCode *ic)
9887 operand *left,*right, *result;
9890 symbol *tlbl , *tlbl1;
9893 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9895 right = IC_RIGHT(ic);
9897 result = IC_RESULT(ic);
9899 pic16_aopOp(right,ic,FALSE);
9901 /* if the shift count is known then do it
9902 as efficiently as possible */
9903 if (AOP_TYPE(right) == AOP_LIT) {
9904 pic16_genLeftShiftLiteral (left,right,result,ic);
9908 /* shift count is unknown then we have to form
9909 a loop get the loop count in B : Note: we take
9910 only the lower order byte since shifting
9911 more that 32 bits make no sense anyway, ( the
9912 largest size of an object can be only 32 bits ) */
9915 pic16_aopOp(left,ic,FALSE);
9916 pic16_aopOp(result,ic,FALSE);
9918 /* now move the left to the result if they are not the
9920 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9921 AOP_SIZE(result) > 1) {
9923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9925 size = AOP_SIZE(result);
9928 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9929 if (*l == '@' && (IS_AOP_PREG(result))) {
9931 pic16_emitcode("mov","a,%s",l);
9932 pic16_aopPut(AOP(result),"a",offset);
9935 /* we don't know if left is a literal or a register, take care -- VR */
9936 mov2f(AOP(result), AOP(left), offset);
9942 size = AOP_SIZE(result);
9944 /* if it is only one byte then */
9946 if(optimized_for_speed) {
9947 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9948 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9949 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9950 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9952 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9953 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9954 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9955 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9956 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9957 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9958 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9963 tlbl = newiTempLabel(NULL);
9964 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9965 mov2f(AOP(result), AOP(left), 0);
9967 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9968 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9971 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9972 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9973 pic16_emitpLabel(tlbl->key);
9974 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9975 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9977 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9982 if (pic16_sameRegs(AOP(left),AOP(result))) {
9984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9986 tlbl = newiTempLabel(NULL);
9987 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9988 genMultiAsm(POC_RRCF, result, size,1);
9989 pic16_emitpLabel(tlbl->key);
9990 genMultiAsm(POC_RLCF, result, size,0);
9991 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9993 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9997 //tlbl = newiTempLabel(NULL);
9999 //tlbl1 = newiTempLabel(NULL);
10001 //reAdjustPreg(AOP(result));
10003 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10004 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10005 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10007 //pic16_emitcode("add","a,acc");
10008 //pic16_aopPut(AOP(result),"a",offset++);
10010 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10012 // pic16_emitcode("rlc","a");
10013 // pic16_aopPut(AOP(result),"a",offset++);
10015 //reAdjustPreg(AOP(result));
10017 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10018 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10021 tlbl = newiTempLabel(NULL);
10022 tlbl1= newiTempLabel(NULL);
10024 size = AOP_SIZE(result);
10027 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10029 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10031 /* offset should be 0, 1 or 3 */
10033 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10035 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10037 pic16_emitpcode(POC_MOVWF, pctemp);
10040 pic16_emitpLabel(tlbl->key);
10043 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10045 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10047 pic16_emitpcode(POC_DECFSZ, pctemp);
10048 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10049 pic16_emitpLabel(tlbl1->key);
10051 pic16_popReleaseTempReg(pctemp,1);
10055 pic16_freeAsmop (right,NULL,ic,TRUE);
10056 pic16_freeAsmop(left,NULL,ic,TRUE);
10057 pic16_freeAsmop(result,NULL,ic,TRUE);
10061 /*-----------------------------------------------------------------*/
10062 /* genrshOne - right shift a one byte quantity by known count */
10063 /*-----------------------------------------------------------------*/
10064 static void genrshOne (operand *result, operand *left,
10065 int shCount, int sign)
10067 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10068 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10071 /*-----------------------------------------------------------------*/
10072 /* genrshTwo - right shift two bytes by known amount != 0 */
10073 /*-----------------------------------------------------------------*/
10074 static void genrshTwo (operand *result,operand *left,
10075 int shCount, int sign)
10077 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10078 /* if shCount >= 8 */
10079 if (shCount >= 8) {
10082 shiftR1Left2Result(left, MSB16, result, LSB,
10085 movLeft2Result(left, MSB16, result, LSB);
10087 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10090 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10091 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10095 /* 1 <= shCount <= 7 */
10097 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10100 /*-----------------------------------------------------------------*/
10101 /* shiftRLong - shift right one long from left to result */
10102 /* offl = LSB or MSB16 */
10103 /*-----------------------------------------------------------------*/
10104 static void shiftRLong (operand *left, int offl,
10105 operand *result, int sign)
10107 int size = AOP_SIZE(result);
10108 int same = pic16_sameRegs(AOP(left),AOP(result));
10110 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10112 if (same && (offl == MSB16)) { //shift one byte right
10113 for(i=MSB16;i<size;i++) {
10114 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10120 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10126 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10128 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10129 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10132 if(offl == MSB16) {
10133 /* add sign of "a" */
10134 pic16_addSign(result, MSB32, sign);
10138 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10140 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10141 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10145 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10147 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10148 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10152 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10155 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10156 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10161 /*-----------------------------------------------------------------*/
10162 /* genrshFour - shift four byte by a known amount != 0 */
10163 /*-----------------------------------------------------------------*/
10164 static void genrshFour (operand *result, operand *left,
10165 int shCount, int sign)
10167 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10168 /* if shifting more that 3 bytes */
10169 if(shCount >= 24 ) {
10172 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10174 movLeft2Result(left, MSB32, result, LSB);
10176 pic16_addSign(result, MSB16, sign);
10178 else if(shCount >= 16){
10181 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10183 movLeft2Result(left, MSB24, result, LSB);
10184 movLeft2Result(left, MSB32, result, MSB16);
10186 pic16_addSign(result, MSB24, sign);
10188 else if(shCount >= 8){
10191 shiftRLong(left, MSB16, result, sign);
10192 else if(shCount == 0){
10193 movLeft2Result(left, MSB16, result, LSB);
10194 movLeft2Result(left, MSB24, result, MSB16);
10195 movLeft2Result(left, MSB32, result, MSB24);
10196 pic16_addSign(result, MSB32, sign);
10198 else{ //shcount >= 2
10199 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10200 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10201 /* the last shift is signed */
10202 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10203 pic16_addSign(result, MSB32, sign);
10206 else{ /* 1 <= shCount <= 7 */
10208 shiftRLong(left, LSB, result, sign);
10210 shiftRLong(result, LSB, result, sign);
10213 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10214 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10215 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10220 /*-----------------------------------------------------------------*/
10221 /* genRightShiftLiteral - right shifting by known count */
10222 /*-----------------------------------------------------------------*/
10223 static void genRightShiftLiteral (operand *left,
10229 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10230 int lsize,res_size;
10232 pic16_freeAsmop(right,NULL,ic,TRUE);
10234 pic16_aopOp(left,ic,FALSE);
10235 pic16_aopOp(result,ic,FALSE);
10237 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10240 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10244 lsize = pic16_getDataSize(left);
10245 res_size = pic16_getDataSize(result);
10246 /* test the LEFT size !!! */
10248 /* I suppose that the left size >= result size */
10251 movLeft2Result(left, lsize, result, res_size);
10254 else if(shCount >= (lsize * 8)){
10256 if(res_size == 1) {
10257 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10259 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10260 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10265 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10266 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10267 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10269 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10274 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10279 switch (res_size) {
10281 genrshOne (result,left,shCount,sign);
10285 genrshTwo (result,left,shCount,sign);
10289 genrshFour (result,left,shCount,sign);
10297 pic16_freeAsmop(left,NULL,ic,TRUE);
10298 pic16_freeAsmop(result,NULL,ic,TRUE);
10301 #if !(USE_GENERIC_SIGNED_SHIFT)
10302 /*-----------------------------------------------------------------*/
10303 /* genSignedRightShift - right shift of signed number */
10304 /*-----------------------------------------------------------------*/
10305 static void genSignedRightShift (iCode *ic)
10307 operand *right, *left, *result;
10310 symbol *tlbl, *tlbl1 ;
10313 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10315 /* we do it the hard way put the shift count in b
10316 and loop thru preserving the sign */
10317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10319 right = IC_RIGHT(ic);
10320 left = IC_LEFT(ic);
10321 result = IC_RESULT(ic);
10323 pic16_aopOp(right,ic,FALSE);
10324 pic16_aopOp(left,ic,FALSE);
10325 pic16_aopOp(result,ic,FALSE);
10328 if ( AOP_TYPE(right) == AOP_LIT) {
10329 genRightShiftLiteral (left,right,result,ic,1);
10332 /* shift count is unknown then we have to form
10333 a loop get the loop count in B : Note: we take
10334 only the lower order byte since shifting
10335 more that 32 bits make no sense anyway, ( the
10336 largest size of an object can be only 32 bits ) */
10338 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10339 //pic16_emitcode("inc","b");
10340 //pic16_freeAsmop (right,NULL,ic,TRUE);
10341 //pic16_aopOp(left,ic,FALSE);
10342 //pic16_aopOp(result,ic,FALSE);
10344 /* now move the left to the result if they are not the
10346 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10347 AOP_SIZE(result) > 1) {
10349 size = AOP_SIZE(result);
10353 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10354 if (*l == '@' && IS_AOP_PREG(result)) {
10356 pic16_emitcode("mov","a,%s",l);
10357 pic16_aopPut(AOP(result),"a",offset);
10359 pic16_aopPut(AOP(result),l,offset);
10361 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10362 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10368 /* mov the highest order bit to OVR */
10369 tlbl = newiTempLabel(NULL);
10370 tlbl1= newiTempLabel(NULL);
10372 size = AOP_SIZE(result);
10375 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10377 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10379 /* offset should be 0, 1 or 3 */
10380 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10382 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10384 pic16_emitpcode(POC_MOVWF, pctemp);
10387 pic16_emitpLabel(tlbl->key);
10389 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10390 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10393 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10396 pic16_emitpcode(POC_DECFSZ, pctemp);
10397 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10398 pic16_emitpLabel(tlbl1->key);
10400 pic16_popReleaseTempReg(pctemp,1);
10402 size = AOP_SIZE(result);
10404 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10405 pic16_emitcode("rlc","a");
10406 pic16_emitcode("mov","ov,c");
10407 /* if it is only one byte then */
10409 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10411 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10412 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10413 pic16_emitcode("mov","c,ov");
10414 pic16_emitcode("rrc","a");
10415 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10416 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10417 pic16_aopPut(AOP(result),"a",0);
10421 reAdjustPreg(AOP(result));
10422 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10423 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10424 pic16_emitcode("mov","c,ov");
10426 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10428 pic16_emitcode("rrc","a");
10429 pic16_aopPut(AOP(result),"a",offset--);
10431 reAdjustPreg(AOP(result));
10432 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10433 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10438 pic16_freeAsmop(left,NULL,ic,TRUE);
10439 pic16_freeAsmop(result,NULL,ic,TRUE);
10440 pic16_freeAsmop(right,NULL,ic,TRUE);
10444 #if !(USE_GENERIC_SIGNED_SHIFT)
10445 #warning This implementation of genRightShift() is incomplete!
10446 /*-----------------------------------------------------------------*/
10447 /* genRightShift - generate code for right shifting */
10448 /*-----------------------------------------------------------------*/
10449 static void genRightShift (iCode *ic)
10451 operand *right, *left, *result;
10455 symbol *tlbl, *tlbl1 ;
10457 /* if signed then we do it the hard way preserve the
10458 sign bit moving it inwards */
10459 letype = getSpec(operandType(IC_LEFT(ic)));
10460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10462 if (!SPEC_USIGN(letype)) {
10463 genSignedRightShift (ic);
10467 /* signed & unsigned types are treated the same : i.e. the
10468 signed is NOT propagated inwards : quoting from the
10469 ANSI - standard : "for E1 >> E2, is equivalent to division
10470 by 2**E2 if unsigned or if it has a non-negative value,
10471 otherwise the result is implementation defined ", MY definition
10472 is that the sign does not get propagated */
10474 right = IC_RIGHT(ic);
10475 left = IC_LEFT(ic);
10476 result = IC_RESULT(ic);
10478 pic16_aopOp(right,ic,FALSE);
10480 /* if the shift count is known then do it
10481 as efficiently as possible */
10482 if (AOP_TYPE(right) == AOP_LIT) {
10483 genRightShiftLiteral (left,right,result,ic, 0);
10487 /* shift count is unknown then we have to form
10488 a loop get the loop count in B : Note: we take
10489 only the lower order byte since shifting
10490 more that 32 bits make no sense anyway, ( the
10491 largest size of an object can be only 32 bits ) */
10493 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10494 pic16_emitcode("inc","b");
10495 pic16_aopOp(left,ic,FALSE);
10496 pic16_aopOp(result,ic,FALSE);
10498 /* now move the left to the result if they are not the
10500 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10501 AOP_SIZE(result) > 1) {
10503 size = AOP_SIZE(result);
10506 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10507 if (*l == '@' && IS_AOP_PREG(result)) {
10509 pic16_emitcode("mov","a,%s",l);
10510 pic16_aopPut(AOP(result),"a",offset);
10512 pic16_aopPut(AOP(result),l,offset);
10517 tlbl = newiTempLabel(NULL);
10518 tlbl1= newiTempLabel(NULL);
10519 size = AOP_SIZE(result);
10522 /* if it is only one byte then */
10525 tlbl = newiTempLabel(NULL);
10526 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10527 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10528 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10531 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10532 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10533 pic16_emitpLabel(tlbl->key);
10534 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10535 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10537 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10542 reAdjustPreg(AOP(result));
10543 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10544 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10547 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10549 pic16_emitcode("rrc","a");
10550 pic16_aopPut(AOP(result),"a",offset--);
10552 reAdjustPreg(AOP(result));
10554 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10555 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10558 pic16_freeAsmop(left,NULL,ic,TRUE);
10559 pic16_freeAsmop (right,NULL,ic,TRUE);
10560 pic16_freeAsmop(result,NULL,ic,TRUE);
10564 #if (USE_GENERIC_SIGNED_SHIFT)
10565 /*-----------------------------------------------------------------*/
10566 /* genGenericShift - generates code for left or right shifting */
10567 /*-----------------------------------------------------------------*/
10568 static void genGenericShift (iCode *ic, int isShiftLeft) {
10569 operand *left,*right, *result;
10571 int sign, signedCount;
10572 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10573 PIC_OPCODE pos_shift, neg_shift;
10577 right = IC_RIGHT(ic);
10578 left = IC_LEFT(ic);
10579 result = IC_RESULT(ic);
10581 pic16_aopOp(right,ic,FALSE);
10582 pic16_aopOp(left,ic,FALSE);
10583 pic16_aopOp(result,ic,FALSE);
10585 sign = !SPEC_USIGN(operandType (left));
10586 signedCount = !SPEC_USIGN(operandType (right));
10588 /* if the shift count is known then do it
10589 as efficiently as possible */
10590 if (AOP_TYPE(right) == AOP_LIT) {
10591 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10592 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10593 // we should modify right->aopu.aop_lit here!
10594 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10595 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10597 pic16_genLeftShiftLiteral (left,right,result,ic);
10599 genRightShiftLiteral (left,right,result,ic, sign);
10602 } // if (right is literal)
10604 /* shift count is unknown then we have to form a loop.
10605 * Note: we take only the lower order byte since shifting
10606 * more than 32 bits make no sense anyway, ( the
10607 * largest size of an object can be only 32 bits )
10608 * Note: we perform arithmetic shifts if the left operand is
10609 * signed and we do an (effective) right shift, i. e. we
10610 * shift in the sign bit from the left. */
10612 label_complete = newiTempLabel ( NULL );
10613 label_loop_pos = newiTempLabel ( NULL );
10614 label_loop_neg = NULL;
10615 label_negative = NULL;
10616 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10617 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10620 // additional labels needed
10621 label_loop_neg = newiTempLabel ( NULL );
10622 label_negative = newiTempLabel ( NULL );
10625 // copy source to result -- this will effectively truncate the left operand to the size of result!
10626 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10627 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10628 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10629 mov2f (AOP(result),AOP(left), offset);
10632 // if result is longer than left, fill with zeros (or sign)
10633 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10634 if (sign && AOP_SIZE(left) > 0) {
10635 // shift signed operand -- fill with sign
10636 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10637 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10638 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10639 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10640 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10643 // shift unsigned operand -- fill result with zeros
10644 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10645 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10648 } // if (size mismatch)
10650 pic16_mov2w (AOP(right), 0);
10651 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10652 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10655 // perform a shift by one (shift count is positive)
10656 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10657 // 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])
10658 pic16_emitpLabel (label_loop_pos->key);
10660 if (sign && (pos_shift == POC_RRCF)) {
10661 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10664 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10665 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10666 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10668 // perform a shift by one (shift count is positive)
10669 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10670 // 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])
10671 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10672 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10674 pic16_emitpLabel (label_loop_pos->key);
10675 if (sign && (pos_shift == POC_RRCF)) {
10676 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10679 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10680 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10681 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10682 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10686 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10688 pic16_emitpLabel (label_negative->key);
10689 // perform a shift by -1 (shift count is negative)
10690 // 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)
10692 pic16_emitpLabel (label_loop_neg->key);
10693 if (sign && (neg_shift == POC_RRCF)) {
10694 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10697 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10698 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10699 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10700 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10701 } // if (signedCount)
10703 pic16_emitpLabel (label_complete->key);
10706 pic16_freeAsmop (right,NULL,ic,TRUE);
10707 pic16_freeAsmop(left,NULL,ic,TRUE);
10708 pic16_freeAsmop(result,NULL,ic,TRUE);
10711 static void genLeftShift (iCode *ic) {
10712 genGenericShift (ic, 1);
10715 static void genRightShift (iCode *ic) {
10716 genGenericShift (ic, 0);
10721 void pic16_loadFSR0(operand *op)
10723 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10726 /*-----------------------------------------------------------------*/
10727 /* genUnpackBits - generates code for unpacking bits */
10728 /*-----------------------------------------------------------------*/
10729 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10733 sym_link *etype, *letype;
10734 int blen=0, bstr=0;
10738 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10739 etype = getSpec(operandType(result));
10740 letype = getSpec(operandType(left));
10742 // if(IS_BITFIELD(etype)) {
10743 blen = SPEC_BLEN(etype);
10744 bstr = SPEC_BSTR(etype);
10747 lbstr = SPEC_BSTR( letype );
10750 if((blen == 1) && (bstr < 8)) {
10751 /* it is a single bit, so use the appropriate bit instructions */
10752 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10754 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10756 if((ptype == POINTER) && (result)) {
10757 /* workaround to reduce the extra lfsr instruction */
10758 pic16_emitpcode(POC_BTFSC,
10759 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10761 pic16_emitpcode(POC_BTFSC,
10762 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10765 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10767 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10773 /* the following call to pic16_loadFSR0 is temporary until
10774 * optimization to handle single bit assignments is added
10775 * to the function. Until then use the old safe way! -- VR */
10776 pic16_loadFSR0( left );
10778 /* read the first byte */
10785 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10788 pic16_emitcode("clr","a");
10789 pic16_emitcode("movc","a","@a+dptr");
10794 /* if we have bitdisplacement then it fits */
10795 /* into this byte completely or if length is */
10796 /* less than a byte */
10797 if ((shCnt = SPEC_BSTR(etype)) ||
10798 (SPEC_BLEN(etype) <= 8)) {
10800 /* shift right acc */
10803 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10804 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10806 /* VR -- normally I would use the following, but since we use the hack,
10807 * to avoid the masking from AccRsh, why not mask it right now? */
10810 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10813 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10819 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10820 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10823 /* bit field did not fit in a byte */
10824 rlen = SPEC_BLEN(etype) - 8;
10825 pic16_aopPut(AOP(result),"a",offset++);
10832 pic16_emitcode("inc","%s",rname);
10833 pic16_emitcode("mov","a,@%s",rname);
10837 pic16_emitcode("inc","%s",rname);
10838 pic16_emitcode("movx","a,@%s",rname);
10842 pic16_emitcode("inc","dptr");
10843 pic16_emitcode("movx","a,@dptr");
10847 pic16_emitcode("clr","a");
10848 pic16_emitcode("inc","dptr");
10849 pic16_emitcode("movc","a","@a+dptr");
10853 pic16_emitcode("inc","dptr");
10854 pic16_emitcode("lcall","__gptrget");
10859 /* if we are done */
10863 pic16_aopPut(AOP(result),"a",offset++);
10868 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10869 pic16_aopPut(AOP(result),"a",offset);
10876 static void genDataPointerGet(operand *left,
10880 int size, offset = 0, leoffset=0 ;
10882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10883 pic16_aopOp(result, ic, FALSE);
10885 size = AOP_SIZE(result);
10886 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10890 /* The following tests may save a redudant movff instruction when
10891 * accessing unions */
10893 /* if they are the same */
10894 if (operandsEqu (left, result)) {
10895 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10901 /* if they are the same registers */
10902 if (pic16_sameRegs(AOP(left),AOP(result))) {
10903 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10909 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10910 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10911 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10918 if ( AOP_TYPE(left) == AOP_PCODE) {
10919 fprintf(stderr,"genDataPointerGet %s, %d\n",
10920 AOP(left)->aopu.pcop->name,
10921 (AOP(left)->aopu.pcop->type == PO_DIR)?
10922 PCOR(AOP(left)->aopu.pcop)->instance:
10923 PCOI(AOP(left)->aopu.pcop)->offset);
10927 if(AOP(left)->aopu.pcop->type == PO_DIR)
10928 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10930 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10933 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10935 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10936 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10937 pic16_mov2w(AOP(left), offset); // patch 8
10938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10940 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10941 pic16_popGet(AOP(left), offset), //patch 8
10942 pic16_popGet(AOP(result), offset)));
10950 pic16_freeAsmop(result,NULL,ic,TRUE);
10955 /*-----------------------------------------------------------------*/
10956 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10957 /*-----------------------------------------------------------------*/
10958 static void genNearPointerGet (operand *left,
10963 //regs *preg = NULL ;
10964 sym_link *rtype, *retype;
10965 sym_link *ltype = operandType(left);
10969 rtype = operandType(result);
10970 retype= getSpec(rtype);
10972 pic16_aopOp(left,ic,FALSE);
10974 // pic16_DumpOp("(left)",left);
10975 // pic16_DumpOp("(result)",result);
10977 /* if left is rematerialisable and
10978 * result is not bit variable type and
10979 * the left is pointer to data space i.e
10980 * lower 128 bytes of space */
10982 if (AOP_TYPE(left) == AOP_PCODE
10983 && !IS_BITFIELD(retype)
10984 && DCL_TYPE(ltype) == POINTER) {
10986 genDataPointerGet (left,result,ic);
10987 pic16_freeAsmop(left, NULL, ic, TRUE);
10991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10993 /* if the value is already in a pointer register
10994 * then don't need anything more */
10995 if (!AOP_INPREG(AOP(left))) {
10996 /* otherwise get a free pointer register */
10997 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10999 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11000 /* bitfields will be handled by genUnpackBits */
11001 if(!IS_BITFIELD(retype)) {
11003 if(is_LitAOp( AOP(left) )) {
11004 pic16_loadFSR0( left );
11006 // set up FSR0 with address from left
11007 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11008 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11013 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11015 pic16_aopOp (result,ic,FALSE);
11017 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11019 /* if bitfield then unpack the bits */
11020 if (IS_BITFIELD(retype))
11021 genUnpackBits (result, left, NULL, POINTER);
11023 /* we have can just get the values */
11024 int size = AOP_SIZE(result);
11027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11029 /* fsr0 is loaded already -- VR */
11030 // pic16_loadFSR0( left );
11032 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11033 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11036 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11037 pic16_popGet(AOP(result), offset++)));
11039 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11040 pic16_popGet(AOP(result), offset++)));
11044 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11045 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11047 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11051 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11053 pic16_emitcode("mov","a,@%s",rname);
11054 pic16_aopPut(AOP(result),"a",offset);
11056 sprintf(buffer,"@%s",rname);
11057 pic16_aopPut(AOP(result),buffer,offset);
11061 pic16_emitcode("inc","%s",rname);
11066 /* now some housekeeping stuff */
11068 /* we had to allocate for this iCode */
11069 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11070 pic16_freeAsmop(NULL,aop,ic,TRUE);
11072 /* we did not allocate which means left
11073 * already in a pointer register, then
11074 * if size > 0 && this could be used again
11075 * we have to point it back to where it
11077 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11078 if (AOP_SIZE(result) > 1
11079 && !OP_SYMBOL(left)->remat
11080 && ( OP_SYMBOL(left)->liveTo > ic->seq
11082 // int size = AOP_SIZE(result) - 1;
11084 // pic16_emitcode("dec","%s",rname);
11089 pic16_freeAsmop(left,NULL,ic,TRUE);
11090 pic16_freeAsmop(result,NULL,ic,TRUE);
11093 /*-----------------------------------------------------------------*/
11094 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11095 /*-----------------------------------------------------------------*/
11096 static void genPagedPointerGet (operand *left,
11101 regs *preg = NULL ;
11103 sym_link *rtype, *retype;
11105 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11107 rtype = operandType(result);
11108 retype= getSpec(rtype);
11110 pic16_aopOp(left,ic,FALSE);
11112 /* if the value is already in a pointer register
11113 then don't need anything more */
11114 if (!AOP_INPREG(AOP(left))) {
11115 /* otherwise get a free pointer register */
11117 preg = getFreePtr(ic,&aop,FALSE);
11118 pic16_emitcode("mov","%s,%s",
11120 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11121 rname = preg->name ;
11123 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11125 pic16_freeAsmop(left,NULL,ic,TRUE);
11126 pic16_aopOp (result,ic,FALSE);
11128 /* if bitfield then unpack the bits */
11129 if (IS_BITFIELD(retype))
11130 genUnpackBits (result,left,rname,PPOINTER);
11132 /* we have can just get the values */
11133 int size = AOP_SIZE(result);
11138 pic16_emitcode("movx","a,@%s",rname);
11139 pic16_aopPut(AOP(result),"a",offset);
11144 pic16_emitcode("inc","%s",rname);
11148 /* now some housekeeping stuff */
11150 /* we had to allocate for this iCode */
11151 pic16_freeAsmop(NULL,aop,ic,TRUE);
11153 /* we did not allocate which means left
11154 already in a pointer register, then
11155 if size > 0 && this could be used again
11156 we have to point it back to where it
11158 if (AOP_SIZE(result) > 1 &&
11159 !OP_SYMBOL(left)->remat &&
11160 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11162 int size = AOP_SIZE(result) - 1;
11164 pic16_emitcode("dec","%s",rname);
11169 pic16_freeAsmop(result,NULL,ic,TRUE);
11174 /*-----------------------------------------------------------------*/
11175 /* genFarPointerGet - gget value from far space */
11176 /*-----------------------------------------------------------------*/
11177 static void genFarPointerGet (operand *left,
11178 operand *result, iCode *ic)
11181 sym_link *retype = getSpec(operandType(result));
11183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11185 pic16_aopOp(left,ic,FALSE);
11187 /* if the operand is already in dptr
11188 then we do nothing else we move the value to dptr */
11189 if (AOP_TYPE(left) != AOP_STR) {
11190 /* if this is remateriazable */
11191 if (AOP_TYPE(left) == AOP_IMMD)
11192 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11193 else { /* we need to get it byte by byte */
11194 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11195 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11196 if (options.model == MODEL_FLAT24)
11198 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11202 /* so dptr know contains the address */
11203 pic16_freeAsmop(left,NULL,ic,TRUE);
11204 pic16_aopOp(result,ic,FALSE);
11206 /* if bit then unpack */
11207 if (IS_BITFIELD(retype))
11208 genUnpackBits(result,left,"dptr",FPOINTER);
11210 size = AOP_SIZE(result);
11214 pic16_emitcode("movx","a,@dptr");
11215 pic16_aopPut(AOP(result),"a",offset++);
11217 pic16_emitcode("inc","dptr");
11221 pic16_freeAsmop(result,NULL,ic,TRUE);
11224 /*-----------------------------------------------------------------*/
11225 /* genCodePointerGet - get value from code space */
11226 /*-----------------------------------------------------------------*/
11227 static void genCodePointerGet (operand *left,
11228 operand *result, iCode *ic)
11231 sym_link *retype = getSpec(operandType(result));
11233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11235 pic16_aopOp(left,ic,FALSE);
11237 /* if the operand is already in dptr
11238 then we do nothing else we move the value to dptr */
11239 if (AOP_TYPE(left) != AOP_STR) {
11240 /* if this is remateriazable */
11241 if (AOP_TYPE(left) == AOP_IMMD)
11242 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11243 else { /* we need to get it byte by byte */
11244 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11245 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11246 if (options.model == MODEL_FLAT24)
11248 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11252 /* so dptr know contains the address */
11253 pic16_freeAsmop(left,NULL,ic,TRUE);
11254 pic16_aopOp(result,ic,FALSE);
11256 /* if bit then unpack */
11257 if (IS_BITFIELD(retype))
11258 genUnpackBits(result,left,"dptr",CPOINTER);
11260 size = AOP_SIZE(result);
11264 pic16_emitcode("clr","a");
11265 pic16_emitcode("movc","a,@a+dptr");
11266 pic16_aopPut(AOP(result),"a",offset++);
11268 pic16_emitcode("inc","dptr");
11272 pic16_freeAsmop(result,NULL,ic,TRUE);
11276 /*-----------------------------------------------------------------*/
11277 /* genGenPointerGet - gget value from generic pointer space */
11278 /*-----------------------------------------------------------------*/
11279 static void genGenPointerGet (operand *left,
11280 operand *result, iCode *ic)
11282 int size, offset, lit;
11283 sym_link *retype = getSpec(operandType(result));
11285 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11286 pic16_aopOp(left,ic,FALSE);
11287 pic16_aopOp(result,ic,FALSE);
11288 size = AOP_SIZE(result);
11290 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11292 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11294 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11295 // load FSR0 from immediate
11296 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11298 // pic16_loadFSR0( left );
11303 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11305 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11312 else { /* we need to get it byte by byte */
11313 // set up FSR0 with address from left
11314 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11315 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11321 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11323 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11330 /* if bit then unpack */
11331 if (IS_BITFIELD(retype))
11332 genUnpackBits(result,left,"BAD",GPOINTER);
11335 pic16_freeAsmop(left,NULL,ic,TRUE);
11336 pic16_freeAsmop(result,NULL,ic,TRUE);
11342 /*-----------------------------------------------------------------*/
11343 /* genGenPointerGet - gget value from generic pointer space */
11344 /*-----------------------------------------------------------------*/
11345 static void genGenPointerGet (operand *left,
11346 operand *result, iCode *ic)
11348 int size, offset, lit;
11349 sym_link *retype = getSpec(operandType(result));
11352 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11353 pic16_aopOp(left,ic,FALSE);
11354 pic16_aopOp(result,ic,FALSE);
11355 size = AOP_SIZE(result);
11357 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11359 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11361 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11362 // load FSR0 from immediate
11363 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11365 werror(W_POSSBUG2, __FILE__, __LINE__);
11370 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11372 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11379 } else { /* we need to get it byte by byte */
11381 /* set up WREG:PRODL:FSR0L with address from left */
11382 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11383 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11384 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11387 case 1: strcpy(fgptrget, "__gptrget1"); break;
11388 case 2: strcpy(fgptrget, "__gptrget2"); break;
11389 case 3: strcpy(fgptrget, "__gptrget3"); break;
11390 case 4: strcpy(fgptrget, "__gptrget4"); break;
11392 werror(W_POSSBUG2, __FILE__, __LINE__);
11396 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11398 assignResultValue(result, 1);
11403 sym = newSymbol( fgptrget, 0 );
11404 strcpy(sym->rname, fgptrget);
11405 checkAddSym(&externs, sym);
11407 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11413 /* if bit then unpack */
11414 if (IS_BITFIELD(retype))
11415 genUnpackBits(result,left,"BAD",GPOINTER);
11418 pic16_freeAsmop(left,NULL,ic,TRUE);
11419 pic16_freeAsmop(result,NULL,ic,TRUE);
11422 /*-----------------------------------------------------------------*/
11423 /* genConstPointerGet - get value from const generic pointer space */
11424 /*-----------------------------------------------------------------*/
11425 static void genConstPointerGet (operand *left,
11426 operand *result, iCode *ic)
11428 //sym_link *retype = getSpec(operandType(result));
11429 // symbol *albl = newiTempLabel(NULL); // patch 15
11430 // symbol *blbl = newiTempLabel(NULL); //
11431 // PIC_OPCODE poc; // patch 15
11435 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11436 pic16_aopOp(left,ic,FALSE);
11437 pic16_aopOp(result,ic,TRUE);
11438 size = AOP_SIZE(result);
11440 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11442 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11444 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11445 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11446 pic16_emitpLabel(albl->key);
11448 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11450 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11451 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11452 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11453 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11454 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11456 pic16_emitpLabel(blbl->key);
11458 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11462 // set up table pointer
11463 if( (AOP_TYPE(left) == AOP_PCODE)
11464 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11465 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
11467 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11468 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11469 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11470 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11471 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11472 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11476 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11477 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11478 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11484 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11485 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11489 pic16_freeAsmop(left,NULL,ic,TRUE);
11490 pic16_freeAsmop(result,NULL,ic,TRUE);
11495 /*-----------------------------------------------------------------*/
11496 /* genPointerGet - generate code for pointer get */
11497 /*-----------------------------------------------------------------*/
11498 static void genPointerGet (iCode *ic)
11500 operand *left, *result ;
11501 sym_link *type, *etype;
11506 left = IC_LEFT(ic);
11507 result = IC_RESULT(ic) ;
11509 /* depending on the type of pointer we need to
11510 move it to the correct pointer register */
11511 type = operandType(left);
11512 etype = getSpec(type);
11515 if (IS_PTR_CONST(type))
11517 if (IS_CODEPTR(type))
11519 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11521 /* if left is of type of pointer then it is simple */
11522 if (IS_PTR(type) && !IS_FUNC(type->next))
11523 p_type = DCL_TYPE(type);
11525 /* we have to go by the storage class */
11526 p_type = PTR_TYPE(SPEC_OCLS(etype));
11528 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11530 if (SPEC_OCLS(etype)->codesp ) {
11531 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11532 //p_type = CPOINTER ;
11535 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11536 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11537 /*p_type = FPOINTER ;*/
11539 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11540 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11541 /* p_type = PPOINTER; */
11543 if (SPEC_OCLS(etype) == idata )
11544 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11545 /* p_type = IPOINTER; */
11547 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11548 /* p_type = POINTER ; */
11551 /* now that we have the pointer type we assign
11552 the pointer values */
11557 genNearPointerGet (left,result,ic);
11561 genPagedPointerGet(left,result,ic);
11565 genFarPointerGet (left,result,ic);
11569 genConstPointerGet (left,result,ic);
11570 //pic16_emitcodePointerGet (left,result,ic);
11575 if (IS_PTR_CONST(type))
11576 genConstPointerGet (left,result,ic);
11579 genGenPointerGet (left,result,ic);
11583 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11584 "genPointerGet: illegal pointer type");
11590 /*-----------------------------------------------------------------*/
11591 /* genPackBits - generates code for packed bit storage */
11592 /*-----------------------------------------------------------------*/
11593 static void genPackBits (sym_link *etype , operand *result,
11595 char *rname, int p_type)
11604 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11605 blen = SPEC_BLEN(etype);
11606 bstr = SPEC_BSTR(etype);
11608 retype = getSpec(operandType(right));
11610 if(AOP_TYPE(right) == AOP_LIT) {
11611 if((blen == 1) && (bstr < 8)) {
11613 /* it is a single bit, so use the appropriate bit instructions */
11615 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11617 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11618 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11619 if((p_type == POINTER) && (result)) {
11620 /* workaround to reduce the extra lfsr instruction */
11622 pic16_emitpcode(POC_BSF,
11623 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11625 pic16_emitpcode(POC_BCF,
11626 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11629 pic16_loadFSR0( result );
11631 pic16_emitpcode(POC_BSF,
11632 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11634 pic16_emitpcode(POC_BCF,
11635 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11642 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11645 if(IS_BITFIELD(retype)
11646 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11650 rblen = SPEC_BLEN( retype );
11651 rbstr = SPEC_BSTR( retype );
11654 if(IS_BITFIELD(etype)) {
11655 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11656 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11658 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11661 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11663 if(IS_BITFIELD(etype)) {
11664 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11666 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11669 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11673 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11675 /* if the bit lenth is less than or */
11676 /* it exactly fits a byte then */
11677 if((shCnt=SPEC_BSTR(etype))
11678 || SPEC_BLEN(etype) <= 8 ) {
11680 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11682 /* shift left acc */
11685 /* using PRODL as a temporary register here */
11686 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11691 pic16_loadFSR0( result );
11692 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11693 // pic16_emitcode ("mov","b,a");
11694 // pic16_emitcode("mov","a,@%s",rname);
11698 werror(W_POSSBUG2, __FILE__, __LINE__);
11703 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11704 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11705 (unsigned char)(0xff >> (8-bstr))) ));
11706 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11707 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11714 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11715 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11720 if ( SPEC_BLEN(etype) <= 8 )
11723 pic16_emitcode("inc","%s",rname);
11724 rLen = SPEC_BLEN(etype) ;
11728 /* now generate for lengths greater than one byte */
11731 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11741 pic16_emitcode("mov","@%s,a",rname);
11743 pic16_emitcode("mov","@%s,%s",rname,l);
11748 pic16_emitcode("movx","@dptr,a");
11753 DEBUGpic16_emitcode(";lcall","__gptrput");
11756 pic16_emitcode ("inc","%s",rname);
11761 /* last last was not complete */
11763 /* save the byte & read byte */
11766 pic16_emitcode ("mov","b,a");
11767 pic16_emitcode("mov","a,@%s",rname);
11771 pic16_emitcode ("mov","b,a");
11772 pic16_emitcode("movx","a,@dptr");
11776 pic16_emitcode ("push","b");
11777 pic16_emitcode ("push","acc");
11778 pic16_emitcode ("lcall","__gptrget");
11779 pic16_emitcode ("pop","b");
11783 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11784 pic16_emitcode ("orl","a,b");
11787 if (p_type == GPOINTER)
11788 pic16_emitcode("pop","b");
11793 pic16_emitcode("mov","@%s,a",rname);
11797 pic16_emitcode("movx","@dptr,a");
11801 DEBUGpic16_emitcode(";lcall","__gptrput");
11805 /*-----------------------------------------------------------------*/
11806 /* genDataPointerSet - remat pointer to data space */
11807 /*-----------------------------------------------------------------*/
11808 static void genDataPointerSet(operand *right,
11812 int size, offset = 0, resoffset=0 ;
11814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11815 pic16_aopOp(right,ic,FALSE);
11817 size = AOP_SIZE(right);
11819 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11822 if ( AOP_TYPE(result) == AOP_PCODE) {
11823 fprintf(stderr,"genDataPointerSet %s, %d\n",
11824 AOP(result)->aopu.pcop->name,
11825 (AOP(result)->aopu.pcop->type == PO_DIR)?
11826 PCOR(AOP(result)->aopu.pcop)->instance:
11827 PCOI(AOP(result)->aopu.pcop)->offset);
11831 if(AOP(result)->aopu.pcop->type == PO_DIR)
11832 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11835 if (AOP_TYPE(right) == AOP_LIT) {
11838 if(!IS_FLOAT(operandType( right )))
11839 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11842 unsigned long lit_int;
11846 /* take care if literal is a float */
11847 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11848 lit = info.lit_int;
11851 lit = lit >> (8*offset);
11853 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11856 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11859 pic16_mov2w(AOP(right), offset);
11860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11866 pic16_freeAsmop(right,NULL,ic,TRUE);
11871 /*-----------------------------------------------------------------*/
11872 /* genNearPointerSet - pic16_emitcode for near pointer put */
11873 /*-----------------------------------------------------------------*/
11874 static void genNearPointerSet (operand *right,
11881 sym_link *ptype = operandType(result);
11882 sym_link *resetype;
11884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11885 retype= getSpec(operandType(right));
11886 resetype = getSpec(operandType(result));
11888 pic16_aopOp(result,ic,FALSE);
11890 /* if the result is rematerializable &
11891 * in data space & not a bit variable */
11893 /* and result is not a bit variable */
11894 if (AOP_TYPE(result) == AOP_PCODE
11895 // && AOP_TYPE(result) == AOP_IMMD
11896 && DCL_TYPE(ptype) == POINTER
11897 && !IS_BITFIELD(retype)
11898 && !IS_BITFIELD(resetype)) {
11900 genDataPointerSet (right,result,ic);
11901 pic16_freeAsmop(result,NULL,ic,TRUE);
11905 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11906 pic16_aopOp(right,ic,FALSE);
11907 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11909 /* if the value is already in a pointer register
11910 * then don't need anything more */
11911 if (!AOP_INPREG(AOP(result))) {
11912 /* otherwise get a free pointer register */
11913 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11915 // if( (AOP_TYPE(result) == AOP_PCODE)
11916 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11917 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11918 if(is_LitAOp( AOP(result) ))
11920 if(!IS_BITFIELD(resetype))
11921 pic16_loadFSR0( result ); // patch 10
11923 if(!IS_BITFIELD(resetype)) {
11924 // set up FSR0 with address of result
11925 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11926 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11932 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11936 // pic16_loadFSR0( result );
11938 /* if bitfield then unpack the bits */
11939 if (IS_BITFIELD(resetype)) {
11940 genPackBits (resetype, result, right, NULL, POINTER);
11942 /* we have can just get the values */
11943 int size = AOP_SIZE(right);
11946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11948 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11951 //pic16_emitcode("mov","@%s,a",rname);
11952 pic16_emitcode("movf","indf0,w ;1");
11955 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
11956 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
11958 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
11960 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
11962 } else { // no literal //
11964 pic16_emitpcode(POC_MOVFF, //
11965 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11966 pic16_popCopyReg(&pic16_pc_postinc0))); //
11968 pic16_emitpcode(POC_MOVFF, //
11969 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11970 pic16_popCopyReg(&pic16_pc_indf0))); //
11978 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11979 /* now some housekeeping stuff */
11981 /* we had to allocate for this iCode */
11982 pic16_freeAsmop(NULL,aop,ic,TRUE);
11984 /* we did not allocate which means left
11985 * already in a pointer register, then
11986 * if size > 0 && this could be used again
11987 * we have to point it back to where it
11989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11990 if (AOP_SIZE(right) > 1
11991 && !OP_SYMBOL(result)->remat
11992 && ( OP_SYMBOL(result)->liveTo > ic->seq
11995 int size = AOP_SIZE(right) - 1;
11998 pic16_emitcode("decf","fsr0,f");
11999 //pic16_emitcode("dec","%s",rname);
12003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12006 pic16_freeAsmop(right,NULL,ic,TRUE);
12007 pic16_freeAsmop(result,NULL,ic,TRUE);
12010 /*-----------------------------------------------------------------*/
12011 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12012 /*-----------------------------------------------------------------*/
12013 static void genPagedPointerSet (operand *right,
12018 regs *preg = NULL ;
12022 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12024 retype= getSpec(operandType(right));
12026 pic16_aopOp(result,ic,FALSE);
12028 /* if the value is already in a pointer register
12029 then don't need anything more */
12030 if (!AOP_INPREG(AOP(result))) {
12031 /* otherwise get a free pointer register */
12033 preg = getFreePtr(ic,&aop,FALSE);
12034 pic16_emitcode("mov","%s,%s",
12036 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12037 rname = preg->name ;
12039 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12041 pic16_freeAsmop(result,NULL,ic,TRUE);
12042 pic16_aopOp (right,ic,FALSE);
12044 /* if bitfield then unpack the bits */
12045 if (IS_BITFIELD(retype))
12046 genPackBits (retype,result,right,rname,PPOINTER);
12048 /* we have can just get the values */
12049 int size = AOP_SIZE(right);
12053 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12056 pic16_emitcode("movx","@%s,a",rname);
12059 pic16_emitcode("inc","%s",rname);
12065 /* now some housekeeping stuff */
12067 /* we had to allocate for this iCode */
12068 pic16_freeAsmop(NULL,aop,ic,TRUE);
12070 /* we did not allocate which means left
12071 already in a pointer register, then
12072 if size > 0 && this could be used again
12073 we have to point it back to where it
12075 if (AOP_SIZE(right) > 1 &&
12076 !OP_SYMBOL(result)->remat &&
12077 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12079 int size = AOP_SIZE(right) - 1;
12081 pic16_emitcode("dec","%s",rname);
12086 pic16_freeAsmop(right,NULL,ic,TRUE);
12091 /*-----------------------------------------------------------------*/
12092 /* genFarPointerSet - set value from far space */
12093 /*-----------------------------------------------------------------*/
12094 static void genFarPointerSet (operand *right,
12095 operand *result, iCode *ic)
12098 sym_link *retype = getSpec(operandType(right));
12100 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12101 pic16_aopOp(result,ic,FALSE);
12103 /* if the operand is already in dptr
12104 then we do nothing else we move the value to dptr */
12105 if (AOP_TYPE(result) != AOP_STR) {
12106 /* if this is remateriazable */
12107 if (AOP_TYPE(result) == AOP_IMMD)
12108 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12109 else { /* we need to get it byte by byte */
12110 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12111 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12112 if (options.model == MODEL_FLAT24)
12114 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12118 /* so dptr know contains the address */
12119 pic16_freeAsmop(result,NULL,ic,TRUE);
12120 pic16_aopOp(right,ic,FALSE);
12122 /* if bit then unpack */
12123 if (IS_BITFIELD(retype))
12124 genPackBits(retype,result,right,"dptr",FPOINTER);
12126 size = AOP_SIZE(right);
12130 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12132 pic16_emitcode("movx","@dptr,a");
12134 pic16_emitcode("inc","dptr");
12138 pic16_freeAsmop(right,NULL,ic,TRUE);
12141 /*-----------------------------------------------------------------*/
12142 /* genGenPointerSet - set value from generic pointer space */
12143 /*-----------------------------------------------------------------*/
12145 static void genGenPointerSet (operand *right,
12146 operand *result, iCode *ic)
12148 int i, size, offset, lit;
12149 sym_link *retype = getSpec(operandType(right));
12151 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12153 pic16_aopOp(result,ic,FALSE);
12154 pic16_aopOp(right,ic,FALSE);
12155 size = AOP_SIZE(right);
12158 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12160 /* if the operand is already in dptr
12161 then we do nothing else we move the value to dptr */
12162 if (AOP_TYPE(result) != AOP_STR) {
12163 /* if this is remateriazable */
12164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12165 // WARNING: anythig until "else" is untested!
12166 if (AOP_TYPE(result) == AOP_IMMD) {
12167 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12168 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12169 // load FSR0 from immediate
12170 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12174 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12176 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12182 else { /* we need to get it byte by byte */
12183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12184 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12186 // set up FSR0 with address of result
12187 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12188 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12190 /* hack hack! see if this the FSR. If so don't load W */
12191 if(AOP_TYPE(right) != AOP_ACC) {
12193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12195 if(AOP_TYPE(right) == AOP_LIT)
12198 // note: pic16_popGet handles sign extension
12199 for(i=0;i<size;i++) {
12200 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12202 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12204 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12209 for(i=0;i<size;i++) {
12211 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12212 pic16_popCopyReg(&pic16_pc_postinc0)));
12214 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12215 pic16_popCopyReg(&pic16_pc_indf0)));
12221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12222 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12224 } // if (AOP_TYPE(result) != AOP_IMMD)
12226 } // if (AOP_TYPE(result) != AOP_STR)
12227 /* so dptr know contains the address */
12230 /* if bit then unpack */
12231 if (IS_BITFIELD(retype))
12232 genPackBits(retype,result,right,"dptr",GPOINTER);
12234 size = AOP_SIZE(right);
12237 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12239 // set up FSR0 with address of result
12240 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12241 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12244 if (AOP_TYPE(right) == AOP_LIT) {
12245 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12247 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12249 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12251 } else { // no literal
12253 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12255 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12263 pic16_freeAsmop(right,NULL,ic,TRUE);
12264 pic16_freeAsmop(result,NULL,ic,TRUE);
12268 static void genGenPointerSet (operand *right,
12269 operand *result, iCode *ic)
12272 sym_link *retype = getSpec(operandType(right));
12275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12277 pic16_aopOp(result,ic,FALSE);
12278 pic16_aopOp(right,ic,FALSE);
12279 size = AOP_SIZE(right);
12281 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12284 /* if bit then unpack */
12285 if (IS_BITFIELD(retype)) {
12286 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12287 genPackBits(retype,result,right,"dptr",GPOINTER);
12291 size = AOP_SIZE(right);
12293 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12297 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12299 /* value of right+0 is placed on stack, which will be retrieved
12300 * by the support function this restoring the stack. The important
12301 * thing is that there is no need to manually restore stack pointer
12303 pushaop(AOP(right), 0);
12304 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12305 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12306 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12307 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12309 /* load address to write to in WREG:FSR0H:FSR0L */
12310 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12311 pic16_popCopyReg(&pic16_pc_fsr0l)));
12312 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12313 pic16_popCopyReg(&pic16_pc_prodl)));
12314 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12317 /* put code here */
12319 case 1: strcpy(fgptrput, "__gptrput1"); break;
12320 case 2: strcpy(fgptrput, "__gptrput2"); break;
12321 case 3: strcpy(fgptrput, "__gptrput3"); break;
12322 case 4: strcpy(fgptrput, "__gptrput4"); break;
12324 werror(W_POSSBUG2, __FILE__, __LINE__);
12328 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12333 sym = newSymbol( fgptrput, 0 );
12334 strcpy(sym->rname, fgptrput);
12335 checkAddSym(&externs, sym);
12339 pic16_freeAsmop(right,NULL,ic,TRUE);
12340 pic16_freeAsmop(result,NULL,ic,TRUE);
12343 /*-----------------------------------------------------------------*/
12344 /* genPointerSet - stores the value into a pointer location */
12345 /*-----------------------------------------------------------------*/
12346 static void genPointerSet (iCode *ic)
12348 operand *right, *result ;
12349 sym_link *type, *etype;
12354 right = IC_RIGHT(ic);
12355 result = IC_RESULT(ic) ;
12357 /* depending on the type of pointer we need to
12358 move it to the correct pointer register */
12359 type = operandType(result);
12360 etype = getSpec(type);
12361 /* if left is of type of pointer then it is simple */
12362 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12363 p_type = DCL_TYPE(type);
12366 /* we have to go by the storage class */
12367 p_type = PTR_TYPE(SPEC_OCLS(etype));
12369 /* if (SPEC_OCLS(etype)->codesp ) { */
12370 /* p_type = CPOINTER ; */
12373 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12374 /* p_type = FPOINTER ; */
12376 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12377 /* p_type = PPOINTER ; */
12379 /* if (SPEC_OCLS(etype) == idata ) */
12380 /* p_type = IPOINTER ; */
12382 /* p_type = POINTER ; */
12385 /* now that we have the pointer type we assign
12386 the pointer values */
12391 genNearPointerSet (right,result,ic);
12395 genPagedPointerSet (right,result,ic);
12399 genFarPointerSet (right,result,ic);
12403 genGenPointerSet (right,result,ic);
12407 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12408 "genPointerSet: illegal pointer type");
12412 /*-----------------------------------------------------------------*/
12413 /* genIfx - generate code for Ifx statement */
12414 /*-----------------------------------------------------------------*/
12415 static void genIfx (iCode *ic, iCode *popIc)
12417 operand *cond = IC_COND(ic);
12422 pic16_aopOp(cond,ic,FALSE);
12424 /* get the value into acc */
12425 if (AOP_TYPE(cond) != AOP_CRY)
12426 pic16_toBoolean(cond);
12429 /* the result is now in the accumulator */
12430 pic16_freeAsmop(cond,NULL,ic,TRUE);
12432 /* if there was something to be popped then do it */
12436 /* if the condition is a bit variable */
12437 if (isbit && IS_ITEMP(cond) &&
12439 genIfxJump(ic,"c");
12440 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12442 if (isbit && !IS_ITEMP(cond))
12443 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12445 genIfxJump(ic,"a");
12450 /*-----------------------------------------------------------------*/
12451 /* genAddrOf - generates code for address of */
12452 /*-----------------------------------------------------------------*/
12453 static void genAddrOf (iCode *ic)
12455 operand *result, *left;
12457 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12458 pCodeOp *pcop0, *pcop1, *pcop2;
12462 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12464 sym = OP_SYMBOL( IC_LEFT(ic) );
12467 /* get address of symbol on stack */
12468 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12470 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12471 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12474 // operands on stack are accessible via "FSR2 + index" with index
12475 // starting at 2 for arguments and growing from 0 downwards for
12476 // local variables (index == 0 is not assigned so we add one here)
12478 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12480 assert (soffs < 0);
12483 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12484 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12485 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12486 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12487 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12488 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12489 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12495 // if(pic16_debug_verbose) {
12496 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12497 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12500 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12501 size = AOP_SIZE(IC_RESULT(ic));
12504 /* Assume that what we want the address of is in data space
12505 * since there is no stack on the PIC, yet! -- VR */
12507 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12508 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12509 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512 pic16_emitpcode(POC_MOVLW, pcop0);
12513 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12514 pic16_emitpcode(POC_MOVLW, pcop1);
12515 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12516 pic16_emitpcode(POC_MOVLW, pcop2);
12517 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12520 pic16_emitpcode(POC_MOVLW, pcop0);
12521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12522 pic16_emitpcode(POC_MOVLW, pcop1);
12523 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12525 pic16_emitpcode(POC_MOVLW, pcop0);
12526 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12529 pic16_freeAsmop(left, NULL, ic, FALSE);
12531 pic16_freeAsmop(result,NULL,ic,TRUE);
12536 /*-----------------------------------------------------------------*/
12537 /* genFarFarAssign - assignment when both are in far space */
12538 /*-----------------------------------------------------------------*/
12539 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12541 int size = AOP_SIZE(right);
12544 /* first push the right side on to the stack */
12546 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12548 pic16_emitcode ("push","acc");
12551 pic16_freeAsmop(right,NULL,ic,FALSE);
12552 /* now assign DPTR to result */
12553 pic16_aopOp(result,ic,FALSE);
12554 size = AOP_SIZE(result);
12556 pic16_emitcode ("pop","acc");
12557 pic16_aopPut(AOP(result),"a",--offset);
12559 pic16_freeAsmop(result,NULL,ic,FALSE);
12564 /*-----------------------------------------------------------------*/
12565 /* genAssign - generate code for assignment */
12566 /*-----------------------------------------------------------------*/
12567 static void genAssign (iCode *ic)
12569 operand *result, *right;
12570 int size, offset,know_W;
12571 unsigned long lit = 0L;
12573 result = IC_RESULT(ic);
12574 right = IC_RIGHT(ic) ;
12578 /* if they are the same */
12579 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12582 /* reversed order operands are aopOp'ed so that result operand
12583 * is effective in case right is a stack symbol. This maneauver
12584 * allows to use the _G.resDirect flag later */
12585 pic16_aopOp(result,ic,TRUE);
12586 pic16_aopOp(right,ic,FALSE);
12588 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12590 /* if they are the same registers */
12591 if (pic16_sameRegs(AOP(right),AOP(result)))
12594 /* if the result is a bit */
12595 if (AOP_TYPE(result) == AOP_CRY) {
12596 /* if the right size is a literal then
12597 we know what the value is */
12598 if (AOP_TYPE(right) == AOP_LIT) {
12600 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12601 pic16_popGet(AOP(result),0));
12603 if (((int) operandLitValue(right)))
12604 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12605 AOP(result)->aopu.aop_dir,
12606 AOP(result)->aopu.aop_dir);
12608 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12609 AOP(result)->aopu.aop_dir,
12610 AOP(result)->aopu.aop_dir);
12614 /* the right is also a bit variable */
12615 if (AOP_TYPE(right) == AOP_CRY) {
12616 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12617 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12618 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12620 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12621 AOP(result)->aopu.aop_dir,
12622 AOP(result)->aopu.aop_dir);
12623 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12624 AOP(right)->aopu.aop_dir,
12625 AOP(right)->aopu.aop_dir);
12626 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12627 AOP(result)->aopu.aop_dir,
12628 AOP(result)->aopu.aop_dir);
12632 /* we need to or */
12633 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12634 pic16_toBoolean(right);
12636 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12637 //pic16_aopPut(AOP(result),"a",0);
12641 /* bit variables done */
12643 size = AOP_SIZE(result);
12646 if(AOP_TYPE(right) == AOP_LIT) {
12647 if(!IS_FLOAT(operandType( right )))
12648 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12651 unsigned long lit_int;
12655 /* take care if literal is a float */
12656 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12657 lit = info.lit_int;
12661 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12662 // sizeof(unsigned long int), sizeof(float));
12665 if (AOP_TYPE(right) == AOP_REG) {
12666 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12669 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12674 if(AOP_TYPE(right) != AOP_LIT
12675 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12676 && !IS_FUNC(OP_SYM_TYPE(right))
12678 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12679 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12681 // set up table pointer
12682 if(is_LitOp(right)) {
12683 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12684 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12685 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12686 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12687 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12688 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12689 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12691 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12692 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12693 pic16_popCopyReg(&pic16_pc_tblptrl)));
12694 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12695 pic16_popCopyReg(&pic16_pc_tblptrh)));
12696 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12697 pic16_popCopyReg(&pic16_pc_tblptru)));
12700 size = min(AOP_SIZE(right), AOP_SIZE(result));
12702 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12703 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12704 pic16_popGet(AOP(result),offset)));
12708 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12709 size = AOP_SIZE(result) - AOP_SIZE(right);
12711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12721 /* VR - What is this?! */
12722 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12724 if(aopIdx(AOP(result),0) == 4) {
12726 /* this is a workaround to save value of right into wreg too,
12727 * value of wreg is going to be used later */
12728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12729 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12730 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12734 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12740 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12741 if(AOP_TYPE(right) == AOP_LIT) {
12743 if(know_W != (lit&0xff))
12744 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12746 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12748 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12752 } else if (AOP_TYPE(right) == AOP_CRY) {
12753 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12755 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12756 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12757 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12759 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12760 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12761 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12765 if(!_G.resDirect) /* use this aopForSym feature */
12766 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12773 pic16_freeAsmop (right,NULL,ic,FALSE);
12774 pic16_freeAsmop (result,NULL,ic,TRUE);
12777 /*-----------------------------------------------------------------*/
12778 /* genJumpTab - generates code for jump table */
12779 /*-----------------------------------------------------------------*/
12780 static void genJumpTab (iCode *ic)
12785 pCodeOp *jt_offs_hi;
12790 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12791 /* get the condition into accumulator */
12792 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12794 /* multiply by three */
12795 pic16_emitcode("add","a,acc");
12796 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12798 jtab = newiTempLabel(NULL);
12799 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12800 pic16_emitcode("jmp","@a+dptr");
12801 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12804 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12805 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12807 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12808 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12809 pic16_emitpLabel(jtab->key);
12813 jt_offs = pic16_popGetTempReg(0);
12814 jt_offs_hi = pic16_popGetTempReg(1);
12815 jt_label = pic16_popGetLabel (jtab->key);
12816 //fprintf (stderr, "Creating jump table...\n");
12818 // calculate offset into jump table (idx * sizeof (GOTO))
12819 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12820 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12821 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12822 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12823 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12824 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12825 pic16_emitpcode(POC_MOVWF , jt_offs);
12827 // prepare PCLATx (set to first entry in jump table)
12828 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12829 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12830 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12831 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12832 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12834 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12835 pic16_emitpcode(POC_ADDWF , jt_offs);
12836 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12837 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12839 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12841 // release temporaries and prepare jump into table (new PCL --> WREG)
12842 pic16_emitpcode(POC_MOVFW , jt_offs);
12843 pic16_popReleaseTempReg (jt_offs_hi, 1);
12844 pic16_popReleaseTempReg (jt_offs, 0);
12846 // jump into the table
12847 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12849 pic16_emitpLabelFORCE(jtab->key);
12852 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12854 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12855 /* now generate the jump labels */
12856 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12857 jtab = setNextItem(IC_JTLABELS(ic))) {
12858 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12859 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12862 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12866 /*-----------------------------------------------------------------*/
12867 /* genMixedOperation - gen code for operators between mixed types */
12868 /*-----------------------------------------------------------------*/
12870 TSD - Written for the PIC port - but this unfortunately is buggy.
12871 This routine is good in that it is able to efficiently promote
12872 types to different (larger) sizes. Unfortunately, the temporary
12873 variables that are optimized out by this routine are sometimes
12874 used in other places. So until I know how to really parse the
12875 iCode tree, I'm going to not be using this routine :(.
12877 static int genMixedOperation (iCode *ic)
12880 operand *result = IC_RESULT(ic);
12881 sym_link *ctype = operandType(IC_LEFT(ic));
12882 operand *right = IC_RIGHT(ic);
12888 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12890 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12896 nextright = IC_RIGHT(nextic);
12897 nextleft = IC_LEFT(nextic);
12898 nextresult = IC_RESULT(nextic);
12900 pic16_aopOp(right,ic,FALSE);
12901 pic16_aopOp(result,ic,FALSE);
12902 pic16_aopOp(nextright, nextic, FALSE);
12903 pic16_aopOp(nextleft, nextic, FALSE);
12904 pic16_aopOp(nextresult, nextic, FALSE);
12906 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12908 operand *t = right;
12912 pic16_emitcode(";remove right +","");
12914 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12916 operand *t = right;
12920 pic16_emitcode(";remove left +","");
12924 big = AOP_SIZE(nextleft);
12925 small = AOP_SIZE(nextright);
12927 switch(nextic->op) {
12930 pic16_emitcode(";optimize a +","");
12931 /* if unsigned or not an integral type */
12932 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12933 pic16_emitcode(";add a bit to something","");
12936 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12938 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12939 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12940 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12942 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12950 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12951 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12952 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12955 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12957 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12958 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12959 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12960 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12961 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12964 pic16_emitcode("rlf","known_zero,w");
12971 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12972 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12973 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12975 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12985 pic16_freeAsmop(right,NULL,ic,TRUE);
12986 pic16_freeAsmop(result,NULL,ic,TRUE);
12987 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12988 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12990 nextic->generated = 1;
12997 /*-----------------------------------------------------------------*/
12998 /* genCast - gen code for casting */
12999 /*-----------------------------------------------------------------*/
13000 static void genCast (iCode *ic)
13002 operand *result = IC_RESULT(ic);
13003 sym_link *ctype = operandType(IC_LEFT(ic));
13004 sym_link *rtype = operandType(IC_RIGHT(ic));
13005 sym_link *restype = operandType(IC_RESULT(ic));
13006 operand *right = IC_RIGHT(ic);
13012 /* if they are equivalent then do nothing */
13013 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13016 pic16_aopOp(right,ic,FALSE) ;
13017 pic16_aopOp(result,ic,FALSE);
13019 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13022 /* if the result is a bit */
13023 if (AOP_TYPE(result) == AOP_CRY) {
13025 /* if the right size is a literal then
13026 * we know what the value is */
13027 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13029 if (AOP_TYPE(right) == AOP_LIT) {
13030 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13031 pic16_popGet(AOP(result),0));
13033 if (((int) operandLitValue(right)))
13034 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13035 AOP(result)->aopu.aop_dir,
13036 AOP(result)->aopu.aop_dir);
13038 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13039 AOP(result)->aopu.aop_dir,
13040 AOP(result)->aopu.aop_dir);
13044 /* the right is also a bit variable */
13045 if (AOP_TYPE(right) == AOP_CRY) {
13047 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13049 pic16_emitcode("clrc","");
13050 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13051 AOP(right)->aopu.aop_dir,
13052 AOP(right)->aopu.aop_dir);
13053 pic16_aopPut(AOP(result),"c",0);
13057 /* we need to or */
13058 if (AOP_TYPE(right) == AOP_REG) {
13059 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13060 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13061 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13063 pic16_toBoolean(right);
13064 pic16_aopPut(AOP(result),"a",0);
13068 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13071 size = AOP_SIZE(result);
13073 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13075 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13076 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13077 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13080 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13085 if(IS_BITFIELD(getSpec(restype))
13086 && IS_BITFIELD(getSpec(rtype))) {
13087 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13090 /* if they are the same size : or less */
13091 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13093 /* if they are in the same place */
13094 if (pic16_sameRegs(AOP(right),AOP(result)))
13097 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13099 if (IS_PTR_CONST(rtype))
13101 if (IS_CODEPTR(rtype))
13103 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13106 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13108 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13110 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13113 if(AOP_TYPE(right) == AOP_IMMD) {
13114 pCodeOp *pcop0, *pcop1, *pcop2;
13115 symbol *sym = OP_SYMBOL( right );
13117 size = AOP_SIZE(result);
13119 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13121 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13123 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13126 pic16_emitpcode(POC_MOVLW, pcop0);
13127 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13128 pic16_emitpcode(POC_MOVLW, pcop1);
13129 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13130 pic16_emitpcode(POC_MOVLW, pcop2);
13131 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13134 pic16_emitpcode(POC_MOVLW, pcop0);
13135 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13136 pic16_emitpcode(POC_MOVLW, pcop1);
13137 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13139 pic16_emitpcode(POC_MOVLW, pcop0);
13140 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13144 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13145 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13146 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13147 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13148 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13149 if(AOP_SIZE(result) <2)
13150 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13152 /* if they in different places then copy */
13153 size = AOP_SIZE(result);
13156 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13164 /* if the result is of type pointer */
13165 if (IS_PTR(ctype)) {
13167 sym_link *type = operandType(right);
13168 sym_link *etype = getSpec(type);
13170 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13172 /* pointer to generic pointer */
13173 if (IS_GENPTR(ctype)) {
13177 p_type = DCL_TYPE(type);
13179 /* we have to go by the storage class */
13180 p_type = PTR_TYPE(SPEC_OCLS(etype));
13182 /* if (SPEC_OCLS(etype)->codesp ) */
13183 /* p_type = CPOINTER ; */
13185 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13186 /* p_type = FPOINTER ; */
13188 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13189 /* p_type = PPOINTER; */
13191 /* if (SPEC_OCLS(etype) == idata ) */
13192 /* p_type = IPOINTER ; */
13194 /* p_type = POINTER ; */
13197 /* the first two bytes are known */
13198 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13199 size = GPTRSIZE - 1;
13202 if(offset < AOP_SIZE(right)) {
13203 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13204 mov2f(AOP(result), AOP(right), offset);
13206 if ((AOP_TYPE(right) == AOP_PCODE) &&
13207 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13208 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13209 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13212 pic16_aopPut(AOP(result),
13213 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13218 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13221 /* the last byte depending on type */
13225 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13226 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13227 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13231 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13235 pic16_emitcode(";BUG!? ","%d",__LINE__);
13239 pic16_emitcode(";BUG!? ","%d",__LINE__);
13244 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13248 /* this should never happen */
13249 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13250 "got unknown pointer type");
13253 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13257 /* just copy the pointers */
13258 size = AOP_SIZE(result);
13261 pic16_aopPut(AOP(result),
13262 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13271 /* so we now know that the size of destination is greater
13272 than the size of the source.
13273 Now, if the next iCode is an operator then we might be
13274 able to optimize the operation without performing a cast.
13276 if(genMixedOperation(ic))
13279 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13281 /* we move to result for the size of source */
13282 size = AOP_SIZE(right);
13285 mov2f(AOP(result), AOP(right), offset);
13289 /* now depending on the sign of the destination */
13290 size = AOP_SIZE(result) - AOP_SIZE(right);
13291 /* if unsigned or not an integral type */
13292 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13294 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13296 /* we need to extend the sign :( */
13299 /* Save one instruction of casting char to int */
13300 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13301 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13302 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13304 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13307 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13309 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13311 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13319 pic16_freeAsmop(right,NULL,ic,TRUE);
13320 pic16_freeAsmop(result,NULL,ic,TRUE);
13324 /*-----------------------------------------------------------------*/
13325 /* genDjnz - generate decrement & jump if not zero instrucion */
13326 /*-----------------------------------------------------------------*/
13327 static int genDjnz (iCode *ic, iCode *ifx)
13329 symbol *lbl, *lbl1;
13330 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13335 /* if the if condition has a false label
13336 then we cannot save */
13340 /* if the minus is not of the form
13342 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13343 !IS_OP_LITERAL(IC_RIGHT(ic)))
13346 if (operandLitValue(IC_RIGHT(ic)) != 1)
13349 /* if the size of this greater than one then no
13351 if (getSize(operandType(IC_RESULT(ic))) > 1)
13354 /* otherwise we can save BIG */
13355 lbl = newiTempLabel(NULL);
13356 lbl1= newiTempLabel(NULL);
13358 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13360 if (IS_AOP_PREG(IC_RESULT(ic))) {
13361 pic16_emitcode("dec","%s",
13362 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13363 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13364 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13368 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13369 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13371 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13372 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13376 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13377 ifx->generated = 1;
13381 /*-----------------------------------------------------------------*/
13382 /* genReceive - generate code for a receive iCode */
13383 /*-----------------------------------------------------------------*/
13384 static void genReceive (iCode *ic)
13390 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13391 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13393 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13395 if (isOperandInFarSpace(IC_RESULT(ic))
13396 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13397 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13399 int size = getSize(operandType(IC_RESULT(ic)));
13400 int offset = pic16_fReturnSizePic - size;
13404 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13405 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13409 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13411 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13412 size = AOP_SIZE(IC_RESULT(ic));
13415 pic16_emitcode ("pop","acc");
13416 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13419 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13421 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13424 /* set pseudo stack pointer to where it should be - dw*/
13425 GpsuedoStkPtr = ic->parmBytes;
13427 /* setting GpsuedoStkPtr has side effects here: */
13428 assignResultValue(IC_RESULT(ic), 0);
13431 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13434 /*-----------------------------------------------------------------*/
13435 /* genDummyRead - generate code for dummy read of volatiles */
13436 /*-----------------------------------------------------------------*/
13438 genDummyRead (iCode * ic)
13440 pic16_emitcode ("; genDummyRead","");
13441 pic16_emitcode ("; not implemented","");
13446 /*-----------------------------------------------------------------*/
13447 /* genpic16Code - generate code for pic16 based controllers */
13448 /*-----------------------------------------------------------------*/
13450 * At this point, ralloc.c has gone through the iCode and attempted
13451 * to optimize in a way suitable for a PIC. Now we've got to generate
13452 * PIC instructions that correspond to the iCode.
13454 * Once the instructions are generated, we'll pass through both the
13455 * peep hole optimizer and the pCode optimizer.
13456 *-----------------------------------------------------------------*/
13458 void genpic16Code (iCode *lic)
13463 lineHead = lineCurr = NULL;
13465 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13466 pic16_addpBlock(pb);
13469 /* if debug information required */
13470 if (options.debug && currFunc) {
13472 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13477 for (ic = lic ; ic ; ic = ic->next ) {
13479 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13480 if ( cln != ic->lineno ) {
13481 if ( options.debug ) {
13482 debugFile->writeCLine (ic);
13485 if(!options.noCcodeInAsm) {
13486 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13487 printCLine(ic->filename, ic->lineno)));
13493 if(options.iCodeInAsm) {
13496 /* insert here code to print iCode as comment */
13497 l = Safe_strdup(printILine(ic));
13498 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13501 /* if the result is marked as
13502 * spilt and rematerializable or code for
13503 * this has already been generated then
13505 if (resultRemat(ic) || ic->generated )
13508 /* depending on the operation */
13527 /* IPOP happens only when trying to restore a
13528 * spilt live range, if there is an ifx statement
13529 * following this pop then the if statement might
13530 * be using some of the registers being popped which
13531 * would destroy the contents of the register so
13532 * we need to check for this condition and handle it */
13534 && ic->next->op == IFX
13535 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13536 genIfx (ic->next,ic);
13554 genEndFunction (ic);
13570 pic16_genPlus (ic) ;
13574 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13575 pic16_genMinus (ic);
13591 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13595 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13601 /* note these two are xlated by algebraic equivalence
13602 * during parsing SDCC.y */
13603 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13604 "got '>=' or '<=' shouldn't have come here");
13608 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13620 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13624 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13628 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13652 genRightShift (ic);
13655 case GET_VALUE_AT_ADDRESS:
13660 if (POINTER_SET(ic))
13687 addSet(&_G.sendSet,ic);
13690 case DUMMY_READ_VOLATILE:
13700 /* now we are ready to call the
13701 peep hole optimizer */
13702 if (!options.nopeep)
13703 peepHole (&lineHead);
13705 /* now do the actual printing */
13706 printLine (lineHead, codeOutFile);
13709 DFPRINTF((stderr,"printing pBlock\n\n"));
13710 pic16_printpBlock(stdout,pb);