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_pc_plusw2), 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_pc_plusw2)));
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_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_pc_preinc1), 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_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_pc_postdec1));
2345 pic16_emitpcode(POC_MOVFF,
2346 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2349 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2350 if(pic16_options.gstack)
2351 pic16_testStackOverflow();
2354 /*-----------------------------------------------------------------*/
2355 /* popaop - pops aop from stack */
2356 /*-----------------------------------------------------------------*/
2357 void popaop(asmop *aop, int offset)
2359 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2360 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2361 if(pic16_options.gstack)
2362 pic16_testStackOverflow();
2365 void popaopidx(asmop *aop, int offset, int index)
2369 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2371 if(STACK_MODEL_LARGE)ofs++;
2373 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2374 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2375 if(pic16_options.gstack)
2376 pic16_testStackOverflow();
2379 #if !(USE_GENERIC_SIGNED_SHIFT)
2380 /*-----------------------------------------------------------------*/
2381 /* reAdjustPreg - points a register back to where it should */
2382 /*-----------------------------------------------------------------*/
2383 static void reAdjustPreg (asmop *aop)
2387 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2389 if ((size = aop->size) <= 1)
2392 switch (aop->type) {
2396 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2400 if (aop->type == AOP_DPTR2)
2406 pic16_emitcode("lcall","__decdptr");
2409 if (aop->type == AOP_DPTR2)
2421 /*-----------------------------------------------------------------*/
2422 /* opIsGptr: returns non-zero if the passed operand is */
2423 /* a generic pointer type. */
2424 /*-----------------------------------------------------------------*/
2425 static int opIsGptr(operand *op)
2427 sym_link *type = operandType(op);
2429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2430 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2438 /*-----------------------------------------------------------------*/
2439 /* pic16_getDataSize - get the operand data size */
2440 /*-----------------------------------------------------------------*/
2441 int pic16_getDataSize(operand *op)
2443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2446 return AOP_SIZE(op);
2448 // tsd- in the pic port, the genptr size is 1, so this code here
2449 // fails. ( in the 8051 port, the size was 4).
2452 size = AOP_SIZE(op);
2453 if (size == GPTRSIZE)
2455 sym_link *type = operandType(op);
2456 if (IS_GENPTR(type))
2458 /* generic pointer; arithmetic operations
2459 * should ignore the high byte (pointer type).
2462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2469 /*-----------------------------------------------------------------*/
2470 /* pic16_outAcc - output Acc */
2471 /*-----------------------------------------------------------------*/
2472 void pic16_outAcc(operand *result)
2475 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2476 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2479 size = pic16_getDataSize(result);
2481 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2484 /* unsigned or positive */
2486 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2491 /*-----------------------------------------------------------------*/
2492 /* pic16_outBitC - output a bit C */
2493 /* Move to result the value of Carry flag -- VR */
2494 /*-----------------------------------------------------------------*/
2495 void pic16_outBitC(operand *result)
2499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2501 /* if the result is bit */
2502 if (AOP_TYPE(result) == AOP_CRY) {
2503 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2504 pic16_aopPut(AOP(result),"c",0);
2507 i = AOP_SIZE(result);
2509 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2511 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2515 /*-----------------------------------------------------------------*/
2516 /* pic16_outBitOp - output a bit from Op */
2517 /* Move to result the value of set/clr op -- VR */
2518 /*-----------------------------------------------------------------*/
2519 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2523 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2525 /* if the result is bit */
2526 if (AOP_TYPE(result) == AOP_CRY) {
2527 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2528 pic16_aopPut(AOP(result),"c",0);
2531 i = AOP_SIZE(result);
2533 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2535 pic16_emitpcode(POC_RRCF, pcop);
2536 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2540 /*-----------------------------------------------------------------*/
2541 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2542 /*-----------------------------------------------------------------*/
2543 void pic16_toBoolean(operand *oper)
2545 int size = AOP_SIZE(oper) - 1;
2548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2550 if ( AOP_TYPE(oper) != AOP_ACC) {
2551 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2554 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2559 #if !defined(GEN_Not)
2560 /*-----------------------------------------------------------------*/
2561 /* genNot - generate code for ! operation */
2562 /*-----------------------------------------------------------------*/
2563 static void pic16_genNot (iCode *ic)
2569 /* assign asmOps to operand & result */
2570 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2571 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2573 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2574 /* if in bit space then a special case */
2575 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2576 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2577 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2578 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2580 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2581 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2582 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2587 size = AOP_SIZE(IC_LEFT(ic));
2589 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2590 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2591 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2594 pic16_toBoolean(IC_LEFT(ic));
2596 tlbl = newiTempLabel(NULL);
2597 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2598 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2599 pic16_outBitC(IC_RESULT(ic));
2602 /* release the aops */
2603 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2604 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2609 #if !defined(GEN_Cpl)
2610 /*-----------------------------------------------------------------*/
2611 /* genCpl - generate code for complement */
2612 /*-----------------------------------------------------------------*/
2613 static void pic16_genCpl (iCode *ic)
2619 /* assign asmOps to operand & result */
2620 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2621 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2623 /* if both are in bit space then
2625 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2626 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2628 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2629 pic16_emitcode("cpl","c");
2630 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2634 size = AOP_SIZE(IC_RESULT(ic));
2637 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2639 pic16_emitcode("cpl","a");
2640 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2642 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2643 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2645 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2646 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2654 /* release the aops */
2655 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2656 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2660 /*-----------------------------------------------------------------*/
2661 /* genUminusFloat - unary minus for floating points */
2662 /*-----------------------------------------------------------------*/
2663 static void genUminusFloat(operand *op,operand *result)
2665 int size ,offset =0 ;
2668 /* for this we just need to flip the
2669 first it then copy the rest in place */
2670 size = AOP_SIZE(op);
2673 mov2f(AOP(result), AOP(op), offset);
2677 /* toggle the MSB's highest bit */
2678 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2681 /*-----------------------------------------------------------------*/
2682 /* genUminus - unary minus code generation */
2683 /*-----------------------------------------------------------------*/
2684 static void genUminus (iCode *ic)
2687 sym_link *optype, *rtype;
2692 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2693 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2695 /* if both in bit space then special case */
2696 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2697 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2699 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2700 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2701 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2705 optype = operandType(IC_LEFT(ic));
2706 rtype = operandType(IC_RESULT(ic));
2708 /* if float then do float stuff */
2709 if (IS_FLOAT(optype)) {
2710 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2714 /* otherwise subtract from zero by taking the 2's complement */
2715 size = AOP_SIZE(IC_LEFT(ic));
2717 for(i=0; i<size; i++) {
2718 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2719 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2721 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2722 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2726 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2727 for(i=1; i<size; i++) {
2729 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2733 /* release the aops */
2734 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2735 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2739 /*-----------------------------------------------------------------*/
2740 /* saveRegisters - will look for a call and save the registers */
2741 /*-----------------------------------------------------------------*/
2742 static void saveRegisters(iCode *lic)
2749 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2751 for (ic = lic ; ic ; ic = ic->next)
2752 if (ic->op == CALL || ic->op == PCALL)
2756 fprintf(stderr,"found parameter push with no function call\n");
2760 /* if the registers have been saved already then
2762 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2765 /* find the registers in use at this time
2766 and push them away to safety */
2767 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2771 if (options.useXstack) {
2772 if (bitVectBitValue(rsave,R0_IDX))
2773 pic16_emitcode("mov","b,r0");
2774 pic16_emitcode("mov","r0,%s",spname);
2775 for (i = 0 ; i < pic16_nRegs ; i++) {
2776 if (bitVectBitValue(rsave,i)) {
2778 pic16_emitcode("mov","a,b");
2780 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2781 pic16_emitcode("movx","@r0,a");
2782 pic16_emitcode("inc","r0");
2785 pic16_emitcode("mov","%s,r0",spname);
2786 if (bitVectBitValue(rsave,R0_IDX))
2787 pic16_emitcode("mov","r0,b");
2789 //for (i = 0 ; i < pic16_nRegs ; i++) {
2790 // if (bitVectBitValue(rsave,i))
2791 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2794 dtype = operandType(IC_LEFT(ic));
2795 if (currFunc && dtype &&
2796 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2797 IFFUNC_ISISR(currFunc->type) &&
2800 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2803 /*-----------------------------------------------------------------*/
2804 /* unsaveRegisters - pop the pushed registers */
2805 /*-----------------------------------------------------------------*/
2806 static void unsaveRegisters (iCode *ic)
2811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2812 /* find the registers in use at this time
2813 and push them away to safety */
2814 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2817 if (options.useXstack) {
2818 pic16_emitcode("mov","r0,%s",spname);
2819 for (i = pic16_nRegs ; i >= 0 ; i--) {
2820 if (bitVectBitValue(rsave,i)) {
2821 pic16_emitcode("dec","r0");
2822 pic16_emitcode("movx","a,@r0");
2824 pic16_emitcode("mov","b,a");
2826 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2830 pic16_emitcode("mov","%s,r0",spname);
2831 if (bitVectBitValue(rsave,R0_IDX))
2832 pic16_emitcode("mov","r0,b");
2834 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2835 // if (bitVectBitValue(rsave,i))
2836 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2843 /*-----------------------------------------------------------------*/
2845 /*-----------------------------------------------------------------*/
2846 static void pushSide(operand * oper, int size)
2849 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2851 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2852 if (AOP_TYPE(oper) != AOP_REG &&
2853 AOP_TYPE(oper) != AOP_DIR &&
2855 pic16_emitcode("mov","a,%s",l);
2856 pic16_emitcode("push","acc");
2858 pic16_emitcode("push","%s",l);
2863 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2865 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2866 pic16_emitpcode(POC_MOVFW, src);
2867 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2869 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2870 src, pic16_popGet(AOP(op), offset)));
2875 /*-----------------------------------------------------------------*/
2876 /* assignResultValue - assign results to oper, rescall==1 is */
2877 /* called from genCall() or genPcall() */
2878 /*-----------------------------------------------------------------*/
2879 static void assignResultValue(operand * oper, int rescall)
2881 int size = AOP_SIZE(oper);
2885 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2886 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2889 /* assign result from a call/pcall function() */
2891 /* function results are stored in a special order,
2892 * see top of file with Function return policy, or manual */
2895 /* 8-bits, result in WREG */
2896 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2899 /* 16-bits, result in PRODL:WREG */
2900 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2904 /* 24-bits, result in PRODH:PRODL:WREG */
2905 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2909 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2910 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2914 /* >32-bits, result on stack, and FSR0 points to beginning.
2915 * Fix stack when done */
2917 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2919 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2920 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2922 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2927 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2928 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2929 if(STACK_MODEL_LARGE) {
2931 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2935 int areg = 0; /* matching argument register */
2937 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2938 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2941 /* its called from genReceive (probably) -- VR */
2942 /* I hope this code will not be called from somewhere else in the future!
2943 * We manually set the pseudo stack pointer in genReceive. - dw
2945 if(!GpsuedoStkPtr && _G.useWreg) {
2946 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2948 /* The last byte in the assignment is in W */
2949 if(areg <= GpsuedoStkPtr) {
2951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2953 // debugf("receive from WREG\n", 0);
2955 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2958 _G.stack_lat = AOP_SIZE(oper)-1;
2963 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2964 // debugf("receive from STACK\n", 0);
2971 /*-----------------------------------------------------------------*/
2972 /* genIpush - generate code for pushing this gets a little complex */
2973 /*-----------------------------------------------------------------*/
2974 static void genIpush (iCode *ic)
2976 // int size, offset=0;
2979 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2982 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2984 /* send to stack as normal */
2985 addSet(&_G.sendSet,ic);
2986 // addSetHead(&_G.sendSet,ic);
2987 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2992 int size, offset = 0 ;
2996 /* if this is not a parm push : ie. it is spill push
2997 and spill push is always done on the local stack */
2998 if (!ic->parmPush) {
3000 /* and the item is spilt then do nothing */
3001 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3004 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3005 size = AOP_SIZE(IC_LEFT(ic));
3006 /* push it on the stack */
3008 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3013 pic16_emitcode("push","%s",l);
3018 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3022 /*-----------------------------------------------------------------*/
3023 /* genIpop - recover the registers: can happen only for spilling */
3024 /*-----------------------------------------------------------------*/
3025 static void genIpop (iCode *ic)
3028 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3033 /* if the temp was not pushed then */
3034 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3037 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3038 size = AOP_SIZE(IC_LEFT(ic));
3041 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3044 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3049 /*-----------------------------------------------------------------*/
3050 /* unsaverbank - restores the resgister bank from stack */
3051 /*-----------------------------------------------------------------*/
3052 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3054 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3062 if (options.useXstack) {
3064 r = getFreePtr(ic,&aop,FALSE);
3067 pic16_emitcode("mov","%s,_spx",r->name);
3068 pic16_emitcode("movx","a,@%s",r->name);
3069 pic16_emitcode("mov","psw,a");
3070 pic16_emitcode("dec","%s",r->name);
3073 pic16_emitcode ("pop","psw");
3076 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3077 if (options.useXstack) {
3078 pic16_emitcode("movx","a,@%s",r->name);
3079 //pic16_emitcode("mov","(%s+%d),a",
3080 // regspic16[i].base,8*bank+regspic16[i].offset);
3081 pic16_emitcode("dec","%s",r->name);
3084 pic16_emitcode("pop",""); //"(%s+%d)",
3085 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3088 if (options.useXstack) {
3090 pic16_emitcode("mov","_spx,%s",r->name);
3091 pic16_freeAsmop(NULL,aop,ic,TRUE);
3097 /*-----------------------------------------------------------------*/
3098 /* saverbank - saves an entire register bank on the stack */
3099 /*-----------------------------------------------------------------*/
3100 static void saverbank (int bank, iCode *ic, bool pushPsw)
3102 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3109 if (options.useXstack) {
3112 r = getFreePtr(ic,&aop,FALSE);
3113 pic16_emitcode("mov","%s,_spx",r->name);
3117 for (i = 0 ; i < pic16_nRegs ;i++) {
3118 if (options.useXstack) {
3119 pic16_emitcode("inc","%s",r->name);
3120 //pic16_emitcode("mov","a,(%s+%d)",
3121 // regspic16[i].base,8*bank+regspic16[i].offset);
3122 pic16_emitcode("movx","@%s,a",r->name);
3124 pic16_emitcode("push","");// "(%s+%d)",
3125 //regspic16[i].base,8*bank+regspic16[i].offset);
3129 if (options.useXstack) {
3130 pic16_emitcode("mov","a,psw");
3131 pic16_emitcode("movx","@%s,a",r->name);
3132 pic16_emitcode("inc","%s",r->name);
3133 pic16_emitcode("mov","_spx,%s",r->name);
3134 pic16_freeAsmop (NULL,aop,ic,TRUE);
3137 pic16_emitcode("push","psw");
3139 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3147 static int wparamCmp(void *p1, void *p2)
3149 return (!strcmp((char *)p1, (char *)p2));
3152 int inWparamList(char *s)
3154 return isinSetWith(wparamList, s, wparamCmp);
3158 /*-----------------------------------------------------------------*/
3159 /* genCall - generates a call statement */
3160 /*-----------------------------------------------------------------*/
3161 static void genCall (iCode *ic)
3171 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3172 /* if caller saves & we have not saved then */
3173 // if (!ic->regsSaved)
3174 // saveRegisters(ic);
3176 /* initialise stackParms for IPUSH pushes */
3177 // stackParms = psuedoStkPtr;
3178 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3179 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3180 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3183 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3186 /* if send set is not empty the assign */
3189 int psuedoStkPtr=-1;
3190 int firstTimeThruLoop = 1;
3193 /* reverse sendSet if function is not reentrant */
3194 if(!IFFUNC_ISREENT(ftype))
3195 _G.sendSet = reverseSet(_G.sendSet);
3197 /* First figure how many parameters are getting passed */
3201 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3205 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3206 size = AOP_SIZE(IC_LEFT(sic));
3210 /* pass the last byte through WREG */
3214 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3215 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3216 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3218 if(!firstTimeThruLoop) {
3219 /* If this is not the first time we've been through the loop
3220 * then we need to save the parameter in a temporary
3221 * register. The last byte of the last parameter is
3225 // --psuedoStkPtr; // sanity check
3229 firstTimeThruLoop=0;
3231 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3236 /* all arguments are passed via stack */
3240 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3241 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3242 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3244 // pushaop(AOP(IC_LEFT(sic)), size);
3245 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3250 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3254 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3255 pushw(); /* save last parameter to stack if functions has varargs */
3259 } else use_wreg = 0;
3261 _G.stackRegSet = _G.sendSet;
3266 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3270 /* if we need to assign a result value */
3271 if ((IS_ITEMP(IC_RESULT(ic))
3272 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3273 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3274 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3277 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3280 assignResultValue(IC_RESULT(ic), 1);
3282 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3283 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3285 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3288 if(!stackParms && ic->parmBytes) {
3289 stackParms = ic->parmBytes;
3292 stackParms -= use_wreg;
3295 if(stackParms == 1) {
3296 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3298 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3299 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3301 if(STACK_MODEL_LARGE) {
3303 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3308 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3311 /* adjust the stack for parameters if required */
3312 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3315 /* if register bank was saved then pop them */
3317 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3319 /* if we hade saved some registers then unsave them */
3320 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3321 unsaveRegisters (ic);
3327 /*-----------------------------------------------------------------*/
3328 /* genPcall - generates a call by pointer statement */
3329 /* new version, created from genCall - HJD */
3330 /*-----------------------------------------------------------------*/
3331 static void genPcall (iCode *ic)
3333 sym_link *ftype, *fntype;
3335 symbol *retlbl = newiTempLabel(NULL);
3336 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3340 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3341 fntype = operandType( IC_LEFT(ic) )->next;
3343 /* if send set is not empty the assign */
3346 int psuedoStkPtr=-1;
3348 /* reverse sendSet if function is not reentrant */
3349 if(!IFFUNC_ISREENT(fntype))
3350 _G.sendSet = reverseSet(_G.sendSet);
3354 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3357 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3358 size = AOP_SIZE(IC_LEFT(sic));
3361 /* all parameters are passed via stack, since WREG is clobbered
3362 * by the calling sequence */
3364 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3365 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3366 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3368 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3372 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3375 _G.stackRegSet = _G.sendSet;
3379 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3381 // push return address
3382 // push $ on return stack, then replace with retlbl
3384 pic16_emitpcodeNULLop(POC_PUSH);
3386 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3387 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3388 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3389 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3390 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3391 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3393 /* make the call by writing the pointer into pc */
3394 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3397 // note: MOVFF to PCL not allowed
3398 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3399 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3402 /* return address is here: (X) */
3403 pic16_emitpLabelFORCE(retlbl->key);
3405 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3408 /* if we need assign a result value */
3409 if ((IS_ITEMP(IC_RESULT(ic))
3410 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3411 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3412 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3415 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3418 assignResultValue(IC_RESULT(ic), 1);
3420 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3421 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3423 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3426 // stackParms -= use_wreg;
3429 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3430 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3431 if(STACK_MODEL_LARGE) {
3432 /* this implies that stackParms < 256 !!! -- VR */
3434 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3439 /*-----------------------------------------------------------------*/
3440 /* resultRemat - result is rematerializable */
3441 /*-----------------------------------------------------------------*/
3442 static int resultRemat (iCode *ic)
3444 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3445 if (SKIP_IC(ic) || ic->op == IFX)
3448 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3449 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3450 if (sym->remat && !POINTER_SET(ic))
3457 #if defined(__BORLANDC__) || defined(_MSC_VER)
3458 #define STRCASECMP stricmp
3460 #define STRCASECMP strcasecmp
3464 /*-----------------------------------------------------------------*/
3465 /* inExcludeList - return 1 if the string is in exclude Reg list */
3466 /*-----------------------------------------------------------------*/
3467 static bool inExcludeList(char *s)
3469 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3473 if (options.excludeRegs[i] &&
3474 STRCASECMP(options.excludeRegs[i],"none") == 0)
3477 for ( i = 0 ; options.excludeRegs[i]; i++) {
3478 if (options.excludeRegs[i] &&
3479 STRCASECMP(s,options.excludeRegs[i]) == 0)
3486 /*-----------------------------------------------------------------*/
3487 /* genFunction - generated code for function entry */
3488 /*-----------------------------------------------------------------*/
3489 static void genFunction (iCode *ic)
3495 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3497 pic16_labelOffset += (max_key+4);
3502 ftype = operandType(IC_LEFT(ic));
3503 sym = OP_SYMBOL(IC_LEFT(ic));
3505 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3506 /* create an absolute section at the interrupt vector:
3507 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3515 sym = OP_SYMBOL( IC_LEFT(ic));
3517 if(interrupts[i]->name
3518 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3525 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3526 __FILE__, __LINE__, sym->name);
3529 _G.interruptvector = found;
3532 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3533 asym = newSymbol(asymname, 0);
3535 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3536 pic16_addpBlock( apb );
3538 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3539 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3540 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3542 /* mark the end of this tiny function */
3543 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3548 abSym = Safe_calloc(1, sizeof(absSym));
3549 strcpy(abSym->name, asymname);
3551 switch( _G.interruptvector ) {
3552 case 0: abSym->address = 0x000000; break;
3553 case 1: abSym->address = 0x000008; break;
3554 case 2: abSym->address = 0x000018; break;
3557 /* relocate interrupt vectors if needed */
3558 abSym->address += pic16_options.ivt_loc;
3560 addSet(&absSymSet, abSym);
3564 /* create the function header */
3565 pic16_emitcode(";","-----------------------------------------");
3566 pic16_emitcode(";"," function %s",sym->name);
3567 pic16_emitcode(";","-----------------------------------------");
3569 pic16_emitcode("","%s:",sym->rname);
3570 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3576 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3577 if(!strcmp(ab->name, sym->rname)) {
3578 pic16_pBlockConvert2Absolute(pb);
3585 if(IFFUNC_ISNAKED(ftype)) {
3586 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3590 /* if critical function then turn interrupts off */
3591 if (IFFUNC_ISCRITICAL(ftype)) {
3592 //pic16_emitcode("clr","ea");
3595 _G.fregsUsed = sym->regsUsed;
3597 /* if this is an interrupt service routine then
3598 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3599 if (IFFUNC_ISISR(sym->type)) {
3600 _G.usefastretfie = 1; /* use shadow registers by default */
3602 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3603 if(!(_G.interruptvector == 1)) {
3604 /* do not save WREG,STATUS,BSR for high priority interrupts
3605 * because they are stored in the hardware shadow registers already */
3606 _G.usefastretfie = 0;
3607 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3608 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3609 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3612 /* these should really be optimized somehow, because not all
3613 * interrupt handlers modify them */
3614 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3615 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3616 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3617 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3619 // pic16_pBlockConvert2ISR(pb);
3623 /* emit code to setup stack frame if user enabled,
3624 * and function is not main() */
3626 //fprintf(stderr, "function name: %s\n", sym->name);
3627 if(strcmp(sym->name, "main")) {
3628 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3629 /* setup the stack frame */
3630 if(STACK_MODEL_LARGE)
3631 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3632 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3633 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3634 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3635 if(STACK_MODEL_LARGE)
3636 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3640 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3643 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3645 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3646 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3648 pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3651 if(inWparamList(sym->name)) {
3652 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3659 /* if callee-save to be used for this function
3660 * then save the registers being used in this function */
3661 // if (IFFUNC_CALLEESAVES(sym->type))
3665 /* if any registers used */
3666 if (sym->regsUsed) {
3667 /* save the registers used */
3668 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3669 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3670 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3671 if (bitVectBitValue(sym->regsUsed,i)) {
3672 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3675 if(!pic16_regWithIdx(i)->wasUsed) {
3676 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3677 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3678 pic16_regWithIdx(i)->wasUsed = 1;
3682 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3686 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3687 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3690 /*-----------------------------------------------------------------*/
3691 /* genEndFunction - generates epilogue for functions */
3692 /*-----------------------------------------------------------------*/
3693 static void genEndFunction (iCode *ic)
3695 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3699 if(IFFUNC_ISNAKED(sym->type)) {
3700 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3706 /* add code for ISCRITICAL */
3707 if(IFFUNC_ISCRITICAL(sym->type)) {
3708 /* if critical function, turn on interrupts */
3710 /* TODO: add code here -- VR */
3713 // sym->regsUsed = _G.fregsUsed;
3715 /* now we need to restore the registers */
3716 /* if any registers used */
3717 if (sym->regsUsed) {
3720 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3721 /* restore registers used */
3722 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3723 for ( i = sym->regsUsed->size; i >= 0; i--) {
3724 if (bitVectBitValue(sym->regsUsed,i)) {
3725 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3729 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3733 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3735 if (sym->stack == 1) {
3736 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
3737 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3739 // we have to add more than one...
3740 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
3741 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3742 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3744 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3745 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3746 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
3750 if(strcmp(sym->name, "main")) {
3751 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3752 /* restore stack frame */
3753 if(STACK_MODEL_LARGE)
3754 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3755 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3756 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3757 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3763 if (IFFUNC_ISISR(sym->type)) {
3764 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3765 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3766 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3767 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3769 if(!(_G.interruptvector == 1)) {
3770 /* do not restore interrupt vector for WREG,STATUS,BSR
3771 * for high priority interrupt, see genFunction */
3772 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3773 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3774 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3776 _G.interruptvector = 0; /* sanity check */
3779 /* if debug then send end of function */
3780 /* if (options.debug && currFunc) */
3782 debugFile->writeEndFunction (currFunc, ic, 1);
3785 if(_G.usefastretfie)
3786 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3788 pic16_emitpcodeNULLop(POC_RETFIE);
3790 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3792 _G.usefastretfie = 0;
3796 if (IFFUNC_ISCRITICAL(sym->type)) {
3797 pic16_emitcode("setb","ea");
3800 /* if debug then send end of function */
3802 debugFile->writeEndFunction (currFunc, ic, 1);
3805 /* insert code to restore stack frame, if user enabled it
3806 * and function is not main() */
3809 pic16_emitpcodeNULLop(POC_RETURN);
3811 /* Mark the end of a function */
3812 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3816 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3819 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3821 pic16_emitpcode(POC_CLRF, dest);
3823 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3824 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3827 if(dest->type == PO_WREG && (offset == 0)) {
3828 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3831 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3835 /*-----------------------------------------------------------------*/
3836 /* genRet - generate code for return statement */
3837 /*-----------------------------------------------------------------*/
3838 static void genRet (iCode *ic)
3844 /* if we have no return value then
3845 * just generate the "ret" */
3850 /* we have something to return then
3851 * move the return value into place */
3852 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3853 size = AOP_SIZE(IC_LEFT(ic));
3857 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3858 // pic16_emitpcode(POC_MOVFF,
3859 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3862 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3863 // pic16_emitpcode(POC_MOVFF,
3864 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3867 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3868 // pic16_emitpcode(POC_MOVFF,
3869 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3872 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3874 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3875 // pic16_emitpcode(POC_MOVFF,
3876 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3879 /* >32-bits, setup stack and FSR0 */
3881 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3882 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3884 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3886 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3891 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3892 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3894 if(STACK_MODEL_LARGE) {
3895 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3896 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3898 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3903 /* old code, left here for reference -- VR */
3907 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3909 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3910 pic16_emitpcomment("push %s",l);
3913 DEBUGpic16_emitcode(";", "%d", __LINE__);
3914 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3915 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3917 if (strcmp(fReturn[offset],l)) {
3918 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3919 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3920 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3922 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3926 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3936 if (strcmp(fReturn[pushed],"a"))
3937 pic16_emitcode("pop",fReturn[pushed]);
3939 pic16_emitcode("pop","acc");
3945 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3948 /* generate a jump to the return label
3949 * if the next is not the return statement */
3950 if (!(ic->next && ic->next->op == LABEL
3951 && IC_LABEL(ic->next) == returnLabel)) {
3953 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3954 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3958 /*-----------------------------------------------------------------*/
3959 /* genLabel - generates a label */
3960 /*-----------------------------------------------------------------*/
3961 static void genLabel (iCode *ic)
3965 /* special case never generate */
3966 if (IC_LABEL(ic) == entryLabel)
3969 pic16_emitpLabel(IC_LABEL(ic)->key);
3970 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3973 /*-----------------------------------------------------------------*/
3974 /* genGoto - generates a goto */
3975 /*-----------------------------------------------------------------*/
3977 static void genGoto (iCode *ic)
3980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3981 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3985 /*-----------------------------------------------------------------*/
3986 /* genMultbits :- multiplication of bits */
3987 /*-----------------------------------------------------------------*/
3988 static void genMultbits (operand *left,
3994 if(!pic16_sameRegs(AOP(result),AOP(right)))
3995 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3997 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3998 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3999 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4004 /*-----------------------------------------------------------------*/
4005 /* genMultOneByte : 8 bit multiplication & division */
4006 /*-----------------------------------------------------------------*/
4007 static void genMultOneByte (operand *left,
4013 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4014 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4016 /* (if two literals, the value is computed before) */
4017 /* if one literal, literal on the right */
4018 if (AOP_TYPE(left) == AOP_LIT){
4024 /* size is already checked in genMult == 1 */
4025 // size = AOP_SIZE(result);
4027 if (AOP_TYPE(right) == AOP_LIT){
4028 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4029 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4030 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4031 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4033 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4034 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4035 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4036 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4039 pic16_genMult8X8_8 (left, right,result);
4042 /*-----------------------------------------------------------------*/
4043 /* genMultOneWord : 16 bit multiplication */
4044 /*-----------------------------------------------------------------*/
4045 static void genMultOneWord (operand *left,
4050 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4051 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4053 /* (if two literals, the value is computed before)
4054 * if one literal, literal on the right */
4055 if (AOP_TYPE(left) == AOP_LIT){
4061 /* size is checked already == 2 */
4062 // size = AOP_SIZE(result);
4064 if (AOP_TYPE(right) == AOP_LIT) {
4065 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4066 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4067 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4068 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4070 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4071 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4072 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4073 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4076 pic16_genMult16X16_16(left, right,result);
4079 /*-----------------------------------------------------------------*/
4080 /* genMultOneLong : 32 bit multiplication */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultOneLong (operand *left,
4087 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4088 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4090 /* (if two literals, the value is computed before)
4091 * if one literal, literal on the right */
4092 if (AOP_TYPE(left) == AOP_LIT){
4098 /* size is checked already == 4 */
4099 // size = AOP_SIZE(result);
4101 if (AOP_TYPE(right) == AOP_LIT) {
4102 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4103 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4104 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4105 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4107 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4108 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4109 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4110 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4113 pic16_genMult32X32_32(left, right,result);
4118 /*-----------------------------------------------------------------*/
4119 /* genMult - generates code for multiplication */
4120 /*-----------------------------------------------------------------*/
4121 static void genMult (iCode *ic)
4123 operand *left = IC_LEFT(ic);
4124 operand *right = IC_RIGHT(ic);
4125 operand *result= IC_RESULT(ic);
4128 /* assign the amsops */
4129 pic16_aopOp (left,ic,FALSE);
4130 pic16_aopOp (right,ic,FALSE);
4131 pic16_aopOp (result,ic,TRUE);
4133 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4135 /* special cases first *
4137 if (AOP_TYPE(left) == AOP_CRY
4138 && AOP_TYPE(right)== AOP_CRY) {
4139 genMultbits(left,right,result);
4143 /* if both are of size == 1 */
4144 if(AOP_SIZE(left) == 1
4145 && AOP_SIZE(right) == 1) {
4146 genMultOneByte(left,right,result);
4150 /* if both are of size == 2 */
4151 if(AOP_SIZE(left) == 2
4152 && AOP_SIZE(right) == 2) {
4153 genMultOneWord(left, right, result);
4157 /* if both are of size == 4 */
4158 if(AOP_SIZE(left) == 4
4159 && AOP_SIZE(right) == 4) {
4160 genMultOneLong(left, right, result);
4164 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4167 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4168 /* should have been converted to function call */
4172 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4174 pic16_freeAsmop(result,NULL,ic,TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* genDivbits :- division of bits */
4179 /*-----------------------------------------------------------------*/
4180 static void genDivbits (operand *left,
4187 /* the result must be bit */
4188 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4189 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4193 pic16_emitcode("div","ab");
4194 pic16_emitcode("rrc","a");
4195 pic16_aopPut(AOP(result),"c",0);
4198 /*-----------------------------------------------------------------*/
4199 /* genDivOneByte : 8 bit division */
4200 /*-----------------------------------------------------------------*/
4201 static void genDivOneByte (operand *left,
4205 sym_link *opetype = operandType(result);
4210 /* result = divident / divisor
4211 * - divident may be a register or a literal,
4212 * - divisor may be a register or a literal,
4213 * so there are 3 cases (literal / literal is optimized
4214 * by the front-end) to handle.
4215 * In addition we must handle signed and unsigned, which
4216 * result in 6 final different cases -- VR */
4220 size = AOP_SIZE(result) - 1;
4222 /* signed or unsigned */
4223 if (SPEC_USIGN(opetype)) {
4224 pCodeOp *pct1, /* count */
4227 symbol *label1, *label2, *label3;;
4230 /* unsigned is easy */
4232 pct1 = pic16_popGetTempReg(1);
4233 pct2 = pic16_popGetTempReg(1);
4234 pct3 = pic16_popGetTempReg(1);
4236 label1 = newiTempLabel(NULL);
4237 label2 = newiTempLabel(NULL);
4238 label3 = newiTempLabel(NULL);
4240 /* the following algorithm is extracted from divuint.c */
4242 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4243 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4245 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4247 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4249 pic16_emitpLabel(label1->key);
4252 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4256 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4260 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4262 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4263 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4265 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4266 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4267 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4269 pic16_emitpLabel( label3->key );
4270 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4271 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4275 pic16_emitpLabel(label2->key);
4276 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4277 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4278 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4280 /* result is in wreg */
4281 if(AOP_TYPE(result) != AOP_ACC)
4282 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4284 pic16_popReleaseTempReg( pct3, 1);
4285 pic16_popReleaseTempReg( pct2, 1);
4286 pic16_popReleaseTempReg( pct1, 1);
4291 /* signed is a little bit more difficult */
4293 /* save the signs of the operands */
4294 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4296 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4297 pic16_emitcode("push","acc"); /* save it on the stack */
4299 /* now sign adjust for both left & right */
4300 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4302 lbl = newiTempLabel(NULL);
4303 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4304 pic16_emitcode("cpl","a");
4305 pic16_emitcode("inc","a");
4306 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4307 pic16_emitcode("mov","b,a");
4309 /* sign adjust left side */
4310 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4313 lbl = newiTempLabel(NULL);
4314 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4315 pic16_emitcode("cpl","a");
4316 pic16_emitcode("inc","a");
4317 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4319 /* now the division */
4320 pic16_emitcode("div","ab");
4321 /* we are interested in the lower order
4323 pic16_emitcode("mov","b,a");
4324 lbl = newiTempLabel(NULL);
4325 pic16_emitcode("pop","acc");
4326 /* if there was an over flow we don't
4327 adjust the sign of the result */
4328 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4329 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4331 pic16_emitcode("clr","a");
4332 pic16_emitcode("subb","a,b");
4333 pic16_emitcode("mov","b,a");
4334 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4336 /* now we are done */
4337 pic16_aopPut(AOP(result),"b",0);
4339 pic16_emitcode("mov","c,b.7");
4340 pic16_emitcode("subb","a,acc");
4343 pic16_aopPut(AOP(result),"a",offset++);
4347 /*-----------------------------------------------------------------*/
4348 /* genDiv - generates code for division */
4349 /*-----------------------------------------------------------------*/
4350 static void genDiv (iCode *ic)
4352 operand *left = IC_LEFT(ic);
4353 operand *right = IC_RIGHT(ic);
4354 operand *result= IC_RESULT(ic);
4357 /* Division is a very lengthy algorithm, so it is better
4358 * to call support routines than inlining algorithm.
4359 * Division functions written here just in case someone
4360 * wants to inline and not use the support libraries -- VR */
4364 /* assign the amsops */
4365 pic16_aopOp (left,ic,FALSE);
4366 pic16_aopOp (right,ic,FALSE);
4367 pic16_aopOp (result,ic,TRUE);
4369 /* special cases first */
4371 if (AOP_TYPE(left) == AOP_CRY &&
4372 AOP_TYPE(right)== AOP_CRY) {
4373 genDivbits(left,right,result);
4377 /* if both are of size == 1 */
4378 if (AOP_SIZE(left) == 1 &&
4379 AOP_SIZE(right) == 1 ) {
4380 genDivOneByte(left,right,result);
4384 /* should have been converted to function call */
4387 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4388 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4389 pic16_freeAsmop(result,NULL,ic,TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genModbits :- modulus of bits */
4394 /*-----------------------------------------------------------------*/
4395 static void genModbits (operand *left,
4403 werror(W_POSSBUG2, __FILE__, __LINE__);
4404 /* the result must be bit */
4405 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4406 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4410 pic16_emitcode("div","ab");
4411 pic16_emitcode("mov","a,b");
4412 pic16_emitcode("rrc","a");
4413 pic16_aopPut(AOP(result),"c",0);
4416 /*-----------------------------------------------------------------*/
4417 /* genModOneByte : 8 bit modulus */
4418 /*-----------------------------------------------------------------*/
4419 static void genModOneByte (operand *left,
4423 sym_link *opetype = operandType(result);
4428 werror(W_POSSBUG2, __FILE__, __LINE__);
4430 /* signed or unsigned */
4431 if (SPEC_USIGN(opetype)) {
4432 /* unsigned is easy */
4433 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4434 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4436 pic16_emitcode("div","ab");
4437 pic16_aopPut(AOP(result),"b",0);
4441 /* signed is a little bit more difficult */
4443 /* save the signs of the operands */
4444 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4447 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4448 pic16_emitcode("push","acc"); /* save it on the stack */
4450 /* now sign adjust for both left & right */
4451 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4454 lbl = newiTempLabel(NULL);
4455 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4456 pic16_emitcode("cpl","a");
4457 pic16_emitcode("inc","a");
4458 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4459 pic16_emitcode("mov","b,a");
4461 /* sign adjust left side */
4462 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4465 lbl = newiTempLabel(NULL);
4466 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4467 pic16_emitcode("cpl","a");
4468 pic16_emitcode("inc","a");
4469 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4471 /* now the multiplication */
4472 pic16_emitcode("div","ab");
4473 /* we are interested in the lower order
4475 lbl = newiTempLabel(NULL);
4476 pic16_emitcode("pop","acc");
4477 /* if there was an over flow we don't
4478 adjust the sign of the result */
4479 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4480 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4482 pic16_emitcode("clr","a");
4483 pic16_emitcode("subb","a,b");
4484 pic16_emitcode("mov","b,a");
4485 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4487 /* now we are done */
4488 pic16_aopPut(AOP(result),"b",0);
4492 /*-----------------------------------------------------------------*/
4493 /* genMod - generates code for division */
4494 /*-----------------------------------------------------------------*/
4495 static void genMod (iCode *ic)
4497 operand *left = IC_LEFT(ic);
4498 operand *right = IC_RIGHT(ic);
4499 operand *result= IC_RESULT(ic);
4503 /* assign the amsops */
4504 pic16_aopOp (left,ic,FALSE);
4505 pic16_aopOp (right,ic,FALSE);
4506 pic16_aopOp (result,ic,TRUE);
4508 /* special cases first */
4510 if (AOP_TYPE(left) == AOP_CRY &&
4511 AOP_TYPE(right)== AOP_CRY) {
4512 genModbits(left,right,result);
4516 /* if both are of size == 1 */
4517 if (AOP_SIZE(left) == 1 &&
4518 AOP_SIZE(right) == 1 ) {
4519 genModOneByte(left,right,result);
4523 /* should have been converted to function call */
4527 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4528 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4529 pic16_freeAsmop(result,NULL,ic,TRUE);
4532 /*-----------------------------------------------------------------*/
4533 /* genIfxJump :- will create a jump depending on the ifx */
4534 /*-----------------------------------------------------------------*/
4536 note: May need to add parameter to indicate when a variable is in bit space.
4538 static void genIfxJump (iCode *ic, char *jval)
4542 /* if true label then we jump if condition
4544 if ( IC_TRUE(ic) ) {
4546 if(strcmp(jval,"a") == 0)
4548 else if (strcmp(jval,"c") == 0)
4551 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4552 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4555 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4556 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4560 /* false label is present */
4561 if(strcmp(jval,"a") == 0)
4563 else if (strcmp(jval,"c") == 0)
4566 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4567 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4570 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4571 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4576 /* mark the icode as generated */
4583 /*-----------------------------------------------------------------*/
4585 /*-----------------------------------------------------------------*/
4586 static void genSkip(iCode *ifx,int status_bit)
4588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4592 if ( IC_TRUE(ifx) ) {
4593 switch(status_bit) {
4608 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4609 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4613 switch(status_bit) {
4627 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4628 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4635 /*-----------------------------------------------------------------*/
4637 /*-----------------------------------------------------------------*/
4638 static void genSkipc(resolvedIfx *rifx)
4640 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4650 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4651 rifx->generated = 1;
4654 #if !(USE_SIMPLE_GENCMP)
4655 /*-----------------------------------------------------------------*/
4657 /*-----------------------------------------------------------------*/
4658 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4660 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4665 if( (rifx->condition ^ invert_condition) & 1)
4670 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4671 rifx->generated = 1;
4676 /*-----------------------------------------------------------------*/
4678 /*-----------------------------------------------------------------*/
4679 static void genSkipz(iCode *ifx, int condition)
4690 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4692 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4695 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4697 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4702 #if !(USE_SIMPLE_GENCMP)
4703 /*-----------------------------------------------------------------*/
4705 /*-----------------------------------------------------------------*/
4706 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4712 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4714 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4717 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4718 rifx->generated = 1;
4723 /*-----------------------------------------------------------------*/
4724 /* genChkZeroes :- greater or less than comparison */
4725 /* For each byte in a literal that is zero, inclusive or the */
4726 /* the corresponding byte in the operand with W */
4727 /* returns true if any of the bytes are zero */
4728 /*-----------------------------------------------------------------*/
4729 static int genChkZeroes(operand *op, int lit, int size)
4736 i = (lit >> (size*8)) & 0xff;
4740 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4742 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4751 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4752 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4754 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4755 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4757 /*-----------------------------------------------------------------*/
4758 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4759 /* aop (if it's NOT a literal) or from lit (if */
4760 /* aop is a literal) */
4761 /*-----------------------------------------------------------------*/
4762 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4763 if (aop->type == AOP_LIT) {
4764 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4766 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4770 /*-----------------------------------------------------------------*/
4771 /* genCmp :- greater or less than comparison */
4772 /*-----------------------------------------------------------------*/
4774 #if USE_SIMPLE_GENCMP
4776 /* genCmp performs a left < right comparison, stores
4777 * the outcome in result (if != NULL) and generates
4778 * control flow code for the ifx (if != NULL).
4780 * This version leaves in sequences like
4781 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4782 * which should be optmized by the peephole
4783 * optimizer - RN 2005-01-01 */
4784 static void genCmp (operand *left,operand *right,
4785 operand *result, iCode *ifx, int sign)
4798 assert (AOP_SIZE(left) == AOP_SIZE(right));
4799 assert (left && right);
4801 size = AOP_SIZE(right) - 1;
4802 mask = (0x100UL << (size*8)) - 1;
4803 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4808 resolveIfx (&rIfx, ifx);
4810 /**********************************************************************
4811 * handle bits - bit compares are promoted to int compares seemingly! *
4812 **********************************************************************/
4814 // THIS IS COMPLETELY UNTESTED!
4815 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4816 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4817 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4818 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4821 // 1 < {0,1} is false --> clear C by skipping the next instruction
4822 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4823 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4824 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4825 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4826 emitCLRC; // only skipped for left=0 && right=1
4828 goto correct_result_in_carry;
4832 /*************************************************
4833 * make sure that left is register (or the like) *
4834 *************************************************/
4835 if (!isAOP_REGlike(left)) {
4836 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4837 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4839 assert (isAOP_LIT(left));
4840 assert (isAOP_REGlike(right));
4841 // swap left and right
4842 // left < right <==> right > left <==> (right >= left + 1)
4843 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4845 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4846 // MAXVALUE < right? always false
4847 if (performedLt) emitCLRC; else emitSETC;
4848 goto correct_result_in_carry;
4851 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4852 // that's we handled it above.
4859 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4860 } else if (isAOP_LIT(right)) {
4861 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4864 assert (isAOP_REGlike(left)); // left must be register or the like
4865 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4867 /*************************************************
4868 * special cases go here *
4869 *************************************************/
4871 if (isAOP_LIT(right)) {
4873 // unsigned comparison to a literal
4874 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4875 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4878 // unsigned left < 0? always false
4879 if (performedLt) emitCLRC; else emitSETC;
4880 goto correct_result_in_carry;
4883 // signed comparison to a literal
4884 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4885 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4887 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4888 // signed left < 0x80000000? always false
4889 if (performedLt) emitCLRC; else emitSETC;
4890 goto correct_result_in_carry;
4891 } else if (lit == 0) {
4892 // compare left < 0; set CARRY if SIGNBIT(left) is set
4893 if (performedLt) emitSETC; else emitCLRC;
4894 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4895 if (performedLt) emitCLRC; else emitSETC;
4896 goto correct_result_in_carry;
4899 } // right is literal
4901 /*************************************************
4902 * perform a general case comparison *
4903 * make sure we get CARRY==1 <==> left >= right *
4904 *************************************************/
4905 // compare most significant bytes
4906 //DEBUGpc ("comparing bytes at offset %d", size);
4908 // unsigned comparison
4909 mov2w_regOrLit (AOP(right), lit, size);
4910 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4912 // signed comparison
4913 // (add 2^n to both operands then perform an unsigned comparison)
4914 if (isAOP_LIT(right)) {
4915 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4916 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4918 if (litbyte == 0x80) {
4919 // left >= 0x80 -- always true, but more bytes to come
4920 pic16_mov2w (AOP(left), size);
4921 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4924 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4925 pic16_mov2w (AOP(left), size);
4926 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4927 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4930 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4931 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4932 pic16_mov2w (AOP(left), size);
4933 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4934 pic16_emitpcode (POC_MOVWF, pctemp);
4935 pic16_mov2w (AOP(right), size);
4936 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4937 pic16_emitpcode (POC_SUBFW, pctemp);
4938 //pic16_popReleaseTempReg(pctemp, 1);
4942 // compare remaining bytes (treat as unsigned case from above)
4943 templbl = newiTempLabel ( NULL );
4946 //DEBUGpc ("comparing bytes at offset %d", offs);
4947 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4948 mov2w_regOrLit (AOP(right), lit, offs);
4949 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4951 pic16_emitpLabel (templbl->key);
4952 goto result_in_carry;
4956 /****************************************************
4957 * now CARRY contains the result of the comparison: *
4958 * SUBWF sets CARRY iff *
4959 * F-W >= 0 <==> F >= W <==> !(F < W) *
4961 ****************************************************/
4964 if (result && AOP_TYPE(result) != AOP_CRY) {
4965 // value will be stored
4968 // value wil only be used in the following genSkipc()
4969 rIfx.condition ^= 1;
4973 correct_result_in_carry:
4975 // assign result to variable (if neccessary)
4976 if (result && AOP_TYPE(result) != AOP_CRY) {
4977 //DEBUGpc ("assign result");
4978 size = AOP_SIZE(result);
4980 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4982 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4985 // perform conditional jump
4986 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
4988 //DEBUGpc ("generate control flow");
4989 rIfx.condition ^= 1;
4998 static void genCmp (operand *left,operand *right,
4999 operand *result, iCode *ifx, int sign)
5001 int size; //, offset = 0 ;
5002 unsigned long lit = 0L,i = 0;
5003 resolvedIfx rFalseIfx;
5004 // resolvedIfx rTrueIfx;
5006 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5009 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5010 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5016 resolveIfx(&rFalseIfx,ifx);
5017 truelbl = newiTempLabel(NULL);
5018 size = max(AOP_SIZE(left),AOP_SIZE(right));
5020 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5024 /* if literal is on the right then swap with left */
5025 if ((AOP_TYPE(right) == AOP_LIT)) {
5026 operand *tmp = right ;
5027 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5028 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5031 lit = (lit - 1) & mask;
5034 rFalseIfx.condition ^= 1;
5037 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5038 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5042 //if(IC_TRUE(ifx) == NULL)
5043 /* if left & right are bit variables */
5044 if (AOP_TYPE(left) == AOP_CRY &&
5045 AOP_TYPE(right) == AOP_CRY ) {
5046 assert (0 && "bit variables used in genCmp");
5047 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5048 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5050 /* subtract right from left if at the
5051 end the carry flag is set then we know that
5052 left is greater than right */
5054 symbol *lbl = newiTempLabel(NULL);
5057 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5058 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5062 if(AOP_TYPE(right) == AOP_LIT) {
5064 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5066 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5073 genSkipCond(&rFalseIfx,left,size-1,7);
5075 /* no need to compare to 0...*/
5076 /* NOTE: this is a de-generate compare that most certainly
5077 * creates some dead code. */
5078 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5080 if(ifx) ifx->generated = 1;
5087 //i = (lit >> (size*8)) & 0xff;
5088 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5090 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5092 i = ((0-lit) & 0xff);
5095 /* lit is 0x7f, all signed chars are less than
5096 * this except for 0x7f itself */
5097 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5098 genSkipz2(&rFalseIfx,0);
5100 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5101 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5102 genSkipc(&rFalseIfx);
5107 genSkipz2(&rFalseIfx,1);
5109 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5110 genSkipc(&rFalseIfx);
5114 if(ifx) ifx->generated = 1;
5118 /* chars are out of the way. now do ints and longs */
5121 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5128 genSkipCond(&rFalseIfx,left,size,7);
5129 if(ifx) ifx->generated = 1;
5134 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5136 //rFalseIfx.condition ^= 1;
5137 //genSkipCond(&rFalseIfx,left,size,7);
5138 //rFalseIfx.condition ^= 1;
5140 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5141 if(rFalseIfx.condition)
5142 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5144 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5146 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5147 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5148 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5151 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5153 if(rFalseIfx.condition) {
5155 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5161 genSkipc(&rFalseIfx);
5162 pic16_emitpLabel(truelbl->key);
5163 if(ifx) ifx->generated = 1;
5170 if( (lit & 0xff) == 0) {
5171 /* lower byte is zero */
5172 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5173 i = ((lit >> 8) & 0xff) ^0x80;
5174 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5175 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5176 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5177 genSkipc(&rFalseIfx);
5180 if(ifx) ifx->generated = 1;
5185 /* Special cases for signed longs */
5186 if( (lit & 0xffffff) == 0) {
5187 /* lower byte is zero */
5188 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5189 i = ((lit >> 8*3) & 0xff) ^0x80;
5190 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5191 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5192 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5193 genSkipc(&rFalseIfx);
5196 if(ifx) ifx->generated = 1;
5204 if(lit & (0x80 << (size*8))) {
5205 /* lit is negative */
5206 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5208 //genSkipCond(&rFalseIfx,left,size,7);
5210 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5212 if(rFalseIfx.condition)
5213 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5215 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5219 /* lit is positive */
5220 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5221 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5222 if(rFalseIfx.condition)
5223 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5225 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5230 This works, but is only good for ints.
5231 It also requires a "known zero" register.
5232 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5233 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5234 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5235 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5236 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5237 genSkipc(&rFalseIfx);
5239 pic16_emitpLabel(truelbl->key);
5240 if(ifx) ifx->generated = 1;
5244 /* There are no more special cases, so perform a general compare */
5246 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5247 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5251 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5253 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5255 //rFalseIfx.condition ^= 1;
5256 genSkipc(&rFalseIfx);
5258 pic16_emitpLabel(truelbl->key);
5260 if(ifx) ifx->generated = 1;
5267 /* sign is out of the way. So now do an unsigned compare */
5268 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5271 /* General case - compare to an unsigned literal on the right.*/
5273 i = (lit >> (size*8)) & 0xff;
5274 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5275 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5277 i = (lit >> (size*8)) & 0xff;
5280 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5282 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5284 /* this byte of the lit is zero,
5285 *if it's not the last then OR in the variable */
5287 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5292 pic16_emitpLabel(lbl->key);
5293 // pic16_emitpLabel(truelbl->key);
5294 //if(emitFinalCheck)
5295 genSkipc(&rFalseIfx);
5297 pic16_emitpLabel(truelbl->key);
5299 if(ifx) ifx->generated = 1;
5306 if(AOP_TYPE(left) == AOP_LIT) {
5307 //symbol *lbl = newiTempLabel(NULL);
5309 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5312 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5315 if((lit == 0) && (sign == 0)){
5318 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5320 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5322 genSkipz2(&rFalseIfx,0);
5323 if(ifx) ifx->generated = 1;
5330 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5331 /* degenerate compare can never be true */
5332 if(rFalseIfx.condition == 0)
5333 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5335 if(ifx) ifx->generated = 1;
5340 /* signed comparisons to a literal byte */
5342 int lp1 = (lit+1) & 0xff;
5344 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5347 rFalseIfx.condition ^= 1;
5348 genSkipCond(&rFalseIfx,right,0,7);
5351 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5352 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5353 genSkipz2(&rFalseIfx,1);
5356 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5357 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5358 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5359 rFalseIfx.condition ^= 1;
5360 genSkipc(&rFalseIfx);
5364 /* unsigned comparisons to a literal byte */
5366 switch(lit & 0xff ) {
5368 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5369 genSkipz2(&rFalseIfx,0);
5372 rFalseIfx.condition ^= 1;
5373 genSkipCond(&rFalseIfx,right,0,7);
5377 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5378 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5380 rFalseIfx.condition ^= 1;
5381 if (AOP_TYPE(result) == AOP_CRY)
5382 genSkipc(&rFalseIfx);
5384 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5385 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5391 if(ifx) ifx->generated = 1;
5392 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5398 /* Size is greater than 1 */
5406 /* this means lit = 0xffffffff, or -1 */
5409 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5410 rFalseIfx.condition ^= 1;
5411 genSkipCond(&rFalseIfx,right,size,7);
5412 if(ifx) ifx->generated = 1;
5414 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5423 if(rFalseIfx.condition) {
5424 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5425 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5428 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5430 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5434 if(rFalseIfx.condition) {
5435 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5436 pic16_emitpLabel(truelbl->key);
5438 rFalseIfx.condition ^= 1;
5439 genSkipCond(&rFalseIfx,right,s,7);
5442 if(ifx) ifx->generated = 1;
5444 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5450 if((size == 1) && (0 == (lp1&0xff))) {
5451 /* lower byte of signed word is zero */
5452 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5453 i = ((lp1 >> 8) & 0xff) ^0x80;
5454 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5455 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5456 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5458 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5460 if(ifx) ifx->generated = 1;
5463 rFalseIfx.condition ^= 1;
5464 genSkipc(&rFalseIfx);
5465 if(ifx) ifx->generated = 1;
5471 if(lit & (0x80 << (size*8))) {
5472 /* Lit is less than zero */
5473 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5474 //rFalseIfx.condition ^= 1;
5475 //genSkipCond(&rFalseIfx,left,size,7);
5476 //rFalseIfx.condition ^= 1;
5477 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5478 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5480 if(rFalseIfx.condition)
5481 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5483 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5487 /* Lit is greater than or equal to zero */
5488 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5489 //rFalseIfx.condition ^= 1;
5490 //genSkipCond(&rFalseIfx,right,size,7);
5491 //rFalseIfx.condition ^= 1;
5493 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5494 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5496 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5497 if(rFalseIfx.condition)
5498 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5500 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5504 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5505 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5509 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5511 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5513 rFalseIfx.condition ^= 1;
5514 //rFalseIfx.condition = 1;
5515 genSkipc(&rFalseIfx);
5517 pic16_emitpLabel(truelbl->key);
5519 if(ifx) ifx->generated = 1;
5522 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5529 /* compare word or long to an unsigned literal on the right.*/
5534 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5537 break; /* handled above */
5540 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5542 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5543 genSkipz2(&rFalseIfx,0);
5547 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5549 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5552 if(rFalseIfx.condition)
5553 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5555 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5558 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5559 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5561 rFalseIfx.condition ^= 1;
5562 genSkipc(&rFalseIfx);
5565 pic16_emitpLabel(truelbl->key);
5567 if(ifx) ifx->generated = 1;
5569 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5577 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5578 i = (lit >> (size*8)) & 0xff;
5580 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5581 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5584 i = (lit >> (size*8)) & 0xff;
5587 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5589 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5591 /* this byte of the lit is zero,
5592 * if it's not the last then OR in the variable */
5594 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5599 pic16_emitpLabel(lbl->key);
5601 rFalseIfx.condition ^= 1;
5603 genSkipc(&rFalseIfx);
5607 pic16_emitpLabel(truelbl->key);
5608 if(ifx) ifx->generated = 1;
5610 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5616 /* Compare two variables */
5618 DEBUGpic16_emitcode(";sign","%d",sign);
5622 /* Sigh. thus sucks... */
5626 pctemp = pic16_popGetTempReg(1);
5627 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5628 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5629 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5630 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5631 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5632 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5633 pic16_popReleaseTempReg(pctemp, 1);
5635 /* Signed char comparison */
5636 /* Special thanks to Nikolai Golovchenko for this snippet */
5637 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5638 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5639 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5640 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5641 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5642 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5645 genSkipc(&rFalseIfx);
5647 if(ifx) ifx->generated = 1;
5649 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5657 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5658 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5662 /* The rest of the bytes of a multi-byte compare */
5666 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5669 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5670 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5675 pic16_emitpLabel(lbl->key);
5677 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5678 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5679 (AOP_TYPE(result) == AOP_REG)) {
5680 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5681 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5683 genSkipc(&rFalseIfx);
5685 //genSkipc(&rFalseIfx);
5686 if(ifx) ifx->generated = 1;
5689 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5697 if ((AOP_TYPE(result) != AOP_CRY)
5698 && AOP_SIZE(result)) {
5699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5701 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5703 pic16_outBitC(result);
5705 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5706 /* if the result is used in the next
5707 ifx conditional branch then generate
5708 code a little differently */
5710 genIfxJump (ifx,"c");
5712 pic16_outBitC(result);
5713 /* leave the result in acc */
5718 #else /* old version of genCmp() */ /* } else { */
5720 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5721 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5722 operand *result, int offset, int invert_op)
5726 /* check condition, > or < ?? */
5727 if(rIfx->condition != 0)invert_op ^= 1;
5729 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5731 if(!ifx)invert_op ^= 1;
5733 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5734 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5737 if(!invert_op)return POC_CPFSGT;
5738 else return POC_CPFSLT;
5741 static int compareAopfirstpass=1;
5743 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5744 operand *oper, int offset, operand *result,
5745 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5751 /* invert if there is a result to be loaded, in order to fit,
5752 * SETC/CLRC sequence */
5753 if(AOP_SIZE(result))invert_op ^= 1;
5755 // if(sign && !offset)invert_op ^= 1;
5757 // if(sign)invert_op ^= 1;
5759 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5761 if(AOP_SIZE(result) && compareAopfirstpass) {
5764 pic16_emitpcode(POC_SETF, pcop2);
5769 pic16_emitpcode(POC_CLRF, pcop2);
5775 compareAopfirstpass = 0;
5777 /* there is a bug when comparing operands with size > 1,
5778 * because higher bytes can be equal and test should be performed
5779 * to the next lower byte, current algorithm, considers operands
5780 * inequal in these cases! -- VR 20041107 */
5784 pic16_emitpcode(op, pcop);
5786 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5789 if((!sign || !offset) && AOP_SIZE(result)) {
5792 pic16_emitpcode(POC_CLRF, pcop2);
5797 pic16_emitpcode(POC_SETF, pcop2);
5802 /* don't emit final branch (offset == 0) */
5806 pic16_emitpcode(POC_RRCF, pcop2);
5808 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5811 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5812 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5813 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5815 truelbl = newiTempLabel( NULL );
5816 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5817 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5818 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5820 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5821 pic16_emitpLabel(truelbl->key);
5823 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5832 static void genCmp (operand *left, operand *right,
5833 operand *result, iCode *ifx, int sign)
5837 resolvedIfx rFalseIfx;
5838 symbol *falselbl, *tlbl;
5842 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5844 resolveIfx(&rFalseIfx, ifx);
5845 size = max(AOP_SIZE(left), AOP_SIZE(right));
5847 /* if left & right are bit variables */
5848 if(AOP_TYPE(left) == AOP_CRY
5849 && AOP_TYPE(right) == AOP_CRY ) {
5851 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5852 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5854 werror(W_POSSBUG2, __FILE__, __LINE__);
5858 /* if literal is on the right then swap with left */
5859 if((AOP_TYPE(right) == AOP_LIT)) {
5860 operand *tmp = right ;
5861 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5863 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5865 // lit = (lit - 1) & mask;
5868 rFalseIfx.condition ^= 1; /* reverse compare */
5870 if ((AOP_TYPE(left) == AOP_LIT)) {
5871 /* float compares are handled by support functions */
5872 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5875 /* actual comparing algorithm */
5876 // size = AOP_SIZE( right );
5878 falselbl = newiTempLabel( NULL );
5879 if(AOP_TYPE(left) == AOP_LIT) {
5880 /* compare to literal */
5881 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5884 pCodeOp *pct, *pct2;
5887 /* signed compare */
5888 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5890 pct = pic16_popCopyReg(&pic16_pc_prodl);
5891 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5892 tlbl = newiTempLabel( NULL );
5894 /* first compare signs:
5895 * a. if both are positive, compare just like unsigned
5896 * b. if both are negative, invert cmpop, compare just like unsigned
5897 * c. if different signs, determine the result directly */
5903 tlbl1 = newiTempLabel( NULL );
5904 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5908 /* literal is zero or positive:
5909 * a. if carry is zero, too, continue compare,
5910 * b. if carry is set, then continue depending on cmpop ^ condition:
5911 * 1. '<' return false (literal < variable),
5912 * 2. '>' return true (literal > variable) */
5913 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5914 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5917 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5918 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5922 /* literal is negative:
5923 * a. if carry is set, too, continue compare,
5924 * b. if carry is zero, then continue depending on cmpop ^ condition:
5925 * 1. '<' return true (literal < variable),
5926 * 2. '>' return false (literal > variable) */
5927 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5928 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5930 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5931 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5936 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5938 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5939 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5944 pic16_emitpLabel( tlbl1->key );
5947 compareAopfirstpass=1;
5948 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5949 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5950 // pic16_emitpcode(POC_MOVWF, pct);
5952 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5954 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5955 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5959 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5960 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5961 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5962 // pic16_emitpcode(POC_MOVWF, pct);
5964 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5965 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5966 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5967 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5968 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5972 if(ifx)ifx->generated = 1;
5974 if(AOP_SIZE(result)) {
5975 pic16_emitpLabel(tlbl->key);
5976 pic16_emitpLabel(falselbl->key);
5977 pic16_outBitOp( result, pct2 );
5979 pic16_emitpLabel(tlbl->key);
5984 /* unsigned compare */
5985 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5987 compareAopfirstpass=1;
5990 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5991 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5995 if(ifx)ifx->generated = 1;
5998 if(AOP_SIZE(result)) {
5999 pic16_emitpLabel(falselbl->key);
6000 pic16_outBitC( result );
6005 /* compare registers */
6006 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6010 pCodeOp *pct, *pct2;
6012 /* signed compare */
6013 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6015 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6016 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6017 tlbl = newiTempLabel( NULL );
6019 compareAopfirstpass=1;
6022 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6023 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6024 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6025 pic16_emitpcode(POC_MOVWF, pct);
6027 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6028 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6029 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6031 /* WREG already holds left + 0x80 */
6032 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6035 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6036 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6037 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6038 pic16_emitpcode(POC_MOVWF, pct);
6040 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6041 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6042 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6044 /* WREG already holds left + 0x80 */
6045 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6046 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6049 if(ifx)ifx->generated = 1;
6051 if(AOP_SIZE(result)) {
6052 pic16_emitpLabel(tlbl->key);
6053 pic16_emitpLabel(falselbl->key);
6054 pic16_outBitOp( result, pct2 );
6056 pic16_emitpLabel(tlbl->key);
6060 /* unsigned compare */
6061 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6063 compareAopfirstpass=1;
6066 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6067 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6071 if(ifx)ifx->generated = 1;
6072 if(AOP_SIZE(result)) {
6074 pic16_emitpLabel(falselbl->key);
6075 pic16_outBitC( result );
6082 #else /* } else { */
6084 /* new version of genCmp -- VR 20041012 */
6085 static void genCmp (operand *left,operand *right,
6086 operand *result, iCode *ifx, int sign)
6088 int size; //, offset = 0 ;
6089 unsigned long lit = 0L,i = 0;
6090 resolvedIfx rFalseIfx;
6091 int willCheckCarry=0;
6092 // resolvedIfx rTrueIfx;
6098 * subtract right from left if at the end the carry flag is set then we
6099 * know that left is greater than right */
6101 resolveIfx(&rFalseIfx,ifx);
6102 truelbl = newiTempLabel(NULL);
6103 size = max(AOP_SIZE(left),AOP_SIZE(right));
6105 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6107 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6108 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6111 /* if literal is on the right then swap with left */
6112 if ((AOP_TYPE(right) == AOP_LIT)) {
6113 operand *tmp = right ;
6114 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6116 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6118 // lit = (lit - 1) & mask;
6121 rFalseIfx.condition ^= 1; /* reverse compare */
6123 if ((AOP_TYPE(left) == AOP_LIT)) {
6124 /* float compares are handled by support functions */
6125 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6129 //if(IC_TRUE(ifx) == NULL)
6130 /* if left & right are bit variables */
6131 if (AOP_TYPE(left) == AOP_CRY &&
6132 AOP_TYPE(right) == AOP_CRY ) {
6134 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6135 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6138 symbol *lbl = newiTempLabel(NULL);
6140 if(AOP_TYPE(left) == AOP_LIT) {
6141 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6143 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6145 else willCheckCarry = 0;
6148 if((lit == 0) && (sign == 0)) {
6149 /* unsigned compare to 0 */
6150 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6153 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6155 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6157 genSkipz2(&rFalseIfx,0);
6158 if(ifx)ifx->generated = 1;
6165 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6166 /* degenerate compare can never be true */
6167 if(rFalseIfx.condition == 0)
6168 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6170 if(ifx) ifx->generated = 1;
6175 /* signed comparisons to a literal byte */
6176 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6178 int lp1 = (lit+1) & 0xff;
6180 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6183 rFalseIfx.condition ^= 1;
6184 genSkipCond(&rFalseIfx,right,0,7);
6187 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6188 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6189 genSkipz2(&rFalseIfx,1);
6192 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6194 if(rFalseIfx.condition)
6195 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6197 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6199 if(willCheckCarry) {
6200 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6201 else { emitSETC; emitCLRC; }
6204 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6207 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6208 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6209 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6210 rFalseIfx.condition ^= 1;
6211 genSkipc(&rFalseIfx);
6216 /* unsigned comparisons to a literal byte */
6217 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6219 switch(lit & 0xff ) {
6222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6223 genSkipz2(&rFalseIfx,0);
6226 rFalseIfx.condition ^= 1;
6227 genSkipCond(&rFalseIfx,right,0,7);
6230 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6231 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6233 rFalseIfx.condition ^= 1;
6234 if (AOP_TYPE(result) == AOP_CRY)
6235 genSkipc(&rFalseIfx);
6237 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6238 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6244 if(ifx) ifx->generated = 1;
6245 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6251 /* Size is greater than 1 */
6259 /* this means lit = 0xffffffff, or -1 */
6262 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6263 rFalseIfx.condition ^= 1;
6264 genSkipCond(&rFalseIfx,right,size,7);
6265 if(ifx) ifx->generated = 1;
6272 if(rFalseIfx.condition) {
6273 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6274 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6277 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6279 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6283 if(rFalseIfx.condition) {
6284 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6285 pic16_emitpLabel(truelbl->key);
6287 rFalseIfx.condition ^= 1;
6288 genSkipCond(&rFalseIfx,right,s,7);
6291 if(ifx) ifx->generated = 1;
6295 if((size == 1) && (0 == (lp1&0xff))) {
6296 /* lower byte of signed word is zero */
6297 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6298 i = ((lp1 >> 8) & 0xff) ^0x80;
6299 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6300 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6301 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6302 rFalseIfx.condition ^= 1;
6303 genSkipc(&rFalseIfx);
6306 if(ifx) ifx->generated = 1;
6310 if(lit & (0x80 << (size*8))) {
6311 /* Lit is less than zero */
6312 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6313 //rFalseIfx.condition ^= 1;
6314 //genSkipCond(&rFalseIfx,left,size,7);
6315 //rFalseIfx.condition ^= 1;
6316 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6317 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6319 if(rFalseIfx.condition)
6320 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6322 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6326 /* Lit is greater than or equal to zero */
6327 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6328 //rFalseIfx.condition ^= 1;
6329 //genSkipCond(&rFalseIfx,right,size,7);
6330 //rFalseIfx.condition ^= 1;
6332 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6333 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6335 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6336 if(rFalseIfx.condition)
6337 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6344 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6345 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6349 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6351 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6353 rFalseIfx.condition ^= 1;
6354 //rFalseIfx.condition = 1;
6355 genSkipc(&rFalseIfx);
6357 pic16_emitpLabel(truelbl->key);
6359 if(ifx) ifx->generated = 1;
6364 /* compare word or long to an unsigned literal on the right.*/
6369 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6372 break; /* handled above */
6375 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6377 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6378 genSkipz2(&rFalseIfx,0);
6382 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6384 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6387 if(rFalseIfx.condition)
6388 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6390 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6393 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6394 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6396 rFalseIfx.condition ^= 1;
6397 genSkipc(&rFalseIfx);
6400 pic16_emitpLabel(truelbl->key);
6402 if(ifx) ifx->generated = 1;
6408 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6409 i = (lit >> (size*8)) & 0xff;
6411 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6412 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6415 i = (lit >> (size*8)) & 0xff;
6418 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6420 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6422 /* this byte of the lit is zero,
6423 * if it's not the last then OR in the variable */
6425 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6430 pic16_emitpLabel(lbl->key);
6432 rFalseIfx.condition ^= 1;
6434 genSkipc(&rFalseIfx);
6438 pic16_emitpLabel(truelbl->key);
6439 if(ifx) ifx->generated = 1;
6443 /* Compare two variables */
6445 DEBUGpic16_emitcode(";sign","%d",sign);
6449 /* Sigh. thus sucks... */
6453 pctemp = pic16_popGetTempReg(1);
6454 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6455 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6456 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6457 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6458 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6459 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6460 pic16_popReleaseTempReg(pctemp, 1);
6462 /* Signed char comparison */
6463 /* Special thanks to Nikolai Golovchenko for this snippet */
6464 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6465 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6466 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6467 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6468 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6469 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6471 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6472 genSkipc(&rFalseIfx);
6474 if(ifx) ifx->generated = 1;
6480 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6481 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6485 /* The rest of the bytes of a multi-byte compare */
6489 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6492 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6493 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6498 pic16_emitpLabel(lbl->key);
6500 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6501 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6502 (AOP_TYPE(result) == AOP_REG)) {
6503 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6504 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6506 genSkipc(&rFalseIfx);
6508 //genSkipc(&rFalseIfx);
6509 if(ifx) ifx->generated = 1;
6516 if ((AOP_TYPE(result) != AOP_CRY)
6517 && AOP_SIZE(result)) {
6518 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6520 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6522 pic16_outBitC(result);
6524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6525 /* if the result is used in the next
6526 ifx conditional branch then generate
6527 code a little differently */
6529 genIfxJump (ifx,"c");
6531 pic16_outBitC(result);
6532 /* leave the result in acc */
6543 /*-----------------------------------------------------------------*/
6544 /* genCmpGt :- greater than comparison */
6545 /*-----------------------------------------------------------------*/
6546 static void genCmpGt (iCode *ic, iCode *ifx)
6548 operand *left, *right, *result;
6549 sym_link *letype , *retype;
6555 right= IC_RIGHT(ic);
6556 result = IC_RESULT(ic);
6558 letype = getSpec(operandType(left));
6559 retype =getSpec(operandType(right));
6560 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6561 /* assign the amsops */
6562 pic16_aopOp (left,ic,FALSE);
6563 pic16_aopOp (right,ic,FALSE);
6564 pic16_aopOp (result,ic,TRUE);
6566 genCmp(right, left, result, ifx, sign);
6568 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6569 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6570 pic16_freeAsmop(result,NULL,ic,TRUE);
6573 /*-----------------------------------------------------------------*/
6574 /* genCmpLt - less than comparisons */
6575 /*-----------------------------------------------------------------*/
6576 static void genCmpLt (iCode *ic, iCode *ifx)
6578 operand *left, *right, *result;
6579 sym_link *letype , *retype;
6585 right= IC_RIGHT(ic);
6586 result = IC_RESULT(ic);
6588 letype = getSpec(operandType(left));
6589 retype =getSpec(operandType(right));
6590 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6592 /* assign the amsops */
6593 pic16_aopOp (left,ic,FALSE);
6594 pic16_aopOp (right,ic,FALSE);
6595 pic16_aopOp (result,ic,TRUE);
6597 genCmp(left, right, result, ifx, sign);
6599 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6600 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6601 pic16_freeAsmop(result,NULL,ic,TRUE);
6606 // FIXME reenable literal optimisation when the pic16 port is stable
6608 /*-----------------------------------------------------------------*/
6609 /* genc16bit2lit - compare a 16 bit value to a literal */
6610 /*-----------------------------------------------------------------*/
6611 static void genc16bit2lit(operand *op, int lit, int offset)
6615 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6616 if( (lit&0xff) == 0)
6621 switch( BYTEofLONG(lit,i)) {
6623 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6626 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6629 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6632 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6633 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6638 switch( BYTEofLONG(lit,i)) {
6640 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6644 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6648 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6651 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6653 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6662 /*-----------------------------------------------------------------*/
6663 /* gencjneshort - compare and jump if not equal */
6664 /*-----------------------------------------------------------------*/
6665 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6667 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6669 int res_offset = 0; /* the result may be a different size then left or right */
6670 int res_size = AOP_SIZE(result);
6672 symbol *lbl, *lbl_done;
6674 unsigned long lit = 0L;
6675 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6677 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6678 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6680 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6681 resolveIfx(&rIfx,ifx);
6682 lbl = newiTempLabel(NULL);
6683 lbl_done = newiTempLabel(NULL);
6686 /* if the left side is a literal or
6687 if the right is in a pointer register and left
6689 if ((AOP_TYPE(left) == AOP_LIT) ||
6690 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6695 if(AOP_TYPE(right) == AOP_LIT)
6696 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6698 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6699 preserve_result = 1;
6701 if(result && !preserve_result)
6704 for(i = 0; i < AOP_SIZE(result); i++)
6705 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6709 /* if the right side is a literal then anything goes */
6710 if (AOP_TYPE(right) == AOP_LIT &&
6711 AOP_TYPE(left) != AOP_DIR ) {
6714 genc16bit2lit(left, lit, 0);
6716 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6722 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6723 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6725 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6731 if(res_offset < res_size-1)
6739 /* if the right side is in a register or in direct space or
6740 if the left is a pointer register & right is not */
6741 else if (AOP_TYPE(right) == AOP_REG ||
6742 AOP_TYPE(right) == AOP_DIR ||
6743 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6744 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6745 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6746 int lbl_key = lbl->key;
6749 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6750 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6752 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6753 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6754 __FUNCTION__,__LINE__);
6758 /* switch(size) { */
6760 /* genc16bit2lit(left, lit, 0); */
6762 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6767 if((AOP_TYPE(left) == AOP_DIR) &&
6768 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6770 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6771 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6773 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6775 switch (lit & 0xff) {
6777 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6780 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6781 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6782 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6786 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6787 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6788 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6789 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6793 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6794 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6799 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6802 if(AOP_TYPE(result) == AOP_CRY) {
6803 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6808 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6810 /* fix me. probably need to check result size too */
6811 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6817 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6824 if(res_offset < res_size-1)
6829 } else if(AOP_TYPE(right) == AOP_REG &&
6830 AOP_TYPE(left) != AOP_DIR){
6833 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6834 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6835 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6840 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6842 if(res_offset < res_size-1)
6847 /* right is a pointer reg need both a & b */
6849 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6851 pic16_emitcode("mov","b,%s",l);
6852 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6853 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6858 if(result && preserve_result)
6861 for(i = 0; i < AOP_SIZE(result); i++)
6862 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6865 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6867 if(result && preserve_result)
6868 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6873 pic16_emitpLabel(lbl->key);
6875 if(result && preserve_result)
6878 for(i = 0; i < AOP_SIZE(result); i++)
6879 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6881 pic16_emitpLabel(lbl_done->key);
6884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6892 /*-----------------------------------------------------------------*/
6893 /* gencjne - compare and jump if not equal */
6894 /*-----------------------------------------------------------------*/
6895 static void gencjne(operand *left, operand *right, iCode *ifx)
6897 symbol *tlbl = newiTempLabel(NULL);
6899 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6900 gencjneshort(left, right, lbl);
6902 pic16_emitcode("mov","a,%s",one);
6903 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6904 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6905 pic16_emitcode("clr","a");
6906 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6908 pic16_emitpLabel(lbl->key);
6909 pic16_emitpLabel(tlbl->key);
6915 /*-----------------------------------------------------------------*/
6916 /* is_LitOp - check if operand has to be treated as literal */
6917 /*-----------------------------------------------------------------*/
6918 static bool is_LitOp(operand *op)
6920 return ((AOP_TYPE(op) == AOP_LIT)
6921 || ( (AOP_TYPE(op) == AOP_PCODE)
6922 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6923 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6926 /*-----------------------------------------------------------------*/
6927 /* is_LitAOp - check if operand has to be treated as literal */
6928 /*-----------------------------------------------------------------*/
6929 static bool is_LitAOp(asmop *aop)
6931 return ((aop->type == AOP_LIT)
6932 || ( (aop->type == AOP_PCODE)
6933 && ( (aop->aopu.pcop->type == PO_LITERAL)
6934 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6939 /*-----------------------------------------------------------------*/
6940 /* genCmpEq - generates code for equal to */
6941 /*-----------------------------------------------------------------*/
6942 static void genCmpEq (iCode *ic, iCode *ifx)
6944 operand *left, *right, *result;
6945 symbol *falselbl = newiTempLabel(NULL);
6946 symbol *donelbl = newiTempLabel(NULL);
6948 int preserve_result = 0;
6949 int generate_result = 0;
6954 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6955 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6956 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6958 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6960 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6962 werror(W_POSSBUG2, __FILE__, __LINE__);
6963 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6964 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6968 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6970 operand *tmp = right ;
6975 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6976 preserve_result = 1;
6978 if(result && AOP_SIZE(result))
6979 generate_result = 1;
6981 if(generate_result && !preserve_result)
6983 for(i = 0; i < AOP_SIZE(result); i++)
6984 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6987 for(i=0; i < AOP_SIZE(left); i++)
6989 if(AOP_TYPE(left) != AOP_ACC)
6992 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6997 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6999 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7001 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7006 if(generate_result && preserve_result)
7008 for(i = 0; i < AOP_SIZE(result); i++)
7009 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7013 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7015 if(generate_result && preserve_result)
7016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7018 if(ifx && IC_TRUE(ifx))
7019 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7021 if(ifx && IC_FALSE(ifx))
7022 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7024 pic16_emitpLabel(falselbl->key);
7028 if(ifx && IC_FALSE(ifx))
7029 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7031 if(generate_result && preserve_result)
7033 for(i = 0; i < AOP_SIZE(result); i++)
7034 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7037 pic16_emitpLabel(donelbl->key);
7043 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7044 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7045 pic16_freeAsmop(result,NULL,ic,TRUE);
7051 // old version kept for reference
7053 /*-----------------------------------------------------------------*/
7054 /* genCmpEq - generates code for equal to */
7055 /*-----------------------------------------------------------------*/
7056 static void genCmpEq (iCode *ic, iCode *ifx)
7058 operand *left, *right, *result;
7059 unsigned long lit = 0L;
7061 symbol *falselbl = newiTempLabel(NULL);
7064 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7067 DEBUGpic16_emitcode ("; ifx is non-null","");
7069 DEBUGpic16_emitcode ("; ifx is null","");
7071 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7072 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7073 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7075 size = max(AOP_SIZE(left),AOP_SIZE(right));
7077 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7079 /* if literal, literal on the right or
7080 if the right is in a pointer register and left
7082 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7083 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7084 operand *tmp = right ;
7090 if(ifx && !AOP_SIZE(result)){
7092 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7093 /* if they are both bit variables */
7094 if (AOP_TYPE(left) == AOP_CRY &&
7095 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7096 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7097 if(AOP_TYPE(right) == AOP_LIT){
7098 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7100 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7101 pic16_emitcode("cpl","c");
7102 } else if(lit == 1L) {
7103 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7105 pic16_emitcode("clr","c");
7107 /* AOP_TYPE(right) == AOP_CRY */
7109 symbol *lbl = newiTempLabel(NULL);
7110 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7111 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7112 pic16_emitcode("cpl","c");
7113 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7115 /* if true label then we jump if condition
7117 tlbl = newiTempLabel(NULL);
7118 if ( IC_TRUE(ifx) ) {
7119 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7120 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7122 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7123 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7125 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7128 /* left and right are both bit variables, result is carry */
7131 resolveIfx(&rIfx,ifx);
7133 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7134 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7135 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7136 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7141 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7143 /* They're not both bit variables. Is the right a literal? */
7144 if(AOP_TYPE(right) == AOP_LIT) {
7145 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7150 switch(lit & 0xff) {
7152 if ( IC_TRUE(ifx) ) {
7153 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7155 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7157 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7158 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7162 if ( IC_TRUE(ifx) ) {
7163 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7165 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7167 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7168 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7172 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7174 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7179 /* end of size == 1 */
7183 genc16bit2lit(left,lit,offset);
7186 /* end of size == 2 */
7191 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7192 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7193 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7194 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7197 /* search for patterns that can be optimized */
7199 genc16bit2lit(left,lit,0);
7203 emitSKPZ; // if hi word unequal
7205 emitSKPNZ; // if hi word equal
7207 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7208 genc16bit2lit(left,lit,2);
7211 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7212 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7216 pic16_emitpLabel(falselbl->key);
7225 } else if(AOP_TYPE(right) == AOP_CRY ) {
7226 /* we know the left is not a bit, but that the right is */
7227 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7228 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7229 pic16_popGet(AOP(right),offset));
7230 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7232 /* if the two are equal, then W will be 0 and the Z bit is set
7233 * we could test Z now, or go ahead and check the high order bytes if
7234 * the variable we're comparing is larger than a byte. */
7237 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7239 if ( IC_TRUE(ifx) ) {
7241 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7242 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7245 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7246 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7250 /* They're both variables that are larger than bits */
7253 tlbl = newiTempLabel(NULL);
7256 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7257 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7259 if ( IC_TRUE(ifx) ) {
7263 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7266 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7270 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7273 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7274 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7279 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7281 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7282 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7286 if(s>1 && IC_TRUE(ifx)) {
7287 pic16_emitpLabel(tlbl->key);
7288 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7292 /* mark the icode as generated */
7297 /* if they are both bit variables */
7298 if (AOP_TYPE(left) == AOP_CRY &&
7299 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7300 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7301 if(AOP_TYPE(right) == AOP_LIT){
7302 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7304 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7305 pic16_emitcode("cpl","c");
7306 } else if(lit == 1L) {
7307 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7309 pic16_emitcode("clr","c");
7311 /* AOP_TYPE(right) == AOP_CRY */
7313 symbol *lbl = newiTempLabel(NULL);
7314 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7315 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7316 pic16_emitcode("cpl","c");
7317 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7320 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7321 pic16_outBitC(result);
7325 genIfxJump (ifx,"c");
7328 /* if the result is used in an arithmetic operation
7329 then put the result in place */
7330 pic16_outBitC(result);
7333 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7334 gencjne(left,right,result,ifx);
7337 gencjne(left,right,newiTempLabel(NULL));
7339 if(IC_TRUE(ifx)->key)
7340 gencjne(left,right,IC_TRUE(ifx)->key);
7342 gencjne(left,right,IC_FALSE(ifx)->key);
7346 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7347 pic16_aopPut(AOP(result),"a",0);
7352 genIfxJump (ifx,"a");
7356 /* if the result is used in an arithmetic operation
7357 then put the result in place */
7359 if (AOP_TYPE(result) != AOP_CRY)
7360 pic16_outAcc(result);
7362 /* leave the result in acc */
7366 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7367 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7368 pic16_freeAsmop(result,NULL,ic,TRUE);
7372 /*-----------------------------------------------------------------*/
7373 /* ifxForOp - returns the icode containing the ifx for operand */
7374 /*-----------------------------------------------------------------*/
7375 static iCode *ifxForOp ( operand *op, iCode *ic )
7379 /* if true symbol then needs to be assigned */
7380 if (IS_TRUE_SYMOP(op))
7383 /* if this has register type condition and
7384 the next instruction is ifx with the same operand
7385 and live to of the operand is upto the ifx only then */
7387 && ic->next->op == IFX
7388 && IC_COND(ic->next)->key == op->key
7389 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7391 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7397 ic->next->op == IFX &&
7398 IC_COND(ic->next)->key == op->key) {
7399 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7404 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7406 ic->next->op == IFX)
7407 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7410 ic->next->op == IFX &&
7411 IC_COND(ic->next)->key == op->key) {
7412 DEBUGpic16_emitcode ("; "," key is okay");
7413 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7414 OP_SYMBOL(op)->liveTo,
7419 /* the code below is completely untested
7420 * it just allows ulong2fs.c compile -- VR */
7423 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7424 __FILE__, __FUNCTION__, __LINE__);
7426 /* if this has register type condition and
7427 the next instruction is ifx with the same operand
7428 and live to of the operand is upto the ifx only then */
7430 ic->next->op == IFX &&
7431 IC_COND(ic->next)->key == op->key &&
7432 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7436 ic->next->op == IFX &&
7437 IC_COND(ic->next)->key == op->key) {
7438 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7442 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7443 __FILE__, __FUNCTION__, __LINE__);
7445 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7450 /*-----------------------------------------------------------------*/
7451 /* genAndOp - for && operation */
7452 /*-----------------------------------------------------------------*/
7453 static void genAndOp (iCode *ic)
7455 operand *left,*right, *result;
7460 /* note here that && operations that are in an
7461 if statement are taken away by backPatchLabels
7462 only those used in arthmetic operations remain */
7463 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7464 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7465 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7467 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7469 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7470 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7471 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7473 /* if both are bit variables */
7474 /* if (AOP_TYPE(left) == AOP_CRY && */
7475 /* AOP_TYPE(right) == AOP_CRY ) { */
7476 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7477 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7478 /* pic16_outBitC(result); */
7480 /* tlbl = newiTempLabel(NULL); */
7481 /* pic16_toBoolean(left); */
7482 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7483 /* pic16_toBoolean(right); */
7484 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7485 /* pic16_outBitAcc(result); */
7488 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7489 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7490 pic16_freeAsmop(result,NULL,ic,TRUE);
7494 /*-----------------------------------------------------------------*/
7495 /* genOrOp - for || operation */
7496 /*-----------------------------------------------------------------*/
7499 modified this code, but it doesn't appear to ever get called
7502 static void genOrOp (iCode *ic)
7504 operand *left,*right, *result;
7509 /* note here that || operations that are in an
7510 if statement are taken away by backPatchLabels
7511 only those used in arthmetic operations remain */
7512 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7513 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7514 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7516 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7518 /* if both are bit variables */
7519 if (AOP_TYPE(left) == AOP_CRY &&
7520 AOP_TYPE(right) == AOP_CRY ) {
7521 pic16_emitcode("clrc","");
7522 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7523 AOP(left)->aopu.aop_dir,
7524 AOP(left)->aopu.aop_dir);
7525 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7526 AOP(right)->aopu.aop_dir,
7527 AOP(right)->aopu.aop_dir);
7528 pic16_emitcode("setc","");
7531 tlbl = newiTempLabel(NULL);
7532 pic16_toBoolean(left);
7534 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7535 pic16_toBoolean(right);
7536 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7538 pic16_outBitAcc(result);
7541 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7542 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7543 pic16_freeAsmop(result,NULL,ic,TRUE);
7546 /*-----------------------------------------------------------------*/
7547 /* isLiteralBit - test if lit == 2^n */
7548 /*-----------------------------------------------------------------*/
7549 static int isLiteralBit(unsigned long lit)
7551 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7552 0x100L,0x200L,0x400L,0x800L,
7553 0x1000L,0x2000L,0x4000L,0x8000L,
7554 0x10000L,0x20000L,0x40000L,0x80000L,
7555 0x100000L,0x200000L,0x400000L,0x800000L,
7556 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7557 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7560 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7561 for(idx = 0; idx < 32; idx++)
7567 /*-----------------------------------------------------------------*/
7568 /* continueIfTrue - */
7569 /*-----------------------------------------------------------------*/
7570 static void continueIfTrue (iCode *ic)
7574 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7578 /*-----------------------------------------------------------------*/
7580 /*-----------------------------------------------------------------*/
7581 static void jumpIfTrue (iCode *ic)
7585 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7589 /*-----------------------------------------------------------------*/
7590 /* jmpTrueOrFalse - */
7591 /*-----------------------------------------------------------------*/
7592 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7594 // ugly but optimized by peephole
7597 symbol *nlbl = newiTempLabel(NULL);
7598 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7599 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7600 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7601 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7603 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7604 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7609 /*-----------------------------------------------------------------*/
7610 /* genAnd - code for and */
7611 /*-----------------------------------------------------------------*/
7612 static void genAnd (iCode *ic, iCode *ifx)
7614 operand *left, *right, *result;
7616 unsigned long lit = 0L;
7622 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7623 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7624 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7626 resolveIfx(&rIfx,ifx);
7628 /* if left is a literal & right is not then exchange them */
7629 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7630 AOP_NEEDSACC(left)) {
7631 operand *tmp = right ;
7636 /* if result = right then exchange them */
7637 if(pic16_sameRegs(AOP(result),AOP(right))){
7638 operand *tmp = right ;
7643 /* if right is bit then exchange them */
7644 if (AOP_TYPE(right) == AOP_CRY &&
7645 AOP_TYPE(left) != AOP_CRY){
7646 operand *tmp = right ;
7650 if(AOP_TYPE(right) == AOP_LIT)
7651 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7653 size = AOP_SIZE(result);
7655 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7658 // result = bit & yy;
7659 if (AOP_TYPE(left) == AOP_CRY){
7660 // c = bit & literal;
7661 if(AOP_TYPE(right) == AOP_LIT){
7663 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7666 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7669 if(size && (AOP_TYPE(result) == AOP_CRY)){
7670 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7673 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7677 pic16_emitcode("clr","c");
7680 if (AOP_TYPE(right) == AOP_CRY){
7682 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7683 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7686 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7688 pic16_emitcode("rrc","a");
7689 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7695 pic16_outBitC(result);
7697 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7698 genIfxJump(ifx, "c");
7702 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7703 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7704 if((AOP_TYPE(right) == AOP_LIT) &&
7705 (AOP_TYPE(result) == AOP_CRY) &&
7706 (AOP_TYPE(left) != AOP_CRY)){
7707 int posbit = isLiteralBit(lit);
7711 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7714 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7720 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7721 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7723 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7724 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7727 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7728 size = AOP_SIZE(left);
7731 int bp = posbit, ofs=0;
7738 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7739 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7743 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7744 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7746 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7753 symbol *tlbl = newiTempLabel(NULL);
7754 int sizel = AOP_SIZE(left);
7760 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7762 /* patch provided by Aaron Colwell */
7763 if((posbit = isLiteralBit(bytelit)) != 0) {
7764 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7765 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7766 (posbit-1),0, PO_GPR_REGISTER));
7768 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7769 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7771 if (bytelit == 0xff) {
7772 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7773 * a peephole could optimize it out -- VR */
7774 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7776 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7777 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7780 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7781 pic16_popGetLabel(tlbl->key));
7785 /* old code, left here for reference -- VR 09/2004 */
7786 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7788 if((posbit = isLiteralBit(bytelit)) != 0)
7789 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7791 if(bytelit != 0x0FFL)
7792 pic16_emitcode("anl","a,%s",
7793 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7794 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7800 // bit = left & literal
7803 pic16_emitpLabel(tlbl->key);
7805 // if(left & literal)
7808 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7811 pic16_emitpLabel(tlbl->key);
7816 pic16_outBitC(result);
7820 /* if left is same as result */
7821 if(pic16_sameRegs(AOP(result),AOP(left))){
7823 for(;size--; offset++,lit>>=8) {
7824 if(AOP_TYPE(right) == AOP_LIT){
7825 switch(lit & 0xff) {
7827 /* and'ing with 0 has clears the result */
7828 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7829 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7832 /* and'ing with 0xff is a nop when the result and left are the same */
7837 int p = pic16_my_powof2( (~lit) & 0xff );
7839 /* only one bit is set in the literal, so use a bcf instruction */
7840 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7841 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7844 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7845 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7846 if(know_W != (lit&0xff))
7847 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7849 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7854 if (AOP_TYPE(left) == AOP_ACC) {
7855 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7857 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7858 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7865 // left & result in different registers
7866 if(AOP_TYPE(result) == AOP_CRY){
7868 // if(size), result in bit
7869 // if(!size && ifx), conditional oper: if(left & right)
7870 symbol *tlbl = newiTempLabel(NULL);
7871 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7873 pic16_emitcode("setb","c");
7875 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7876 pic16_emitcode("anl","a,%s",
7877 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7878 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7883 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7884 pic16_outBitC(result);
7886 jmpTrueOrFalse(ifx, tlbl);
7888 for(;(size--);offset++) {
7890 // result = left & right
7891 if(AOP_TYPE(right) == AOP_LIT){
7892 int t = (lit >> (offset*8)) & 0x0FFL;
7895 pic16_emitcode("clrf","%s",
7896 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7897 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7900 pic16_emitcode("movf","%s,w",
7901 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7902 pic16_emitcode("movwf","%s",
7903 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7904 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7905 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7908 pic16_emitcode("movlw","0x%x",t);
7909 pic16_emitcode("andwf","%s,w",
7910 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7911 pic16_emitcode("movwf","%s",
7912 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7914 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7915 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7916 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7921 if (AOP_TYPE(left) == AOP_ACC) {
7922 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7923 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7925 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926 pic16_emitcode("andwf","%s,w",
7927 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7929 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7931 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7932 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7938 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7939 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7940 pic16_freeAsmop(result,NULL,ic,TRUE);
7943 /*-----------------------------------------------------------------*/
7944 /* genOr - code for or */
7945 /*-----------------------------------------------------------------*/
7946 static void genOr (iCode *ic, iCode *ifx)
7948 operand *left, *right, *result;
7950 unsigned long lit = 0L;
7952 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7954 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7955 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7956 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7958 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7960 /* if left is a literal & right is not then exchange them */
7961 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7962 AOP_NEEDSACC(left)) {
7963 operand *tmp = right ;
7968 /* if result = right then exchange them */
7969 if(pic16_sameRegs(AOP(result),AOP(right))){
7970 operand *tmp = right ;
7975 /* if right is bit then exchange them */
7976 if (AOP_TYPE(right) == AOP_CRY &&
7977 AOP_TYPE(left) != AOP_CRY){
7978 operand *tmp = right ;
7983 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7985 if(AOP_TYPE(right) == AOP_LIT)
7986 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7988 size = AOP_SIZE(result);
7992 if (AOP_TYPE(left) == AOP_CRY){
7993 if(AOP_TYPE(right) == AOP_LIT){
7994 // c = bit & literal;
7996 // lit != 0 => result = 1
7997 if(AOP_TYPE(result) == AOP_CRY){
7999 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8000 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8001 // AOP(result)->aopu.aop_dir,
8002 // AOP(result)->aopu.aop_dir);
8004 continueIfTrue(ifx);
8008 // lit == 0 => result = left
8009 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8011 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8014 if (AOP_TYPE(right) == AOP_CRY){
8015 if(pic16_sameRegs(AOP(result),AOP(left))){
8017 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8018 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8019 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8021 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8022 AOP(result)->aopu.aop_dir,
8023 AOP(result)->aopu.aop_dir);
8024 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8025 AOP(right)->aopu.aop_dir,
8026 AOP(right)->aopu.aop_dir);
8027 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8028 AOP(result)->aopu.aop_dir,
8029 AOP(result)->aopu.aop_dir);
8031 if( AOP_TYPE(result) == AOP_ACC) {
8032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8033 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8034 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8039 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8040 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8041 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8042 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8044 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8045 AOP(result)->aopu.aop_dir,
8046 AOP(result)->aopu.aop_dir);
8047 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8048 AOP(right)->aopu.aop_dir,
8049 AOP(right)->aopu.aop_dir);
8050 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8051 AOP(left)->aopu.aop_dir,
8052 AOP(left)->aopu.aop_dir);
8053 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8054 AOP(result)->aopu.aop_dir,
8055 AOP(result)->aopu.aop_dir);
8060 symbol *tlbl = newiTempLabel(NULL);
8061 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8064 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8065 if( AOP_TYPE(right) == AOP_ACC) {
8066 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8068 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8069 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8074 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8075 pic16_emitcode(";XXX setb","c");
8076 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8077 AOP(left)->aopu.aop_dir,tlbl->key+100);
8078 pic16_toBoolean(right);
8079 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8080 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8081 jmpTrueOrFalse(ifx, tlbl);
8085 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8092 pic16_outBitC(result);
8094 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8095 genIfxJump(ifx, "c");
8099 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8100 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8101 if((AOP_TYPE(right) == AOP_LIT) &&
8102 (AOP_TYPE(result) == AOP_CRY) &&
8103 (AOP_TYPE(left) != AOP_CRY)){
8105 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8108 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8110 continueIfTrue(ifx);
8113 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8114 // lit = 0, result = boolean(left)
8116 pic16_emitcode(";XXX setb","c");
8117 pic16_toBoolean(right);
8119 symbol *tlbl = newiTempLabel(NULL);
8120 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8122 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8124 genIfxJump (ifx,"a");
8128 pic16_outBitC(result);
8132 /* if left is same as result */
8133 if(pic16_sameRegs(AOP(result),AOP(left))){
8135 for(;size--; offset++,lit>>=8) {
8136 if(AOP_TYPE(right) == AOP_LIT){
8137 if((lit & 0xff) == 0)
8138 /* or'ing with 0 has no effect */
8141 int p = pic16_my_powof2(lit & 0xff);
8143 /* only one bit is set in the literal, so use a bsf instruction */
8144 pic16_emitpcode(POC_BSF,
8145 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8147 if(know_W != (lit & 0xff))
8148 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8149 know_W = lit & 0xff;
8150 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8155 if (AOP_TYPE(left) == AOP_ACC) {
8156 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8157 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8160 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8162 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8163 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8169 // left & result in different registers
8170 if(AOP_TYPE(result) == AOP_CRY){
8172 // if(size), result in bit
8173 // if(!size && ifx), conditional oper: if(left | right)
8174 symbol *tlbl = newiTempLabel(NULL);
8175 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8176 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8180 pic16_emitcode(";XXX setb","c");
8182 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8183 pic16_emitcode(";XXX orl","a,%s",
8184 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8190 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8191 pic16_outBitC(result);
8193 jmpTrueOrFalse(ifx, tlbl);
8194 } else for(;(size--);offset++){
8196 // result = left & right
8197 if(AOP_TYPE(right) == AOP_LIT){
8198 int t = (lit >> (offset*8)) & 0x0FFL;
8201 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8202 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8204 pic16_emitcode("movf","%s,w",
8205 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8206 pic16_emitcode("movwf","%s",
8207 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8210 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8211 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8212 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8214 pic16_emitcode("movlw","0x%x",t);
8215 pic16_emitcode("iorwf","%s,w",
8216 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8217 pic16_emitcode("movwf","%s",
8218 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8224 // faster than result <- left, anl result,right
8225 // and better if result is SFR
8226 if (AOP_TYPE(left) == AOP_ACC) {
8227 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8228 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8230 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8231 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8233 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8234 pic16_emitcode("iorwf","%s,w",
8235 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8238 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8243 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8244 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8245 pic16_freeAsmop(result,NULL,ic,TRUE);
8248 /*-----------------------------------------------------------------*/
8249 /* genXor - code for xclusive or */
8250 /*-----------------------------------------------------------------*/
8251 static void genXor (iCode *ic, iCode *ifx)
8253 operand *left, *right, *result;
8255 unsigned long lit = 0L;
8257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8259 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8260 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8261 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8263 /* if left is a literal & right is not ||
8264 if left needs acc & right does not */
8265 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8266 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8267 operand *tmp = right ;
8272 /* if result = right then exchange them */
8273 if(pic16_sameRegs(AOP(result),AOP(right))){
8274 operand *tmp = right ;
8279 /* if right is bit then exchange them */
8280 if (AOP_TYPE(right) == AOP_CRY &&
8281 AOP_TYPE(left) != AOP_CRY){
8282 operand *tmp = right ;
8286 if(AOP_TYPE(right) == AOP_LIT)
8287 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8289 size = AOP_SIZE(result);
8293 if (AOP_TYPE(left) == AOP_CRY){
8294 if(AOP_TYPE(right) == AOP_LIT){
8295 // c = bit & literal;
8297 // lit>>1 != 0 => result = 1
8298 if(AOP_TYPE(result) == AOP_CRY){
8300 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8301 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8303 continueIfTrue(ifx);
8306 pic16_emitcode("setb","c");
8310 // lit == 0, result = left
8311 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8313 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8315 // lit == 1, result = not(left)
8316 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8317 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8318 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8319 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8322 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8323 pic16_emitcode("cpl","c");
8330 symbol *tlbl = newiTempLabel(NULL);
8331 if (AOP_TYPE(right) == AOP_CRY){
8333 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8336 int sizer = AOP_SIZE(right);
8338 // if val>>1 != 0, result = 1
8339 pic16_emitcode("setb","c");
8341 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8343 // test the msb of the lsb
8344 pic16_emitcode("anl","a,#0xfe");
8345 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8349 pic16_emitcode("rrc","a");
8351 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8352 pic16_emitcode("cpl","c");
8353 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8358 pic16_outBitC(result);
8360 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8361 genIfxJump(ifx, "c");
8365 if(pic16_sameRegs(AOP(result),AOP(left))){
8366 /* if left is same as result */
8367 for(;size--; offset++) {
8368 if(AOP_TYPE(right) == AOP_LIT){
8369 int t = (lit >> (offset*8)) & 0x0FFL;
8373 if (IS_AOP_PREG(left)) {
8374 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8375 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8376 pic16_aopPut(AOP(result),"a",offset);
8378 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8379 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8380 pic16_emitcode("xrl","%s,%s",
8381 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8382 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8385 if (AOP_TYPE(left) == AOP_ACC)
8386 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8388 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8389 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8391 if (IS_AOP_PREG(left)) {
8392 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8393 pic16_aopPut(AOP(result),"a",offset);
8395 pic16_emitcode("xrl","%s,a",
8396 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8402 // left & result in different registers
8403 if(AOP_TYPE(result) == AOP_CRY){
8405 // if(size), result in bit
8406 // if(!size && ifx), conditional oper: if(left ^ right)
8407 symbol *tlbl = newiTempLabel(NULL);
8408 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8410 pic16_emitcode("setb","c");
8412 if((AOP_TYPE(right) == AOP_LIT) &&
8413 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8414 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8416 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8417 pic16_emitcode("xrl","a,%s",
8418 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8420 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8425 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8426 pic16_outBitC(result);
8428 jmpTrueOrFalse(ifx, tlbl);
8429 } else for(;(size--);offset++){
8431 // result = left & right
8432 if(AOP_TYPE(right) == AOP_LIT){
8433 int t = (lit >> (offset*8)) & 0x0FFL;
8436 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8437 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8438 pic16_emitcode("movf","%s,w",
8439 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8440 pic16_emitcode("movwf","%s",
8441 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8444 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8445 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8446 pic16_emitcode("comf","%s,w",
8447 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8448 pic16_emitcode("movwf","%s",
8449 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8452 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8453 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8454 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8455 pic16_emitcode("movlw","0x%x",t);
8456 pic16_emitcode("xorwf","%s,w",
8457 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8458 pic16_emitcode("movwf","%s",
8459 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8465 // faster than result <- left, anl result,right
8466 // and better if result is SFR
8467 if (AOP_TYPE(left) == AOP_ACC) {
8468 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8469 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8471 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8472 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8473 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8474 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8476 if ( AOP_TYPE(result) != AOP_ACC){
8477 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8478 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8484 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8485 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8486 pic16_freeAsmop(result,NULL,ic,TRUE);
8489 /*-----------------------------------------------------------------*/
8490 /* genInline - write the inline code out */
8491 /*-----------------------------------------------------------------*/
8492 static void genInline (iCode *ic)
8494 char *buffer, *bp, *bp1;
8496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8498 _G.inLine += (!options.asmpeep);
8500 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8501 strcpy(buffer,IC_INLINE(ic));
8503 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8505 /* emit each line as a code */
8511 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8519 /* print label, use this special format with NULL directive
8520 * to denote that the argument should not be indented with tab */
8521 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8528 if ((bp1 != bp) && *bp1)
8529 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8534 _G.inLine -= (!options.asmpeep);
8537 /*-----------------------------------------------------------------*/
8538 /* genRRC - rotate right with carry */
8539 /*-----------------------------------------------------------------*/
8540 static void genRRC (iCode *ic)
8542 operand *left , *result ;
8543 int size, offset = 0, same;
8545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8547 /* rotate right with carry */
8549 result=IC_RESULT(ic);
8550 pic16_aopOp (left,ic,FALSE);
8551 pic16_aopOp (result,ic,FALSE);
8553 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8555 same = pic16_sameRegs(AOP(result),AOP(left));
8557 size = AOP_SIZE(result);
8559 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8561 /* get the lsb and put it into the carry */
8562 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8569 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8571 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8572 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8578 pic16_freeAsmop(left,NULL,ic,TRUE);
8579 pic16_freeAsmop(result,NULL,ic,TRUE);
8582 /*-----------------------------------------------------------------*/
8583 /* genRLC - generate code for rotate left with carry */
8584 /*-----------------------------------------------------------------*/
8585 static void genRLC (iCode *ic)
8587 operand *left , *result ;
8588 int size, offset = 0;
8591 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8592 /* rotate right with carry */
8594 result=IC_RESULT(ic);
8595 pic16_aopOp (left,ic,FALSE);
8596 pic16_aopOp (result,ic,FALSE);
8598 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8600 same = pic16_sameRegs(AOP(result),AOP(left));
8602 /* move it to the result */
8603 size = AOP_SIZE(result);
8605 /* get the msb and put it into the carry */
8606 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8613 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8615 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8616 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8623 pic16_freeAsmop(left,NULL,ic,TRUE);
8624 pic16_freeAsmop(result,NULL,ic,TRUE);
8628 /* gpasm can get the highest order bit with HIGH/UPPER
8629 * so the following probably is not needed -- VR */
8631 /*-----------------------------------------------------------------*/
8632 /* genGetHbit - generates code get highest order bit */
8633 /*-----------------------------------------------------------------*/
8634 static void genGetHbit (iCode *ic)
8636 operand *left, *result;
8638 result=IC_RESULT(ic);
8639 pic16_aopOp (left,ic,FALSE);
8640 pic16_aopOp (result,ic,FALSE);
8642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8643 /* get the highest order byte into a */
8644 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8645 if(AOP_TYPE(result) == AOP_CRY){
8646 pic16_emitcode("rlc","a");
8647 pic16_outBitC(result);
8650 pic16_emitcode("rl","a");
8651 pic16_emitcode("anl","a,#0x01");
8652 pic16_outAcc(result);
8656 pic16_freeAsmop(left,NULL,ic,TRUE);
8657 pic16_freeAsmop(result,NULL,ic,TRUE);
8661 /*-----------------------------------------------------------------*/
8662 /* AccRol - rotate left accumulator by known count */
8663 /*-----------------------------------------------------------------*/
8664 static void AccRol (int shCount)
8666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8667 shCount &= 0x0007; // shCount : 0..7
8672 pic16_emitcode("rl","a");
8675 pic16_emitcode("rl","a");
8676 pic16_emitcode("rl","a");
8679 pic16_emitcode("swap","a");
8680 pic16_emitcode("rr","a");
8683 pic16_emitcode("swap","a");
8686 pic16_emitcode("swap","a");
8687 pic16_emitcode("rl","a");
8690 pic16_emitcode("rr","a");
8691 pic16_emitcode("rr","a");
8694 pic16_emitcode("rr","a");
8700 /*-----------------------------------------------------------------*/
8701 /* AccLsh - left shift accumulator by known count */
8702 /*-----------------------------------------------------------------*/
8703 static void AccLsh (int shCount)
8705 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8711 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8714 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8715 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8718 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8719 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8722 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8725 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8726 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8729 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8730 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8733 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8737 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8740 /*-----------------------------------------------------------------*/
8741 /* AccRsh - right shift accumulator by known count */
8742 /*-----------------------------------------------------------------*/
8743 static void AccRsh (int shCount, int andmask)
8745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8750 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8753 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8754 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8757 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8758 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8761 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8764 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8765 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8768 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8772 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8777 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8779 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8783 /*-----------------------------------------------------------------*/
8784 /* AccSRsh - signed right shift accumulator by known count */
8785 /*-----------------------------------------------------------------*/
8786 static void AccSRsh (int shCount)
8789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8792 pic16_emitcode("mov","c,acc.7");
8793 pic16_emitcode("rrc","a");
8794 } else if(shCount == 2){
8795 pic16_emitcode("mov","c,acc.7");
8796 pic16_emitcode("rrc","a");
8797 pic16_emitcode("mov","c,acc.7");
8798 pic16_emitcode("rrc","a");
8800 tlbl = newiTempLabel(NULL);
8801 /* rotate right accumulator */
8802 AccRol(8 - shCount);
8803 /* and kill the higher order bits */
8804 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8805 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8806 pic16_emitcode("orl","a,#0x%02x",
8807 (unsigned char)~SRMask[shCount]);
8808 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8814 /*-----------------------------------------------------------------*/
8815 /* shiftR1Left2Result - shift right one byte from left to result */
8816 /*-----------------------------------------------------------------*/
8817 static void shiftR1Left2ResultSigned (operand *left, int offl,
8818 operand *result, int offr,
8823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8825 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8829 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8831 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8833 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8834 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8840 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8842 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8844 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8845 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8848 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8861 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8864 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8865 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8867 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8872 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8873 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8874 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8875 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8881 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8882 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8886 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8887 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8888 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8893 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8894 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8895 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8896 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8897 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8898 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8900 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8902 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8903 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8904 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8910 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8911 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8912 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8915 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8916 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8917 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8925 /*-----------------------------------------------------------------*/
8926 /* shiftR1Left2Result - shift right one byte from left to result */
8927 /*-----------------------------------------------------------------*/
8928 static void shiftR1Left2Result (operand *left, int offl,
8929 operand *result, int offr,
8930 int shCount, int sign)
8934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8936 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8938 /* Copy the msb into the carry if signed. */
8940 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8950 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8973 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8976 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8977 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8979 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8983 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8984 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8985 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8989 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8990 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8991 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8998 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8999 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9001 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9002 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9008 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9009 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9018 /*-----------------------------------------------------------------*/
9019 /* shiftL1Left2Result - shift left one byte from left to result */
9020 /*-----------------------------------------------------------------*/
9021 static void shiftL1Left2Result (operand *left, int offl,
9022 operand *result, int offr, int shCount)
9027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9029 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9030 DEBUGpic16_emitcode ("; ***","same = %d",same);
9031 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9033 /* shift left accumulator */
9034 //AccLsh(shCount); // don't comment out just yet...
9035 // pic16_aopPut(AOP(result),"a",offr);
9039 /* Shift left 1 bit position */
9040 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9042 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9044 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9045 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9050 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9051 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9052 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9056 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9057 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9063 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9064 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9067 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9068 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9069 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9073 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9074 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9075 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9076 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9077 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9080 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9081 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9082 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9086 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9091 /*-----------------------------------------------------------------*/
9092 /* movLeft2Result - move byte from left to result */
9093 /*-----------------------------------------------------------------*/
9094 static void movLeft2Result (operand *left, int offl,
9095 operand *result, int offr)
9098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9099 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9100 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9102 if (*l == '@' && (IS_AOP_PREG(result))) {
9103 pic16_emitcode("mov","a,%s",l);
9104 pic16_aopPut(AOP(result),"a",offr);
9106 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9107 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9112 /*-----------------------------------------------------------------*/
9113 /* shiftL2Left2Result - shift left two bytes from left to result */
9114 /*-----------------------------------------------------------------*/
9115 static void shiftL2Left2Result (operand *left, int offl,
9116 operand *result, int offr, int shCount)
9118 int same = pic16_sameRegs(AOP(result), AOP(left));
9121 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9123 if (same && (offl != offr)) { // shift bytes
9126 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9127 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9129 } else { // just treat as different later on
9142 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9148 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9149 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9156 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9158 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9160 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9163 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9164 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9168 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9169 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9170 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9171 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9172 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9173 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9174 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9175 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9180 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9181 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9183 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9184 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9194 /* note, use a mov/add for the shift since the mov has a
9195 chance of getting optimized out */
9196 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9197 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9198 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9199 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9200 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9204 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9205 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9211 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9212 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9213 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9214 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9215 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9216 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9217 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9218 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9222 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9223 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9227 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9228 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9229 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9230 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9232 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9233 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9234 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9235 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9236 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9237 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9238 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9239 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9242 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9243 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9244 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9245 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9246 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9251 /*-----------------------------------------------------------------*/
9252 /* shiftR2Left2Result - shift right two bytes from left to result */
9253 /*-----------------------------------------------------------------*/
9254 static void shiftR2Left2Result (operand *left, int offl,
9255 operand *result, int offr,
9256 int shCount, int sign)
9258 int same = pic16_sameRegs(AOP(result), AOP(left));
9260 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9262 if (same && (offl != offr)) { // shift right bytes
9265 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9266 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9268 } else { // just treat as different later on
9280 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9285 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9286 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9288 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9289 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9291 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9296 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9299 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9300 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9307 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9308 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9309 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9311 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9312 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9313 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9314 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9316 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9317 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9318 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9320 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9321 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9322 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9323 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9324 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9328 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9329 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9333 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9334 pic16_emitpcode(POC_BTFSC,
9335 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9336 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9344 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9345 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9347 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9348 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9349 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9350 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9352 pic16_emitpcode(POC_BTFSC,
9353 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9354 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9356 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9357 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9358 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9359 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9361 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9362 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9363 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9364 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9365 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9366 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9367 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9368 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9370 pic16_emitpcode(POC_BTFSC,
9371 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9372 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9374 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9375 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9382 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9383 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9384 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9385 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9388 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9390 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9395 /*-----------------------------------------------------------------*/
9396 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9397 /*-----------------------------------------------------------------*/
9398 static void shiftLLeftOrResult (operand *left, int offl,
9399 operand *result, int offr, int shCount)
9401 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9403 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9404 /* shift left accumulator */
9406 /* or with result */
9407 /* back to result */
9408 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9411 /*-----------------------------------------------------------------*/
9412 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9413 /*-----------------------------------------------------------------*/
9414 static void shiftRLeftOrResult (operand *left, int offl,
9415 operand *result, int offr, int shCount)
9417 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9419 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9420 /* shift right accumulator */
9422 /* or with result */
9423 /* back to result */
9424 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9427 /*-----------------------------------------------------------------*/
9428 /* genlshOne - left shift a one byte quantity by known count */
9429 /*-----------------------------------------------------------------*/
9430 static void genlshOne (operand *result, operand *left, int shCount)
9432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9433 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9436 /*-----------------------------------------------------------------*/
9437 /* genlshTwo - left shift two bytes by known amount != 0 */
9438 /*-----------------------------------------------------------------*/
9439 static void genlshTwo (operand *result,operand *left, int shCount)
9443 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9444 size = pic16_getDataSize(result);
9446 /* if shCount >= 8 */
9452 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9454 movLeft2Result(left, LSB, result, MSB16);
9456 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9459 /* 1 <= shCount <= 7 */
9462 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9464 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9468 /*-----------------------------------------------------------------*/
9469 /* shiftLLong - shift left one long from left to result */
9470 /* offr = LSB or MSB16 */
9471 /*-----------------------------------------------------------------*/
9472 static void shiftLLong (operand *left, operand *result, int offr )
9474 int size = AOP_SIZE(result);
9475 int same = pic16_sameRegs(AOP(left),AOP(result));
9478 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9480 if (same && (offr == MSB16)) { //shift one byte
9481 for(i=size-1;i>=MSB16;i--) {
9482 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9483 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9486 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9489 if (size > LSB+offr ){
9491 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9493 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9494 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9498 if(size > MSB16+offr){
9500 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9502 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9503 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9507 if(size > MSB24+offr){
9509 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9511 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9512 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9516 if(size > MSB32+offr){
9518 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9520 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9521 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9525 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9529 /*-----------------------------------------------------------------*/
9530 /* genlshFour - shift four byte by a known amount != 0 */
9531 /*-----------------------------------------------------------------*/
9532 static void genlshFour (operand *result, operand *left, int shCount)
9536 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9537 size = AOP_SIZE(result);
9539 /* if shifting more that 3 bytes */
9540 if (shCount >= 24 ) {
9543 /* lowest order of left goes to the highest
9544 order of the destination */
9545 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9547 movLeft2Result(left, LSB, result, MSB32);
9549 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9550 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9551 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9556 /* more than two bytes */
9557 else if ( shCount >= 16 ) {
9558 /* lower order two bytes goes to higher order two bytes */
9560 /* if some more remaining */
9562 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9564 movLeft2Result(left, MSB16, result, MSB32);
9565 movLeft2Result(left, LSB, result, MSB24);
9567 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9568 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9572 /* if more than 1 byte */
9573 else if ( shCount >= 8 ) {
9574 /* lower order three bytes goes to higher order three bytes */
9578 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9580 movLeft2Result(left, LSB, result, MSB16);
9582 else{ /* size = 4 */
9584 movLeft2Result(left, MSB24, result, MSB32);
9585 movLeft2Result(left, MSB16, result, MSB24);
9586 movLeft2Result(left, LSB, result, MSB16);
9587 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9589 else if(shCount == 1)
9590 shiftLLong(left, result, MSB16);
9592 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9593 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9594 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9595 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9600 /* 1 <= shCount <= 7 */
9601 else if(shCount <= 3)
9603 shiftLLong(left, result, LSB);
9604 while(--shCount >= 1)
9605 shiftLLong(result, result, LSB);
9607 /* 3 <= shCount <= 7, optimize */
9609 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9610 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9611 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9615 /*-----------------------------------------------------------------*/
9616 /* genLeftShiftLiteral - left shifting by known count */
9617 /*-----------------------------------------------------------------*/
9618 void pic16_genLeftShiftLiteral (operand *left,
9623 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9627 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9628 pic16_freeAsmop(right,NULL,ic,TRUE);
9630 pic16_aopOp(left,ic,FALSE);
9631 pic16_aopOp(result,ic,FALSE);
9633 size = getSize(operandType(result));
9636 pic16_emitcode("; shift left ","result %d, left %d",size,
9640 /* I suppose that the left size >= result size */
9643 movLeft2Result(left, size, result, size);
9647 else if(shCount >= (size * 8))
9649 pic16_aopPut(AOP(result),zero,size);
9653 genlshOne (result,left,shCount);
9658 genlshTwo (result,left,shCount);
9662 genlshFour (result,left,shCount);
9666 pic16_freeAsmop(left,NULL,ic,TRUE);
9667 pic16_freeAsmop(result,NULL,ic,TRUE);
9670 /*-----------------------------------------------------------------*
9671 * genMultiAsm - repeat assembly instruction for size of register.
9672 * if endian == 1, then the high byte (i.e base address + size of
9673 * register) is used first else the low byte is used first;
9674 *-----------------------------------------------------------------*/
9675 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9680 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9693 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9699 #if !(USE_GENERIC_SIGNED_SHIFT)
9700 /*-----------------------------------------------------------------*/
9701 /* genLeftShift - generates code for left shifting */
9702 /*-----------------------------------------------------------------*/
9703 static void genLeftShift (iCode *ic)
9705 operand *left,*right, *result;
9708 symbol *tlbl , *tlbl1;
9711 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9713 right = IC_RIGHT(ic);
9715 result = IC_RESULT(ic);
9717 pic16_aopOp(right,ic,FALSE);
9719 /* if the shift count is known then do it
9720 as efficiently as possible */
9721 if (AOP_TYPE(right) == AOP_LIT) {
9722 pic16_genLeftShiftLiteral (left,right,result,ic);
9726 /* shift count is unknown then we have to form
9727 * a loop. Get the loop count in WREG : Note: we take
9728 * only the lower order byte since shifting
9729 * more than 32 bits make no sense anyway, ( the
9730 * largest size of an object can be only 32 bits ) */
9732 pic16_aopOp(left,ic,FALSE);
9733 pic16_aopOp(result,ic,FALSE);
9735 /* now move the left to the result if they are not the
9736 * same, and if size > 1,
9737 * and if right is not same to result (!!!) -- VR */
9738 if (!pic16_sameRegs(AOP(left),AOP(result))
9739 && (AOP_SIZE(result) > 1)) {
9741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9743 size = AOP_SIZE(result);
9748 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9749 if (*l == '@' && (IS_AOP_PREG(result))) {
9751 pic16_emitcode("mov","a,%s",l);
9752 pic16_aopPut(AOP(result),"a",offset);
9756 /* we don't know if left is a literal or a register, take care -- VR */
9757 mov2f(AOP(result), AOP(left), offset);
9763 size = AOP_SIZE(result);
9765 /* if it is only one byte then */
9767 if(optimized_for_speed) {
9768 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9769 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9770 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9771 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9772 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9773 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9774 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9775 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9777 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9778 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9779 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9784 tlbl = newiTempLabel(NULL);
9787 /* this is already done, why change it? */
9788 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9789 mov2f(AOP(result), AOP(left), 0);
9793 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9794 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9795 pic16_emitpLabel(tlbl->key);
9796 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9797 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9804 if (pic16_sameRegs(AOP(left),AOP(result))) {
9806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9808 tlbl = newiTempLabel(NULL);
9809 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9810 genMultiAsm(POC_RRCF, result, size,1);
9811 pic16_emitpLabel(tlbl->key);
9812 genMultiAsm(POC_RLCF, result, size,0);
9813 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9815 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9819 //tlbl = newiTempLabel(NULL);
9821 //tlbl1 = newiTempLabel(NULL);
9823 //reAdjustPreg(AOP(result));
9825 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9826 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9827 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9829 //pic16_emitcode("add","a,acc");
9830 //pic16_aopPut(AOP(result),"a",offset++);
9832 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9834 // pic16_emitcode("rlc","a");
9835 // pic16_aopPut(AOP(result),"a",offset++);
9837 //reAdjustPreg(AOP(result));
9839 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9840 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9843 tlbl = newiTempLabel(NULL);
9844 tlbl1= newiTempLabel(NULL);
9846 size = AOP_SIZE(result);
9849 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9851 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9853 /* offset should be 0, 1 or 3 */
9855 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9857 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9859 pic16_emitpcode(POC_MOVWF, pctemp);
9862 pic16_emitpLabel(tlbl->key);
9865 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9869 pic16_emitpcode(POC_DECFSZ, pctemp);
9870 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9871 pic16_emitpLabel(tlbl1->key);
9873 pic16_popReleaseTempReg(pctemp,1);
9877 pic16_freeAsmop (right,NULL,ic,TRUE);
9878 pic16_freeAsmop(left,NULL,ic,TRUE);
9879 pic16_freeAsmop(result,NULL,ic,TRUE);
9885 #error old code (left here for reference)
9886 /*-----------------------------------------------------------------*/
9887 /* genLeftShift - generates code for left shifting */
9888 /*-----------------------------------------------------------------*/
9889 static void genLeftShift (iCode *ic)
9891 operand *left,*right, *result;
9894 symbol *tlbl , *tlbl1;
9897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9899 right = IC_RIGHT(ic);
9901 result = IC_RESULT(ic);
9903 pic16_aopOp(right,ic,FALSE);
9905 /* if the shift count is known then do it
9906 as efficiently as possible */
9907 if (AOP_TYPE(right) == AOP_LIT) {
9908 pic16_genLeftShiftLiteral (left,right,result,ic);
9912 /* shift count is unknown then we have to form
9913 a loop get the loop count in B : Note: we take
9914 only the lower order byte since shifting
9915 more that 32 bits make no sense anyway, ( the
9916 largest size of an object can be only 32 bits ) */
9919 pic16_aopOp(left,ic,FALSE);
9920 pic16_aopOp(result,ic,FALSE);
9922 /* now move the left to the result if they are not the
9924 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9925 AOP_SIZE(result) > 1) {
9927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9929 size = AOP_SIZE(result);
9932 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9933 if (*l == '@' && (IS_AOP_PREG(result))) {
9935 pic16_emitcode("mov","a,%s",l);
9936 pic16_aopPut(AOP(result),"a",offset);
9939 /* we don't know if left is a literal or a register, take care -- VR */
9940 mov2f(AOP(result), AOP(left), offset);
9946 size = AOP_SIZE(result);
9948 /* if it is only one byte then */
9950 if(optimized_for_speed) {
9951 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9952 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9953 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9954 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9956 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9957 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9958 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9959 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9960 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9961 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9962 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9967 tlbl = newiTempLabel(NULL);
9968 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9969 mov2f(AOP(result), AOP(left), 0);
9971 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9972 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9975 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9976 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9977 pic16_emitpLabel(tlbl->key);
9978 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9979 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9981 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9986 if (pic16_sameRegs(AOP(left),AOP(result))) {
9988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9990 tlbl = newiTempLabel(NULL);
9991 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9992 genMultiAsm(POC_RRCF, result, size,1);
9993 pic16_emitpLabel(tlbl->key);
9994 genMultiAsm(POC_RLCF, result, size,0);
9995 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9997 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10001 //tlbl = newiTempLabel(NULL);
10003 //tlbl1 = newiTempLabel(NULL);
10005 //reAdjustPreg(AOP(result));
10007 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10008 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10009 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10011 //pic16_emitcode("add","a,acc");
10012 //pic16_aopPut(AOP(result),"a",offset++);
10014 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10016 // pic16_emitcode("rlc","a");
10017 // pic16_aopPut(AOP(result),"a",offset++);
10019 //reAdjustPreg(AOP(result));
10021 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10022 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10025 tlbl = newiTempLabel(NULL);
10026 tlbl1= newiTempLabel(NULL);
10028 size = AOP_SIZE(result);
10031 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10033 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10035 /* offset should be 0, 1 or 3 */
10037 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10039 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10041 pic16_emitpcode(POC_MOVWF, pctemp);
10044 pic16_emitpLabel(tlbl->key);
10047 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10049 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10051 pic16_emitpcode(POC_DECFSZ, pctemp);
10052 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10053 pic16_emitpLabel(tlbl1->key);
10055 pic16_popReleaseTempReg(pctemp,1);
10059 pic16_freeAsmop (right,NULL,ic,TRUE);
10060 pic16_freeAsmop(left,NULL,ic,TRUE);
10061 pic16_freeAsmop(result,NULL,ic,TRUE);
10065 /*-----------------------------------------------------------------*/
10066 /* genrshOne - right shift a one byte quantity by known count */
10067 /*-----------------------------------------------------------------*/
10068 static void genrshOne (operand *result, operand *left,
10069 int shCount, int sign)
10071 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10072 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10075 /*-----------------------------------------------------------------*/
10076 /* genrshTwo - right shift two bytes by known amount != 0 */
10077 /*-----------------------------------------------------------------*/
10078 static void genrshTwo (operand *result,operand *left,
10079 int shCount, int sign)
10081 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10082 /* if shCount >= 8 */
10083 if (shCount >= 8) {
10086 shiftR1Left2Result(left, MSB16, result, LSB,
10089 movLeft2Result(left, MSB16, result, LSB);
10091 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10094 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10095 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10099 /* 1 <= shCount <= 7 */
10101 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10104 /*-----------------------------------------------------------------*/
10105 /* shiftRLong - shift right one long from left to result */
10106 /* offl = LSB or MSB16 */
10107 /*-----------------------------------------------------------------*/
10108 static void shiftRLong (operand *left, int offl,
10109 operand *result, int sign)
10111 int size = AOP_SIZE(result);
10112 int same = pic16_sameRegs(AOP(left),AOP(result));
10114 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10116 if (same && (offl == MSB16)) { //shift one byte right
10117 for(i=MSB16;i<size;i++) {
10118 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10124 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10130 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10132 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10133 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10136 if(offl == MSB16) {
10137 /* add sign of "a" */
10138 pic16_addSign(result, MSB32, sign);
10142 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10144 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10149 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10151 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10152 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10156 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10159 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10160 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10165 /*-----------------------------------------------------------------*/
10166 /* genrshFour - shift four byte by a known amount != 0 */
10167 /*-----------------------------------------------------------------*/
10168 static void genrshFour (operand *result, operand *left,
10169 int shCount, int sign)
10171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10172 /* if shifting more that 3 bytes */
10173 if(shCount >= 24 ) {
10176 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10178 movLeft2Result(left, MSB32, result, LSB);
10180 pic16_addSign(result, MSB16, sign);
10182 else if(shCount >= 16){
10185 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10187 movLeft2Result(left, MSB24, result, LSB);
10188 movLeft2Result(left, MSB32, result, MSB16);
10190 pic16_addSign(result, MSB24, sign);
10192 else if(shCount >= 8){
10195 shiftRLong(left, MSB16, result, sign);
10196 else if(shCount == 0){
10197 movLeft2Result(left, MSB16, result, LSB);
10198 movLeft2Result(left, MSB24, result, MSB16);
10199 movLeft2Result(left, MSB32, result, MSB24);
10200 pic16_addSign(result, MSB32, sign);
10202 else{ //shcount >= 2
10203 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10204 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10205 /* the last shift is signed */
10206 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10207 pic16_addSign(result, MSB32, sign);
10210 else{ /* 1 <= shCount <= 7 */
10212 shiftRLong(left, LSB, result, sign);
10214 shiftRLong(result, LSB, result, sign);
10217 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10218 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10219 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10224 /*-----------------------------------------------------------------*/
10225 /* genRightShiftLiteral - right shifting by known count */
10226 /*-----------------------------------------------------------------*/
10227 static void genRightShiftLiteral (operand *left,
10233 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10234 int lsize,res_size;
10236 pic16_freeAsmop(right,NULL,ic,TRUE);
10238 pic16_aopOp(left,ic,FALSE);
10239 pic16_aopOp(result,ic,FALSE);
10241 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10244 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10248 lsize = pic16_getDataSize(left);
10249 res_size = pic16_getDataSize(result);
10250 /* test the LEFT size !!! */
10252 /* I suppose that the left size >= result size */
10255 movLeft2Result(left, lsize, result, res_size);
10258 else if(shCount >= (lsize * 8)){
10260 if(res_size == 1) {
10261 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10263 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10264 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10269 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10270 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10271 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10278 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10283 switch (res_size) {
10285 genrshOne (result,left,shCount,sign);
10289 genrshTwo (result,left,shCount,sign);
10293 genrshFour (result,left,shCount,sign);
10301 pic16_freeAsmop(left,NULL,ic,TRUE);
10302 pic16_freeAsmop(result,NULL,ic,TRUE);
10305 #if !(USE_GENERIC_SIGNED_SHIFT)
10306 /*-----------------------------------------------------------------*/
10307 /* genSignedRightShift - right shift of signed number */
10308 /*-----------------------------------------------------------------*/
10309 static void genSignedRightShift (iCode *ic)
10311 operand *right, *left, *result;
10314 symbol *tlbl, *tlbl1 ;
10317 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10319 /* we do it the hard way put the shift count in b
10320 and loop thru preserving the sign */
10321 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10323 right = IC_RIGHT(ic);
10324 left = IC_LEFT(ic);
10325 result = IC_RESULT(ic);
10327 pic16_aopOp(right,ic,FALSE);
10328 pic16_aopOp(left,ic,FALSE);
10329 pic16_aopOp(result,ic,FALSE);
10332 if ( AOP_TYPE(right) == AOP_LIT) {
10333 genRightShiftLiteral (left,right,result,ic,1);
10336 /* shift count is unknown then we have to form
10337 a loop get the loop count in B : Note: we take
10338 only the lower order byte since shifting
10339 more that 32 bits make no sense anyway, ( the
10340 largest size of an object can be only 32 bits ) */
10342 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10343 //pic16_emitcode("inc","b");
10344 //pic16_freeAsmop (right,NULL,ic,TRUE);
10345 //pic16_aopOp(left,ic,FALSE);
10346 //pic16_aopOp(result,ic,FALSE);
10348 /* now move the left to the result if they are not the
10350 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10351 AOP_SIZE(result) > 1) {
10353 size = AOP_SIZE(result);
10357 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10358 if (*l == '@' && IS_AOP_PREG(result)) {
10360 pic16_emitcode("mov","a,%s",l);
10361 pic16_aopPut(AOP(result),"a",offset);
10363 pic16_aopPut(AOP(result),l,offset);
10365 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10366 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10372 /* mov the highest order bit to OVR */
10373 tlbl = newiTempLabel(NULL);
10374 tlbl1= newiTempLabel(NULL);
10376 size = AOP_SIZE(result);
10379 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10381 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10383 /* offset should be 0, 1 or 3 */
10384 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10386 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10388 pic16_emitpcode(POC_MOVWF, pctemp);
10391 pic16_emitpLabel(tlbl->key);
10393 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10394 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10397 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10400 pic16_emitpcode(POC_DECFSZ, pctemp);
10401 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10402 pic16_emitpLabel(tlbl1->key);
10404 pic16_popReleaseTempReg(pctemp,1);
10406 size = AOP_SIZE(result);
10408 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10409 pic16_emitcode("rlc","a");
10410 pic16_emitcode("mov","ov,c");
10411 /* if it is only one byte then */
10413 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10415 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10416 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10417 pic16_emitcode("mov","c,ov");
10418 pic16_emitcode("rrc","a");
10419 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10420 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10421 pic16_aopPut(AOP(result),"a",0);
10425 reAdjustPreg(AOP(result));
10426 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10427 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10428 pic16_emitcode("mov","c,ov");
10430 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10432 pic16_emitcode("rrc","a");
10433 pic16_aopPut(AOP(result),"a",offset--);
10435 reAdjustPreg(AOP(result));
10436 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10437 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10442 pic16_freeAsmop(left,NULL,ic,TRUE);
10443 pic16_freeAsmop(result,NULL,ic,TRUE);
10444 pic16_freeAsmop(right,NULL,ic,TRUE);
10448 #if !(USE_GENERIC_SIGNED_SHIFT)
10449 #warning This implementation of genRightShift() is incomplete!
10450 /*-----------------------------------------------------------------*/
10451 /* genRightShift - generate code for right shifting */
10452 /*-----------------------------------------------------------------*/
10453 static void genRightShift (iCode *ic)
10455 operand *right, *left, *result;
10459 symbol *tlbl, *tlbl1 ;
10461 /* if signed then we do it the hard way preserve the
10462 sign bit moving it inwards */
10463 letype = getSpec(operandType(IC_LEFT(ic)));
10464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10466 if (!SPEC_USIGN(letype)) {
10467 genSignedRightShift (ic);
10471 /* signed & unsigned types are treated the same : i.e. the
10472 signed is NOT propagated inwards : quoting from the
10473 ANSI - standard : "for E1 >> E2, is equivalent to division
10474 by 2**E2 if unsigned or if it has a non-negative value,
10475 otherwise the result is implementation defined ", MY definition
10476 is that the sign does not get propagated */
10478 right = IC_RIGHT(ic);
10479 left = IC_LEFT(ic);
10480 result = IC_RESULT(ic);
10482 pic16_aopOp(right,ic,FALSE);
10484 /* if the shift count is known then do it
10485 as efficiently as possible */
10486 if (AOP_TYPE(right) == AOP_LIT) {
10487 genRightShiftLiteral (left,right,result,ic, 0);
10491 /* shift count is unknown then we have to form
10492 a loop get the loop count in B : Note: we take
10493 only the lower order byte since shifting
10494 more that 32 bits make no sense anyway, ( the
10495 largest size of an object can be only 32 bits ) */
10497 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10498 pic16_emitcode("inc","b");
10499 pic16_aopOp(left,ic,FALSE);
10500 pic16_aopOp(result,ic,FALSE);
10502 /* now move the left to the result if they are not the
10504 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10505 AOP_SIZE(result) > 1) {
10507 size = AOP_SIZE(result);
10510 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10511 if (*l == '@' && IS_AOP_PREG(result)) {
10513 pic16_emitcode("mov","a,%s",l);
10514 pic16_aopPut(AOP(result),"a",offset);
10516 pic16_aopPut(AOP(result),l,offset);
10521 tlbl = newiTempLabel(NULL);
10522 tlbl1= newiTempLabel(NULL);
10523 size = AOP_SIZE(result);
10526 /* if it is only one byte then */
10529 tlbl = newiTempLabel(NULL);
10530 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10531 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10532 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10535 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10536 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10537 pic16_emitpLabel(tlbl->key);
10538 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10539 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10541 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10546 reAdjustPreg(AOP(result));
10547 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10548 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10551 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10553 pic16_emitcode("rrc","a");
10554 pic16_aopPut(AOP(result),"a",offset--);
10556 reAdjustPreg(AOP(result));
10558 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10559 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10562 pic16_freeAsmop(left,NULL,ic,TRUE);
10563 pic16_freeAsmop (right,NULL,ic,TRUE);
10564 pic16_freeAsmop(result,NULL,ic,TRUE);
10568 #if (USE_GENERIC_SIGNED_SHIFT)
10569 /*-----------------------------------------------------------------*/
10570 /* genGenericShift - generates code for left or right shifting */
10571 /*-----------------------------------------------------------------*/
10572 static void genGenericShift (iCode *ic, int isShiftLeft) {
10573 operand *left,*right, *result;
10575 int sign, signedCount;
10576 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10577 PIC_OPCODE pos_shift, neg_shift;
10581 right = IC_RIGHT(ic);
10582 left = IC_LEFT(ic);
10583 result = IC_RESULT(ic);
10585 pic16_aopOp(right,ic,FALSE);
10586 pic16_aopOp(left,ic,FALSE);
10587 pic16_aopOp(result,ic,FALSE);
10589 sign = !SPEC_USIGN(operandType (left));
10590 signedCount = !SPEC_USIGN(operandType (right));
10592 /* if the shift count is known then do it
10593 as efficiently as possible */
10594 if (AOP_TYPE(right) == AOP_LIT) {
10595 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10596 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10597 // we should modify right->aopu.aop_lit here!
10598 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10599 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10601 pic16_genLeftShiftLiteral (left,right,result,ic);
10603 genRightShiftLiteral (left,right,result,ic, sign);
10606 } // if (right is literal)
10608 /* shift count is unknown then we have to form a loop.
10609 * Note: we take only the lower order byte since shifting
10610 * more than 32 bits make no sense anyway, ( the
10611 * largest size of an object can be only 32 bits )
10612 * Note: we perform arithmetic shifts if the left operand is
10613 * signed and we do an (effective) right shift, i. e. we
10614 * shift in the sign bit from the left. */
10616 label_complete = newiTempLabel ( NULL );
10617 label_loop_pos = newiTempLabel ( NULL );
10618 label_loop_neg = NULL;
10619 label_negative = NULL;
10620 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10621 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10624 // additional labels needed
10625 label_loop_neg = newiTempLabel ( NULL );
10626 label_negative = newiTempLabel ( NULL );
10629 // copy source to result -- this will effectively truncate the left operand to the size of result!
10630 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10631 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10632 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10633 mov2f (AOP(result),AOP(left), offset);
10636 // if result is longer than left, fill with zeros (or sign)
10637 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10638 if (sign && AOP_SIZE(left) > 0) {
10639 // shift signed operand -- fill with sign
10640 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10641 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10642 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10643 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10644 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10647 // shift unsigned operand -- fill result with zeros
10648 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10649 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10652 } // if (size mismatch)
10654 pic16_mov2w (AOP(right), 0);
10655 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10656 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10659 // perform a shift by one (shift count is positive)
10660 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10661 // 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])
10662 pic16_emitpLabel (label_loop_pos->key);
10664 if (sign && (pos_shift == POC_RRCF)) {
10665 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10668 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10669 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10670 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10672 // perform a shift by one (shift count is positive)
10673 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10674 // 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])
10675 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10676 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10678 pic16_emitpLabel (label_loop_pos->key);
10679 if (sign && (pos_shift == POC_RRCF)) {
10680 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10683 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10684 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10685 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10686 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10690 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10692 pic16_emitpLabel (label_negative->key);
10693 // perform a shift by -1 (shift count is negative)
10694 // 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)
10696 pic16_emitpLabel (label_loop_neg->key);
10697 if (sign && (neg_shift == POC_RRCF)) {
10698 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10701 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10702 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10703 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10704 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10705 } // if (signedCount)
10707 pic16_emitpLabel (label_complete->key);
10710 pic16_freeAsmop (right,NULL,ic,TRUE);
10711 pic16_freeAsmop(left,NULL,ic,TRUE);
10712 pic16_freeAsmop(result,NULL,ic,TRUE);
10715 static void genLeftShift (iCode *ic) {
10716 genGenericShift (ic, 1);
10719 static void genRightShift (iCode *ic) {
10720 genGenericShift (ic, 0);
10725 void pic16_loadFSR0(operand *op)
10727 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10730 /*-----------------------------------------------------------------*/
10731 /* genUnpackBits - generates code for unpacking bits */
10732 /*-----------------------------------------------------------------*/
10733 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10737 sym_link *etype, *letype;
10738 int blen=0, bstr=0;
10742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10743 etype = getSpec(operandType(result));
10744 letype = getSpec(operandType(left));
10746 // if(IS_BITFIELD(etype)) {
10747 blen = SPEC_BLEN(etype);
10748 bstr = SPEC_BSTR(etype);
10751 lbstr = SPEC_BSTR( letype );
10754 if((blen == 1) && (bstr < 8)) {
10755 /* it is a single bit, so use the appropriate bit instructions */
10756 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10758 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10760 if((ptype == POINTER) && (result)) {
10761 /* workaround to reduce the extra lfsr instruction */
10762 pic16_emitpcode(POC_BTFSC,
10763 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10765 pic16_emitpcode(POC_BTFSC,
10766 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10769 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10771 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10777 /* the following call to pic16_loadFSR0 is temporary until
10778 * optimization to handle single bit assignments is added
10779 * to the function. Until then use the old safe way! -- VR */
10780 pic16_loadFSR0( left );
10782 /* read the first byte */
10789 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10792 pic16_emitcode("clr","a");
10793 pic16_emitcode("movc","a","@a+dptr");
10798 /* if we have bitdisplacement then it fits */
10799 /* into this byte completely or if length is */
10800 /* less than a byte */
10801 if ((shCnt = SPEC_BSTR(etype)) ||
10802 (SPEC_BLEN(etype) <= 8)) {
10804 /* shift right acc */
10807 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10808 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10810 /* VR -- normally I would use the following, but since we use the hack,
10811 * to avoid the masking from AccRsh, why not mask it right now? */
10814 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10817 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10823 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10824 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10827 /* bit field did not fit in a byte */
10828 rlen = SPEC_BLEN(etype) - 8;
10829 pic16_aopPut(AOP(result),"a",offset++);
10836 pic16_emitcode("inc","%s",rname);
10837 pic16_emitcode("mov","a,@%s",rname);
10841 pic16_emitcode("inc","%s",rname);
10842 pic16_emitcode("movx","a,@%s",rname);
10846 pic16_emitcode("inc","dptr");
10847 pic16_emitcode("movx","a,@dptr");
10851 pic16_emitcode("clr","a");
10852 pic16_emitcode("inc","dptr");
10853 pic16_emitcode("movc","a","@a+dptr");
10857 pic16_emitcode("inc","dptr");
10858 pic16_emitcode("lcall","__gptrget");
10863 /* if we are done */
10867 pic16_aopPut(AOP(result),"a",offset++);
10872 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10873 pic16_aopPut(AOP(result),"a",offset);
10880 static void genDataPointerGet(operand *left,
10884 int size, offset = 0, leoffset=0 ;
10886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10887 pic16_aopOp(result, ic, FALSE);
10889 size = AOP_SIZE(result);
10890 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10894 /* The following tests may save a redudant movff instruction when
10895 * accessing unions */
10897 /* if they are the same */
10898 if (operandsEqu (left, result)) {
10899 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10905 /* if they are the same registers */
10906 if (pic16_sameRegs(AOP(left),AOP(result))) {
10907 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10913 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10914 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10915 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10922 if ( AOP_TYPE(left) == AOP_PCODE) {
10923 fprintf(stderr,"genDataPointerGet %s, %d\n",
10924 AOP(left)->aopu.pcop->name,
10925 (AOP(left)->aopu.pcop->type == PO_DIR)?
10926 PCOR(AOP(left)->aopu.pcop)->instance:
10927 PCOI(AOP(left)->aopu.pcop)->offset);
10931 if(AOP(left)->aopu.pcop->type == PO_DIR)
10932 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10934 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10937 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10939 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10940 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10941 pic16_mov2w(AOP(left), offset); // patch 8
10942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10944 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10945 pic16_popGet(AOP(left), offset), //patch 8
10946 pic16_popGet(AOP(result), offset)));
10954 pic16_freeAsmop(result,NULL,ic,TRUE);
10959 /*-----------------------------------------------------------------*/
10960 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10961 /*-----------------------------------------------------------------*/
10962 static void genNearPointerGet (operand *left,
10967 //regs *preg = NULL ;
10968 sym_link *rtype, *retype;
10969 sym_link *ltype = operandType(left);
10973 rtype = operandType(result);
10974 retype= getSpec(rtype);
10976 pic16_aopOp(left,ic,FALSE);
10978 // pic16_DumpOp("(left)",left);
10979 // pic16_DumpOp("(result)",result);
10981 /* if left is rematerialisable and
10982 * result is not bit variable type and
10983 * the left is pointer to data space i.e
10984 * lower 128 bytes of space */
10986 if (AOP_TYPE(left) == AOP_PCODE
10987 && !IS_BITFIELD(retype)
10988 && DCL_TYPE(ltype) == POINTER) {
10990 genDataPointerGet (left,result,ic);
10991 pic16_freeAsmop(left, NULL, ic, TRUE);
10995 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10997 /* if the value is already in a pointer register
10998 * then don't need anything more */
10999 if (!AOP_INPREG(AOP(left))) {
11000 /* otherwise get a free pointer register */
11001 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11003 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11004 /* bitfields will be handled by genUnpackBits */
11005 if(!IS_BITFIELD(retype)) {
11007 if(is_LitAOp( AOP(left) )) {
11008 pic16_loadFSR0( left );
11010 // set up FSR0 with address from left
11011 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11012 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11017 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11019 pic16_aopOp (result,ic,FALSE);
11021 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11023 /* if bitfield then unpack the bits */
11024 if (IS_BITFIELD(retype))
11025 genUnpackBits (result, left, NULL, POINTER);
11027 /* we have can just get the values */
11028 int size = AOP_SIZE(result);
11031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11033 /* fsr0 is loaded already -- VR */
11034 // pic16_loadFSR0( left );
11036 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11037 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11040 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11041 pic16_popGet(AOP(result), offset++)));
11043 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11044 pic16_popGet(AOP(result), offset++)));
11048 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11049 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11051 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11055 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11057 pic16_emitcode("mov","a,@%s",rname);
11058 pic16_aopPut(AOP(result),"a",offset);
11060 sprintf(buffer,"@%s",rname);
11061 pic16_aopPut(AOP(result),buffer,offset);
11065 pic16_emitcode("inc","%s",rname);
11070 /* now some housekeeping stuff */
11072 /* we had to allocate for this iCode */
11073 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11074 pic16_freeAsmop(NULL,aop,ic,TRUE);
11076 /* we did not allocate which means left
11077 * already in a pointer register, then
11078 * if size > 0 && this could be used again
11079 * we have to point it back to where it
11081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11082 if (AOP_SIZE(result) > 1
11083 && !OP_SYMBOL(left)->remat
11084 && ( OP_SYMBOL(left)->liveTo > ic->seq
11086 // int size = AOP_SIZE(result) - 1;
11088 // pic16_emitcode("dec","%s",rname);
11093 pic16_freeAsmop(left,NULL,ic,TRUE);
11094 pic16_freeAsmop(result,NULL,ic,TRUE);
11097 /*-----------------------------------------------------------------*/
11098 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11099 /*-----------------------------------------------------------------*/
11100 static void genPagedPointerGet (operand *left,
11105 regs *preg = NULL ;
11107 sym_link *rtype, *retype;
11109 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11111 rtype = operandType(result);
11112 retype= getSpec(rtype);
11114 pic16_aopOp(left,ic,FALSE);
11116 /* if the value is already in a pointer register
11117 then don't need anything more */
11118 if (!AOP_INPREG(AOP(left))) {
11119 /* otherwise get a free pointer register */
11121 preg = getFreePtr(ic,&aop,FALSE);
11122 pic16_emitcode("mov","%s,%s",
11124 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11125 rname = preg->name ;
11127 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11129 pic16_freeAsmop(left,NULL,ic,TRUE);
11130 pic16_aopOp (result,ic,FALSE);
11132 /* if bitfield then unpack the bits */
11133 if (IS_BITFIELD(retype))
11134 genUnpackBits (result,left,rname,PPOINTER);
11136 /* we have can just get the values */
11137 int size = AOP_SIZE(result);
11142 pic16_emitcode("movx","a,@%s",rname);
11143 pic16_aopPut(AOP(result),"a",offset);
11148 pic16_emitcode("inc","%s",rname);
11152 /* now some housekeeping stuff */
11154 /* we had to allocate for this iCode */
11155 pic16_freeAsmop(NULL,aop,ic,TRUE);
11157 /* we did not allocate which means left
11158 already in a pointer register, then
11159 if size > 0 && this could be used again
11160 we have to point it back to where it
11162 if (AOP_SIZE(result) > 1 &&
11163 !OP_SYMBOL(left)->remat &&
11164 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11166 int size = AOP_SIZE(result) - 1;
11168 pic16_emitcode("dec","%s",rname);
11173 pic16_freeAsmop(result,NULL,ic,TRUE);
11178 /*-----------------------------------------------------------------*/
11179 /* genFarPointerGet - gget value from far space */
11180 /*-----------------------------------------------------------------*/
11181 static void genFarPointerGet (operand *left,
11182 operand *result, iCode *ic)
11185 sym_link *retype = getSpec(operandType(result));
11187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11189 pic16_aopOp(left,ic,FALSE);
11191 /* if the operand is already in dptr
11192 then we do nothing else we move the value to dptr */
11193 if (AOP_TYPE(left) != AOP_STR) {
11194 /* if this is remateriazable */
11195 if (AOP_TYPE(left) == AOP_IMMD)
11196 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11197 else { /* we need to get it byte by byte */
11198 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11199 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11200 if (options.model == MODEL_FLAT24)
11202 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11206 /* so dptr know contains the address */
11207 pic16_freeAsmop(left,NULL,ic,TRUE);
11208 pic16_aopOp(result,ic,FALSE);
11210 /* if bit then unpack */
11211 if (IS_BITFIELD(retype))
11212 genUnpackBits(result,left,"dptr",FPOINTER);
11214 size = AOP_SIZE(result);
11218 pic16_emitcode("movx","a,@dptr");
11219 pic16_aopPut(AOP(result),"a",offset++);
11221 pic16_emitcode("inc","dptr");
11225 pic16_freeAsmop(result,NULL,ic,TRUE);
11228 /*-----------------------------------------------------------------*/
11229 /* genCodePointerGet - get value from code space */
11230 /*-----------------------------------------------------------------*/
11231 static void genCodePointerGet (operand *left,
11232 operand *result, iCode *ic)
11235 sym_link *retype = getSpec(operandType(result));
11237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11239 pic16_aopOp(left,ic,FALSE);
11241 /* if the operand is already in dptr
11242 then we do nothing else we move the value to dptr */
11243 if (AOP_TYPE(left) != AOP_STR) {
11244 /* if this is remateriazable */
11245 if (AOP_TYPE(left) == AOP_IMMD)
11246 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11247 else { /* we need to get it byte by byte */
11248 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11249 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11250 if (options.model == MODEL_FLAT24)
11252 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11256 /* so dptr know contains the address */
11257 pic16_freeAsmop(left,NULL,ic,TRUE);
11258 pic16_aopOp(result,ic,FALSE);
11260 /* if bit then unpack */
11261 if (IS_BITFIELD(retype))
11262 genUnpackBits(result,left,"dptr",CPOINTER);
11264 size = AOP_SIZE(result);
11268 pic16_emitcode("clr","a");
11269 pic16_emitcode("movc","a,@a+dptr");
11270 pic16_aopPut(AOP(result),"a",offset++);
11272 pic16_emitcode("inc","dptr");
11276 pic16_freeAsmop(result,NULL,ic,TRUE);
11280 /*-----------------------------------------------------------------*/
11281 /* genGenPointerGet - gget value from generic pointer space */
11282 /*-----------------------------------------------------------------*/
11283 static void genGenPointerGet (operand *left,
11284 operand *result, iCode *ic)
11286 int size, offset, lit;
11287 sym_link *retype = getSpec(operandType(result));
11289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11290 pic16_aopOp(left,ic,FALSE);
11291 pic16_aopOp(result,ic,FALSE);
11292 size = AOP_SIZE(result);
11294 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11296 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11298 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11299 // load FSR0 from immediate
11300 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11302 // pic16_loadFSR0( left );
11307 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11309 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11316 else { /* we need to get it byte by byte */
11317 // set up FSR0 with address from left
11318 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11319 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11325 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11327 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11334 /* if bit then unpack */
11335 if (IS_BITFIELD(retype))
11336 genUnpackBits(result,left,"BAD",GPOINTER);
11339 pic16_freeAsmop(left,NULL,ic,TRUE);
11340 pic16_freeAsmop(result,NULL,ic,TRUE);
11346 /*-----------------------------------------------------------------*/
11347 /* genGenPointerGet - gget value from generic pointer space */
11348 /*-----------------------------------------------------------------*/
11349 static void genGenPointerGet (operand *left,
11350 operand *result, iCode *ic)
11352 int size, offset, lit;
11353 sym_link *retype = getSpec(operandType(result));
11356 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11357 pic16_aopOp(left,ic,FALSE);
11358 pic16_aopOp(result,ic,FALSE);
11359 size = AOP_SIZE(result);
11361 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11363 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11365 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11366 // load FSR0 from immediate
11367 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11369 werror(W_POSSBUG2, __FILE__, __LINE__);
11374 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11376 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11383 } else { /* we need to get it byte by byte */
11385 /* set up WREG:PRODL:FSR0L with address from left */
11386 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11387 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11388 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11391 case 1: strcpy(fgptrget, "__gptrget1"); break;
11392 case 2: strcpy(fgptrget, "__gptrget2"); break;
11393 case 3: strcpy(fgptrget, "__gptrget3"); break;
11394 case 4: strcpy(fgptrget, "__gptrget4"); break;
11396 werror(W_POSSBUG2, __FILE__, __LINE__);
11400 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11402 assignResultValue(result, 1);
11407 sym = newSymbol( fgptrget, 0 );
11408 strcpy(sym->rname, fgptrget);
11409 checkAddSym(&externs, sym);
11411 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11417 /* if bit then unpack */
11418 if (IS_BITFIELD(retype))
11419 genUnpackBits(result,left,"BAD",GPOINTER);
11422 pic16_freeAsmop(left,NULL,ic,TRUE);
11423 pic16_freeAsmop(result,NULL,ic,TRUE);
11426 /*-----------------------------------------------------------------*/
11427 /* genConstPointerGet - get value from const generic pointer space */
11428 /*-----------------------------------------------------------------*/
11429 static void genConstPointerGet (operand *left,
11430 operand *result, iCode *ic)
11432 //sym_link *retype = getSpec(operandType(result));
11433 // symbol *albl = newiTempLabel(NULL); // patch 15
11434 // symbol *blbl = newiTempLabel(NULL); //
11435 // PIC_OPCODE poc; // patch 15
11439 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11440 pic16_aopOp(left,ic,FALSE);
11441 pic16_aopOp(result,ic,TRUE);
11442 size = AOP_SIZE(result);
11444 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11446 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11448 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11449 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11450 pic16_emitpLabel(albl->key);
11452 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11454 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11455 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11456 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11457 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11458 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11460 pic16_emitpLabel(blbl->key);
11462 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11466 // set up table pointer
11467 if( (AOP_TYPE(left) == AOP_PCODE)
11468 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11469 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
11471 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11472 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11473 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11474 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11475 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11476 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11480 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11481 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11482 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11488 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11489 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11493 pic16_freeAsmop(left,NULL,ic,TRUE);
11494 pic16_freeAsmop(result,NULL,ic,TRUE);
11499 /*-----------------------------------------------------------------*/
11500 /* genPointerGet - generate code for pointer get */
11501 /*-----------------------------------------------------------------*/
11502 static void genPointerGet (iCode *ic)
11504 operand *left, *result ;
11505 sym_link *type, *etype;
11510 left = IC_LEFT(ic);
11511 result = IC_RESULT(ic) ;
11513 /* depending on the type of pointer we need to
11514 move it to the correct pointer register */
11515 type = operandType(left);
11516 etype = getSpec(type);
11519 if (IS_PTR_CONST(type))
11521 if (IS_CODEPTR(type))
11523 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11525 /* if left is of type of pointer then it is simple */
11526 if (IS_PTR(type) && !IS_FUNC(type->next))
11527 p_type = DCL_TYPE(type);
11529 /* we have to go by the storage class */
11530 p_type = PTR_TYPE(SPEC_OCLS(etype));
11532 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11534 if (SPEC_OCLS(etype)->codesp ) {
11535 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11536 //p_type = CPOINTER ;
11539 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11540 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11541 /*p_type = FPOINTER ;*/
11543 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11544 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11545 /* p_type = PPOINTER; */
11547 if (SPEC_OCLS(etype) == idata )
11548 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11549 /* p_type = IPOINTER; */
11551 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11552 /* p_type = POINTER ; */
11555 /* now that we have the pointer type we assign
11556 the pointer values */
11561 genNearPointerGet (left,result,ic);
11565 genPagedPointerGet(left,result,ic);
11569 genFarPointerGet (left,result,ic);
11573 genConstPointerGet (left,result,ic);
11574 //pic16_emitcodePointerGet (left,result,ic);
11579 if (IS_PTR_CONST(type))
11580 genConstPointerGet (left,result,ic);
11583 genGenPointerGet (left,result,ic);
11587 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11588 "genPointerGet: illegal pointer type");
11594 /*-----------------------------------------------------------------*/
11595 /* genPackBits - generates code for packed bit storage */
11596 /*-----------------------------------------------------------------*/
11597 static void genPackBits (sym_link *etype , operand *result,
11599 char *rname, int p_type)
11608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11609 blen = SPEC_BLEN(etype);
11610 bstr = SPEC_BSTR(etype);
11612 retype = getSpec(operandType(right));
11614 if(AOP_TYPE(right) == AOP_LIT) {
11615 if((blen == 1) && (bstr < 8)) {
11617 /* it is a single bit, so use the appropriate bit instructions */
11619 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11621 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11622 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11623 if((p_type == POINTER) && (result)) {
11624 /* workaround to reduce the extra lfsr instruction */
11626 pic16_emitpcode(POC_BSF,
11627 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11629 pic16_emitpcode(POC_BCF,
11630 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11633 pic16_loadFSR0( result );
11635 pic16_emitpcode(POC_BSF,
11636 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11638 pic16_emitpcode(POC_BCF,
11639 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11646 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11649 if(IS_BITFIELD(retype)
11650 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11654 rblen = SPEC_BLEN( retype );
11655 rbstr = SPEC_BSTR( retype );
11658 if(IS_BITFIELD(etype)) {
11659 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11660 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11662 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11665 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11667 if(IS_BITFIELD(etype)) {
11668 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11670 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11673 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11677 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11679 /* if the bit lenth is less than or */
11680 /* it exactly fits a byte then */
11681 if((shCnt=SPEC_BSTR(etype))
11682 || SPEC_BLEN(etype) <= 8 ) {
11684 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11686 /* shift left acc */
11689 /* using PRODL as a temporary register here */
11690 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11695 pic16_loadFSR0( result );
11696 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11697 // pic16_emitcode ("mov","b,a");
11698 // pic16_emitcode("mov","a,@%s",rname);
11702 werror(W_POSSBUG2, __FILE__, __LINE__);
11707 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11708 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11709 (unsigned char)(0xff >> (8-bstr))) ));
11710 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11711 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11718 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11719 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11724 if ( SPEC_BLEN(etype) <= 8 )
11727 pic16_emitcode("inc","%s",rname);
11728 rLen = SPEC_BLEN(etype) ;
11732 /* now generate for lengths greater than one byte */
11735 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11745 pic16_emitcode("mov","@%s,a",rname);
11747 pic16_emitcode("mov","@%s,%s",rname,l);
11752 pic16_emitcode("movx","@dptr,a");
11757 DEBUGpic16_emitcode(";lcall","__gptrput");
11760 pic16_emitcode ("inc","%s",rname);
11765 /* last last was not complete */
11767 /* save the byte & read byte */
11770 pic16_emitcode ("mov","b,a");
11771 pic16_emitcode("mov","a,@%s",rname);
11775 pic16_emitcode ("mov","b,a");
11776 pic16_emitcode("movx","a,@dptr");
11780 pic16_emitcode ("push","b");
11781 pic16_emitcode ("push","acc");
11782 pic16_emitcode ("lcall","__gptrget");
11783 pic16_emitcode ("pop","b");
11787 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11788 pic16_emitcode ("orl","a,b");
11791 if (p_type == GPOINTER)
11792 pic16_emitcode("pop","b");
11797 pic16_emitcode("mov","@%s,a",rname);
11801 pic16_emitcode("movx","@dptr,a");
11805 DEBUGpic16_emitcode(";lcall","__gptrput");
11809 /*-----------------------------------------------------------------*/
11810 /* genDataPointerSet - remat pointer to data space */
11811 /*-----------------------------------------------------------------*/
11812 static void genDataPointerSet(operand *right,
11816 int size, offset = 0, resoffset=0 ;
11818 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11819 pic16_aopOp(right,ic,FALSE);
11821 size = AOP_SIZE(right);
11823 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11826 if ( AOP_TYPE(result) == AOP_PCODE) {
11827 fprintf(stderr,"genDataPointerSet %s, %d\n",
11828 AOP(result)->aopu.pcop->name,
11829 (AOP(result)->aopu.pcop->type == PO_DIR)?
11830 PCOR(AOP(result)->aopu.pcop)->instance:
11831 PCOI(AOP(result)->aopu.pcop)->offset);
11835 if(AOP(result)->aopu.pcop->type == PO_DIR)
11836 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11839 if (AOP_TYPE(right) == AOP_LIT) {
11842 if(!IS_FLOAT(operandType( right )))
11843 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11846 unsigned long lit_int;
11850 /* take care if literal is a float */
11851 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11852 lit = info.lit_int;
11855 lit = lit >> (8*offset);
11857 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11858 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11860 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11863 pic16_mov2w(AOP(right), offset);
11864 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11870 pic16_freeAsmop(right,NULL,ic,TRUE);
11875 /*-----------------------------------------------------------------*/
11876 /* genNearPointerSet - pic16_emitcode for near pointer put */
11877 /*-----------------------------------------------------------------*/
11878 static void genNearPointerSet (operand *right,
11885 sym_link *ptype = operandType(result);
11886 sym_link *resetype;
11888 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11889 retype= getSpec(operandType(right));
11890 resetype = getSpec(operandType(result));
11892 pic16_aopOp(result,ic,FALSE);
11894 /* if the result is rematerializable &
11895 * in data space & not a bit variable */
11897 /* and result is not a bit variable */
11898 if (AOP_TYPE(result) == AOP_PCODE
11899 // && AOP_TYPE(result) == AOP_IMMD
11900 && DCL_TYPE(ptype) == POINTER
11901 && !IS_BITFIELD(retype)
11902 && !IS_BITFIELD(resetype)) {
11904 genDataPointerSet (right,result,ic);
11905 pic16_freeAsmop(result,NULL,ic,TRUE);
11909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11910 pic16_aopOp(right,ic,FALSE);
11911 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11913 /* if the value is already in a pointer register
11914 * then don't need anything more */
11915 if (!AOP_INPREG(AOP(result))) {
11916 /* otherwise get a free pointer register */
11917 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11919 // if( (AOP_TYPE(result) == AOP_PCODE)
11920 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11921 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11922 if(is_LitAOp( AOP(result) ))
11924 if(!IS_BITFIELD(resetype))
11925 pic16_loadFSR0( result ); // patch 10
11927 if(!IS_BITFIELD(resetype)) {
11928 // set up FSR0 with address of result
11929 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11930 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11936 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11940 // pic16_loadFSR0( result );
11942 /* if bitfield then unpack the bits */
11943 if (IS_BITFIELD(resetype)) {
11944 genPackBits (resetype, result, right, NULL, POINTER);
11946 /* we have can just get the values */
11947 int size = AOP_SIZE(right);
11950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11952 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11955 //pic16_emitcode("mov","@%s,a",rname);
11956 pic16_emitcode("movf","indf0,w ;1");
11959 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
11960 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
11962 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
11964 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
11966 } else { // no literal //
11968 pic16_emitpcode(POC_MOVFF, //
11969 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11970 pic16_popCopyReg(&pic16_pc_postinc0))); //
11972 pic16_emitpcode(POC_MOVFF, //
11973 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11974 pic16_popCopyReg(&pic16_pc_indf0))); //
11982 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11983 /* now some housekeeping stuff */
11985 /* we had to allocate for this iCode */
11986 pic16_freeAsmop(NULL,aop,ic,TRUE);
11988 /* we did not allocate which means left
11989 * already in a pointer register, then
11990 * if size > 0 && this could be used again
11991 * we have to point it back to where it
11993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11994 if (AOP_SIZE(right) > 1
11995 && !OP_SYMBOL(result)->remat
11996 && ( OP_SYMBOL(result)->liveTo > ic->seq
11999 int size = AOP_SIZE(right) - 1;
12002 pic16_emitcode("decf","fsr0,f");
12003 //pic16_emitcode("dec","%s",rname);
12007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12010 pic16_freeAsmop(right,NULL,ic,TRUE);
12011 pic16_freeAsmop(result,NULL,ic,TRUE);
12014 /*-----------------------------------------------------------------*/
12015 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12016 /*-----------------------------------------------------------------*/
12017 static void genPagedPointerSet (operand *right,
12022 regs *preg = NULL ;
12026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12028 retype= getSpec(operandType(right));
12030 pic16_aopOp(result,ic,FALSE);
12032 /* if the value is already in a pointer register
12033 then don't need anything more */
12034 if (!AOP_INPREG(AOP(result))) {
12035 /* otherwise get a free pointer register */
12037 preg = getFreePtr(ic,&aop,FALSE);
12038 pic16_emitcode("mov","%s,%s",
12040 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12041 rname = preg->name ;
12043 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12045 pic16_freeAsmop(result,NULL,ic,TRUE);
12046 pic16_aopOp (right,ic,FALSE);
12048 /* if bitfield then unpack the bits */
12049 if (IS_BITFIELD(retype))
12050 genPackBits (retype,result,right,rname,PPOINTER);
12052 /* we have can just get the values */
12053 int size = AOP_SIZE(right);
12057 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12060 pic16_emitcode("movx","@%s,a",rname);
12063 pic16_emitcode("inc","%s",rname);
12069 /* now some housekeeping stuff */
12071 /* we had to allocate for this iCode */
12072 pic16_freeAsmop(NULL,aop,ic,TRUE);
12074 /* we did not allocate which means left
12075 already in a pointer register, then
12076 if size > 0 && this could be used again
12077 we have to point it back to where it
12079 if (AOP_SIZE(right) > 1 &&
12080 !OP_SYMBOL(result)->remat &&
12081 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12083 int size = AOP_SIZE(right) - 1;
12085 pic16_emitcode("dec","%s",rname);
12090 pic16_freeAsmop(right,NULL,ic,TRUE);
12095 /*-----------------------------------------------------------------*/
12096 /* genFarPointerSet - set value from far space */
12097 /*-----------------------------------------------------------------*/
12098 static void genFarPointerSet (operand *right,
12099 operand *result, iCode *ic)
12102 sym_link *retype = getSpec(operandType(right));
12104 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12105 pic16_aopOp(result,ic,FALSE);
12107 /* if the operand is already in dptr
12108 then we do nothing else we move the value to dptr */
12109 if (AOP_TYPE(result) != AOP_STR) {
12110 /* if this is remateriazable */
12111 if (AOP_TYPE(result) == AOP_IMMD)
12112 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12113 else { /* we need to get it byte by byte */
12114 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12115 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12116 if (options.model == MODEL_FLAT24)
12118 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12122 /* so dptr know contains the address */
12123 pic16_freeAsmop(result,NULL,ic,TRUE);
12124 pic16_aopOp(right,ic,FALSE);
12126 /* if bit then unpack */
12127 if (IS_BITFIELD(retype))
12128 genPackBits(retype,result,right,"dptr",FPOINTER);
12130 size = AOP_SIZE(right);
12134 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12136 pic16_emitcode("movx","@dptr,a");
12138 pic16_emitcode("inc","dptr");
12142 pic16_freeAsmop(right,NULL,ic,TRUE);
12145 /*-----------------------------------------------------------------*/
12146 /* genGenPointerSet - set value from generic pointer space */
12147 /*-----------------------------------------------------------------*/
12149 static void genGenPointerSet (operand *right,
12150 operand *result, iCode *ic)
12152 int i, size, offset, lit;
12153 sym_link *retype = getSpec(operandType(right));
12155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12157 pic16_aopOp(result,ic,FALSE);
12158 pic16_aopOp(right,ic,FALSE);
12159 size = AOP_SIZE(right);
12162 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12164 /* if the operand is already in dptr
12165 then we do nothing else we move the value to dptr */
12166 if (AOP_TYPE(result) != AOP_STR) {
12167 /* if this is remateriazable */
12168 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12169 // WARNING: anythig until "else" is untested!
12170 if (AOP_TYPE(result) == AOP_IMMD) {
12171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12172 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12173 // load FSR0 from immediate
12174 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12178 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12180 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12186 else { /* we need to get it byte by byte */
12187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12188 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12190 // set up FSR0 with address of result
12191 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12192 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12194 /* hack hack! see if this the FSR. If so don't load W */
12195 if(AOP_TYPE(right) != AOP_ACC) {
12197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12199 if(AOP_TYPE(right) == AOP_LIT)
12202 // note: pic16_popGet handles sign extension
12203 for(i=0;i<size;i++) {
12204 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12206 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12208 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12213 for(i=0;i<size;i++) {
12215 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12216 pic16_popCopyReg(&pic16_pc_postinc0)));
12218 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12219 pic16_popCopyReg(&pic16_pc_indf0)));
12225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12226 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12228 } // if (AOP_TYPE(result) != AOP_IMMD)
12230 } // if (AOP_TYPE(result) != AOP_STR)
12231 /* so dptr know contains the address */
12234 /* if bit then unpack */
12235 if (IS_BITFIELD(retype))
12236 genPackBits(retype,result,right,"dptr",GPOINTER);
12238 size = AOP_SIZE(right);
12241 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12243 // set up FSR0 with address of result
12244 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12245 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12248 if (AOP_TYPE(right) == AOP_LIT) {
12249 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12251 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12253 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12255 } else { // no literal
12257 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12259 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12267 pic16_freeAsmop(right,NULL,ic,TRUE);
12268 pic16_freeAsmop(result,NULL,ic,TRUE);
12272 static void genGenPointerSet (operand *right,
12273 operand *result, iCode *ic)
12276 sym_link *retype = getSpec(operandType(right));
12279 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12281 pic16_aopOp(result,ic,FALSE);
12282 pic16_aopOp(right,ic,FALSE);
12283 size = AOP_SIZE(right);
12285 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12288 /* if bit then unpack */
12289 if (IS_BITFIELD(retype)) {
12290 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12291 genPackBits(retype,result,right,"dptr",GPOINTER);
12295 size = AOP_SIZE(right);
12297 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12301 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12303 /* value of right+0 is placed on stack, which will be retrieved
12304 * by the support function this restoring the stack. The important
12305 * thing is that there is no need to manually restore stack pointer
12307 pushaop(AOP(right), 0);
12308 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12309 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12310 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12311 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12313 /* load address to write to in WREG:FSR0H:FSR0L */
12314 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12315 pic16_popCopyReg(&pic16_pc_fsr0l)));
12316 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12317 pic16_popCopyReg(&pic16_pc_prodl)));
12318 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12321 /* put code here */
12323 case 1: strcpy(fgptrput, "__gptrput1"); break;
12324 case 2: strcpy(fgptrput, "__gptrput2"); break;
12325 case 3: strcpy(fgptrput, "__gptrput3"); break;
12326 case 4: strcpy(fgptrput, "__gptrput4"); break;
12328 werror(W_POSSBUG2, __FILE__, __LINE__);
12332 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12337 sym = newSymbol( fgptrput, 0 );
12338 strcpy(sym->rname, fgptrput);
12339 checkAddSym(&externs, sym);
12343 pic16_freeAsmop(right,NULL,ic,TRUE);
12344 pic16_freeAsmop(result,NULL,ic,TRUE);
12347 /*-----------------------------------------------------------------*/
12348 /* genPointerSet - stores the value into a pointer location */
12349 /*-----------------------------------------------------------------*/
12350 static void genPointerSet (iCode *ic)
12352 operand *right, *result ;
12353 sym_link *type, *etype;
12358 right = IC_RIGHT(ic);
12359 result = IC_RESULT(ic) ;
12361 /* depending on the type of pointer we need to
12362 move it to the correct pointer register */
12363 type = operandType(result);
12364 etype = getSpec(type);
12365 /* if left is of type of pointer then it is simple */
12366 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12367 p_type = DCL_TYPE(type);
12370 /* we have to go by the storage class */
12371 p_type = PTR_TYPE(SPEC_OCLS(etype));
12373 /* if (SPEC_OCLS(etype)->codesp ) { */
12374 /* p_type = CPOINTER ; */
12377 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12378 /* p_type = FPOINTER ; */
12380 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12381 /* p_type = PPOINTER ; */
12383 /* if (SPEC_OCLS(etype) == idata ) */
12384 /* p_type = IPOINTER ; */
12386 /* p_type = POINTER ; */
12389 /* now that we have the pointer type we assign
12390 the pointer values */
12395 genNearPointerSet (right,result,ic);
12399 genPagedPointerSet (right,result,ic);
12403 genFarPointerSet (right,result,ic);
12407 genGenPointerSet (right,result,ic);
12411 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12412 "genPointerSet: illegal pointer type");
12416 /*-----------------------------------------------------------------*/
12417 /* genIfx - generate code for Ifx statement */
12418 /*-----------------------------------------------------------------*/
12419 static void genIfx (iCode *ic, iCode *popIc)
12421 operand *cond = IC_COND(ic);
12426 pic16_aopOp(cond,ic,FALSE);
12428 /* get the value into acc */
12429 if (AOP_TYPE(cond) != AOP_CRY)
12430 pic16_toBoolean(cond);
12433 /* the result is now in the accumulator */
12434 pic16_freeAsmop(cond,NULL,ic,TRUE);
12436 /* if there was something to be popped then do it */
12440 /* if the condition is a bit variable */
12441 if (isbit && IS_ITEMP(cond) &&
12443 genIfxJump(ic,"c");
12444 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12446 if (isbit && !IS_ITEMP(cond))
12447 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12449 genIfxJump(ic,"a");
12454 /*-----------------------------------------------------------------*/
12455 /* genAddrOf - generates code for address of */
12456 /*-----------------------------------------------------------------*/
12457 static void genAddrOf (iCode *ic)
12459 operand *result, *left;
12461 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12462 pCodeOp *pcop0, *pcop1, *pcop2;
12466 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12468 sym = OP_SYMBOL( IC_LEFT(ic) );
12471 /* get address of symbol on stack */
12472 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12474 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12475 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12478 // operands on stack are accessible via "FSR2 + index" with index
12479 // starting at 2 for arguments and growing from 0 downwards for
12480 // local variables (index == 0 is not assigned so we add one here)
12482 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12484 assert (soffs < 0);
12487 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12488 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12489 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(&pic16_pc_fsr2l));
12490 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12491 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12492 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(&pic16_pc_fsr2h));
12493 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12499 // if(pic16_debug_verbose) {
12500 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12501 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12504 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12505 size = AOP_SIZE(IC_RESULT(ic));
12508 /* Assume that what we want the address of is in data space
12509 * since there is no stack on the PIC, yet! -- VR */
12511 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12513 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12516 pic16_emitpcode(POC_MOVLW, pcop0);
12517 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12518 pic16_emitpcode(POC_MOVLW, pcop1);
12519 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12520 pic16_emitpcode(POC_MOVLW, pcop2);
12521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12524 pic16_emitpcode(POC_MOVLW, pcop0);
12525 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12526 pic16_emitpcode(POC_MOVLW, pcop1);
12527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12529 pic16_emitpcode(POC_MOVLW, pcop0);
12530 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12533 pic16_freeAsmop(left, NULL, ic, FALSE);
12535 pic16_freeAsmop(result,NULL,ic,TRUE);
12540 /*-----------------------------------------------------------------*/
12541 /* genFarFarAssign - assignment when both are in far space */
12542 /*-----------------------------------------------------------------*/
12543 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12545 int size = AOP_SIZE(right);
12548 /* first push the right side on to the stack */
12550 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12552 pic16_emitcode ("push","acc");
12555 pic16_freeAsmop(right,NULL,ic,FALSE);
12556 /* now assign DPTR to result */
12557 pic16_aopOp(result,ic,FALSE);
12558 size = AOP_SIZE(result);
12560 pic16_emitcode ("pop","acc");
12561 pic16_aopPut(AOP(result),"a",--offset);
12563 pic16_freeAsmop(result,NULL,ic,FALSE);
12568 /*-----------------------------------------------------------------*/
12569 /* genAssign - generate code for assignment */
12570 /*-----------------------------------------------------------------*/
12571 static void genAssign (iCode *ic)
12573 operand *result, *right;
12574 int size, offset,know_W;
12575 unsigned long lit = 0L;
12577 result = IC_RESULT(ic);
12578 right = IC_RIGHT(ic) ;
12582 /* if they are the same */
12583 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12586 /* reversed order operands are aopOp'ed so that result operand
12587 * is effective in case right is a stack symbol. This maneauver
12588 * allows to use the _G.resDirect flag later */
12589 pic16_aopOp(result,ic,TRUE);
12590 pic16_aopOp(right,ic,FALSE);
12592 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12594 /* if they are the same registers */
12595 if (pic16_sameRegs(AOP(right),AOP(result)))
12598 /* if the result is a bit */
12599 if (AOP_TYPE(result) == AOP_CRY) {
12600 /* if the right size is a literal then
12601 we know what the value is */
12602 if (AOP_TYPE(right) == AOP_LIT) {
12604 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12605 pic16_popGet(AOP(result),0));
12607 if (((int) operandLitValue(right)))
12608 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12609 AOP(result)->aopu.aop_dir,
12610 AOP(result)->aopu.aop_dir);
12612 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12613 AOP(result)->aopu.aop_dir,
12614 AOP(result)->aopu.aop_dir);
12618 /* the right is also a bit variable */
12619 if (AOP_TYPE(right) == AOP_CRY) {
12620 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12621 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12622 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12624 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12625 AOP(result)->aopu.aop_dir,
12626 AOP(result)->aopu.aop_dir);
12627 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12628 AOP(right)->aopu.aop_dir,
12629 AOP(right)->aopu.aop_dir);
12630 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12631 AOP(result)->aopu.aop_dir,
12632 AOP(result)->aopu.aop_dir);
12636 /* we need to or */
12637 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12638 pic16_toBoolean(right);
12640 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12641 //pic16_aopPut(AOP(result),"a",0);
12645 /* bit variables done */
12647 size = AOP_SIZE(result);
12650 if(AOP_TYPE(right) == AOP_LIT) {
12651 if(!IS_FLOAT(operandType( right )))
12652 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12655 unsigned long lit_int;
12659 /* take care if literal is a float */
12660 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12661 lit = info.lit_int;
12665 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12666 // sizeof(unsigned long int), sizeof(float));
12669 if (AOP_TYPE(right) == AOP_REG) {
12670 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12673 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12678 if(AOP_TYPE(right) != AOP_LIT
12679 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12680 && !IS_FUNC(OP_SYM_TYPE(right))
12682 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12683 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12685 // set up table pointer
12686 if(is_LitOp(right)) {
12687 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12688 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12689 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12690 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12691 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12692 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12693 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12695 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12696 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12697 pic16_popCopyReg(&pic16_pc_tblptrl)));
12698 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12699 pic16_popCopyReg(&pic16_pc_tblptrh)));
12700 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12701 pic16_popCopyReg(&pic16_pc_tblptru)));
12704 size = min(AOP_SIZE(right), AOP_SIZE(result));
12706 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12707 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12708 pic16_popGet(AOP(result),offset)));
12712 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12713 size = AOP_SIZE(result) - AOP_SIZE(right);
12715 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12725 /* VR - What is this?! */
12726 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12727 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12728 if(aopIdx(AOP(result),0) == 4) {
12730 /* this is a workaround to save value of right into wreg too,
12731 * value of wreg is going to be used later */
12732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12733 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12734 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12738 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12744 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12745 if(AOP_TYPE(right) == AOP_LIT) {
12747 if(know_W != (lit&0xff))
12748 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12750 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12752 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12756 } else if (AOP_TYPE(right) == AOP_CRY) {
12757 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12759 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12760 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12761 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12763 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12764 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12765 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12769 if(!_G.resDirect) /* use this aopForSym feature */
12770 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12777 pic16_freeAsmop (right,NULL,ic,FALSE);
12778 pic16_freeAsmop (result,NULL,ic,TRUE);
12781 /*-----------------------------------------------------------------*/
12782 /* genJumpTab - generates code for jump table */
12783 /*-----------------------------------------------------------------*/
12784 static void genJumpTab (iCode *ic)
12789 pCodeOp *jt_offs_hi;
12794 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12795 /* get the condition into accumulator */
12796 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12798 /* multiply by three */
12799 pic16_emitcode("add","a,acc");
12800 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12802 jtab = newiTempLabel(NULL);
12803 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12804 pic16_emitcode("jmp","@a+dptr");
12805 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12808 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12809 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12811 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12812 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12813 pic16_emitpLabel(jtab->key);
12817 jt_offs = pic16_popGetTempReg(0);
12818 jt_offs_hi = pic16_popGetTempReg(1);
12819 jt_label = pic16_popGetLabel (jtab->key);
12820 //fprintf (stderr, "Creating jump table...\n");
12822 // calculate offset into jump table (idx * sizeof (GOTO))
12823 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12824 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12825 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12826 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12827 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12828 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12829 pic16_emitpcode(POC_MOVWF , jt_offs);
12831 // prepare PCLATx (set to first entry in jump table)
12832 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12833 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12834 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12835 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12836 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12838 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12839 pic16_emitpcode(POC_ADDWF , jt_offs);
12840 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12841 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12843 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12845 // release temporaries and prepare jump into table (new PCL --> WREG)
12846 pic16_emitpcode(POC_MOVFW , jt_offs);
12847 pic16_popReleaseTempReg (jt_offs_hi, 1);
12848 pic16_popReleaseTempReg (jt_offs, 0);
12850 // jump into the table
12851 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12853 pic16_emitpLabelFORCE(jtab->key);
12856 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12858 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12859 /* now generate the jump labels */
12860 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12861 jtab = setNextItem(IC_JTLABELS(ic))) {
12862 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12863 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12866 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12870 /*-----------------------------------------------------------------*/
12871 /* genMixedOperation - gen code for operators between mixed types */
12872 /*-----------------------------------------------------------------*/
12874 TSD - Written for the PIC port - but this unfortunately is buggy.
12875 This routine is good in that it is able to efficiently promote
12876 types to different (larger) sizes. Unfortunately, the temporary
12877 variables that are optimized out by this routine are sometimes
12878 used in other places. So until I know how to really parse the
12879 iCode tree, I'm going to not be using this routine :(.
12881 static int genMixedOperation (iCode *ic)
12884 operand *result = IC_RESULT(ic);
12885 sym_link *ctype = operandType(IC_LEFT(ic));
12886 operand *right = IC_RIGHT(ic);
12892 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12894 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12900 nextright = IC_RIGHT(nextic);
12901 nextleft = IC_LEFT(nextic);
12902 nextresult = IC_RESULT(nextic);
12904 pic16_aopOp(right,ic,FALSE);
12905 pic16_aopOp(result,ic,FALSE);
12906 pic16_aopOp(nextright, nextic, FALSE);
12907 pic16_aopOp(nextleft, nextic, FALSE);
12908 pic16_aopOp(nextresult, nextic, FALSE);
12910 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12912 operand *t = right;
12916 pic16_emitcode(";remove right +","");
12918 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12920 operand *t = right;
12924 pic16_emitcode(";remove left +","");
12928 big = AOP_SIZE(nextleft);
12929 small = AOP_SIZE(nextright);
12931 switch(nextic->op) {
12934 pic16_emitcode(";optimize a +","");
12935 /* if unsigned or not an integral type */
12936 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12937 pic16_emitcode(";add a bit to something","");
12940 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12942 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12943 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12944 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12946 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12954 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12955 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12956 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12959 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12961 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12962 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12963 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12964 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12965 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12968 pic16_emitcode("rlf","known_zero,w");
12975 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12976 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12977 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12979 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12989 pic16_freeAsmop(right,NULL,ic,TRUE);
12990 pic16_freeAsmop(result,NULL,ic,TRUE);
12991 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12992 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12994 nextic->generated = 1;
13001 /*-----------------------------------------------------------------*/
13002 /* genCast - gen code for casting */
13003 /*-----------------------------------------------------------------*/
13004 static void genCast (iCode *ic)
13006 operand *result = IC_RESULT(ic);
13007 sym_link *ctype = operandType(IC_LEFT(ic));
13008 sym_link *rtype = operandType(IC_RIGHT(ic));
13009 sym_link *restype = operandType(IC_RESULT(ic));
13010 operand *right = IC_RIGHT(ic);
13016 /* if they are equivalent then do nothing */
13017 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13020 pic16_aopOp(right,ic,FALSE) ;
13021 pic16_aopOp(result,ic,FALSE);
13023 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13026 /* if the result is a bit */
13027 if (AOP_TYPE(result) == AOP_CRY) {
13029 /* if the right size is a literal then
13030 * we know what the value is */
13031 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13033 if (AOP_TYPE(right) == AOP_LIT) {
13034 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13035 pic16_popGet(AOP(result),0));
13037 if (((int) operandLitValue(right)))
13038 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13039 AOP(result)->aopu.aop_dir,
13040 AOP(result)->aopu.aop_dir);
13042 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13043 AOP(result)->aopu.aop_dir,
13044 AOP(result)->aopu.aop_dir);
13048 /* the right is also a bit variable */
13049 if (AOP_TYPE(right) == AOP_CRY) {
13051 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13053 pic16_emitcode("clrc","");
13054 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13055 AOP(right)->aopu.aop_dir,
13056 AOP(right)->aopu.aop_dir);
13057 pic16_aopPut(AOP(result),"c",0);
13061 /* we need to or */
13062 if (AOP_TYPE(right) == AOP_REG) {
13063 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13064 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13065 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13067 pic16_toBoolean(right);
13068 pic16_aopPut(AOP(result),"a",0);
13072 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13075 size = AOP_SIZE(result);
13077 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13079 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13080 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13081 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13084 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13089 if(IS_BITFIELD(getSpec(restype))
13090 && IS_BITFIELD(getSpec(rtype))) {
13091 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13094 /* if they are the same size : or less */
13095 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13097 /* if they are in the same place */
13098 if (pic16_sameRegs(AOP(right),AOP(result)))
13101 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13103 if (IS_PTR_CONST(rtype))
13105 if (IS_CODEPTR(rtype))
13107 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13110 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13112 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13114 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13117 if(AOP_TYPE(right) == AOP_IMMD) {
13118 pCodeOp *pcop0, *pcop1, *pcop2;
13119 symbol *sym = OP_SYMBOL( right );
13121 size = AOP_SIZE(result);
13123 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13125 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13127 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13130 pic16_emitpcode(POC_MOVLW, pcop0);
13131 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13132 pic16_emitpcode(POC_MOVLW, pcop1);
13133 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13134 pic16_emitpcode(POC_MOVLW, pcop2);
13135 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13138 pic16_emitpcode(POC_MOVLW, pcop0);
13139 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13140 pic16_emitpcode(POC_MOVLW, pcop1);
13141 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13143 pic16_emitpcode(POC_MOVLW, pcop0);
13144 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13148 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13149 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13150 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13151 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13152 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13153 if(AOP_SIZE(result) <2)
13154 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13156 /* if they in different places then copy */
13157 size = AOP_SIZE(result);
13160 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13161 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13168 /* if the result is of type pointer */
13169 if (IS_PTR(ctype)) {
13171 sym_link *type = operandType(right);
13172 sym_link *etype = getSpec(type);
13174 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13176 /* pointer to generic pointer */
13177 if (IS_GENPTR(ctype)) {
13181 p_type = DCL_TYPE(type);
13183 /* we have to go by the storage class */
13184 p_type = PTR_TYPE(SPEC_OCLS(etype));
13186 /* if (SPEC_OCLS(etype)->codesp ) */
13187 /* p_type = CPOINTER ; */
13189 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13190 /* p_type = FPOINTER ; */
13192 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13193 /* p_type = PPOINTER; */
13195 /* if (SPEC_OCLS(etype) == idata ) */
13196 /* p_type = IPOINTER ; */
13198 /* p_type = POINTER ; */
13201 /* the first two bytes are known */
13202 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13203 size = GPTRSIZE - 1;
13206 if(offset < AOP_SIZE(right)) {
13207 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13208 mov2f(AOP(result), AOP(right), offset);
13210 if ((AOP_TYPE(right) == AOP_PCODE) &&
13211 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13212 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13213 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13216 pic16_aopPut(AOP(result),
13217 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13222 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13225 /* the last byte depending on type */
13229 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13230 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13231 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13235 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13239 pic16_emitcode(";BUG!? ","%d",__LINE__);
13243 pic16_emitcode(";BUG!? ","%d",__LINE__);
13248 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13252 /* this should never happen */
13253 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13254 "got unknown pointer type");
13257 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13261 /* just copy the pointers */
13262 size = AOP_SIZE(result);
13265 pic16_aopPut(AOP(result),
13266 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13275 /* so we now know that the size of destination is greater
13276 than the size of the source.
13277 Now, if the next iCode is an operator then we might be
13278 able to optimize the operation without performing a cast.
13280 if(genMixedOperation(ic))
13283 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13285 /* we move to result for the size of source */
13286 size = AOP_SIZE(right);
13289 mov2f(AOP(result), AOP(right), offset);
13293 /* now depending on the sign of the destination */
13294 size = AOP_SIZE(result) - AOP_SIZE(right);
13295 /* if unsigned or not an integral type */
13296 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13298 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13300 /* we need to extend the sign :( */
13303 /* Save one instruction of casting char to int */
13304 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13305 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13306 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13308 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13311 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13313 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13315 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13318 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13323 pic16_freeAsmop(right,NULL,ic,TRUE);
13324 pic16_freeAsmop(result,NULL,ic,TRUE);
13328 /*-----------------------------------------------------------------*/
13329 /* genDjnz - generate decrement & jump if not zero instrucion */
13330 /*-----------------------------------------------------------------*/
13331 static int genDjnz (iCode *ic, iCode *ifx)
13333 symbol *lbl, *lbl1;
13334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13339 /* if the if condition has a false label
13340 then we cannot save */
13344 /* if the minus is not of the form
13346 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13347 !IS_OP_LITERAL(IC_RIGHT(ic)))
13350 if (operandLitValue(IC_RIGHT(ic)) != 1)
13353 /* if the size of this greater than one then no
13355 if (getSize(operandType(IC_RESULT(ic))) > 1)
13358 /* otherwise we can save BIG */
13359 lbl = newiTempLabel(NULL);
13360 lbl1= newiTempLabel(NULL);
13362 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13364 if (IS_AOP_PREG(IC_RESULT(ic))) {
13365 pic16_emitcode("dec","%s",
13366 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13367 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13368 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13372 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13373 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13375 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13376 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13380 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13381 ifx->generated = 1;
13385 /*-----------------------------------------------------------------*/
13386 /* genReceive - generate code for a receive iCode */
13387 /*-----------------------------------------------------------------*/
13388 static void genReceive (iCode *ic)
13394 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13395 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13397 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13399 if (isOperandInFarSpace(IC_RESULT(ic))
13400 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13401 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13403 int size = getSize(operandType(IC_RESULT(ic)));
13404 int offset = pic16_fReturnSizePic - size;
13408 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13409 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13413 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13415 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13416 size = AOP_SIZE(IC_RESULT(ic));
13419 pic16_emitcode ("pop","acc");
13420 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13423 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13425 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13428 /* set pseudo stack pointer to where it should be - dw*/
13429 GpsuedoStkPtr = ic->parmBytes;
13431 /* setting GpsuedoStkPtr has side effects here: */
13432 assignResultValue(IC_RESULT(ic), 0);
13435 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13438 /*-----------------------------------------------------------------*/
13439 /* genDummyRead - generate code for dummy read of volatiles */
13440 /*-----------------------------------------------------------------*/
13442 genDummyRead (iCode * ic)
13444 pic16_emitcode ("; genDummyRead","");
13445 pic16_emitcode ("; not implemented","");
13450 /*-----------------------------------------------------------------*/
13451 /* genpic16Code - generate code for pic16 based controllers */
13452 /*-----------------------------------------------------------------*/
13454 * At this point, ralloc.c has gone through the iCode and attempted
13455 * to optimize in a way suitable for a PIC. Now we've got to generate
13456 * PIC instructions that correspond to the iCode.
13458 * Once the instructions are generated, we'll pass through both the
13459 * peep hole optimizer and the pCode optimizer.
13460 *-----------------------------------------------------------------*/
13462 void genpic16Code (iCode *lic)
13467 lineHead = lineCurr = NULL;
13469 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13470 pic16_addpBlock(pb);
13473 /* if debug information required */
13474 if (options.debug && currFunc) {
13476 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13481 for (ic = lic ; ic ; ic = ic->next ) {
13483 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13484 if ( cln != ic->lineno ) {
13485 if ( options.debug ) {
13486 debugFile->writeCLine (ic);
13489 if(!options.noCcodeInAsm) {
13490 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13491 printCLine(ic->filename, ic->lineno)));
13497 if(options.iCodeInAsm) {
13500 /* insert here code to print iCode as comment */
13501 l = Safe_strdup(printILine(ic));
13502 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13505 /* if the result is marked as
13506 * spilt and rematerializable or code for
13507 * this has already been generated then
13509 if (resultRemat(ic) || ic->generated )
13512 /* depending on the operation */
13531 /* IPOP happens only when trying to restore a
13532 * spilt live range, if there is an ifx statement
13533 * following this pop then the if statement might
13534 * be using some of the registers being popped which
13535 * would destroy the contents of the register so
13536 * we need to check for this condition and handle it */
13538 && ic->next->op == IFX
13539 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13540 genIfx (ic->next,ic);
13558 genEndFunction (ic);
13574 pic16_genPlus (ic) ;
13578 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13579 pic16_genMinus (ic);
13595 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13599 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13605 /* note these two are xlated by algebraic equivalence
13606 * during parsing SDCC.y */
13607 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13608 "got '>=' or '<=' shouldn't have come here");
13612 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13624 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13628 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13632 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13656 genRightShift (ic);
13659 case GET_VALUE_AT_ADDRESS:
13664 if (POINTER_SET(ic))
13691 addSet(&_G.sendSet,ic);
13694 case DUMMY_READ_VOLATILE:
13704 /* now we are ready to call the
13705 peep hole optimizer */
13706 if (!options.nopeep)
13707 peepHole (&lineHead);
13709 /* now do the actual printing */
13710 printLine (lineHead, codeOutFile);
13713 DFPRINTF((stderr,"printing pBlock\n\n"));
13714 pic16_printpBlock(stdout,pb);