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 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4752 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4753 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4755 /*-----------------------------------------------------------------*/
4756 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4757 /* aop (if it's NOT a literal) or from lit (if */
4758 /* aop is a literal) */
4759 /*-----------------------------------------------------------------*/
4760 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4761 if (aop->type == AOP_LIT) {
4762 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4764 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4768 /*-----------------------------------------------------------------*/
4769 /* genCmp :- greater or less than comparison */
4770 /*-----------------------------------------------------------------*/
4772 #if USE_SIMPLE_GENCMP
4774 /* genCmp performs a left < right comparison, stores
4775 * the outcome in result (if != NULL) and generates
4776 * control flow code for the ifx (if != NULL).
4778 * This version leaves in sequences like
4779 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4780 * which should be optmized by the peephole
4781 * optimizer - RN 2005-01-01 */
4782 static void genCmp (operand *left,operand *right,
4783 operand *result, iCode *ifx, int sign)
4796 assert (AOP_SIZE(left) == AOP_SIZE(right));
4797 assert (left && right);
4799 size = AOP_SIZE(right) - 1;
4800 mask = (0x100UL << (size*8)) - 1;
4801 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4806 resolveIfx (&rIfx, ifx);
4808 /**********************************************************************
4809 * handle bits - bit compares are promoted to int compares seemingly! *
4810 **********************************************************************/
4812 // THIS IS COMPLETELY UNTESTED!
4813 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4814 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4815 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4816 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4819 // 1 < {0,1} is false --> clear C by skipping the next instruction
4820 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4821 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4822 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4823 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4824 emitCLRC; // only skipped for left=0 && right=1
4826 goto correct_result_in_carry;
4830 /*************************************************
4831 * make sure that left is register (or the like) *
4832 *************************************************/
4833 if (!isAOP_REGlike(left)) {
4834 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4835 assert (isAOP_LIT(left));
4836 assert (isAOP_REGlike(right));
4837 // swap left and right
4838 // left < right <==> right > left <==> (right >= left + 1)
4839 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4841 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4842 // MAXVALUE < right? always false
4843 if (performedLt) emitCLRC; else emitSETC;
4844 goto correct_result_in_carry;
4847 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4848 // that's we handled it above.
4855 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4856 } else if (isAOP_LIT(right)) {
4857 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4860 assert (isAOP_REGlike(left)); // left must be register or the like
4861 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4863 /*************************************************
4864 * special cases go here *
4865 *************************************************/
4867 if (isAOP_LIT(right)) {
4869 // unsigned comparison to a literal
4870 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4872 // unsigned left < 0? always false
4873 if (performedLt) emitCLRC; else emitSETC;
4874 goto correct_result_in_carry;
4877 // signed comparison to a literal
4878 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4879 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4880 // signed left < 0x80000000? always false
4881 if (performedLt) emitCLRC; else emitSETC;
4882 goto correct_result_in_carry;
4883 } else if (lit == 0) {
4884 // compare left < 0; set CARRY if SIGNBIT(left) is set
4885 if (performedLt) emitSETC; else emitCLRC;
4886 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4887 if (performedLt) emitCLRC; else emitSETC;
4888 goto correct_result_in_carry;
4891 } // right is literal
4893 /*************************************************
4894 * perform a general case comparison *
4895 * make sure we get CARRY==1 <==> left >= right *
4896 *************************************************/
4897 // compare most significant bytes
4898 //DEBUGpc ("comparing bytes at offset %d", size);
4900 // unsigned comparison
4901 mov2w_regOrLit (AOP(right), lit, size);
4902 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4904 // signed comparison
4905 // (add 2^n to both operands then perform an unsigned comparison)
4906 if (isAOP_LIT(right)) {
4907 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4908 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4910 if (litbyte == 0x80) {
4911 // left >= 0x80 -- always true, but more bytes to come
4912 pic16_mov2w (AOP(left), size);
4913 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4916 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4917 pic16_mov2w (AOP(left), size);
4918 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4919 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4922 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4923 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4924 pic16_mov2w (AOP(left), size);
4925 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4926 pic16_emitpcode (POC_MOVWF, pctemp);
4927 pic16_mov2w (AOP(right), size);
4928 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4929 pic16_emitpcode (POC_SUBFW, pctemp);
4930 //pic16_popReleaseTempReg(pctemp, 1);
4934 // compare remaining bytes (treat as unsigned case from above)
4935 templbl = newiTempLabel ( NULL );
4938 //DEBUGpc ("comparing bytes at offset %d", offs);
4939 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4940 mov2w_regOrLit (AOP(right), lit, offs);
4941 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4943 pic16_emitpLabel (templbl->key);
4944 goto result_in_carry;
4948 /****************************************************
4949 * now CARRY contains the result of the comparison: *
4950 * SUBWF sets CARRY iff *
4951 * F-W >= 0 <==> F >= W <==> !(F < W) *
4953 ****************************************************/
4956 if (result && AOP_TYPE(result) != AOP_CRY) {
4957 // value will be stored
4960 // value wil only be used in the following genSkipc()
4961 rIfx.condition ^= 1;
4965 correct_result_in_carry:
4967 // assign result to variable (if neccessary)
4968 if (result && AOP_TYPE(result) != AOP_CRY) {
4969 //DEBUGpc ("assign result");
4970 size = AOP_SIZE(result);
4972 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4974 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4977 // perform conditional jump
4978 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
4980 //DEBUGpc ("generate control flow");
4981 rIfx.condition ^= 1;
4990 static void genCmp (operand *left,operand *right,
4991 operand *result, iCode *ifx, int sign)
4993 int size; //, offset = 0 ;
4994 unsigned long lit = 0L,i = 0;
4995 resolvedIfx rFalseIfx;
4996 // resolvedIfx rTrueIfx;
4998 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5001 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5002 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5008 resolveIfx(&rFalseIfx,ifx);
5009 truelbl = newiTempLabel(NULL);
5010 size = max(AOP_SIZE(left),AOP_SIZE(right));
5012 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5016 /* if literal is on the right then swap with left */
5017 if ((AOP_TYPE(right) == AOP_LIT)) {
5018 operand *tmp = right ;
5019 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5020 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5023 lit = (lit - 1) & mask;
5026 rFalseIfx.condition ^= 1;
5029 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5030 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5034 //if(IC_TRUE(ifx) == NULL)
5035 /* if left & right are bit variables */
5036 if (AOP_TYPE(left) == AOP_CRY &&
5037 AOP_TYPE(right) == AOP_CRY ) {
5038 assert (0 && "bit variables used in genCmp");
5039 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5040 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5042 /* subtract right from left if at the
5043 end the carry flag is set then we know that
5044 left is greater than right */
5046 symbol *lbl = newiTempLabel(NULL);
5049 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5050 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5054 if(AOP_TYPE(right) == AOP_LIT) {
5056 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5058 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5065 genSkipCond(&rFalseIfx,left,size-1,7);
5067 /* no need to compare to 0...*/
5068 /* NOTE: this is a de-generate compare that most certainly
5069 * creates some dead code. */
5070 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5072 if(ifx) ifx->generated = 1;
5079 //i = (lit >> (size*8)) & 0xff;
5080 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5082 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5084 i = ((0-lit) & 0xff);
5087 /* lit is 0x7f, all signed chars are less than
5088 * this except for 0x7f itself */
5089 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5090 genSkipz2(&rFalseIfx,0);
5092 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5093 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5094 genSkipc(&rFalseIfx);
5099 genSkipz2(&rFalseIfx,1);
5101 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5102 genSkipc(&rFalseIfx);
5106 if(ifx) ifx->generated = 1;
5110 /* chars are out of the way. now do ints and longs */
5113 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5120 genSkipCond(&rFalseIfx,left,size,7);
5121 if(ifx) ifx->generated = 1;
5126 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5128 //rFalseIfx.condition ^= 1;
5129 //genSkipCond(&rFalseIfx,left,size,7);
5130 //rFalseIfx.condition ^= 1;
5132 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5133 if(rFalseIfx.condition)
5134 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5136 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5138 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5139 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5140 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5143 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5145 if(rFalseIfx.condition) {
5147 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5153 genSkipc(&rFalseIfx);
5154 pic16_emitpLabel(truelbl->key);
5155 if(ifx) ifx->generated = 1;
5162 if( (lit & 0xff) == 0) {
5163 /* lower byte is zero */
5164 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5165 i = ((lit >> 8) & 0xff) ^0x80;
5166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5167 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5168 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5169 genSkipc(&rFalseIfx);
5172 if(ifx) ifx->generated = 1;
5177 /* Special cases for signed longs */
5178 if( (lit & 0xffffff) == 0) {
5179 /* lower byte is zero */
5180 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5181 i = ((lit >> 8*3) & 0xff) ^0x80;
5182 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5183 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5184 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5185 genSkipc(&rFalseIfx);
5188 if(ifx) ifx->generated = 1;
5196 if(lit & (0x80 << (size*8))) {
5197 /* lit is negative */
5198 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5200 //genSkipCond(&rFalseIfx,left,size,7);
5202 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5204 if(rFalseIfx.condition)
5205 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5207 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5211 /* lit is positive */
5212 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5213 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5214 if(rFalseIfx.condition)
5215 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5217 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5222 This works, but is only good for ints.
5223 It also requires a "known zero" register.
5224 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5225 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5226 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5228 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5229 genSkipc(&rFalseIfx);
5231 pic16_emitpLabel(truelbl->key);
5232 if(ifx) ifx->generated = 1;
5236 /* There are no more special cases, so perform a general compare */
5238 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5239 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5243 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5245 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5247 //rFalseIfx.condition ^= 1;
5248 genSkipc(&rFalseIfx);
5250 pic16_emitpLabel(truelbl->key);
5252 if(ifx) ifx->generated = 1;
5259 /* sign is out of the way. So now do an unsigned compare */
5260 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5263 /* General case - compare to an unsigned literal on the right.*/
5265 i = (lit >> (size*8)) & 0xff;
5266 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5267 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5269 i = (lit >> (size*8)) & 0xff;
5272 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5274 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5276 /* this byte of the lit is zero,
5277 *if it's not the last then OR in the variable */
5279 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5284 pic16_emitpLabel(lbl->key);
5285 // pic16_emitpLabel(truelbl->key);
5286 //if(emitFinalCheck)
5287 genSkipc(&rFalseIfx);
5289 pic16_emitpLabel(truelbl->key);
5291 if(ifx) ifx->generated = 1;
5298 if(AOP_TYPE(left) == AOP_LIT) {
5299 //symbol *lbl = newiTempLabel(NULL);
5301 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5304 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5307 if((lit == 0) && (sign == 0)){
5310 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5312 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5314 genSkipz2(&rFalseIfx,0);
5315 if(ifx) ifx->generated = 1;
5322 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5323 /* degenerate compare can never be true */
5324 if(rFalseIfx.condition == 0)
5325 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5327 if(ifx) ifx->generated = 1;
5332 /* signed comparisons to a literal byte */
5334 int lp1 = (lit+1) & 0xff;
5336 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5339 rFalseIfx.condition ^= 1;
5340 genSkipCond(&rFalseIfx,right,0,7);
5343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5344 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5345 genSkipz2(&rFalseIfx,1);
5348 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5349 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5350 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5351 rFalseIfx.condition ^= 1;
5352 genSkipc(&rFalseIfx);
5356 /* unsigned comparisons to a literal byte */
5358 switch(lit & 0xff ) {
5360 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5361 genSkipz2(&rFalseIfx,0);
5364 rFalseIfx.condition ^= 1;
5365 genSkipCond(&rFalseIfx,right,0,7);
5369 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5370 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5371 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5372 rFalseIfx.condition ^= 1;
5373 if (AOP_TYPE(result) == AOP_CRY)
5374 genSkipc(&rFalseIfx);
5376 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5377 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5383 if(ifx) ifx->generated = 1;
5384 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5390 /* Size is greater than 1 */
5398 /* this means lit = 0xffffffff, or -1 */
5401 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5402 rFalseIfx.condition ^= 1;
5403 genSkipCond(&rFalseIfx,right,size,7);
5404 if(ifx) ifx->generated = 1;
5406 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5415 if(rFalseIfx.condition) {
5416 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5420 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5422 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5426 if(rFalseIfx.condition) {
5427 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5428 pic16_emitpLabel(truelbl->key);
5430 rFalseIfx.condition ^= 1;
5431 genSkipCond(&rFalseIfx,right,s,7);
5434 if(ifx) ifx->generated = 1;
5436 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5442 if((size == 1) && (0 == (lp1&0xff))) {
5443 /* lower byte of signed word is zero */
5444 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5445 i = ((lp1 >> 8) & 0xff) ^0x80;
5446 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5447 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5448 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5450 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5452 if(ifx) ifx->generated = 1;
5455 rFalseIfx.condition ^= 1;
5456 genSkipc(&rFalseIfx);
5457 if(ifx) ifx->generated = 1;
5463 if(lit & (0x80 << (size*8))) {
5464 /* Lit is less than zero */
5465 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5466 //rFalseIfx.condition ^= 1;
5467 //genSkipCond(&rFalseIfx,left,size,7);
5468 //rFalseIfx.condition ^= 1;
5469 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5470 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5472 if(rFalseIfx.condition)
5473 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5475 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5479 /* Lit is greater than or equal to zero */
5480 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5481 //rFalseIfx.condition ^= 1;
5482 //genSkipCond(&rFalseIfx,right,size,7);
5483 //rFalseIfx.condition ^= 1;
5485 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5486 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5488 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5489 if(rFalseIfx.condition)
5490 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5492 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5496 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5497 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5501 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5503 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5505 rFalseIfx.condition ^= 1;
5506 //rFalseIfx.condition = 1;
5507 genSkipc(&rFalseIfx);
5509 pic16_emitpLabel(truelbl->key);
5511 if(ifx) ifx->generated = 1;
5514 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5521 /* compare word or long to an unsigned literal on the right.*/
5526 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5529 break; /* handled above */
5532 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5534 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5535 genSkipz2(&rFalseIfx,0);
5539 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5541 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5544 if(rFalseIfx.condition)
5545 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5547 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5550 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5551 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5553 rFalseIfx.condition ^= 1;
5554 genSkipc(&rFalseIfx);
5557 pic16_emitpLabel(truelbl->key);
5559 if(ifx) ifx->generated = 1;
5561 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5569 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5570 i = (lit >> (size*8)) & 0xff;
5572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5573 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5576 i = (lit >> (size*8)) & 0xff;
5579 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5581 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5583 /* this byte of the lit is zero,
5584 * if it's not the last then OR in the variable */
5586 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5591 pic16_emitpLabel(lbl->key);
5593 rFalseIfx.condition ^= 1;
5595 genSkipc(&rFalseIfx);
5599 pic16_emitpLabel(truelbl->key);
5600 if(ifx) ifx->generated = 1;
5602 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5608 /* Compare two variables */
5610 DEBUGpic16_emitcode(";sign","%d",sign);
5614 /* Sigh. thus sucks... */
5618 pctemp = pic16_popGetTempReg(1);
5619 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5620 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5621 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5622 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5623 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5624 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5625 pic16_popReleaseTempReg(pctemp, 1);
5627 /* Signed char comparison */
5628 /* Special thanks to Nikolai Golovchenko for this snippet */
5629 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5630 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5631 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5632 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5633 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5634 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5637 genSkipc(&rFalseIfx);
5639 if(ifx) ifx->generated = 1;
5641 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5654 /* The rest of the bytes of a multi-byte compare */
5658 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5661 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5662 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5667 pic16_emitpLabel(lbl->key);
5669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5670 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5671 (AOP_TYPE(result) == AOP_REG)) {
5672 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5673 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5675 genSkipc(&rFalseIfx);
5677 //genSkipc(&rFalseIfx);
5678 if(ifx) ifx->generated = 1;
5681 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5689 if ((AOP_TYPE(result) != AOP_CRY)
5690 && AOP_SIZE(result)) {
5691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5693 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5695 pic16_outBitC(result);
5697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5698 /* if the result is used in the next
5699 ifx conditional branch then generate
5700 code a little differently */
5702 genIfxJump (ifx,"c");
5704 pic16_outBitC(result);
5705 /* leave the result in acc */
5710 #else /* old version of genCmp() */ /* } else { */
5712 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5713 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5714 operand *result, int offset, int invert_op)
5718 /* check condition, > or < ?? */
5719 if(rIfx->condition != 0)invert_op ^= 1;
5721 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5723 if(!ifx)invert_op ^= 1;
5725 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5726 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5729 if(!invert_op)return POC_CPFSGT;
5730 else return POC_CPFSLT;
5733 static int compareAopfirstpass=1;
5735 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5736 operand *oper, int offset, operand *result,
5737 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5743 /* invert if there is a result to be loaded, in order to fit,
5744 * SETC/CLRC sequence */
5745 if(AOP_SIZE(result))invert_op ^= 1;
5747 // if(sign && !offset)invert_op ^= 1;
5749 // if(sign)invert_op ^= 1;
5751 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5753 if(AOP_SIZE(result) && compareAopfirstpass) {
5756 pic16_emitpcode(POC_SETF, pcop2);
5761 pic16_emitpcode(POC_CLRF, pcop2);
5767 compareAopfirstpass = 0;
5769 /* there is a bug when comparing operands with size > 1,
5770 * because higher bytes can be equal and test should be performed
5771 * to the next lower byte, current algorithm, considers operands
5772 * inequal in these cases! -- VR 20041107 */
5776 pic16_emitpcode(op, pcop);
5778 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5781 if((!sign || !offset) && AOP_SIZE(result)) {
5784 pic16_emitpcode(POC_CLRF, pcop2);
5789 pic16_emitpcode(POC_SETF, pcop2);
5794 /* don't emit final branch (offset == 0) */
5798 pic16_emitpcode(POC_RRCF, pcop2);
5800 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5803 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5804 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5805 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5807 truelbl = newiTempLabel( NULL );
5808 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5809 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5810 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5812 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5813 pic16_emitpLabel(truelbl->key);
5815 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5824 static void genCmp (operand *left, operand *right,
5825 operand *result, iCode *ifx, int sign)
5829 resolvedIfx rFalseIfx;
5830 symbol *falselbl, *tlbl;
5834 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5836 resolveIfx(&rFalseIfx, ifx);
5837 size = max(AOP_SIZE(left), AOP_SIZE(right));
5839 /* if left & right are bit variables */
5840 if(AOP_TYPE(left) == AOP_CRY
5841 && AOP_TYPE(right) == AOP_CRY ) {
5843 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5844 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5846 werror(W_POSSBUG2, __FILE__, __LINE__);
5850 /* if literal is on the right then swap with left */
5851 if((AOP_TYPE(right) == AOP_LIT)) {
5852 operand *tmp = right ;
5853 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5855 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5857 // lit = (lit - 1) & mask;
5860 rFalseIfx.condition ^= 1; /* reverse compare */
5862 if ((AOP_TYPE(left) == AOP_LIT)) {
5863 /* float compares are handled by support functions */
5864 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5867 /* actual comparing algorithm */
5868 // size = AOP_SIZE( right );
5870 falselbl = newiTempLabel( NULL );
5871 if(AOP_TYPE(left) == AOP_LIT) {
5872 /* compare to literal */
5873 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5876 pCodeOp *pct, *pct2;
5879 /* signed compare */
5880 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5882 pct = pic16_popCopyReg(&pic16_pc_prodl);
5883 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5884 tlbl = newiTempLabel( NULL );
5886 /* first compare signs:
5887 * a. if both are positive, compare just like unsigned
5888 * b. if both are negative, invert cmpop, compare just like unsigned
5889 * c. if different signs, determine the result directly */
5895 tlbl1 = newiTempLabel( NULL );
5896 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5900 /* literal is zero or positive:
5901 * a. if carry is zero, too, continue compare,
5902 * b. if carry is set, then continue depending on cmpop ^ condition:
5903 * 1. '<' return false (literal < variable),
5904 * 2. '>' return true (literal > variable) */
5905 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5906 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5909 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5910 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5914 /* literal is negative:
5915 * a. if carry is set, too, continue compare,
5916 * b. if carry is zero, then continue depending on cmpop ^ condition:
5917 * 1. '<' return true (literal < variable),
5918 * 2. '>' return false (literal > variable) */
5919 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5920 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5922 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5923 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5928 pic16_emitpcode(POC_BTFSC, 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_emitpLabel( tlbl1->key );
5939 compareAopfirstpass=1;
5940 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5941 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5942 // pic16_emitpcode(POC_MOVWF, pct);
5944 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5945 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5946 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5947 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5951 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5952 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5953 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5954 // pic16_emitpcode(POC_MOVWF, pct);
5956 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5958 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5959 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5960 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5964 if(ifx)ifx->generated = 1;
5966 if(AOP_SIZE(result)) {
5967 pic16_emitpLabel(tlbl->key);
5968 pic16_emitpLabel(falselbl->key);
5969 pic16_outBitOp( result, pct2 );
5971 pic16_emitpLabel(tlbl->key);
5976 /* unsigned compare */
5977 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5979 compareAopfirstpass=1;
5982 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5983 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5987 if(ifx)ifx->generated = 1;
5990 if(AOP_SIZE(result)) {
5991 pic16_emitpLabel(falselbl->key);
5992 pic16_outBitC( result );
5997 /* compare registers */
5998 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6002 pCodeOp *pct, *pct2;
6004 /* signed compare */
6005 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6007 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6008 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6009 tlbl = newiTempLabel( NULL );
6011 compareAopfirstpass=1;
6014 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6015 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6016 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6017 pic16_emitpcode(POC_MOVWF, pct);
6019 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6020 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6021 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6023 /* WREG already holds left + 0x80 */
6024 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6027 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6028 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6029 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6030 pic16_emitpcode(POC_MOVWF, pct);
6032 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6033 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6034 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6036 /* WREG already holds left + 0x80 */
6037 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6038 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6041 if(ifx)ifx->generated = 1;
6043 if(AOP_SIZE(result)) {
6044 pic16_emitpLabel(tlbl->key);
6045 pic16_emitpLabel(falselbl->key);
6046 pic16_outBitOp( result, pct2 );
6048 pic16_emitpLabel(tlbl->key);
6052 /* unsigned compare */
6053 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6055 compareAopfirstpass=1;
6058 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6059 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6063 if(ifx)ifx->generated = 1;
6064 if(AOP_SIZE(result)) {
6066 pic16_emitpLabel(falselbl->key);
6067 pic16_outBitC( result );
6074 #else /* } else { */
6076 /* new version of genCmp -- VR 20041012 */
6077 static void genCmp (operand *left,operand *right,
6078 operand *result, iCode *ifx, int sign)
6080 int size; //, offset = 0 ;
6081 unsigned long lit = 0L,i = 0;
6082 resolvedIfx rFalseIfx;
6083 int willCheckCarry=0;
6084 // resolvedIfx rTrueIfx;
6090 * subtract right from left if at the end the carry flag is set then we
6091 * know that left is greater than right */
6093 resolveIfx(&rFalseIfx,ifx);
6094 truelbl = newiTempLabel(NULL);
6095 size = max(AOP_SIZE(left),AOP_SIZE(right));
6097 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6099 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6100 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6103 /* if literal is on the right then swap with left */
6104 if ((AOP_TYPE(right) == AOP_LIT)) {
6105 operand *tmp = right ;
6106 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6108 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6110 // lit = (lit - 1) & mask;
6113 rFalseIfx.condition ^= 1; /* reverse compare */
6115 if ((AOP_TYPE(left) == AOP_LIT)) {
6116 /* float compares are handled by support functions */
6117 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6121 //if(IC_TRUE(ifx) == NULL)
6122 /* if left & right are bit variables */
6123 if (AOP_TYPE(left) == AOP_CRY &&
6124 AOP_TYPE(right) == AOP_CRY ) {
6126 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6127 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6130 symbol *lbl = newiTempLabel(NULL);
6132 if(AOP_TYPE(left) == AOP_LIT) {
6133 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6135 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6137 else willCheckCarry = 0;
6140 if((lit == 0) && (sign == 0)) {
6141 /* unsigned compare to 0 */
6142 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6145 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6147 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6149 genSkipz2(&rFalseIfx,0);
6150 if(ifx)ifx->generated = 1;
6157 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6158 /* degenerate compare can never be true */
6159 if(rFalseIfx.condition == 0)
6160 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6162 if(ifx) ifx->generated = 1;
6167 /* signed comparisons to a literal byte */
6168 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6170 int lp1 = (lit+1) & 0xff;
6172 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6175 rFalseIfx.condition ^= 1;
6176 genSkipCond(&rFalseIfx,right,0,7);
6179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6180 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6181 genSkipz2(&rFalseIfx,1);
6184 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6186 if(rFalseIfx.condition)
6187 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6189 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6191 if(willCheckCarry) {
6192 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6193 else { emitSETC; emitCLRC; }
6196 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6199 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6200 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6201 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6202 rFalseIfx.condition ^= 1;
6203 genSkipc(&rFalseIfx);
6208 /* unsigned comparisons to a literal byte */
6209 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6211 switch(lit & 0xff ) {
6214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6215 genSkipz2(&rFalseIfx,0);
6218 rFalseIfx.condition ^= 1;
6219 genSkipCond(&rFalseIfx,right,0,7);
6222 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6223 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6225 rFalseIfx.condition ^= 1;
6226 if (AOP_TYPE(result) == AOP_CRY)
6227 genSkipc(&rFalseIfx);
6229 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6230 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6236 if(ifx) ifx->generated = 1;
6237 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6243 /* Size is greater than 1 */
6251 /* this means lit = 0xffffffff, or -1 */
6254 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6255 rFalseIfx.condition ^= 1;
6256 genSkipCond(&rFalseIfx,right,size,7);
6257 if(ifx) ifx->generated = 1;
6264 if(rFalseIfx.condition) {
6265 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6266 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6269 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6271 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6275 if(rFalseIfx.condition) {
6276 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6277 pic16_emitpLabel(truelbl->key);
6279 rFalseIfx.condition ^= 1;
6280 genSkipCond(&rFalseIfx,right,s,7);
6283 if(ifx) ifx->generated = 1;
6287 if((size == 1) && (0 == (lp1&0xff))) {
6288 /* lower byte of signed word is zero */
6289 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6290 i = ((lp1 >> 8) & 0xff) ^0x80;
6291 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6292 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6293 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6294 rFalseIfx.condition ^= 1;
6295 genSkipc(&rFalseIfx);
6298 if(ifx) ifx->generated = 1;
6302 if(lit & (0x80 << (size*8))) {
6303 /* Lit is less than zero */
6304 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6305 //rFalseIfx.condition ^= 1;
6306 //genSkipCond(&rFalseIfx,left,size,7);
6307 //rFalseIfx.condition ^= 1;
6308 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6309 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6311 if(rFalseIfx.condition)
6312 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6314 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6318 /* Lit is greater than or equal to zero */
6319 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6320 //rFalseIfx.condition ^= 1;
6321 //genSkipCond(&rFalseIfx,right,size,7);
6322 //rFalseIfx.condition ^= 1;
6324 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6325 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6327 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6328 if(rFalseIfx.condition)
6329 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6331 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6336 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6337 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6343 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6345 rFalseIfx.condition ^= 1;
6346 //rFalseIfx.condition = 1;
6347 genSkipc(&rFalseIfx);
6349 pic16_emitpLabel(truelbl->key);
6351 if(ifx) ifx->generated = 1;
6356 /* compare word or long to an unsigned literal on the right.*/
6361 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6364 break; /* handled above */
6367 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6369 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6370 genSkipz2(&rFalseIfx,0);
6374 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6376 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6379 if(rFalseIfx.condition)
6380 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6382 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6385 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6386 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6388 rFalseIfx.condition ^= 1;
6389 genSkipc(&rFalseIfx);
6392 pic16_emitpLabel(truelbl->key);
6394 if(ifx) ifx->generated = 1;
6400 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6401 i = (lit >> (size*8)) & 0xff;
6403 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6404 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6407 i = (lit >> (size*8)) & 0xff;
6410 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6412 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6414 /* this byte of the lit is zero,
6415 * if it's not the last then OR in the variable */
6417 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6422 pic16_emitpLabel(lbl->key);
6424 rFalseIfx.condition ^= 1;
6426 genSkipc(&rFalseIfx);
6430 pic16_emitpLabel(truelbl->key);
6431 if(ifx) ifx->generated = 1;
6435 /* Compare two variables */
6437 DEBUGpic16_emitcode(";sign","%d",sign);
6441 /* Sigh. thus sucks... */
6445 pctemp = pic16_popGetTempReg(1);
6446 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6447 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6448 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6449 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6450 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6451 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6452 pic16_popReleaseTempReg(pctemp, 1);
6454 /* Signed char comparison */
6455 /* Special thanks to Nikolai Golovchenko for this snippet */
6456 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6457 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6458 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6459 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6460 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6461 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6464 genSkipc(&rFalseIfx);
6466 if(ifx) ifx->generated = 1;
6472 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6473 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6477 /* The rest of the bytes of a multi-byte compare */
6481 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6484 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6485 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6490 pic16_emitpLabel(lbl->key);
6492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6493 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6494 (AOP_TYPE(result) == AOP_REG)) {
6495 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6496 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6498 genSkipc(&rFalseIfx);
6500 //genSkipc(&rFalseIfx);
6501 if(ifx) ifx->generated = 1;
6508 if ((AOP_TYPE(result) != AOP_CRY)
6509 && AOP_SIZE(result)) {
6510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6512 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6514 pic16_outBitC(result);
6516 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6517 /* if the result is used in the next
6518 ifx conditional branch then generate
6519 code a little differently */
6521 genIfxJump (ifx,"c");
6523 pic16_outBitC(result);
6524 /* leave the result in acc */
6535 /*-----------------------------------------------------------------*/
6536 /* genCmpGt :- greater than comparison */
6537 /*-----------------------------------------------------------------*/
6538 static void genCmpGt (iCode *ic, iCode *ifx)
6540 operand *left, *right, *result;
6541 sym_link *letype , *retype;
6547 right= IC_RIGHT(ic);
6548 result = IC_RESULT(ic);
6550 letype = getSpec(operandType(left));
6551 retype =getSpec(operandType(right));
6552 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6553 /* assign the amsops */
6554 pic16_aopOp (left,ic,FALSE);
6555 pic16_aopOp (right,ic,FALSE);
6556 pic16_aopOp (result,ic,TRUE);
6558 genCmp(right, left, result, ifx, sign);
6560 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6561 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6562 pic16_freeAsmop(result,NULL,ic,TRUE);
6565 /*-----------------------------------------------------------------*/
6566 /* genCmpLt - less than comparisons */
6567 /*-----------------------------------------------------------------*/
6568 static void genCmpLt (iCode *ic, iCode *ifx)
6570 operand *left, *right, *result;
6571 sym_link *letype , *retype;
6577 right= IC_RIGHT(ic);
6578 result = IC_RESULT(ic);
6580 letype = getSpec(operandType(left));
6581 retype =getSpec(operandType(right));
6582 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6584 /* assign the amsops */
6585 pic16_aopOp (left,ic,FALSE);
6586 pic16_aopOp (right,ic,FALSE);
6587 pic16_aopOp (result,ic,TRUE);
6589 genCmp(left, right, result, ifx, sign);
6591 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6592 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6593 pic16_freeAsmop(result,NULL,ic,TRUE);
6598 // FIXME reenable literal optimisation when the pic16 port is stable
6600 /*-----------------------------------------------------------------*/
6601 /* genc16bit2lit - compare a 16 bit value to a literal */
6602 /*-----------------------------------------------------------------*/
6603 static void genc16bit2lit(operand *op, int lit, int offset)
6607 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6608 if( (lit&0xff) == 0)
6613 switch( BYTEofLONG(lit,i)) {
6615 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6618 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6621 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6624 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6625 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6630 switch( BYTEofLONG(lit,i)) {
6632 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6636 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6640 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6643 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6645 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6654 /*-----------------------------------------------------------------*/
6655 /* gencjneshort - compare and jump if not equal */
6656 /*-----------------------------------------------------------------*/
6657 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6659 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6661 int res_offset = 0; /* the result may be a different size then left or right */
6662 int res_size = AOP_SIZE(result);
6664 symbol *lbl, *lbl_done;
6666 unsigned long lit = 0L;
6667 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6670 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6672 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6673 resolveIfx(&rIfx,ifx);
6674 lbl = newiTempLabel(NULL);
6675 lbl_done = newiTempLabel(NULL);
6678 /* if the left side is a literal or
6679 if the right is in a pointer register and left
6681 if ((AOP_TYPE(left) == AOP_LIT) ||
6682 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6687 if(AOP_TYPE(right) == AOP_LIT)
6688 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6690 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6691 preserve_result = 1;
6693 if(result && !preserve_result)
6696 for(i = 0; i < AOP_SIZE(result); i++)
6697 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6701 /* if the right side is a literal then anything goes */
6702 if (AOP_TYPE(right) == AOP_LIT &&
6703 AOP_TYPE(left) != AOP_DIR ) {
6706 genc16bit2lit(left, lit, 0);
6708 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6711 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6714 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6715 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6717 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6721 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6723 if(res_offset < res_size-1)
6731 /* if the right side is in a register or in direct space or
6732 if the left is a pointer register & right is not */
6733 else if (AOP_TYPE(right) == AOP_REG ||
6734 AOP_TYPE(right) == AOP_DIR ||
6735 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6736 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6737 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6738 int lbl_key = lbl->key;
6741 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6742 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6744 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6745 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6746 __FUNCTION__,__LINE__);
6750 /* switch(size) { */
6752 /* genc16bit2lit(left, lit, 0); */
6754 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6759 if((AOP_TYPE(left) == AOP_DIR) &&
6760 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6762 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6763 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6765 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6767 switch (lit & 0xff) {
6769 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6772 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6773 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6774 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6778 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6779 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6780 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6781 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6785 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6786 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6791 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6794 if(AOP_TYPE(result) == AOP_CRY) {
6795 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6802 /* fix me. probably need to check result size too */
6803 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6808 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6809 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6816 if(res_offset < res_size-1)
6821 } else if(AOP_TYPE(right) == AOP_REG &&
6822 AOP_TYPE(left) != AOP_DIR){
6825 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6826 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6827 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6832 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6834 if(res_offset < res_size-1)
6839 /* right is a pointer reg need both a & b */
6841 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6843 pic16_emitcode("mov","b,%s",l);
6844 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6845 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6850 if(result && preserve_result)
6853 for(i = 0; i < AOP_SIZE(result); i++)
6854 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6857 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6859 if(result && preserve_result)
6860 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6863 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6865 pic16_emitpLabel(lbl->key);
6867 if(result && preserve_result)
6870 for(i = 0; i < AOP_SIZE(result); i++)
6871 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6873 pic16_emitpLabel(lbl_done->key);
6876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6884 /*-----------------------------------------------------------------*/
6885 /* gencjne - compare and jump if not equal */
6886 /*-----------------------------------------------------------------*/
6887 static void gencjne(operand *left, operand *right, iCode *ifx)
6889 symbol *tlbl = newiTempLabel(NULL);
6891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6892 gencjneshort(left, right, lbl);
6894 pic16_emitcode("mov","a,%s",one);
6895 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6896 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6897 pic16_emitcode("clr","a");
6898 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6900 pic16_emitpLabel(lbl->key);
6901 pic16_emitpLabel(tlbl->key);
6907 /*-----------------------------------------------------------------*/
6908 /* is_LitOp - check if operand has to be treated as literal */
6909 /*-----------------------------------------------------------------*/
6910 static bool is_LitOp(operand *op)
6912 return ((AOP_TYPE(op) == AOP_LIT)
6913 || ( (AOP_TYPE(op) == AOP_PCODE)
6914 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6915 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6918 /*-----------------------------------------------------------------*/
6919 /* is_LitAOp - check if operand has to be treated as literal */
6920 /*-----------------------------------------------------------------*/
6921 static bool is_LitAOp(asmop *aop)
6923 return ((aop->type == AOP_LIT)
6924 || ( (aop->type == AOP_PCODE)
6925 && ( (aop->aopu.pcop->type == PO_LITERAL)
6926 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6931 /*-----------------------------------------------------------------*/
6932 /* genCmpEq - generates code for equal to */
6933 /*-----------------------------------------------------------------*/
6934 static void genCmpEq (iCode *ic, iCode *ifx)
6936 operand *left, *right, *result;
6937 symbol *falselbl = newiTempLabel(NULL);
6938 symbol *donelbl = newiTempLabel(NULL);
6940 int preserve_result = 0;
6941 int generate_result = 0;
6946 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6947 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6948 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6950 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6952 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6954 werror(W_POSSBUG2, __FILE__, __LINE__);
6955 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6956 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6960 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6962 operand *tmp = right ;
6967 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6968 preserve_result = 1;
6970 if(result && AOP_SIZE(result))
6971 generate_result = 1;
6973 if(generate_result && !preserve_result)
6975 for(i = 0; i < AOP_SIZE(result); i++)
6976 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6979 for(i=0; i < AOP_SIZE(left); i++)
6981 if(AOP_TYPE(left) != AOP_ACC)
6984 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6989 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6991 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6993 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6998 if(generate_result && preserve_result)
7000 for(i = 0; i < AOP_SIZE(result); i++)
7001 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7005 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7007 if(generate_result && preserve_result)
7008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7010 if(ifx && IC_TRUE(ifx))
7011 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7013 if(ifx && IC_FALSE(ifx))
7014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7016 pic16_emitpLabel(falselbl->key);
7020 if(ifx && IC_FALSE(ifx))
7021 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7023 if(generate_result && preserve_result)
7025 for(i = 0; i < AOP_SIZE(result); i++)
7026 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7029 pic16_emitpLabel(donelbl->key);
7035 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7036 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7037 pic16_freeAsmop(result,NULL,ic,TRUE);
7043 // old version kept for reference
7045 /*-----------------------------------------------------------------*/
7046 /* genCmpEq - generates code for equal to */
7047 /*-----------------------------------------------------------------*/
7048 static void genCmpEq (iCode *ic, iCode *ifx)
7050 operand *left, *right, *result;
7051 unsigned long lit = 0L;
7053 symbol *falselbl = newiTempLabel(NULL);
7056 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7059 DEBUGpic16_emitcode ("; ifx is non-null","");
7061 DEBUGpic16_emitcode ("; ifx is null","");
7063 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7064 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7065 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7067 size = max(AOP_SIZE(left),AOP_SIZE(right));
7069 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7071 /* if literal, literal on the right or
7072 if the right is in a pointer register and left
7074 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7075 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7076 operand *tmp = right ;
7082 if(ifx && !AOP_SIZE(result)){
7084 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7085 /* if they are both bit variables */
7086 if (AOP_TYPE(left) == AOP_CRY &&
7087 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7088 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7089 if(AOP_TYPE(right) == AOP_LIT){
7090 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7092 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7093 pic16_emitcode("cpl","c");
7094 } else if(lit == 1L) {
7095 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7097 pic16_emitcode("clr","c");
7099 /* AOP_TYPE(right) == AOP_CRY */
7101 symbol *lbl = newiTempLabel(NULL);
7102 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7103 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7104 pic16_emitcode("cpl","c");
7105 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7107 /* if true label then we jump if condition
7109 tlbl = newiTempLabel(NULL);
7110 if ( IC_TRUE(ifx) ) {
7111 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7112 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7114 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7115 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7117 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7120 /* left and right are both bit variables, result is carry */
7123 resolveIfx(&rIfx,ifx);
7125 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7126 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7127 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7128 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7133 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7135 /* They're not both bit variables. Is the right a literal? */
7136 if(AOP_TYPE(right) == AOP_LIT) {
7137 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7142 switch(lit & 0xff) {
7144 if ( IC_TRUE(ifx) ) {
7145 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7147 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7149 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7150 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7154 if ( IC_TRUE(ifx) ) {
7155 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7157 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7159 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7160 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7164 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7166 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7171 /* end of size == 1 */
7175 genc16bit2lit(left,lit,offset);
7178 /* end of size == 2 */
7183 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7184 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7185 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7186 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7189 /* search for patterns that can be optimized */
7191 genc16bit2lit(left,lit,0);
7195 emitSKPZ; // if hi word unequal
7197 emitSKPNZ; // if hi word equal
7199 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7200 genc16bit2lit(left,lit,2);
7203 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7204 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7208 pic16_emitpLabel(falselbl->key);
7217 } else if(AOP_TYPE(right) == AOP_CRY ) {
7218 /* we know the left is not a bit, but that the right is */
7219 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7220 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7221 pic16_popGet(AOP(right),offset));
7222 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7224 /* if the two are equal, then W will be 0 and the Z bit is set
7225 * we could test Z now, or go ahead and check the high order bytes if
7226 * the variable we're comparing is larger than a byte. */
7229 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7231 if ( IC_TRUE(ifx) ) {
7233 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7234 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7237 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7238 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7242 /* They're both variables that are larger than bits */
7245 tlbl = newiTempLabel(NULL);
7248 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7249 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7251 if ( IC_TRUE(ifx) ) {
7255 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7257 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7258 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7262 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7266 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7271 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7273 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7274 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7278 if(s>1 && IC_TRUE(ifx)) {
7279 pic16_emitpLabel(tlbl->key);
7280 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7284 /* mark the icode as generated */
7289 /* if they are both bit variables */
7290 if (AOP_TYPE(left) == AOP_CRY &&
7291 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7292 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7293 if(AOP_TYPE(right) == AOP_LIT){
7294 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7296 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7297 pic16_emitcode("cpl","c");
7298 } else if(lit == 1L) {
7299 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7301 pic16_emitcode("clr","c");
7303 /* AOP_TYPE(right) == AOP_CRY */
7305 symbol *lbl = newiTempLabel(NULL);
7306 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7307 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7308 pic16_emitcode("cpl","c");
7309 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7312 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7313 pic16_outBitC(result);
7317 genIfxJump (ifx,"c");
7320 /* if the result is used in an arithmetic operation
7321 then put the result in place */
7322 pic16_outBitC(result);
7325 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7326 gencjne(left,right,result,ifx);
7329 gencjne(left,right,newiTempLabel(NULL));
7331 if(IC_TRUE(ifx)->key)
7332 gencjne(left,right,IC_TRUE(ifx)->key);
7334 gencjne(left,right,IC_FALSE(ifx)->key);
7338 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7339 pic16_aopPut(AOP(result),"a",0);
7344 genIfxJump (ifx,"a");
7348 /* if the result is used in an arithmetic operation
7349 then put the result in place */
7351 if (AOP_TYPE(result) != AOP_CRY)
7352 pic16_outAcc(result);
7354 /* leave the result in acc */
7358 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7359 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7360 pic16_freeAsmop(result,NULL,ic,TRUE);
7364 /*-----------------------------------------------------------------*/
7365 /* ifxForOp - returns the icode containing the ifx for operand */
7366 /*-----------------------------------------------------------------*/
7367 static iCode *ifxForOp ( operand *op, iCode *ic )
7371 /* if true symbol then needs to be assigned */
7372 if (IS_TRUE_SYMOP(op))
7375 /* if this has register type condition and
7376 the next instruction is ifx with the same operand
7377 and live to of the operand is upto the ifx only then */
7379 && ic->next->op == IFX
7380 && IC_COND(ic->next)->key == op->key
7381 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7383 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7389 ic->next->op == IFX &&
7390 IC_COND(ic->next)->key == op->key) {
7391 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7396 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7398 ic->next->op == IFX)
7399 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7402 ic->next->op == IFX &&
7403 IC_COND(ic->next)->key == op->key) {
7404 DEBUGpic16_emitcode ("; "," key is okay");
7405 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7406 OP_SYMBOL(op)->liveTo,
7411 /* the code below is completely untested
7412 * it just allows ulong2fs.c compile -- VR */
7415 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7416 __FILE__, __FUNCTION__, __LINE__);
7418 /* if this has register type condition and
7419 the next instruction is ifx with the same operand
7420 and live to of the operand is upto the ifx only then */
7422 ic->next->op == IFX &&
7423 IC_COND(ic->next)->key == op->key &&
7424 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7428 ic->next->op == IFX &&
7429 IC_COND(ic->next)->key == op->key) {
7430 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7434 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7435 __FILE__, __FUNCTION__, __LINE__);
7437 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7442 /*-----------------------------------------------------------------*/
7443 /* genAndOp - for && operation */
7444 /*-----------------------------------------------------------------*/
7445 static void genAndOp (iCode *ic)
7447 operand *left,*right, *result;
7452 /* note here that && operations that are in an
7453 if statement are taken away by backPatchLabels
7454 only those used in arthmetic operations remain */
7455 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7456 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7457 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7459 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7461 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7462 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7463 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7465 /* if both are bit variables */
7466 /* if (AOP_TYPE(left) == AOP_CRY && */
7467 /* AOP_TYPE(right) == AOP_CRY ) { */
7468 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7469 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7470 /* pic16_outBitC(result); */
7472 /* tlbl = newiTempLabel(NULL); */
7473 /* pic16_toBoolean(left); */
7474 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7475 /* pic16_toBoolean(right); */
7476 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7477 /* pic16_outBitAcc(result); */
7480 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7481 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7482 pic16_freeAsmop(result,NULL,ic,TRUE);
7486 /*-----------------------------------------------------------------*/
7487 /* genOrOp - for || operation */
7488 /*-----------------------------------------------------------------*/
7491 modified this code, but it doesn't appear to ever get called
7494 static void genOrOp (iCode *ic)
7496 operand *left,*right, *result;
7501 /* note here that || operations that are in an
7502 if statement are taken away by backPatchLabels
7503 only those used in arthmetic operations remain */
7504 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7505 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7506 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7508 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7510 /* if both are bit variables */
7511 if (AOP_TYPE(left) == AOP_CRY &&
7512 AOP_TYPE(right) == AOP_CRY ) {
7513 pic16_emitcode("clrc","");
7514 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7515 AOP(left)->aopu.aop_dir,
7516 AOP(left)->aopu.aop_dir);
7517 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7518 AOP(right)->aopu.aop_dir,
7519 AOP(right)->aopu.aop_dir);
7520 pic16_emitcode("setc","");
7523 tlbl = newiTempLabel(NULL);
7524 pic16_toBoolean(left);
7526 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7527 pic16_toBoolean(right);
7528 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7530 pic16_outBitAcc(result);
7533 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7534 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7535 pic16_freeAsmop(result,NULL,ic,TRUE);
7538 /*-----------------------------------------------------------------*/
7539 /* isLiteralBit - test if lit == 2^n */
7540 /*-----------------------------------------------------------------*/
7541 static int isLiteralBit(unsigned long lit)
7543 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7544 0x100L,0x200L,0x400L,0x800L,
7545 0x1000L,0x2000L,0x4000L,0x8000L,
7546 0x10000L,0x20000L,0x40000L,0x80000L,
7547 0x100000L,0x200000L,0x400000L,0x800000L,
7548 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7549 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7553 for(idx = 0; idx < 32; idx++)
7559 /*-----------------------------------------------------------------*/
7560 /* continueIfTrue - */
7561 /*-----------------------------------------------------------------*/
7562 static void continueIfTrue (iCode *ic)
7566 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7570 /*-----------------------------------------------------------------*/
7572 /*-----------------------------------------------------------------*/
7573 static void jumpIfTrue (iCode *ic)
7577 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7581 /*-----------------------------------------------------------------*/
7582 /* jmpTrueOrFalse - */
7583 /*-----------------------------------------------------------------*/
7584 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7586 // ugly but optimized by peephole
7589 symbol *nlbl = newiTempLabel(NULL);
7590 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7591 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7592 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7593 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7595 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7596 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7601 /*-----------------------------------------------------------------*/
7602 /* genAnd - code for and */
7603 /*-----------------------------------------------------------------*/
7604 static void genAnd (iCode *ic, iCode *ifx)
7606 operand *left, *right, *result;
7608 unsigned long lit = 0L;
7614 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7615 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7616 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7618 resolveIfx(&rIfx,ifx);
7620 /* if left is a literal & right is not then exchange them */
7621 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7622 AOP_NEEDSACC(left)) {
7623 operand *tmp = right ;
7628 /* if result = right then exchange them */
7629 if(pic16_sameRegs(AOP(result),AOP(right))){
7630 operand *tmp = right ;
7635 /* if right is bit then exchange them */
7636 if (AOP_TYPE(right) == AOP_CRY &&
7637 AOP_TYPE(left) != AOP_CRY){
7638 operand *tmp = right ;
7642 if(AOP_TYPE(right) == AOP_LIT)
7643 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7645 size = AOP_SIZE(result);
7647 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7650 // result = bit & yy;
7651 if (AOP_TYPE(left) == AOP_CRY){
7652 // c = bit & literal;
7653 if(AOP_TYPE(right) == AOP_LIT){
7655 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7658 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7661 if(size && (AOP_TYPE(result) == AOP_CRY)){
7662 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7665 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7669 pic16_emitcode("clr","c");
7672 if (AOP_TYPE(right) == AOP_CRY){
7674 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7675 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7678 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7680 pic16_emitcode("rrc","a");
7681 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7687 pic16_outBitC(result);
7689 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7690 genIfxJump(ifx, "c");
7694 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7695 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7696 if((AOP_TYPE(right) == AOP_LIT) &&
7697 (AOP_TYPE(result) == AOP_CRY) &&
7698 (AOP_TYPE(left) != AOP_CRY)){
7699 int posbit = isLiteralBit(lit);
7703 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7706 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7712 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7713 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7715 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7716 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7719 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7720 size = AOP_SIZE(left);
7723 int bp = posbit, ofs=0;
7730 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7731 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7735 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7736 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7738 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7745 symbol *tlbl = newiTempLabel(NULL);
7746 int sizel = AOP_SIZE(left);
7752 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7754 /* patch provided by Aaron Colwell */
7755 if((posbit = isLiteralBit(bytelit)) != 0) {
7756 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7757 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7758 (posbit-1),0, PO_GPR_REGISTER));
7760 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7761 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7763 if (bytelit == 0xff) {
7764 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7765 * a peephole could optimize it out -- VR */
7766 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7768 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7769 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7772 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7773 pic16_popGetLabel(tlbl->key));
7777 /* old code, left here for reference -- VR 09/2004 */
7778 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7780 if((posbit = isLiteralBit(bytelit)) != 0)
7781 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7783 if(bytelit != 0x0FFL)
7784 pic16_emitcode("anl","a,%s",
7785 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7786 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7792 // bit = left & literal
7795 pic16_emitpLabel(tlbl->key);
7797 // if(left & literal)
7800 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7803 pic16_emitpLabel(tlbl->key);
7808 pic16_outBitC(result);
7812 /* if left is same as result */
7813 if(pic16_sameRegs(AOP(result),AOP(left))){
7815 for(;size--; offset++,lit>>=8) {
7816 if(AOP_TYPE(right) == AOP_LIT){
7817 switch(lit & 0xff) {
7819 /* and'ing with 0 has clears the result */
7820 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7821 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7824 /* and'ing with 0xff is a nop when the result and left are the same */
7829 int p = pic16_my_powof2( (~lit) & 0xff );
7831 /* only one bit is set in the literal, so use a bcf instruction */
7832 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7833 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7836 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7837 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7838 if(know_W != (lit&0xff))
7839 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7841 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7846 if (AOP_TYPE(left) == AOP_ACC) {
7847 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7849 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7850 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7857 // left & result in different registers
7858 if(AOP_TYPE(result) == AOP_CRY){
7860 // if(size), result in bit
7861 // if(!size && ifx), conditional oper: if(left & right)
7862 symbol *tlbl = newiTempLabel(NULL);
7863 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7865 pic16_emitcode("setb","c");
7867 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7868 pic16_emitcode("anl","a,%s",
7869 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7870 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7875 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7876 pic16_outBitC(result);
7878 jmpTrueOrFalse(ifx, tlbl);
7880 for(;(size--);offset++) {
7882 // result = left & right
7883 if(AOP_TYPE(right) == AOP_LIT){
7884 int t = (lit >> (offset*8)) & 0x0FFL;
7887 pic16_emitcode("clrf","%s",
7888 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7889 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7892 pic16_emitcode("movf","%s,w",
7893 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7894 pic16_emitcode("movwf","%s",
7895 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7896 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7897 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7900 pic16_emitcode("movlw","0x%x",t);
7901 pic16_emitcode("andwf","%s,w",
7902 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7903 pic16_emitcode("movwf","%s",
7904 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7906 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7907 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7908 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7913 if (AOP_TYPE(left) == AOP_ACC) {
7914 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7915 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7917 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7918 pic16_emitcode("andwf","%s,w",
7919 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7921 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7923 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7924 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7930 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7931 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7932 pic16_freeAsmop(result,NULL,ic,TRUE);
7935 /*-----------------------------------------------------------------*/
7936 /* genOr - code for or */
7937 /*-----------------------------------------------------------------*/
7938 static void genOr (iCode *ic, iCode *ifx)
7940 operand *left, *right, *result;
7942 unsigned long lit = 0L;
7944 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7946 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7947 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7948 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7950 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7952 /* if left is a literal & right is not then exchange them */
7953 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7954 AOP_NEEDSACC(left)) {
7955 operand *tmp = right ;
7960 /* if result = right then exchange them */
7961 if(pic16_sameRegs(AOP(result),AOP(right))){
7962 operand *tmp = right ;
7967 /* if right is bit then exchange them */
7968 if (AOP_TYPE(right) == AOP_CRY &&
7969 AOP_TYPE(left) != AOP_CRY){
7970 operand *tmp = right ;
7975 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7977 if(AOP_TYPE(right) == AOP_LIT)
7978 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7980 size = AOP_SIZE(result);
7984 if (AOP_TYPE(left) == AOP_CRY){
7985 if(AOP_TYPE(right) == AOP_LIT){
7986 // c = bit & literal;
7988 // lit != 0 => result = 1
7989 if(AOP_TYPE(result) == AOP_CRY){
7991 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7992 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7993 // AOP(result)->aopu.aop_dir,
7994 // AOP(result)->aopu.aop_dir);
7996 continueIfTrue(ifx);
8000 // lit == 0 => result = left
8001 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8003 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8006 if (AOP_TYPE(right) == AOP_CRY){
8007 if(pic16_sameRegs(AOP(result),AOP(left))){
8009 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8010 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8011 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8013 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8014 AOP(result)->aopu.aop_dir,
8015 AOP(result)->aopu.aop_dir);
8016 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8017 AOP(right)->aopu.aop_dir,
8018 AOP(right)->aopu.aop_dir);
8019 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8020 AOP(result)->aopu.aop_dir,
8021 AOP(result)->aopu.aop_dir);
8023 if( AOP_TYPE(result) == AOP_ACC) {
8024 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8025 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8026 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8027 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8031 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8032 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8033 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8034 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8036 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8037 AOP(result)->aopu.aop_dir,
8038 AOP(result)->aopu.aop_dir);
8039 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8040 AOP(right)->aopu.aop_dir,
8041 AOP(right)->aopu.aop_dir);
8042 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8043 AOP(left)->aopu.aop_dir,
8044 AOP(left)->aopu.aop_dir);
8045 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8046 AOP(result)->aopu.aop_dir,
8047 AOP(result)->aopu.aop_dir);
8052 symbol *tlbl = newiTempLabel(NULL);
8053 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8056 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8057 if( AOP_TYPE(right) == AOP_ACC) {
8058 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8060 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8061 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8066 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8067 pic16_emitcode(";XXX setb","c");
8068 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8069 AOP(left)->aopu.aop_dir,tlbl->key+100);
8070 pic16_toBoolean(right);
8071 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8072 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8073 jmpTrueOrFalse(ifx, tlbl);
8077 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8084 pic16_outBitC(result);
8086 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8087 genIfxJump(ifx, "c");
8091 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8092 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8093 if((AOP_TYPE(right) == AOP_LIT) &&
8094 (AOP_TYPE(result) == AOP_CRY) &&
8095 (AOP_TYPE(left) != AOP_CRY)){
8097 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8100 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8102 continueIfTrue(ifx);
8105 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8106 // lit = 0, result = boolean(left)
8108 pic16_emitcode(";XXX setb","c");
8109 pic16_toBoolean(right);
8111 symbol *tlbl = newiTempLabel(NULL);
8112 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8114 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8116 genIfxJump (ifx,"a");
8120 pic16_outBitC(result);
8124 /* if left is same as result */
8125 if(pic16_sameRegs(AOP(result),AOP(left))){
8127 for(;size--; offset++,lit>>=8) {
8128 if(AOP_TYPE(right) == AOP_LIT){
8129 if((lit & 0xff) == 0)
8130 /* or'ing with 0 has no effect */
8133 int p = pic16_my_powof2(lit & 0xff);
8135 /* only one bit is set in the literal, so use a bsf instruction */
8136 pic16_emitpcode(POC_BSF,
8137 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8139 if(know_W != (lit & 0xff))
8140 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8141 know_W = lit & 0xff;
8142 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8147 if (AOP_TYPE(left) == AOP_ACC) {
8148 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8149 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8152 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8154 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8155 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8161 // left & result in different registers
8162 if(AOP_TYPE(result) == AOP_CRY){
8164 // if(size), result in bit
8165 // if(!size && ifx), conditional oper: if(left | right)
8166 symbol *tlbl = newiTempLabel(NULL);
8167 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8168 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8172 pic16_emitcode(";XXX setb","c");
8174 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8175 pic16_emitcode(";XXX orl","a,%s",
8176 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8182 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8183 pic16_outBitC(result);
8185 jmpTrueOrFalse(ifx, tlbl);
8186 } else for(;(size--);offset++){
8188 // result = left & right
8189 if(AOP_TYPE(right) == AOP_LIT){
8190 int t = (lit >> (offset*8)) & 0x0FFL;
8193 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8196 pic16_emitcode("movf","%s,w",
8197 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8198 pic16_emitcode("movwf","%s",
8199 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8202 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8203 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8204 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8206 pic16_emitcode("movlw","0x%x",t);
8207 pic16_emitcode("iorwf","%s,w",
8208 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8209 pic16_emitcode("movwf","%s",
8210 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8216 // faster than result <- left, anl result,right
8217 // and better if result is SFR
8218 if (AOP_TYPE(left) == AOP_ACC) {
8219 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8220 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8223 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8225 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8226 pic16_emitcode("iorwf","%s,w",
8227 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8229 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8230 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8235 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8236 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8237 pic16_freeAsmop(result,NULL,ic,TRUE);
8240 /*-----------------------------------------------------------------*/
8241 /* genXor - code for xclusive or */
8242 /*-----------------------------------------------------------------*/
8243 static void genXor (iCode *ic, iCode *ifx)
8245 operand *left, *right, *result;
8247 unsigned long lit = 0L;
8249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8251 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8252 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8253 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8255 /* if left is a literal & right is not ||
8256 if left needs acc & right does not */
8257 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8258 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8259 operand *tmp = right ;
8264 /* if result = right then exchange them */
8265 if(pic16_sameRegs(AOP(result),AOP(right))){
8266 operand *tmp = right ;
8271 /* if right is bit then exchange them */
8272 if (AOP_TYPE(right) == AOP_CRY &&
8273 AOP_TYPE(left) != AOP_CRY){
8274 operand *tmp = right ;
8278 if(AOP_TYPE(right) == AOP_LIT)
8279 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8281 size = AOP_SIZE(result);
8285 if (AOP_TYPE(left) == AOP_CRY){
8286 if(AOP_TYPE(right) == AOP_LIT){
8287 // c = bit & literal;
8289 // lit>>1 != 0 => result = 1
8290 if(AOP_TYPE(result) == AOP_CRY){
8292 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8293 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8295 continueIfTrue(ifx);
8298 pic16_emitcode("setb","c");
8302 // lit == 0, result = left
8303 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8305 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8307 // lit == 1, result = not(left)
8308 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8309 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8310 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8311 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8314 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8315 pic16_emitcode("cpl","c");
8322 symbol *tlbl = newiTempLabel(NULL);
8323 if (AOP_TYPE(right) == AOP_CRY){
8325 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8328 int sizer = AOP_SIZE(right);
8330 // if val>>1 != 0, result = 1
8331 pic16_emitcode("setb","c");
8333 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8335 // test the msb of the lsb
8336 pic16_emitcode("anl","a,#0xfe");
8337 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8341 pic16_emitcode("rrc","a");
8343 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8344 pic16_emitcode("cpl","c");
8345 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8350 pic16_outBitC(result);
8352 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8353 genIfxJump(ifx, "c");
8357 if(pic16_sameRegs(AOP(result),AOP(left))){
8358 /* if left is same as result */
8359 for(;size--; offset++) {
8360 if(AOP_TYPE(right) == AOP_LIT){
8361 int t = (lit >> (offset*8)) & 0x0FFL;
8365 if (IS_AOP_PREG(left)) {
8366 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8367 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8368 pic16_aopPut(AOP(result),"a",offset);
8370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8371 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8372 pic16_emitcode("xrl","%s,%s",
8373 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8374 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8377 if (AOP_TYPE(left) == AOP_ACC)
8378 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8380 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8381 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8383 if (IS_AOP_PREG(left)) {
8384 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8385 pic16_aopPut(AOP(result),"a",offset);
8387 pic16_emitcode("xrl","%s,a",
8388 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8394 // left & result in different registers
8395 if(AOP_TYPE(result) == AOP_CRY){
8397 // if(size), result in bit
8398 // if(!size && ifx), conditional oper: if(left ^ right)
8399 symbol *tlbl = newiTempLabel(NULL);
8400 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8402 pic16_emitcode("setb","c");
8404 if((AOP_TYPE(right) == AOP_LIT) &&
8405 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8406 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8408 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8409 pic16_emitcode("xrl","a,%s",
8410 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8412 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8417 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8418 pic16_outBitC(result);
8420 jmpTrueOrFalse(ifx, tlbl);
8421 } else for(;(size--);offset++){
8423 // result = left & right
8424 if(AOP_TYPE(right) == AOP_LIT){
8425 int t = (lit >> (offset*8)) & 0x0FFL;
8428 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8429 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8430 pic16_emitcode("movf","%s,w",
8431 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8432 pic16_emitcode("movwf","%s",
8433 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8436 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8437 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8438 pic16_emitcode("comf","%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_MOVLW, pic16_popGetLit(t));
8445 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8446 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8447 pic16_emitcode("movlw","0x%x",t);
8448 pic16_emitcode("xorwf","%s,w",
8449 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8450 pic16_emitcode("movwf","%s",
8451 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8457 // faster than result <- left, anl result,right
8458 // and better if result is SFR
8459 if (AOP_TYPE(left) == AOP_ACC) {
8460 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8461 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8463 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8464 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8465 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8466 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8468 if ( AOP_TYPE(result) != AOP_ACC){
8469 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8470 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8476 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8477 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8478 pic16_freeAsmop(result,NULL,ic,TRUE);
8481 /*-----------------------------------------------------------------*/
8482 /* genInline - write the inline code out */
8483 /*-----------------------------------------------------------------*/
8484 static void genInline (iCode *ic)
8486 char *buffer, *bp, *bp1;
8488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8490 _G.inLine += (!options.asmpeep);
8492 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8493 strcpy(buffer,IC_INLINE(ic));
8495 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8497 /* emit each line as a code */
8503 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8511 /* print label, use this special format with NULL directive
8512 * to denote that the argument should not be indented with tab */
8513 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8520 if ((bp1 != bp) && *bp1)
8521 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8526 _G.inLine -= (!options.asmpeep);
8529 /*-----------------------------------------------------------------*/
8530 /* genRRC - rotate right with carry */
8531 /*-----------------------------------------------------------------*/
8532 static void genRRC (iCode *ic)
8534 operand *left , *result ;
8535 int size, offset = 0, same;
8537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8539 /* rotate right with carry */
8541 result=IC_RESULT(ic);
8542 pic16_aopOp (left,ic,FALSE);
8543 pic16_aopOp (result,ic,FALSE);
8545 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8547 same = pic16_sameRegs(AOP(result),AOP(left));
8549 size = AOP_SIZE(result);
8551 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8553 /* get the lsb and put it into the carry */
8554 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8561 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8563 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8564 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8570 pic16_freeAsmop(left,NULL,ic,TRUE);
8571 pic16_freeAsmop(result,NULL,ic,TRUE);
8574 /*-----------------------------------------------------------------*/
8575 /* genRLC - generate code for rotate left with carry */
8576 /*-----------------------------------------------------------------*/
8577 static void genRLC (iCode *ic)
8579 operand *left , *result ;
8580 int size, offset = 0;
8583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8584 /* rotate right with carry */
8586 result=IC_RESULT(ic);
8587 pic16_aopOp (left,ic,FALSE);
8588 pic16_aopOp (result,ic,FALSE);
8590 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8592 same = pic16_sameRegs(AOP(result),AOP(left));
8594 /* move it to the result */
8595 size = AOP_SIZE(result);
8597 /* get the msb and put it into the carry */
8598 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8605 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8607 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8615 pic16_freeAsmop(left,NULL,ic,TRUE);
8616 pic16_freeAsmop(result,NULL,ic,TRUE);
8620 /* gpasm can get the highest order bit with HIGH/UPPER
8621 * so the following probably is not needed -- VR */
8623 /*-----------------------------------------------------------------*/
8624 /* genGetHbit - generates code get highest order bit */
8625 /*-----------------------------------------------------------------*/
8626 static void genGetHbit (iCode *ic)
8628 operand *left, *result;
8630 result=IC_RESULT(ic);
8631 pic16_aopOp (left,ic,FALSE);
8632 pic16_aopOp (result,ic,FALSE);
8634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8635 /* get the highest order byte into a */
8636 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8637 if(AOP_TYPE(result) == AOP_CRY){
8638 pic16_emitcode("rlc","a");
8639 pic16_outBitC(result);
8642 pic16_emitcode("rl","a");
8643 pic16_emitcode("anl","a,#0x01");
8644 pic16_outAcc(result);
8648 pic16_freeAsmop(left,NULL,ic,TRUE);
8649 pic16_freeAsmop(result,NULL,ic,TRUE);
8653 /*-----------------------------------------------------------------*/
8654 /* AccRol - rotate left accumulator by known count */
8655 /*-----------------------------------------------------------------*/
8656 static void AccRol (int shCount)
8658 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8659 shCount &= 0x0007; // shCount : 0..7
8664 pic16_emitcode("rl","a");
8667 pic16_emitcode("rl","a");
8668 pic16_emitcode("rl","a");
8671 pic16_emitcode("swap","a");
8672 pic16_emitcode("rr","a");
8675 pic16_emitcode("swap","a");
8678 pic16_emitcode("swap","a");
8679 pic16_emitcode("rl","a");
8682 pic16_emitcode("rr","a");
8683 pic16_emitcode("rr","a");
8686 pic16_emitcode("rr","a");
8692 /*-----------------------------------------------------------------*/
8693 /* AccLsh - left shift accumulator by known count */
8694 /*-----------------------------------------------------------------*/
8695 static void AccLsh (int shCount)
8697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8703 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8706 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8707 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8710 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8711 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8714 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8717 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8718 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8721 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8722 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8725 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8729 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8732 /*-----------------------------------------------------------------*/
8733 /* AccRsh - right shift accumulator by known count */
8734 /*-----------------------------------------------------------------*/
8735 static void AccRsh (int shCount, int andmask)
8737 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8742 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8745 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8746 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8749 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8750 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8753 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8756 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8757 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8760 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8761 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8764 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8771 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8775 /*-----------------------------------------------------------------*/
8776 /* AccSRsh - signed right shift accumulator by known count */
8777 /*-----------------------------------------------------------------*/
8778 static void AccSRsh (int shCount)
8781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8784 pic16_emitcode("mov","c,acc.7");
8785 pic16_emitcode("rrc","a");
8786 } else if(shCount == 2){
8787 pic16_emitcode("mov","c,acc.7");
8788 pic16_emitcode("rrc","a");
8789 pic16_emitcode("mov","c,acc.7");
8790 pic16_emitcode("rrc","a");
8792 tlbl = newiTempLabel(NULL);
8793 /* rotate right accumulator */
8794 AccRol(8 - shCount);
8795 /* and kill the higher order bits */
8796 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8797 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8798 pic16_emitcode("orl","a,#0x%02x",
8799 (unsigned char)~SRMask[shCount]);
8800 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8806 /*-----------------------------------------------------------------*/
8807 /* shiftR1Left2Result - shift right one byte from left to result */
8808 /*-----------------------------------------------------------------*/
8809 static void shiftR1Left2ResultSigned (operand *left, int offl,
8810 operand *result, int offr,
8815 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8817 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8821 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8823 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8825 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8826 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8832 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8834 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8836 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8839 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8840 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8846 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8848 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8849 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8853 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8856 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8857 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8859 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8864 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8865 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8866 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8867 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8874 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8878 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8879 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8880 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8886 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8887 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8888 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8889 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8890 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8893 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8894 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8895 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8896 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8902 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8903 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8904 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8907 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8909 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8917 /*-----------------------------------------------------------------*/
8918 /* shiftR1Left2Result - shift right one byte from left to result */
8919 /*-----------------------------------------------------------------*/
8920 static void shiftR1Left2Result (operand *left, int offl,
8921 operand *result, int offr,
8922 int shCount, int sign)
8926 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8928 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8930 /* Copy the msb into the carry if signed. */
8932 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8942 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8965 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8969 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8976 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8981 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8982 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8983 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8985 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8990 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8991 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8999 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9000 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9010 /*-----------------------------------------------------------------*/
9011 /* shiftL1Left2Result - shift left one byte from left to result */
9012 /*-----------------------------------------------------------------*/
9013 static void shiftL1Left2Result (operand *left, int offl,
9014 operand *result, int offr, int shCount)
9019 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9021 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9022 DEBUGpic16_emitcode ("; ***","same = %d",same);
9023 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9025 /* shift left accumulator */
9026 //AccLsh(shCount); // don't comment out just yet...
9027 // pic16_aopPut(AOP(result),"a",offr);
9031 /* Shift left 1 bit position */
9032 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9034 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9036 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9042 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9043 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9048 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9049 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9050 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9054 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9055 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9056 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9060 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9061 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9065 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9066 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9067 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9068 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9069 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9072 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9073 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9074 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9078 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9083 /*-----------------------------------------------------------------*/
9084 /* movLeft2Result - move byte from left to result */
9085 /*-----------------------------------------------------------------*/
9086 static void movLeft2Result (operand *left, int offl,
9087 operand *result, int offr)
9090 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9091 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9092 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9094 if (*l == '@' && (IS_AOP_PREG(result))) {
9095 pic16_emitcode("mov","a,%s",l);
9096 pic16_aopPut(AOP(result),"a",offr);
9098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9099 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9104 /*-----------------------------------------------------------------*/
9105 /* shiftL2Left2Result - shift left two bytes from left to result */
9106 /*-----------------------------------------------------------------*/
9107 static void shiftL2Left2Result (operand *left, int offl,
9108 operand *result, int offr, int shCount)
9110 int same = pic16_sameRegs(AOP(result), AOP(left));
9113 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9115 if (same && (offl != offr)) { // shift bytes
9118 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9121 } else { // just treat as different later on
9134 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9136 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9140 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9148 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9149 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9150 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9151 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9153 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9162 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9163 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9164 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9165 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9166 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9167 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9168 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9169 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9172 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9173 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9174 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9175 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9176 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9186 /* note, use a mov/add for the shift since the mov has a
9187 chance of getting optimized out */
9188 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9189 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9190 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9192 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9196 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9197 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9203 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9204 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9205 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9206 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9208 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9209 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9210 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9214 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9215 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9219 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9220 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9221 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9224 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9225 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9226 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9227 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9228 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9229 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9230 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9231 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9234 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9235 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9236 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9237 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9238 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9243 /*-----------------------------------------------------------------*/
9244 /* shiftR2Left2Result - shift right two bytes from left to result */
9245 /*-----------------------------------------------------------------*/
9246 static void shiftR2Left2Result (operand *left, int offl,
9247 operand *result, int offr,
9248 int shCount, int sign)
9250 int same = pic16_sameRegs(AOP(result), AOP(left));
9252 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9254 if (same && (offl != offr)) { // shift right bytes
9257 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9258 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9260 } else { // just treat as different later on
9272 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9277 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9278 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9280 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9281 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9282 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9283 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9288 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9291 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9292 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9299 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9300 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9301 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9303 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9304 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9305 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9306 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9308 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9309 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9310 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9312 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9313 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9314 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9315 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9316 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9320 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9321 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9325 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9326 pic16_emitpcode(POC_BTFSC,
9327 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9328 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9336 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9337 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9339 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9340 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9341 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9342 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9344 pic16_emitpcode(POC_BTFSC,
9345 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9346 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9348 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9349 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9350 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9351 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9353 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9354 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9355 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9356 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9357 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9358 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9359 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9360 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9362 pic16_emitpcode(POC_BTFSC,
9363 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9364 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9366 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9367 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9374 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9375 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9376 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9377 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9380 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9382 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9387 /*-----------------------------------------------------------------*/
9388 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9389 /*-----------------------------------------------------------------*/
9390 static void shiftLLeftOrResult (operand *left, int offl,
9391 operand *result, int offr, int shCount)
9393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9395 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9396 /* shift left accumulator */
9398 /* or with result */
9399 /* back to result */
9400 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9403 /*-----------------------------------------------------------------*/
9404 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9405 /*-----------------------------------------------------------------*/
9406 static void shiftRLeftOrResult (operand *left, int offl,
9407 operand *result, int offr, int shCount)
9409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9411 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9412 /* shift right accumulator */
9414 /* or with result */
9415 /* back to result */
9416 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9419 /*-----------------------------------------------------------------*/
9420 /* genlshOne - left shift a one byte quantity by known count */
9421 /*-----------------------------------------------------------------*/
9422 static void genlshOne (operand *result, operand *left, int shCount)
9424 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9425 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9428 /*-----------------------------------------------------------------*/
9429 /* genlshTwo - left shift two bytes by known amount != 0 */
9430 /*-----------------------------------------------------------------*/
9431 static void genlshTwo (operand *result,operand *left, int shCount)
9435 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9436 size = pic16_getDataSize(result);
9438 /* if shCount >= 8 */
9444 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9446 movLeft2Result(left, LSB, result, MSB16);
9448 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9451 /* 1 <= shCount <= 7 */
9454 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9456 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9460 /*-----------------------------------------------------------------*/
9461 /* shiftLLong - shift left one long from left to result */
9462 /* offr = LSB or MSB16 */
9463 /*-----------------------------------------------------------------*/
9464 static void shiftLLong (operand *left, operand *result, int offr )
9466 int size = AOP_SIZE(result);
9467 int same = pic16_sameRegs(AOP(left),AOP(result));
9470 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9472 if (same && (offr == MSB16)) { //shift one byte
9473 for(i=size-1;i>=MSB16;i--) {
9474 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9475 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9478 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9481 if (size > LSB+offr ){
9483 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9485 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9486 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9490 if(size > MSB16+offr){
9492 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9494 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9495 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9499 if(size > MSB24+offr){
9501 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9503 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9504 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9508 if(size > MSB32+offr){
9510 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9512 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9513 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9517 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9521 /*-----------------------------------------------------------------*/
9522 /* genlshFour - shift four byte by a known amount != 0 */
9523 /*-----------------------------------------------------------------*/
9524 static void genlshFour (operand *result, operand *left, int shCount)
9528 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9529 size = AOP_SIZE(result);
9531 /* if shifting more that 3 bytes */
9532 if (shCount >= 24 ) {
9535 /* lowest order of left goes to the highest
9536 order of the destination */
9537 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9539 movLeft2Result(left, LSB, result, MSB32);
9541 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9542 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9543 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9548 /* more than two bytes */
9549 else if ( shCount >= 16 ) {
9550 /* lower order two bytes goes to higher order two bytes */
9552 /* if some more remaining */
9554 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9556 movLeft2Result(left, MSB16, result, MSB32);
9557 movLeft2Result(left, LSB, result, MSB24);
9559 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9560 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9564 /* if more than 1 byte */
9565 else if ( shCount >= 8 ) {
9566 /* lower order three bytes goes to higher order three bytes */
9570 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9572 movLeft2Result(left, LSB, result, MSB16);
9574 else{ /* size = 4 */
9576 movLeft2Result(left, MSB24, result, MSB32);
9577 movLeft2Result(left, MSB16, result, MSB24);
9578 movLeft2Result(left, LSB, result, MSB16);
9579 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9581 else if(shCount == 1)
9582 shiftLLong(left, result, MSB16);
9584 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9585 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9586 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9587 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9592 /* 1 <= shCount <= 7 */
9593 else if(shCount <= 3)
9595 shiftLLong(left, result, LSB);
9596 while(--shCount >= 1)
9597 shiftLLong(result, result, LSB);
9599 /* 3 <= shCount <= 7, optimize */
9601 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9602 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9603 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9607 /*-----------------------------------------------------------------*/
9608 /* genLeftShiftLiteral - left shifting by known count */
9609 /*-----------------------------------------------------------------*/
9610 void pic16_genLeftShiftLiteral (operand *left,
9615 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9619 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9620 pic16_freeAsmop(right,NULL,ic,TRUE);
9622 pic16_aopOp(left,ic,FALSE);
9623 pic16_aopOp(result,ic,FALSE);
9625 size = getSize(operandType(result));
9628 pic16_emitcode("; shift left ","result %d, left %d",size,
9632 /* I suppose that the left size >= result size */
9635 movLeft2Result(left, size, result, size);
9639 else if(shCount >= (size * 8))
9641 pic16_aopPut(AOP(result),zero,size);
9645 genlshOne (result,left,shCount);
9650 genlshTwo (result,left,shCount);
9654 genlshFour (result,left,shCount);
9658 pic16_freeAsmop(left,NULL,ic,TRUE);
9659 pic16_freeAsmop(result,NULL,ic,TRUE);
9662 /*-----------------------------------------------------------------*
9663 * genMultiAsm - repeat assembly instruction for size of register.
9664 * if endian == 1, then the high byte (i.e base address + size of
9665 * register) is used first else the low byte is used first;
9666 *-----------------------------------------------------------------*/
9667 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9672 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9685 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9691 #if !(USE_GENERIC_SIGNED_SHIFT)
9692 /*-----------------------------------------------------------------*/
9693 /* genLeftShift - generates code for left shifting */
9694 /*-----------------------------------------------------------------*/
9695 static void genLeftShift (iCode *ic)
9697 operand *left,*right, *result;
9700 symbol *tlbl , *tlbl1;
9703 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9705 right = IC_RIGHT(ic);
9707 result = IC_RESULT(ic);
9709 pic16_aopOp(right,ic,FALSE);
9711 /* if the shift count is known then do it
9712 as efficiently as possible */
9713 if (AOP_TYPE(right) == AOP_LIT) {
9714 pic16_genLeftShiftLiteral (left,right,result,ic);
9718 /* shift count is unknown then we have to form
9719 * a loop. Get the loop count in WREG : Note: we take
9720 * only the lower order byte since shifting
9721 * more than 32 bits make no sense anyway, ( the
9722 * largest size of an object can be only 32 bits ) */
9724 pic16_aopOp(left,ic,FALSE);
9725 pic16_aopOp(result,ic,FALSE);
9727 /* now move the left to the result if they are not the
9728 * same, and if size > 1,
9729 * and if right is not same to result (!!!) -- VR */
9730 if (!pic16_sameRegs(AOP(left),AOP(result))
9731 && (AOP_SIZE(result) > 1)) {
9733 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9735 size = AOP_SIZE(result);
9740 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9741 if (*l == '@' && (IS_AOP_PREG(result))) {
9743 pic16_emitcode("mov","a,%s",l);
9744 pic16_aopPut(AOP(result),"a",offset);
9748 /* we don't know if left is a literal or a register, take care -- VR */
9749 mov2f(AOP(result), AOP(left), offset);
9755 size = AOP_SIZE(result);
9757 /* if it is only one byte then */
9759 if(optimized_for_speed) {
9760 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9762 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9765 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9766 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9767 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9768 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9769 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9770 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9771 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9776 tlbl = newiTempLabel(NULL);
9779 /* this is already done, why change it? */
9780 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9781 mov2f(AOP(result), AOP(left), 0);
9785 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9786 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9787 pic16_emitpLabel(tlbl->key);
9788 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9789 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9791 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9796 if (pic16_sameRegs(AOP(left),AOP(result))) {
9798 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9800 tlbl = newiTempLabel(NULL);
9801 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9802 genMultiAsm(POC_RRCF, result, size,1);
9803 pic16_emitpLabel(tlbl->key);
9804 genMultiAsm(POC_RLCF, result, size,0);
9805 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9807 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9811 //tlbl = newiTempLabel(NULL);
9813 //tlbl1 = newiTempLabel(NULL);
9815 //reAdjustPreg(AOP(result));
9817 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9818 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9819 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9821 //pic16_emitcode("add","a,acc");
9822 //pic16_aopPut(AOP(result),"a",offset++);
9824 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9826 // pic16_emitcode("rlc","a");
9827 // pic16_aopPut(AOP(result),"a",offset++);
9829 //reAdjustPreg(AOP(result));
9831 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9832 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9835 tlbl = newiTempLabel(NULL);
9836 tlbl1= newiTempLabel(NULL);
9838 size = AOP_SIZE(result);
9841 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9843 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9845 /* offset should be 0, 1 or 3 */
9847 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9849 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9851 pic16_emitpcode(POC_MOVWF, pctemp);
9854 pic16_emitpLabel(tlbl->key);
9857 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9861 pic16_emitpcode(POC_DECFSZ, pctemp);
9862 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9863 pic16_emitpLabel(tlbl1->key);
9865 pic16_popReleaseTempReg(pctemp,1);
9869 pic16_freeAsmop (right,NULL,ic,TRUE);
9870 pic16_freeAsmop(left,NULL,ic,TRUE);
9871 pic16_freeAsmop(result,NULL,ic,TRUE);
9877 #error old code (left here for reference)
9878 /*-----------------------------------------------------------------*/
9879 /* genLeftShift - generates code for left shifting */
9880 /*-----------------------------------------------------------------*/
9881 static void genLeftShift (iCode *ic)
9883 operand *left,*right, *result;
9886 symbol *tlbl , *tlbl1;
9889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9891 right = IC_RIGHT(ic);
9893 result = IC_RESULT(ic);
9895 pic16_aopOp(right,ic,FALSE);
9897 /* if the shift count is known then do it
9898 as efficiently as possible */
9899 if (AOP_TYPE(right) == AOP_LIT) {
9900 pic16_genLeftShiftLiteral (left,right,result,ic);
9904 /* shift count is unknown then we have to form
9905 a loop get the loop count in B : Note: we take
9906 only the lower order byte since shifting
9907 more that 32 bits make no sense anyway, ( the
9908 largest size of an object can be only 32 bits ) */
9911 pic16_aopOp(left,ic,FALSE);
9912 pic16_aopOp(result,ic,FALSE);
9914 /* now move the left to the result if they are not the
9916 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9917 AOP_SIZE(result) > 1) {
9919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9921 size = AOP_SIZE(result);
9924 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9925 if (*l == '@' && (IS_AOP_PREG(result))) {
9927 pic16_emitcode("mov","a,%s",l);
9928 pic16_aopPut(AOP(result),"a",offset);
9931 /* we don't know if left is a literal or a register, take care -- VR */
9932 mov2f(AOP(result), AOP(left), offset);
9938 size = AOP_SIZE(result);
9940 /* if it is only one byte then */
9942 if(optimized_for_speed) {
9943 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9944 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9945 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9946 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9948 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9949 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9950 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9951 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9952 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9953 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9954 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9959 tlbl = newiTempLabel(NULL);
9960 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9961 mov2f(AOP(result), AOP(left), 0);
9963 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9964 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9967 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9969 pic16_emitpLabel(tlbl->key);
9970 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9971 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9973 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9978 if (pic16_sameRegs(AOP(left),AOP(result))) {
9980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9982 tlbl = newiTempLabel(NULL);
9983 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9984 genMultiAsm(POC_RRCF, result, size,1);
9985 pic16_emitpLabel(tlbl->key);
9986 genMultiAsm(POC_RLCF, result, size,0);
9987 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9989 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9993 //tlbl = newiTempLabel(NULL);
9995 //tlbl1 = newiTempLabel(NULL);
9997 //reAdjustPreg(AOP(result));
9999 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10000 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10001 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10003 //pic16_emitcode("add","a,acc");
10004 //pic16_aopPut(AOP(result),"a",offset++);
10006 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10008 // pic16_emitcode("rlc","a");
10009 // pic16_aopPut(AOP(result),"a",offset++);
10011 //reAdjustPreg(AOP(result));
10013 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10014 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10017 tlbl = newiTempLabel(NULL);
10018 tlbl1= newiTempLabel(NULL);
10020 size = AOP_SIZE(result);
10023 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10025 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10027 /* offset should be 0, 1 or 3 */
10029 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10031 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10033 pic16_emitpcode(POC_MOVWF, pctemp);
10036 pic16_emitpLabel(tlbl->key);
10039 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10041 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10043 pic16_emitpcode(POC_DECFSZ, pctemp);
10044 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10045 pic16_emitpLabel(tlbl1->key);
10047 pic16_popReleaseTempReg(pctemp,1);
10051 pic16_freeAsmop (right,NULL,ic,TRUE);
10052 pic16_freeAsmop(left,NULL,ic,TRUE);
10053 pic16_freeAsmop(result,NULL,ic,TRUE);
10057 /*-----------------------------------------------------------------*/
10058 /* genrshOne - right shift a one byte quantity by known count */
10059 /*-----------------------------------------------------------------*/
10060 static void genrshOne (operand *result, operand *left,
10061 int shCount, int sign)
10063 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10064 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10067 /*-----------------------------------------------------------------*/
10068 /* genrshTwo - right shift two bytes by known amount != 0 */
10069 /*-----------------------------------------------------------------*/
10070 static void genrshTwo (operand *result,operand *left,
10071 int shCount, int sign)
10073 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10074 /* if shCount >= 8 */
10075 if (shCount >= 8) {
10078 shiftR1Left2Result(left, MSB16, result, LSB,
10081 movLeft2Result(left, MSB16, result, LSB);
10083 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10086 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10087 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10091 /* 1 <= shCount <= 7 */
10093 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10096 /*-----------------------------------------------------------------*/
10097 /* shiftRLong - shift right one long from left to result */
10098 /* offl = LSB or MSB16 */
10099 /*-----------------------------------------------------------------*/
10100 static void shiftRLong (operand *left, int offl,
10101 operand *result, int sign)
10103 int size = AOP_SIZE(result);
10104 int same = pic16_sameRegs(AOP(left),AOP(result));
10106 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10108 if (same && (offl == MSB16)) { //shift one byte right
10109 for(i=MSB16;i<size;i++) {
10110 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10111 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10116 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10122 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10124 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10125 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10128 if(offl == MSB16) {
10129 /* add sign of "a" */
10130 pic16_addSign(result, MSB32, sign);
10134 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10136 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10137 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10141 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10143 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10144 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10148 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10151 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10152 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10157 /*-----------------------------------------------------------------*/
10158 /* genrshFour - shift four byte by a known amount != 0 */
10159 /*-----------------------------------------------------------------*/
10160 static void genrshFour (operand *result, operand *left,
10161 int shCount, int sign)
10163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10164 /* if shifting more that 3 bytes */
10165 if(shCount >= 24 ) {
10168 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10170 movLeft2Result(left, MSB32, result, LSB);
10172 pic16_addSign(result, MSB16, sign);
10174 else if(shCount >= 16){
10177 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10179 movLeft2Result(left, MSB24, result, LSB);
10180 movLeft2Result(left, MSB32, result, MSB16);
10182 pic16_addSign(result, MSB24, sign);
10184 else if(shCount >= 8){
10187 shiftRLong(left, MSB16, result, sign);
10188 else if(shCount == 0){
10189 movLeft2Result(left, MSB16, result, LSB);
10190 movLeft2Result(left, MSB24, result, MSB16);
10191 movLeft2Result(left, MSB32, result, MSB24);
10192 pic16_addSign(result, MSB32, sign);
10194 else{ //shcount >= 2
10195 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10196 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10197 /* the last shift is signed */
10198 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10199 pic16_addSign(result, MSB32, sign);
10202 else{ /* 1 <= shCount <= 7 */
10204 shiftRLong(left, LSB, result, sign);
10206 shiftRLong(result, LSB, result, sign);
10209 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10210 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10211 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10216 /*-----------------------------------------------------------------*/
10217 /* genRightShiftLiteral - right shifting by known count */
10218 /*-----------------------------------------------------------------*/
10219 static void genRightShiftLiteral (operand *left,
10225 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10226 int lsize,res_size;
10228 pic16_freeAsmop(right,NULL,ic,TRUE);
10230 pic16_aopOp(left,ic,FALSE);
10231 pic16_aopOp(result,ic,FALSE);
10233 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10236 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10240 lsize = pic16_getDataSize(left);
10241 res_size = pic16_getDataSize(result);
10242 /* test the LEFT size !!! */
10244 /* I suppose that the left size >= result size */
10247 movLeft2Result(left, lsize, result, res_size);
10250 else if(shCount >= (lsize * 8)){
10252 if(res_size == 1) {
10253 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10255 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10256 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10261 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10262 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10263 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10270 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10275 switch (res_size) {
10277 genrshOne (result,left,shCount,sign);
10281 genrshTwo (result,left,shCount,sign);
10285 genrshFour (result,left,shCount,sign);
10293 pic16_freeAsmop(left,NULL,ic,TRUE);
10294 pic16_freeAsmop(result,NULL,ic,TRUE);
10297 #if !(USE_GENERIC_SIGNED_SHIFT)
10298 /*-----------------------------------------------------------------*/
10299 /* genSignedRightShift - right shift of signed number */
10300 /*-----------------------------------------------------------------*/
10301 static void genSignedRightShift (iCode *ic)
10303 operand *right, *left, *result;
10306 symbol *tlbl, *tlbl1 ;
10309 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10311 /* we do it the hard way put the shift count in b
10312 and loop thru preserving the sign */
10313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10315 right = IC_RIGHT(ic);
10316 left = IC_LEFT(ic);
10317 result = IC_RESULT(ic);
10319 pic16_aopOp(right,ic,FALSE);
10320 pic16_aopOp(left,ic,FALSE);
10321 pic16_aopOp(result,ic,FALSE);
10324 if ( AOP_TYPE(right) == AOP_LIT) {
10325 genRightShiftLiteral (left,right,result,ic,1);
10328 /* shift count is unknown then we have to form
10329 a loop get the loop count in B : Note: we take
10330 only the lower order byte since shifting
10331 more that 32 bits make no sense anyway, ( the
10332 largest size of an object can be only 32 bits ) */
10334 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10335 //pic16_emitcode("inc","b");
10336 //pic16_freeAsmop (right,NULL,ic,TRUE);
10337 //pic16_aopOp(left,ic,FALSE);
10338 //pic16_aopOp(result,ic,FALSE);
10340 /* now move the left to the result if they are not the
10342 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10343 AOP_SIZE(result) > 1) {
10345 size = AOP_SIZE(result);
10349 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10350 if (*l == '@' && IS_AOP_PREG(result)) {
10352 pic16_emitcode("mov","a,%s",l);
10353 pic16_aopPut(AOP(result),"a",offset);
10355 pic16_aopPut(AOP(result),l,offset);
10357 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10358 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10364 /* mov the highest order bit to OVR */
10365 tlbl = newiTempLabel(NULL);
10366 tlbl1= newiTempLabel(NULL);
10368 size = AOP_SIZE(result);
10371 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10373 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10375 /* offset should be 0, 1 or 3 */
10376 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10378 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10380 pic16_emitpcode(POC_MOVWF, pctemp);
10383 pic16_emitpLabel(tlbl->key);
10385 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10386 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10389 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10392 pic16_emitpcode(POC_DECFSZ, pctemp);
10393 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10394 pic16_emitpLabel(tlbl1->key);
10396 pic16_popReleaseTempReg(pctemp,1);
10398 size = AOP_SIZE(result);
10400 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10401 pic16_emitcode("rlc","a");
10402 pic16_emitcode("mov","ov,c");
10403 /* if it is only one byte then */
10405 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10407 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10408 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10409 pic16_emitcode("mov","c,ov");
10410 pic16_emitcode("rrc","a");
10411 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10412 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10413 pic16_aopPut(AOP(result),"a",0);
10417 reAdjustPreg(AOP(result));
10418 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10419 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10420 pic16_emitcode("mov","c,ov");
10422 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10424 pic16_emitcode("rrc","a");
10425 pic16_aopPut(AOP(result),"a",offset--);
10427 reAdjustPreg(AOP(result));
10428 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10429 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10434 pic16_freeAsmop(left,NULL,ic,TRUE);
10435 pic16_freeAsmop(result,NULL,ic,TRUE);
10436 pic16_freeAsmop(right,NULL,ic,TRUE);
10440 #if !(USE_GENERIC_SIGNED_SHIFT)
10441 #warning This implementation of genRightShift() is incomplete!
10442 /*-----------------------------------------------------------------*/
10443 /* genRightShift - generate code for right shifting */
10444 /*-----------------------------------------------------------------*/
10445 static void genRightShift (iCode *ic)
10447 operand *right, *left, *result;
10451 symbol *tlbl, *tlbl1 ;
10453 /* if signed then we do it the hard way preserve the
10454 sign bit moving it inwards */
10455 letype = getSpec(operandType(IC_LEFT(ic)));
10456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10458 if (!SPEC_USIGN(letype)) {
10459 genSignedRightShift (ic);
10463 /* signed & unsigned types are treated the same : i.e. the
10464 signed is NOT propagated inwards : quoting from the
10465 ANSI - standard : "for E1 >> E2, is equivalent to division
10466 by 2**E2 if unsigned or if it has a non-negative value,
10467 otherwise the result is implementation defined ", MY definition
10468 is that the sign does not get propagated */
10470 right = IC_RIGHT(ic);
10471 left = IC_LEFT(ic);
10472 result = IC_RESULT(ic);
10474 pic16_aopOp(right,ic,FALSE);
10476 /* if the shift count is known then do it
10477 as efficiently as possible */
10478 if (AOP_TYPE(right) == AOP_LIT) {
10479 genRightShiftLiteral (left,right,result,ic, 0);
10483 /* shift count is unknown then we have to form
10484 a loop get the loop count in B : Note: we take
10485 only the lower order byte since shifting
10486 more that 32 bits make no sense anyway, ( the
10487 largest size of an object can be only 32 bits ) */
10489 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10490 pic16_emitcode("inc","b");
10491 pic16_aopOp(left,ic,FALSE);
10492 pic16_aopOp(result,ic,FALSE);
10494 /* now move the left to the result if they are not the
10496 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10497 AOP_SIZE(result) > 1) {
10499 size = AOP_SIZE(result);
10502 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10503 if (*l == '@' && IS_AOP_PREG(result)) {
10505 pic16_emitcode("mov","a,%s",l);
10506 pic16_aopPut(AOP(result),"a",offset);
10508 pic16_aopPut(AOP(result),l,offset);
10513 tlbl = newiTempLabel(NULL);
10514 tlbl1= newiTempLabel(NULL);
10515 size = AOP_SIZE(result);
10518 /* if it is only one byte then */
10521 tlbl = newiTempLabel(NULL);
10522 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10523 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10527 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10528 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10529 pic16_emitpLabel(tlbl->key);
10530 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10531 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10533 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10538 reAdjustPreg(AOP(result));
10539 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10540 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10543 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10545 pic16_emitcode("rrc","a");
10546 pic16_aopPut(AOP(result),"a",offset--);
10548 reAdjustPreg(AOP(result));
10550 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10551 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10554 pic16_freeAsmop(left,NULL,ic,TRUE);
10555 pic16_freeAsmop (right,NULL,ic,TRUE);
10556 pic16_freeAsmop(result,NULL,ic,TRUE);
10560 #if (USE_GENERIC_SIGNED_SHIFT)
10561 /*-----------------------------------------------------------------*/
10562 /* genGenericShift - generates code for left or right shifting */
10563 /*-----------------------------------------------------------------*/
10564 static void genGenericShift (iCode *ic, int isShiftLeft) {
10565 operand *left,*right, *result;
10567 int sign, signedCount;
10568 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10569 PIC_OPCODE pos_shift, neg_shift;
10573 right = IC_RIGHT(ic);
10574 left = IC_LEFT(ic);
10575 result = IC_RESULT(ic);
10577 pic16_aopOp(right,ic,FALSE);
10578 pic16_aopOp(left,ic,FALSE);
10579 pic16_aopOp(result,ic,FALSE);
10581 sign = !SPEC_USIGN(operandType (left));
10582 signedCount = !SPEC_USIGN(operandType (right));
10584 /* if the shift count is known then do it
10585 as efficiently as possible */
10586 if (AOP_TYPE(right) == AOP_LIT) {
10587 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10588 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10589 // we should modify right->aopu.aop_lit here!
10590 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10591 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10593 pic16_genLeftShiftLiteral (left,right,result,ic);
10595 genRightShiftLiteral (left,right,result,ic, sign);
10598 } // if (right is literal)
10600 /* shift count is unknown then we have to form a loop.
10601 * Note: we take only the lower order byte since shifting
10602 * more than 32 bits make no sense anyway, ( the
10603 * largest size of an object can be only 32 bits )
10604 * Note: we perform arithmetic shifts if the left operand is
10605 * signed and we do an (effective) right shift, i. e. we
10606 * shift in the sign bit from the left. */
10608 label_complete = newiTempLabel ( NULL );
10609 label_loop_pos = newiTempLabel ( NULL );
10610 label_loop_neg = NULL;
10611 label_negative = NULL;
10612 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10613 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10616 // additional labels needed
10617 label_loop_neg = newiTempLabel ( NULL );
10618 label_negative = newiTempLabel ( NULL );
10621 // copy source to result -- this will effectively truncate the left operand to the size of result!
10622 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10623 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10624 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10625 mov2f (AOP(result),AOP(left), offset);
10628 // if result is longer than left, fill with zeros (or sign)
10629 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10630 if (sign && AOP_SIZE(left) > 0) {
10631 // shift signed operand -- fill with sign
10632 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10633 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10634 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10635 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10636 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10639 // shift unsigned operand -- fill result with zeros
10640 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10641 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10644 } // if (size mismatch)
10646 pic16_mov2w (AOP(right), 0);
10647 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10648 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10651 // perform a shift by one (shift count is positive)
10652 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10653 // 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])
10654 pic16_emitpLabel (label_loop_pos->key);
10656 if (sign && (pos_shift == POC_RRCF)) {
10657 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10660 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10661 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10662 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10664 // perform a shift by one (shift count is positive)
10665 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10666 // 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])
10667 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10668 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10670 pic16_emitpLabel (label_loop_pos->key);
10671 if (sign && (pos_shift == POC_RRCF)) {
10672 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10675 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10676 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10677 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10678 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10682 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10684 pic16_emitpLabel (label_negative->key);
10685 // perform a shift by -1 (shift count is negative)
10686 // 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)
10688 pic16_emitpLabel (label_loop_neg->key);
10689 if (sign && (neg_shift == POC_RRCF)) {
10690 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10693 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10694 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10695 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10696 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10697 } // if (signedCount)
10699 pic16_emitpLabel (label_complete->key);
10702 pic16_freeAsmop (right,NULL,ic,TRUE);
10703 pic16_freeAsmop(left,NULL,ic,TRUE);
10704 pic16_freeAsmop(result,NULL,ic,TRUE);
10707 static void genLeftShift (iCode *ic) {
10708 genGenericShift (ic, 1);
10711 static void genRightShift (iCode *ic) {
10712 genGenericShift (ic, 0);
10717 void pic16_loadFSR0(operand *op)
10719 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10722 /*-----------------------------------------------------------------*/
10723 /* genUnpackBits - generates code for unpacking bits */
10724 /*-----------------------------------------------------------------*/
10725 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10729 sym_link *etype, *letype;
10730 int blen=0, bstr=0;
10734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10735 etype = getSpec(operandType(result));
10736 letype = getSpec(operandType(left));
10738 // if(IS_BITFIELD(etype)) {
10739 blen = SPEC_BLEN(etype);
10740 bstr = SPEC_BSTR(etype);
10743 lbstr = SPEC_BSTR( letype );
10746 if((blen == 1) && (bstr < 8)) {
10747 /* it is a single bit, so use the appropriate bit instructions */
10748 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10750 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10752 if((ptype == POINTER) && (result)) {
10753 /* workaround to reduce the extra lfsr instruction */
10754 pic16_emitpcode(POC_BTFSC,
10755 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10757 pic16_emitpcode(POC_BTFSC,
10758 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10761 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10763 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10769 /* the following call to pic16_loadFSR0 is temporary until
10770 * optimization to handle single bit assignments is added
10771 * to the function. Until then use the old safe way! -- VR */
10772 pic16_loadFSR0( left );
10774 /* read the first byte */
10781 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10784 pic16_emitcode("clr","a");
10785 pic16_emitcode("movc","a","@a+dptr");
10790 /* if we have bitdisplacement then it fits */
10791 /* into this byte completely or if length is */
10792 /* less than a byte */
10793 if ((shCnt = SPEC_BSTR(etype)) ||
10794 (SPEC_BLEN(etype) <= 8)) {
10796 /* shift right acc */
10799 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10800 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10802 /* VR -- normally I would use the following, but since we use the hack,
10803 * to avoid the masking from AccRsh, why not mask it right now? */
10806 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10809 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10815 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10816 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10819 /* bit field did not fit in a byte */
10820 rlen = SPEC_BLEN(etype) - 8;
10821 pic16_aopPut(AOP(result),"a",offset++);
10828 pic16_emitcode("inc","%s",rname);
10829 pic16_emitcode("mov","a,@%s",rname);
10833 pic16_emitcode("inc","%s",rname);
10834 pic16_emitcode("movx","a,@%s",rname);
10838 pic16_emitcode("inc","dptr");
10839 pic16_emitcode("movx","a,@dptr");
10843 pic16_emitcode("clr","a");
10844 pic16_emitcode("inc","dptr");
10845 pic16_emitcode("movc","a","@a+dptr");
10849 pic16_emitcode("inc","dptr");
10850 pic16_emitcode("lcall","__gptrget");
10855 /* if we are done */
10859 pic16_aopPut(AOP(result),"a",offset++);
10864 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10865 pic16_aopPut(AOP(result),"a",offset);
10872 static void genDataPointerGet(operand *left,
10876 int size, offset = 0, leoffset=0 ;
10878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10879 pic16_aopOp(result, ic, FALSE);
10881 size = AOP_SIZE(result);
10882 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10886 /* The following tests may save a redudant movff instruction when
10887 * accessing unions */
10889 /* if they are the same */
10890 if (operandsEqu (left, result)) {
10891 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10897 /* if they are the same registers */
10898 if (pic16_sameRegs(AOP(left),AOP(result))) {
10899 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10905 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10906 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10907 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10914 if ( AOP_TYPE(left) == AOP_PCODE) {
10915 fprintf(stderr,"genDataPointerGet %s, %d\n",
10916 AOP(left)->aopu.pcop->name,
10917 (AOP(left)->aopu.pcop->type == PO_DIR)?
10918 PCOR(AOP(left)->aopu.pcop)->instance:
10919 PCOI(AOP(left)->aopu.pcop)->offset);
10923 if(AOP(left)->aopu.pcop->type == PO_DIR)
10924 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10926 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10929 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10931 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10932 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10933 pic16_mov2w(AOP(left), offset); // patch 8
10934 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10936 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10937 pic16_popGet(AOP(left), offset), //patch 8
10938 pic16_popGet(AOP(result), offset)));
10946 pic16_freeAsmop(result,NULL,ic,TRUE);
10951 /*-----------------------------------------------------------------*/
10952 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10953 /*-----------------------------------------------------------------*/
10954 static void genNearPointerGet (operand *left,
10959 //regs *preg = NULL ;
10960 sym_link *rtype, *retype;
10961 sym_link *ltype = operandType(left);
10965 rtype = operandType(result);
10966 retype= getSpec(rtype);
10968 pic16_aopOp(left,ic,FALSE);
10970 // pic16_DumpOp("(left)",left);
10971 // pic16_DumpOp("(result)",result);
10973 /* if left is rematerialisable and
10974 * result is not bit variable type and
10975 * the left is pointer to data space i.e
10976 * lower 128 bytes of space */
10978 if (AOP_TYPE(left) == AOP_PCODE
10979 && !IS_BITFIELD(retype)
10980 && DCL_TYPE(ltype) == POINTER) {
10982 genDataPointerGet (left,result,ic);
10983 pic16_freeAsmop(left, NULL, ic, TRUE);
10987 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10989 /* if the value is already in a pointer register
10990 * then don't need anything more */
10991 if (!AOP_INPREG(AOP(left))) {
10992 /* otherwise get a free pointer register */
10993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10995 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10996 /* bitfields will be handled by genUnpackBits */
10997 if(!IS_BITFIELD(retype)) {
10999 if(is_LitAOp( AOP(left) )) {
11000 pic16_loadFSR0( left );
11002 // set up FSR0 with address from left
11003 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11004 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11009 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11011 pic16_aopOp (result,ic,FALSE);
11013 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11015 /* if bitfield then unpack the bits */
11016 if (IS_BITFIELD(retype))
11017 genUnpackBits (result, left, NULL, POINTER);
11019 /* we have can just get the values */
11020 int size = AOP_SIZE(result);
11023 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11025 /* fsr0 is loaded already -- VR */
11026 // pic16_loadFSR0( left );
11028 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11029 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11032 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11033 pic16_popGet(AOP(result), offset++)));
11035 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11036 pic16_popGet(AOP(result), offset++)));
11040 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11041 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11043 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11047 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11049 pic16_emitcode("mov","a,@%s",rname);
11050 pic16_aopPut(AOP(result),"a",offset);
11052 sprintf(buffer,"@%s",rname);
11053 pic16_aopPut(AOP(result),buffer,offset);
11057 pic16_emitcode("inc","%s",rname);
11062 /* now some housekeeping stuff */
11064 /* we had to allocate for this iCode */
11065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11066 pic16_freeAsmop(NULL,aop,ic,TRUE);
11068 /* we did not allocate which means left
11069 * already in a pointer register, then
11070 * if size > 0 && this could be used again
11071 * we have to point it back to where it
11073 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11074 if (AOP_SIZE(result) > 1
11075 && !OP_SYMBOL(left)->remat
11076 && ( OP_SYMBOL(left)->liveTo > ic->seq
11078 // int size = AOP_SIZE(result) - 1;
11080 // pic16_emitcode("dec","%s",rname);
11085 pic16_freeAsmop(left,NULL,ic,TRUE);
11086 pic16_freeAsmop(result,NULL,ic,TRUE);
11089 /*-----------------------------------------------------------------*/
11090 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11091 /*-----------------------------------------------------------------*/
11092 static void genPagedPointerGet (operand *left,
11097 regs *preg = NULL ;
11099 sym_link *rtype, *retype;
11101 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11103 rtype = operandType(result);
11104 retype= getSpec(rtype);
11106 pic16_aopOp(left,ic,FALSE);
11108 /* if the value is already in a pointer register
11109 then don't need anything more */
11110 if (!AOP_INPREG(AOP(left))) {
11111 /* otherwise get a free pointer register */
11113 preg = getFreePtr(ic,&aop,FALSE);
11114 pic16_emitcode("mov","%s,%s",
11116 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11117 rname = preg->name ;
11119 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11121 pic16_freeAsmop(left,NULL,ic,TRUE);
11122 pic16_aopOp (result,ic,FALSE);
11124 /* if bitfield then unpack the bits */
11125 if (IS_BITFIELD(retype))
11126 genUnpackBits (result,left,rname,PPOINTER);
11128 /* we have can just get the values */
11129 int size = AOP_SIZE(result);
11134 pic16_emitcode("movx","a,@%s",rname);
11135 pic16_aopPut(AOP(result),"a",offset);
11140 pic16_emitcode("inc","%s",rname);
11144 /* now some housekeeping stuff */
11146 /* we had to allocate for this iCode */
11147 pic16_freeAsmop(NULL,aop,ic,TRUE);
11149 /* we did not allocate which means left
11150 already in a pointer register, then
11151 if size > 0 && this could be used again
11152 we have to point it back to where it
11154 if (AOP_SIZE(result) > 1 &&
11155 !OP_SYMBOL(left)->remat &&
11156 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11158 int size = AOP_SIZE(result) - 1;
11160 pic16_emitcode("dec","%s",rname);
11165 pic16_freeAsmop(result,NULL,ic,TRUE);
11170 /*-----------------------------------------------------------------*/
11171 /* genFarPointerGet - gget value from far space */
11172 /*-----------------------------------------------------------------*/
11173 static void genFarPointerGet (operand *left,
11174 operand *result, iCode *ic)
11177 sym_link *retype = getSpec(operandType(result));
11179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11181 pic16_aopOp(left,ic,FALSE);
11183 /* if the operand is already in dptr
11184 then we do nothing else we move the value to dptr */
11185 if (AOP_TYPE(left) != AOP_STR) {
11186 /* if this is remateriazable */
11187 if (AOP_TYPE(left) == AOP_IMMD)
11188 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11189 else { /* we need to get it byte by byte */
11190 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11191 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11192 if (options.model == MODEL_FLAT24)
11194 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11198 /* so dptr know contains the address */
11199 pic16_freeAsmop(left,NULL,ic,TRUE);
11200 pic16_aopOp(result,ic,FALSE);
11202 /* if bit then unpack */
11203 if (IS_BITFIELD(retype))
11204 genUnpackBits(result,left,"dptr",FPOINTER);
11206 size = AOP_SIZE(result);
11210 pic16_emitcode("movx","a,@dptr");
11211 pic16_aopPut(AOP(result),"a",offset++);
11213 pic16_emitcode("inc","dptr");
11217 pic16_freeAsmop(result,NULL,ic,TRUE);
11220 /*-----------------------------------------------------------------*/
11221 /* genCodePointerGet - get value from code space */
11222 /*-----------------------------------------------------------------*/
11223 static void genCodePointerGet (operand *left,
11224 operand *result, iCode *ic)
11227 sym_link *retype = getSpec(operandType(result));
11229 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11231 pic16_aopOp(left,ic,FALSE);
11233 /* if the operand is already in dptr
11234 then we do nothing else we move the value to dptr */
11235 if (AOP_TYPE(left) != AOP_STR) {
11236 /* if this is remateriazable */
11237 if (AOP_TYPE(left) == AOP_IMMD)
11238 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11239 else { /* we need to get it byte by byte */
11240 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11241 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11242 if (options.model == MODEL_FLAT24)
11244 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11248 /* so dptr know contains the address */
11249 pic16_freeAsmop(left,NULL,ic,TRUE);
11250 pic16_aopOp(result,ic,FALSE);
11252 /* if bit then unpack */
11253 if (IS_BITFIELD(retype))
11254 genUnpackBits(result,left,"dptr",CPOINTER);
11256 size = AOP_SIZE(result);
11260 pic16_emitcode("clr","a");
11261 pic16_emitcode("movc","a,@a+dptr");
11262 pic16_aopPut(AOP(result),"a",offset++);
11264 pic16_emitcode("inc","dptr");
11268 pic16_freeAsmop(result,NULL,ic,TRUE);
11272 /*-----------------------------------------------------------------*/
11273 /* genGenPointerGet - gget value from generic pointer space */
11274 /*-----------------------------------------------------------------*/
11275 static void genGenPointerGet (operand *left,
11276 operand *result, iCode *ic)
11278 int size, offset, lit;
11279 sym_link *retype = getSpec(operandType(result));
11281 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11282 pic16_aopOp(left,ic,FALSE);
11283 pic16_aopOp(result,ic,FALSE);
11284 size = AOP_SIZE(result);
11286 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11288 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11290 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11291 // load FSR0 from immediate
11292 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11294 // pic16_loadFSR0( left );
11299 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11301 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11308 else { /* we need to get it byte by byte */
11309 // set up FSR0 with address from left
11310 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11311 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11317 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11319 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11326 /* if bit then unpack */
11327 if (IS_BITFIELD(retype))
11328 genUnpackBits(result,left,"BAD",GPOINTER);
11331 pic16_freeAsmop(left,NULL,ic,TRUE);
11332 pic16_freeAsmop(result,NULL,ic,TRUE);
11338 /*-----------------------------------------------------------------*/
11339 /* genGenPointerGet - gget value from generic pointer space */
11340 /*-----------------------------------------------------------------*/
11341 static void genGenPointerGet (operand *left,
11342 operand *result, iCode *ic)
11344 int size, offset, lit;
11345 sym_link *retype = getSpec(operandType(result));
11348 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11349 pic16_aopOp(left,ic,FALSE);
11350 pic16_aopOp(result,ic,FALSE);
11351 size = AOP_SIZE(result);
11353 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11355 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11357 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11358 // load FSR0 from immediate
11359 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11361 werror(W_POSSBUG2, __FILE__, __LINE__);
11366 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11368 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11375 } else { /* we need to get it byte by byte */
11377 /* set up WREG:PRODL:FSR0L with address from left */
11378 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11379 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11380 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11383 case 1: strcpy(fgptrget, "__gptrget1"); break;
11384 case 2: strcpy(fgptrget, "__gptrget2"); break;
11385 case 3: strcpy(fgptrget, "__gptrget3"); break;
11386 case 4: strcpy(fgptrget, "__gptrget4"); break;
11388 werror(W_POSSBUG2, __FILE__, __LINE__);
11392 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11394 assignResultValue(result, 1);
11399 sym = newSymbol( fgptrget, 0 );
11400 strcpy(sym->rname, fgptrget);
11401 checkAddSym(&externs, sym);
11403 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11409 /* if bit then unpack */
11410 if (IS_BITFIELD(retype))
11411 genUnpackBits(result,left,"BAD",GPOINTER);
11414 pic16_freeAsmop(left,NULL,ic,TRUE);
11415 pic16_freeAsmop(result,NULL,ic,TRUE);
11418 /*-----------------------------------------------------------------*/
11419 /* genConstPointerGet - get value from const generic pointer space */
11420 /*-----------------------------------------------------------------*/
11421 static void genConstPointerGet (operand *left,
11422 operand *result, iCode *ic)
11424 //sym_link *retype = getSpec(operandType(result));
11425 // symbol *albl = newiTempLabel(NULL); // patch 15
11426 // symbol *blbl = newiTempLabel(NULL); //
11427 // PIC_OPCODE poc; // patch 15
11431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11432 pic16_aopOp(left,ic,FALSE);
11433 pic16_aopOp(result,ic,TRUE);
11434 size = AOP_SIZE(result);
11436 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11438 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11440 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11441 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11442 pic16_emitpLabel(albl->key);
11444 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11446 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11447 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11448 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11449 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11450 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11452 pic16_emitpLabel(blbl->key);
11454 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11458 // set up table pointer
11459 if( (AOP_TYPE(left) == AOP_PCODE)
11460 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11461 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
11463 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11464 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11465 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11466 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11467 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11468 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11472 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11473 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11474 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11480 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11481 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11485 pic16_freeAsmop(left,NULL,ic,TRUE);
11486 pic16_freeAsmop(result,NULL,ic,TRUE);
11491 /*-----------------------------------------------------------------*/
11492 /* genPointerGet - generate code for pointer get */
11493 /*-----------------------------------------------------------------*/
11494 static void genPointerGet (iCode *ic)
11496 operand *left, *result ;
11497 sym_link *type, *etype;
11502 left = IC_LEFT(ic);
11503 result = IC_RESULT(ic) ;
11505 /* depending on the type of pointer we need to
11506 move it to the correct pointer register */
11507 type = operandType(left);
11508 etype = getSpec(type);
11511 if (IS_PTR_CONST(type))
11513 if (IS_CODEPTR(type))
11515 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11517 /* if left is of type of pointer then it is simple */
11518 if (IS_PTR(type) && !IS_FUNC(type->next))
11519 p_type = DCL_TYPE(type);
11521 /* we have to go by the storage class */
11522 p_type = PTR_TYPE(SPEC_OCLS(etype));
11524 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11526 if (SPEC_OCLS(etype)->codesp ) {
11527 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11528 //p_type = CPOINTER ;
11531 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11532 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11533 /*p_type = FPOINTER ;*/
11535 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11536 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11537 /* p_type = PPOINTER; */
11539 if (SPEC_OCLS(etype) == idata )
11540 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11541 /* p_type = IPOINTER; */
11543 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11544 /* p_type = POINTER ; */
11547 /* now that we have the pointer type we assign
11548 the pointer values */
11553 genNearPointerGet (left,result,ic);
11557 genPagedPointerGet(left,result,ic);
11561 genFarPointerGet (left,result,ic);
11565 genConstPointerGet (left,result,ic);
11566 //pic16_emitcodePointerGet (left,result,ic);
11571 if (IS_PTR_CONST(type))
11572 genConstPointerGet (left,result,ic);
11575 genGenPointerGet (left,result,ic);
11579 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11580 "genPointerGet: illegal pointer type");
11586 /*-----------------------------------------------------------------*/
11587 /* genPackBits - generates code for packed bit storage */
11588 /*-----------------------------------------------------------------*/
11589 static void genPackBits (sym_link *etype , operand *result,
11591 char *rname, int p_type)
11600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11601 blen = SPEC_BLEN(etype);
11602 bstr = SPEC_BSTR(etype);
11604 retype = getSpec(operandType(right));
11606 if(AOP_TYPE(right) == AOP_LIT) {
11607 if((blen == 1) && (bstr < 8)) {
11609 /* it is a single bit, so use the appropriate bit instructions */
11611 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11613 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11614 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11615 if((p_type == POINTER) && (result)) {
11616 /* workaround to reduce the extra lfsr instruction */
11618 pic16_emitpcode(POC_BSF,
11619 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11621 pic16_emitpcode(POC_BCF,
11622 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11625 pic16_loadFSR0( result );
11627 pic16_emitpcode(POC_BSF,
11628 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11630 pic16_emitpcode(POC_BCF,
11631 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11638 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11641 if(IS_BITFIELD(retype)
11642 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11646 rblen = SPEC_BLEN( retype );
11647 rbstr = SPEC_BSTR( retype );
11650 if(IS_BITFIELD(etype)) {
11651 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11652 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11654 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11657 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11659 if(IS_BITFIELD(etype)) {
11660 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11662 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11665 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11669 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11671 /* if the bit lenth is less than or */
11672 /* it exactly fits a byte then */
11673 if((shCnt=SPEC_BSTR(etype))
11674 || SPEC_BLEN(etype) <= 8 ) {
11676 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11678 /* shift left acc */
11681 /* using PRODL as a temporary register here */
11682 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11687 pic16_loadFSR0( result );
11688 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11689 // pic16_emitcode ("mov","b,a");
11690 // pic16_emitcode("mov","a,@%s",rname);
11694 werror(W_POSSBUG2, __FILE__, __LINE__);
11699 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11700 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11701 (unsigned char)(0xff >> (8-bstr))) ));
11702 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11703 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11710 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11711 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11716 if ( SPEC_BLEN(etype) <= 8 )
11719 pic16_emitcode("inc","%s",rname);
11720 rLen = SPEC_BLEN(etype) ;
11724 /* now generate for lengths greater than one byte */
11727 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11737 pic16_emitcode("mov","@%s,a",rname);
11739 pic16_emitcode("mov","@%s,%s",rname,l);
11744 pic16_emitcode("movx","@dptr,a");
11749 DEBUGpic16_emitcode(";lcall","__gptrput");
11752 pic16_emitcode ("inc","%s",rname);
11757 /* last last was not complete */
11759 /* save the byte & read byte */
11762 pic16_emitcode ("mov","b,a");
11763 pic16_emitcode("mov","a,@%s",rname);
11767 pic16_emitcode ("mov","b,a");
11768 pic16_emitcode("movx","a,@dptr");
11772 pic16_emitcode ("push","b");
11773 pic16_emitcode ("push","acc");
11774 pic16_emitcode ("lcall","__gptrget");
11775 pic16_emitcode ("pop","b");
11779 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11780 pic16_emitcode ("orl","a,b");
11783 if (p_type == GPOINTER)
11784 pic16_emitcode("pop","b");
11789 pic16_emitcode("mov","@%s,a",rname);
11793 pic16_emitcode("movx","@dptr,a");
11797 DEBUGpic16_emitcode(";lcall","__gptrput");
11801 /*-----------------------------------------------------------------*/
11802 /* genDataPointerSet - remat pointer to data space */
11803 /*-----------------------------------------------------------------*/
11804 static void genDataPointerSet(operand *right,
11808 int size, offset = 0, resoffset=0 ;
11810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11811 pic16_aopOp(right,ic,FALSE);
11813 size = AOP_SIZE(right);
11815 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11818 if ( AOP_TYPE(result) == AOP_PCODE) {
11819 fprintf(stderr,"genDataPointerSet %s, %d\n",
11820 AOP(result)->aopu.pcop->name,
11821 (AOP(result)->aopu.pcop->type == PO_DIR)?
11822 PCOR(AOP(result)->aopu.pcop)->instance:
11823 PCOI(AOP(result)->aopu.pcop)->offset);
11827 if(AOP(result)->aopu.pcop->type == PO_DIR)
11828 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11831 if (AOP_TYPE(right) == AOP_LIT) {
11834 if(!IS_FLOAT(operandType( right )))
11835 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11838 unsigned long lit_int;
11842 /* take care if literal is a float */
11843 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11844 lit = info.lit_int;
11847 lit = lit >> (8*offset);
11849 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11850 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11852 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11855 pic16_mov2w(AOP(right), offset);
11856 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11862 pic16_freeAsmop(right,NULL,ic,TRUE);
11867 /*-----------------------------------------------------------------*/
11868 /* genNearPointerSet - pic16_emitcode for near pointer put */
11869 /*-----------------------------------------------------------------*/
11870 static void genNearPointerSet (operand *right,
11877 sym_link *ptype = operandType(result);
11878 sym_link *resetype;
11880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11881 retype= getSpec(operandType(right));
11882 resetype = getSpec(operandType(result));
11884 pic16_aopOp(result,ic,FALSE);
11886 /* if the result is rematerializable &
11887 * in data space & not a bit variable */
11889 /* and result is not a bit variable */
11890 if (AOP_TYPE(result) == AOP_PCODE
11891 // && AOP_TYPE(result) == AOP_IMMD
11892 && DCL_TYPE(ptype) == POINTER
11893 && !IS_BITFIELD(retype)
11894 && !IS_BITFIELD(resetype)) {
11896 genDataPointerSet (right,result,ic);
11897 pic16_freeAsmop(result,NULL,ic,TRUE);
11901 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11902 pic16_aopOp(right,ic,FALSE);
11903 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11905 /* if the value is already in a pointer register
11906 * then don't need anything more */
11907 if (!AOP_INPREG(AOP(result))) {
11908 /* otherwise get a free pointer register */
11909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11911 // if( (AOP_TYPE(result) == AOP_PCODE)
11912 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11913 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11914 if(is_LitAOp( AOP(result) ))
11916 if(!IS_BITFIELD(resetype))
11917 pic16_loadFSR0( result ); // patch 10
11919 if(!IS_BITFIELD(resetype)) {
11920 // set up FSR0 with address of result
11921 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11922 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11928 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11930 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11932 // pic16_loadFSR0( result );
11934 /* if bitfield then unpack the bits */
11935 if (IS_BITFIELD(resetype)) {
11936 genPackBits (resetype, result, right, NULL, POINTER);
11938 /* we have can just get the values */
11939 int size = AOP_SIZE(right);
11942 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11944 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11947 //pic16_emitcode("mov","@%s,a",rname);
11948 pic16_emitcode("movf","indf0,w ;1");
11951 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
11952 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
11954 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
11956 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
11958 } else { // no literal //
11960 pic16_emitpcode(POC_MOVFF, //
11961 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11962 pic16_popCopyReg(&pic16_pc_postinc0))); //
11964 pic16_emitpcode(POC_MOVFF, //
11965 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11966 pic16_popCopyReg(&pic16_pc_indf0))); //
11974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11975 /* now some housekeeping stuff */
11977 /* we had to allocate for this iCode */
11978 pic16_freeAsmop(NULL,aop,ic,TRUE);
11980 /* we did not allocate which means left
11981 * already in a pointer register, then
11982 * if size > 0 && this could be used again
11983 * we have to point it back to where it
11985 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11986 if (AOP_SIZE(right) > 1
11987 && !OP_SYMBOL(result)->remat
11988 && ( OP_SYMBOL(result)->liveTo > ic->seq
11991 int size = AOP_SIZE(right) - 1;
11994 pic16_emitcode("decf","fsr0,f");
11995 //pic16_emitcode("dec","%s",rname);
11999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12002 pic16_freeAsmop(right,NULL,ic,TRUE);
12003 pic16_freeAsmop(result,NULL,ic,TRUE);
12006 /*-----------------------------------------------------------------*/
12007 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12008 /*-----------------------------------------------------------------*/
12009 static void genPagedPointerSet (operand *right,
12014 regs *preg = NULL ;
12018 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12020 retype= getSpec(operandType(right));
12022 pic16_aopOp(result,ic,FALSE);
12024 /* if the value is already in a pointer register
12025 then don't need anything more */
12026 if (!AOP_INPREG(AOP(result))) {
12027 /* otherwise get a free pointer register */
12029 preg = getFreePtr(ic,&aop,FALSE);
12030 pic16_emitcode("mov","%s,%s",
12032 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12033 rname = preg->name ;
12035 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12037 pic16_freeAsmop(result,NULL,ic,TRUE);
12038 pic16_aopOp (right,ic,FALSE);
12040 /* if bitfield then unpack the bits */
12041 if (IS_BITFIELD(retype))
12042 genPackBits (retype,result,right,rname,PPOINTER);
12044 /* we have can just get the values */
12045 int size = AOP_SIZE(right);
12049 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12052 pic16_emitcode("movx","@%s,a",rname);
12055 pic16_emitcode("inc","%s",rname);
12061 /* now some housekeeping stuff */
12063 /* we had to allocate for this iCode */
12064 pic16_freeAsmop(NULL,aop,ic,TRUE);
12066 /* we did not allocate which means left
12067 already in a pointer register, then
12068 if size > 0 && this could be used again
12069 we have to point it back to where it
12071 if (AOP_SIZE(right) > 1 &&
12072 !OP_SYMBOL(result)->remat &&
12073 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12075 int size = AOP_SIZE(right) - 1;
12077 pic16_emitcode("dec","%s",rname);
12082 pic16_freeAsmop(right,NULL,ic,TRUE);
12087 /*-----------------------------------------------------------------*/
12088 /* genFarPointerSet - set value from far space */
12089 /*-----------------------------------------------------------------*/
12090 static void genFarPointerSet (operand *right,
12091 operand *result, iCode *ic)
12094 sym_link *retype = getSpec(operandType(right));
12096 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12097 pic16_aopOp(result,ic,FALSE);
12099 /* if the operand is already in dptr
12100 then we do nothing else we move the value to dptr */
12101 if (AOP_TYPE(result) != AOP_STR) {
12102 /* if this is remateriazable */
12103 if (AOP_TYPE(result) == AOP_IMMD)
12104 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12105 else { /* we need to get it byte by byte */
12106 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12107 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12108 if (options.model == MODEL_FLAT24)
12110 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12114 /* so dptr know contains the address */
12115 pic16_freeAsmop(result,NULL,ic,TRUE);
12116 pic16_aopOp(right,ic,FALSE);
12118 /* if bit then unpack */
12119 if (IS_BITFIELD(retype))
12120 genPackBits(retype,result,right,"dptr",FPOINTER);
12122 size = AOP_SIZE(right);
12126 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12128 pic16_emitcode("movx","@dptr,a");
12130 pic16_emitcode("inc","dptr");
12134 pic16_freeAsmop(right,NULL,ic,TRUE);
12137 /*-----------------------------------------------------------------*/
12138 /* genGenPointerSet - set value from generic pointer space */
12139 /*-----------------------------------------------------------------*/
12141 static void genGenPointerSet (operand *right,
12142 operand *result, iCode *ic)
12144 int i, size, offset, lit;
12145 sym_link *retype = getSpec(operandType(right));
12147 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12149 pic16_aopOp(result,ic,FALSE);
12150 pic16_aopOp(right,ic,FALSE);
12151 size = AOP_SIZE(right);
12154 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12156 /* if the operand is already in dptr
12157 then we do nothing else we move the value to dptr */
12158 if (AOP_TYPE(result) != AOP_STR) {
12159 /* if this is remateriazable */
12160 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12161 // WARNING: anythig until "else" is untested!
12162 if (AOP_TYPE(result) == AOP_IMMD) {
12163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12164 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12165 // load FSR0 from immediate
12166 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12170 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12172 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12178 else { /* we need to get it byte by byte */
12179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12180 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12182 // set up FSR0 with address of result
12183 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12184 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12186 /* hack hack! see if this the FSR. If so don't load W */
12187 if(AOP_TYPE(right) != AOP_ACC) {
12189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12191 if(AOP_TYPE(right) == AOP_LIT)
12194 // note: pic16_popGet handles sign extension
12195 for(i=0;i<size;i++) {
12196 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12198 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12200 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12205 for(i=0;i<size;i++) {
12207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12208 pic16_popCopyReg(&pic16_pc_postinc0)));
12210 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12211 pic16_popCopyReg(&pic16_pc_indf0)));
12217 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12218 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12220 } // if (AOP_TYPE(result) != AOP_IMMD)
12222 } // if (AOP_TYPE(result) != AOP_STR)
12223 /* so dptr know contains the address */
12226 /* if bit then unpack */
12227 if (IS_BITFIELD(retype))
12228 genPackBits(retype,result,right,"dptr",GPOINTER);
12230 size = AOP_SIZE(right);
12233 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12235 // set up FSR0 with address of result
12236 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12237 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12240 if (AOP_TYPE(right) == AOP_LIT) {
12241 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12243 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12245 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12247 } else { // no literal
12249 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12259 pic16_freeAsmop(right,NULL,ic,TRUE);
12260 pic16_freeAsmop(result,NULL,ic,TRUE);
12264 static void genGenPointerSet (operand *right,
12265 operand *result, iCode *ic)
12268 sym_link *retype = getSpec(operandType(right));
12271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12273 pic16_aopOp(result,ic,FALSE);
12274 pic16_aopOp(right,ic,FALSE);
12275 size = AOP_SIZE(right);
12277 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12280 /* if bit then unpack */
12281 if (IS_BITFIELD(retype)) {
12282 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12283 genPackBits(retype,result,right,"dptr",GPOINTER);
12287 size = AOP_SIZE(right);
12289 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12293 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12295 /* value of right+0 is placed on stack, which will be retrieved
12296 * by the support function this restoring the stack. The important
12297 * thing is that there is no need to manually restore stack pointer
12299 pushaop(AOP(right), 0);
12300 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12301 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12302 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12303 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12305 /* load address to write to in WREG:FSR0H:FSR0L */
12306 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12307 pic16_popCopyReg(&pic16_pc_fsr0l)));
12308 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12309 pic16_popCopyReg(&pic16_pc_prodl)));
12310 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12313 /* put code here */
12315 case 1: strcpy(fgptrput, "__gptrput1"); break;
12316 case 2: strcpy(fgptrput, "__gptrput2"); break;
12317 case 3: strcpy(fgptrput, "__gptrput3"); break;
12318 case 4: strcpy(fgptrput, "__gptrput4"); break;
12320 werror(W_POSSBUG2, __FILE__, __LINE__);
12324 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12329 sym = newSymbol( fgptrput, 0 );
12330 strcpy(sym->rname, fgptrput);
12331 checkAddSym(&externs, sym);
12335 pic16_freeAsmop(right,NULL,ic,TRUE);
12336 pic16_freeAsmop(result,NULL,ic,TRUE);
12339 /*-----------------------------------------------------------------*/
12340 /* genPointerSet - stores the value into a pointer location */
12341 /*-----------------------------------------------------------------*/
12342 static void genPointerSet (iCode *ic)
12344 operand *right, *result ;
12345 sym_link *type, *etype;
12350 right = IC_RIGHT(ic);
12351 result = IC_RESULT(ic) ;
12353 /* depending on the type of pointer we need to
12354 move it to the correct pointer register */
12355 type = operandType(result);
12356 etype = getSpec(type);
12357 /* if left is of type of pointer then it is simple */
12358 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12359 p_type = DCL_TYPE(type);
12362 /* we have to go by the storage class */
12363 p_type = PTR_TYPE(SPEC_OCLS(etype));
12365 /* if (SPEC_OCLS(etype)->codesp ) { */
12366 /* p_type = CPOINTER ; */
12369 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12370 /* p_type = FPOINTER ; */
12372 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12373 /* p_type = PPOINTER ; */
12375 /* if (SPEC_OCLS(etype) == idata ) */
12376 /* p_type = IPOINTER ; */
12378 /* p_type = POINTER ; */
12381 /* now that we have the pointer type we assign
12382 the pointer values */
12387 genNearPointerSet (right,result,ic);
12391 genPagedPointerSet (right,result,ic);
12395 genFarPointerSet (right,result,ic);
12399 genGenPointerSet (right,result,ic);
12403 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12404 "genPointerSet: illegal pointer type");
12408 /*-----------------------------------------------------------------*/
12409 /* genIfx - generate code for Ifx statement */
12410 /*-----------------------------------------------------------------*/
12411 static void genIfx (iCode *ic, iCode *popIc)
12413 operand *cond = IC_COND(ic);
12418 pic16_aopOp(cond,ic,FALSE);
12420 /* get the value into acc */
12421 if (AOP_TYPE(cond) != AOP_CRY)
12422 pic16_toBoolean(cond);
12425 /* the result is now in the accumulator */
12426 pic16_freeAsmop(cond,NULL,ic,TRUE);
12428 /* if there was something to be popped then do it */
12432 /* if the condition is a bit variable */
12433 if (isbit && IS_ITEMP(cond) &&
12435 genIfxJump(ic,"c");
12436 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12438 if (isbit && !IS_ITEMP(cond))
12439 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12441 genIfxJump(ic,"a");
12446 /*-----------------------------------------------------------------*/
12447 /* genAddrOf - generates code for address of */
12448 /*-----------------------------------------------------------------*/
12449 static void genAddrOf (iCode *ic)
12451 operand *result, *left;
12453 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12454 pCodeOp *pcop0, *pcop1, *pcop2;
12458 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12460 sym = OP_SYMBOL( IC_LEFT(ic) );
12463 /* get address of symbol on stack */
12464 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12466 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12467 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12470 // operands on stack are accessible via "FSR2 + index" with index
12471 // starting at 2 for arguments and growing from 0 downwards for
12472 // local variables (index == 0 is not assigned so we add one here)
12474 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12476 assert (soffs < 0);
12479 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12480 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12481 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(&pic16_pc_fsr2l));
12482 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12483 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12484 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(&pic16_pc_fsr2h));
12485 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12491 // if(pic16_debug_verbose) {
12492 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12493 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12496 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12497 size = AOP_SIZE(IC_RESULT(ic));
12500 /* Assume that what we want the address of is in data space
12501 * since there is no stack on the PIC, yet! -- VR */
12503 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12504 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12505 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12508 pic16_emitpcode(POC_MOVLW, pcop0);
12509 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12510 pic16_emitpcode(POC_MOVLW, pcop1);
12511 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12512 pic16_emitpcode(POC_MOVLW, pcop2);
12513 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
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));
12521 pic16_emitpcode(POC_MOVLW, pcop0);
12522 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12525 pic16_freeAsmop(left, NULL, ic, FALSE);
12527 pic16_freeAsmop(result,NULL,ic,TRUE);
12532 /*-----------------------------------------------------------------*/
12533 /* genFarFarAssign - assignment when both are in far space */
12534 /*-----------------------------------------------------------------*/
12535 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12537 int size = AOP_SIZE(right);
12540 /* first push the right side on to the stack */
12542 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12544 pic16_emitcode ("push","acc");
12547 pic16_freeAsmop(right,NULL,ic,FALSE);
12548 /* now assign DPTR to result */
12549 pic16_aopOp(result,ic,FALSE);
12550 size = AOP_SIZE(result);
12552 pic16_emitcode ("pop","acc");
12553 pic16_aopPut(AOP(result),"a",--offset);
12555 pic16_freeAsmop(result,NULL,ic,FALSE);
12560 /*-----------------------------------------------------------------*/
12561 /* genAssign - generate code for assignment */
12562 /*-----------------------------------------------------------------*/
12563 static void genAssign (iCode *ic)
12565 operand *result, *right;
12566 int size, offset,know_W;
12567 unsigned long lit = 0L;
12569 result = IC_RESULT(ic);
12570 right = IC_RIGHT(ic) ;
12574 /* if they are the same */
12575 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12578 /* reversed order operands are aopOp'ed so that result operand
12579 * is effective in case right is a stack symbol. This maneauver
12580 * allows to use the _G.resDirect flag later */
12581 pic16_aopOp(result,ic,TRUE);
12582 pic16_aopOp(right,ic,FALSE);
12584 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12586 /* if they are the same registers */
12587 if (pic16_sameRegs(AOP(right),AOP(result)))
12590 /* if the result is a bit */
12591 if (AOP_TYPE(result) == AOP_CRY) {
12592 /* if the right size is a literal then
12593 we know what the value is */
12594 if (AOP_TYPE(right) == AOP_LIT) {
12596 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12597 pic16_popGet(AOP(result),0));
12599 if (((int) operandLitValue(right)))
12600 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12601 AOP(result)->aopu.aop_dir,
12602 AOP(result)->aopu.aop_dir);
12604 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12605 AOP(result)->aopu.aop_dir,
12606 AOP(result)->aopu.aop_dir);
12610 /* the right is also a bit variable */
12611 if (AOP_TYPE(right) == AOP_CRY) {
12612 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12613 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12614 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12616 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12617 AOP(result)->aopu.aop_dir,
12618 AOP(result)->aopu.aop_dir);
12619 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12620 AOP(right)->aopu.aop_dir,
12621 AOP(right)->aopu.aop_dir);
12622 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12623 AOP(result)->aopu.aop_dir,
12624 AOP(result)->aopu.aop_dir);
12628 /* we need to or */
12629 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12630 pic16_toBoolean(right);
12632 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12633 //pic16_aopPut(AOP(result),"a",0);
12637 /* bit variables done */
12639 size = AOP_SIZE(result);
12642 if(AOP_TYPE(right) == AOP_LIT) {
12643 if(!IS_FLOAT(operandType( right )))
12644 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12647 unsigned long lit_int;
12651 /* take care if literal is a float */
12652 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12653 lit = info.lit_int;
12657 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12658 // sizeof(unsigned long int), sizeof(float));
12661 if (AOP_TYPE(right) == AOP_REG) {
12662 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12665 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12670 if(AOP_TYPE(right) != AOP_LIT
12671 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12672 && !IS_FUNC(OP_SYM_TYPE(right))
12674 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12675 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12677 // set up table pointer
12678 if(is_LitOp(right)) {
12679 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12680 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12681 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12682 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12683 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12684 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12685 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12687 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12688 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12689 pic16_popCopyReg(&pic16_pc_tblptrl)));
12690 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12691 pic16_popCopyReg(&pic16_pc_tblptrh)));
12692 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12693 pic16_popCopyReg(&pic16_pc_tblptru)));
12696 size = min(AOP_SIZE(right), AOP_SIZE(result));
12698 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12699 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12700 pic16_popGet(AOP(result),offset)));
12704 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12705 size = AOP_SIZE(result) - AOP_SIZE(right);
12707 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12717 /* VR - What is this?! */
12718 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12720 if(aopIdx(AOP(result),0) == 4) {
12722 /* this is a workaround to save value of right into wreg too,
12723 * value of wreg is going to be used later */
12724 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12725 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12726 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12730 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12736 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12737 if(AOP_TYPE(right) == AOP_LIT) {
12739 if(know_W != (lit&0xff))
12740 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12744 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12748 } else if (AOP_TYPE(right) == AOP_CRY) {
12749 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12751 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12752 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12753 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12755 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12756 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12761 if(!_G.resDirect) /* use this aopForSym feature */
12762 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12769 pic16_freeAsmop (right,NULL,ic,FALSE);
12770 pic16_freeAsmop (result,NULL,ic,TRUE);
12773 /*-----------------------------------------------------------------*/
12774 /* genJumpTab - generates code for jump table */
12775 /*-----------------------------------------------------------------*/
12776 static void genJumpTab (iCode *ic)
12781 pCodeOp *jt_offs_hi;
12786 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12787 /* get the condition into accumulator */
12788 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12790 /* multiply by three */
12791 pic16_emitcode("add","a,acc");
12792 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12794 jtab = newiTempLabel(NULL);
12795 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12796 pic16_emitcode("jmp","@a+dptr");
12797 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12800 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12801 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12803 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12804 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12805 pic16_emitpLabel(jtab->key);
12809 jt_offs = pic16_popGetTempReg(0);
12810 jt_offs_hi = pic16_popGetTempReg(1);
12811 jt_label = pic16_popGetLabel (jtab->key);
12812 //fprintf (stderr, "Creating jump table...\n");
12814 // calculate offset into jump table (idx * sizeof (GOTO))
12815 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12816 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12817 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12818 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12819 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12820 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12821 pic16_emitpcode(POC_MOVWF , jt_offs);
12823 // prepare PCLATx (set to first entry in jump table)
12824 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12825 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12826 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12827 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12828 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12830 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12831 pic16_emitpcode(POC_ADDWF , jt_offs);
12832 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12833 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12835 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12837 // release temporaries and prepare jump into table (new PCL --> WREG)
12838 pic16_emitpcode(POC_MOVFW , jt_offs);
12839 pic16_popReleaseTempReg (jt_offs_hi, 1);
12840 pic16_popReleaseTempReg (jt_offs, 0);
12842 // jump into the table
12843 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12845 pic16_emitpLabelFORCE(jtab->key);
12848 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12850 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12851 /* now generate the jump labels */
12852 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12853 jtab = setNextItem(IC_JTLABELS(ic))) {
12854 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12858 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12862 /*-----------------------------------------------------------------*/
12863 /* genMixedOperation - gen code for operators between mixed types */
12864 /*-----------------------------------------------------------------*/
12866 TSD - Written for the PIC port - but this unfortunately is buggy.
12867 This routine is good in that it is able to efficiently promote
12868 types to different (larger) sizes. Unfortunately, the temporary
12869 variables that are optimized out by this routine are sometimes
12870 used in other places. So until I know how to really parse the
12871 iCode tree, I'm going to not be using this routine :(.
12873 static int genMixedOperation (iCode *ic)
12876 operand *result = IC_RESULT(ic);
12877 sym_link *ctype = operandType(IC_LEFT(ic));
12878 operand *right = IC_RIGHT(ic);
12884 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12886 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12892 nextright = IC_RIGHT(nextic);
12893 nextleft = IC_LEFT(nextic);
12894 nextresult = IC_RESULT(nextic);
12896 pic16_aopOp(right,ic,FALSE);
12897 pic16_aopOp(result,ic,FALSE);
12898 pic16_aopOp(nextright, nextic, FALSE);
12899 pic16_aopOp(nextleft, nextic, FALSE);
12900 pic16_aopOp(nextresult, nextic, FALSE);
12902 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12904 operand *t = right;
12908 pic16_emitcode(";remove right +","");
12910 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12912 operand *t = right;
12916 pic16_emitcode(";remove left +","");
12920 big = AOP_SIZE(nextleft);
12921 small = AOP_SIZE(nextright);
12923 switch(nextic->op) {
12926 pic16_emitcode(";optimize a +","");
12927 /* if unsigned or not an integral type */
12928 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12929 pic16_emitcode(";add a bit to something","");
12932 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12934 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12935 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12936 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12938 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12946 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12947 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12948 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12951 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12953 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12954 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12955 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12956 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12957 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12960 pic16_emitcode("rlf","known_zero,w");
12967 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12968 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12969 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12971 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12981 pic16_freeAsmop(right,NULL,ic,TRUE);
12982 pic16_freeAsmop(result,NULL,ic,TRUE);
12983 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12984 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12986 nextic->generated = 1;
12993 /*-----------------------------------------------------------------*/
12994 /* genCast - gen code for casting */
12995 /*-----------------------------------------------------------------*/
12996 static void genCast (iCode *ic)
12998 operand *result = IC_RESULT(ic);
12999 sym_link *ctype = operandType(IC_LEFT(ic));
13000 sym_link *rtype = operandType(IC_RIGHT(ic));
13001 sym_link *restype = operandType(IC_RESULT(ic));
13002 operand *right = IC_RIGHT(ic);
13008 /* if they are equivalent then do nothing */
13009 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13012 pic16_aopOp(right,ic,FALSE) ;
13013 pic16_aopOp(result,ic,FALSE);
13015 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13018 /* if the result is a bit */
13019 if (AOP_TYPE(result) == AOP_CRY) {
13021 /* if the right size is a literal then
13022 * we know what the value is */
13023 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13025 if (AOP_TYPE(right) == AOP_LIT) {
13026 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13027 pic16_popGet(AOP(result),0));
13029 if (((int) operandLitValue(right)))
13030 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13031 AOP(result)->aopu.aop_dir,
13032 AOP(result)->aopu.aop_dir);
13034 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13035 AOP(result)->aopu.aop_dir,
13036 AOP(result)->aopu.aop_dir);
13040 /* the right is also a bit variable */
13041 if (AOP_TYPE(right) == AOP_CRY) {
13043 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13045 pic16_emitcode("clrc","");
13046 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13047 AOP(right)->aopu.aop_dir,
13048 AOP(right)->aopu.aop_dir);
13049 pic16_aopPut(AOP(result),"c",0);
13053 /* we need to or */
13054 if (AOP_TYPE(right) == AOP_REG) {
13055 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13056 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13057 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13059 pic16_toBoolean(right);
13060 pic16_aopPut(AOP(result),"a",0);
13064 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13067 size = AOP_SIZE(result);
13069 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13071 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13072 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13073 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13076 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13081 if(IS_BITFIELD(getSpec(restype))
13082 && IS_BITFIELD(getSpec(rtype))) {
13083 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13086 /* if they are the same size : or less */
13087 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13089 /* if they are in the same place */
13090 if (pic16_sameRegs(AOP(right),AOP(result)))
13093 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13095 if (IS_PTR_CONST(rtype))
13097 if (IS_CODEPTR(rtype))
13099 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13102 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13104 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13106 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13109 if(AOP_TYPE(right) == AOP_IMMD) {
13110 pCodeOp *pcop0, *pcop1, *pcop2;
13111 symbol *sym = OP_SYMBOL( right );
13113 size = AOP_SIZE(result);
13115 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13117 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13119 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13122 pic16_emitpcode(POC_MOVLW, pcop0);
13123 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13124 pic16_emitpcode(POC_MOVLW, pcop1);
13125 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13126 pic16_emitpcode(POC_MOVLW, pcop2);
13127 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
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));
13135 pic16_emitpcode(POC_MOVLW, pcop0);
13136 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13140 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13141 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13142 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13143 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13144 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13145 if(AOP_SIZE(result) <2)
13146 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13148 /* if they in different places then copy */
13149 size = AOP_SIZE(result);
13152 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13153 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13160 /* if the result is of type pointer */
13161 if (IS_PTR(ctype)) {
13163 sym_link *type = operandType(right);
13164 sym_link *etype = getSpec(type);
13166 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13168 /* pointer to generic pointer */
13169 if (IS_GENPTR(ctype)) {
13173 p_type = DCL_TYPE(type);
13175 /* we have to go by the storage class */
13176 p_type = PTR_TYPE(SPEC_OCLS(etype));
13178 /* if (SPEC_OCLS(etype)->codesp ) */
13179 /* p_type = CPOINTER ; */
13181 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13182 /* p_type = FPOINTER ; */
13184 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13185 /* p_type = PPOINTER; */
13187 /* if (SPEC_OCLS(etype) == idata ) */
13188 /* p_type = IPOINTER ; */
13190 /* p_type = POINTER ; */
13193 /* the first two bytes are known */
13194 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13195 size = GPTRSIZE - 1;
13198 if(offset < AOP_SIZE(right)) {
13199 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13200 mov2f(AOP(result), AOP(right), offset);
13202 if ((AOP_TYPE(right) == AOP_PCODE) &&
13203 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13204 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13205 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13208 pic16_aopPut(AOP(result),
13209 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13214 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13217 /* the last byte depending on type */
13221 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13223 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13227 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13231 pic16_emitcode(";BUG!? ","%d",__LINE__);
13235 pic16_emitcode(";BUG!? ","%d",__LINE__);
13240 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13244 /* this should never happen */
13245 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13246 "got unknown pointer type");
13249 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13253 /* just copy the pointers */
13254 size = AOP_SIZE(result);
13257 pic16_aopPut(AOP(result),
13258 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13267 /* so we now know that the size of destination is greater
13268 than the size of the source.
13269 Now, if the next iCode is an operator then we might be
13270 able to optimize the operation without performing a cast.
13272 if(genMixedOperation(ic))
13275 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13277 /* we move to result for the size of source */
13278 size = AOP_SIZE(right);
13281 mov2f(AOP(result), AOP(right), offset);
13285 /* now depending on the sign of the destination */
13286 size = AOP_SIZE(result) - AOP_SIZE(right);
13287 /* if unsigned or not an integral type */
13288 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13290 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13292 /* we need to extend the sign :( */
13295 /* Save one instruction of casting char to int */
13296 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13297 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13298 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13300 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13303 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13305 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13307 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13310 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13315 pic16_freeAsmop(right,NULL,ic,TRUE);
13316 pic16_freeAsmop(result,NULL,ic,TRUE);
13320 /*-----------------------------------------------------------------*/
13321 /* genDjnz - generate decrement & jump if not zero instrucion */
13322 /*-----------------------------------------------------------------*/
13323 static int genDjnz (iCode *ic, iCode *ifx)
13325 symbol *lbl, *lbl1;
13326 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13331 /* if the if condition has a false label
13332 then we cannot save */
13336 /* if the minus is not of the form
13338 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13339 !IS_OP_LITERAL(IC_RIGHT(ic)))
13342 if (operandLitValue(IC_RIGHT(ic)) != 1)
13345 /* if the size of this greater than one then no
13347 if (getSize(operandType(IC_RESULT(ic))) > 1)
13350 /* otherwise we can save BIG */
13351 lbl = newiTempLabel(NULL);
13352 lbl1= newiTempLabel(NULL);
13354 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13356 if (IS_AOP_PREG(IC_RESULT(ic))) {
13357 pic16_emitcode("dec","%s",
13358 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13359 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13360 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13364 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13365 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13367 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13368 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13372 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13373 ifx->generated = 1;
13377 /*-----------------------------------------------------------------*/
13378 /* genReceive - generate code for a receive iCode */
13379 /*-----------------------------------------------------------------*/
13380 static void genReceive (iCode *ic)
13386 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13387 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13389 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13391 if (isOperandInFarSpace(IC_RESULT(ic))
13392 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13393 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13395 int size = getSize(operandType(IC_RESULT(ic)));
13396 int offset = pic16_fReturnSizePic - size;
13400 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13401 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13405 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13407 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13408 size = AOP_SIZE(IC_RESULT(ic));
13411 pic16_emitcode ("pop","acc");
13412 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13415 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13417 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13420 /* set pseudo stack pointer to where it should be - dw*/
13421 GpsuedoStkPtr = ic->parmBytes;
13423 /* setting GpsuedoStkPtr has side effects here: */
13424 assignResultValue(IC_RESULT(ic), 0);
13427 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13430 /*-----------------------------------------------------------------*/
13431 /* genDummyRead - generate code for dummy read of volatiles */
13432 /*-----------------------------------------------------------------*/
13434 genDummyRead (iCode * ic)
13436 pic16_emitcode ("; genDummyRead","");
13437 pic16_emitcode ("; not implemented","");
13442 /*-----------------------------------------------------------------*/
13443 /* genpic16Code - generate code for pic16 based controllers */
13444 /*-----------------------------------------------------------------*/
13446 * At this point, ralloc.c has gone through the iCode and attempted
13447 * to optimize in a way suitable for a PIC. Now we've got to generate
13448 * PIC instructions that correspond to the iCode.
13450 * Once the instructions are generated, we'll pass through both the
13451 * peep hole optimizer and the pCode optimizer.
13452 *-----------------------------------------------------------------*/
13454 void genpic16Code (iCode *lic)
13459 lineHead = lineCurr = NULL;
13461 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13462 pic16_addpBlock(pb);
13465 /* if debug information required */
13466 if (options.debug && currFunc) {
13468 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13473 for (ic = lic ; ic ; ic = ic->next ) {
13475 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13476 if ( cln != ic->lineno ) {
13477 if ( options.debug ) {
13478 debugFile->writeCLine (ic);
13481 if(!options.noCcodeInAsm) {
13482 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13483 printCLine(ic->filename, ic->lineno)));
13489 if(options.iCodeInAsm) {
13492 /* insert here code to print iCode as comment */
13493 l = Safe_strdup(printILine(ic));
13494 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13497 /* if the result is marked as
13498 * spilt and rematerializable or code for
13499 * this has already been generated then
13501 if (resultRemat(ic) || ic->generated )
13504 /* depending on the operation */
13523 /* IPOP happens only when trying to restore a
13524 * spilt live range, if there is an ifx statement
13525 * following this pop then the if statement might
13526 * be using some of the registers being popped which
13527 * would destroy the contents of the register so
13528 * we need to check for this condition and handle it */
13530 && ic->next->op == IFX
13531 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13532 genIfx (ic->next,ic);
13550 genEndFunction (ic);
13566 pic16_genPlus (ic) ;
13570 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13571 pic16_genMinus (ic);
13587 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13591 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13597 /* note these two are xlated by algebraic equivalence
13598 * during parsing SDCC.y */
13599 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13600 "got '>=' or '<=' shouldn't have come here");
13604 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13616 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13620 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13624 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13648 genRightShift (ic);
13651 case GET_VALUE_AT_ADDRESS:
13656 if (POINTER_SET(ic))
13683 addSet(&_G.sendSet,ic);
13686 case DUMMY_READ_VOLATILE:
13696 /* now we are ready to call the
13697 peep hole optimizer */
13698 if (!options.nopeep)
13699 peepHole (&lineHead);
13701 /* now do the actual printing */
13702 printLine (lineHead, codeOutFile);
13705 DFPRINTF((stderr,"printing pBlock\n\n"));
13706 pic16_printpBlock(stdout,pb);