1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
141 static char *accUse[] = {"WREG"};
143 //static short rbank = -1;
159 int stack_lat; /* stack offset latency */
161 int useWreg; /* flag when WREG is used to pass function parameter */
164 /* Resolved ifx structure. This structure stores information
165 about an iCode ifx that makes it easier to generate code.
167 typedef struct resolvedIfx {
168 symbol *lbl; /* pointer to a label */
169 int condition; /* true or false ifx */
170 int generated; /* set true when the code associated with the ifx
174 extern int pic16_ptrRegReq ;
175 extern int pic16_nRegs;
176 extern FILE *codeOutFile;
177 //static void saverbank (int, iCode *,bool);
179 static lineNode *lineHead = NULL;
180 static lineNode *lineCurr = NULL;
182 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
183 0xE0, 0xC0, 0x80, 0x00};
184 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
185 0x07, 0x03, 0x01, 0x00};
189 /*-----------------------------------------------------------------*/
190 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
191 /* exponent of 2 is returned, otherwise -1 is */
193 /* note that this is similar to the function `powof2' in SDCCsymt */
197 /*-----------------------------------------------------------------*/
198 int pic16_my_powof2 (unsigned long num)
201 if( (num & (num-1)) == 0) {
214 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
216 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
218 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
219 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
220 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
221 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
222 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
223 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
224 ((result) ? AOP_SIZE(result) : 0));
227 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
230 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
232 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
233 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
234 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
235 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
236 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
237 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
241 void pic16_emitpcomment (char *fmt, ...)
244 char lb[INITIAL_INLINEASM];
250 vsprintf(lb+1,fmt,ap);
252 while (isspace(*lbp)) lbp++;
255 lineCurr = (lineCurr ?
256 connectLine(lineCurr,newLineNode(lb)) :
257 (lineHead = newLineNode(lb)));
258 lineCurr->isInline = _G.inLine;
259 lineCurr->isDebug = _G.debugLine;
261 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
264 // fprintf(stderr, "%s\n", lb);
267 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
270 char lb[INITIAL_INLINEASM];
273 if(!pic16_debug_verbose)
280 sprintf(lb,"%s\t",inst);
282 sprintf(lb,"%s",inst);
283 vsprintf(lb+(strlen(lb)),fmt,ap);
287 while (isspace(*lbp)) lbp++;
290 lineCurr = (lineCurr ?
291 connectLine(lineCurr,newLineNode(lb)) :
292 (lineHead = newLineNode(lb)));
293 lineCurr->isInline = _G.inLine;
294 lineCurr->isDebug = _G.debugLine;
296 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
299 // fprintf(stderr, "%s\n", lb);
304 void pic16_emitpLabel(int key)
306 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
309 void pic16_emitpLabelFORCE(int key)
311 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
314 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
318 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
320 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
323 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
326 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
328 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
331 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
334 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
340 #define pic16_emitcode DEBUGpic16_emitcode
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitcode - writes the code into a file : for now it is simple */
344 /*-----------------------------------------------------------------*/
345 void pic16_emitcode (char *inst,char *fmt, ...)
348 char lb[INITIAL_INLINEASM];
355 sprintf(lb,"%s\t",inst);
357 sprintf(lb,"%s",inst);
358 vsprintf(lb+(strlen(lb)),fmt,ap);
362 while (isspace(*lbp)) lbp++;
365 lineCurr = (lineCurr ?
366 connectLine(lineCurr,newLineNode(lb)) :
367 (lineHead = newLineNode(lb)));
368 lineCurr->isInline = _G.inLine;
369 lineCurr->isDebug = _G.debugLine;
371 // VR fprintf(stderr, "lb = <%s>\n", lbp);
373 // if(pic16_debug_verbose)
374 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
381 /*-----------------------------------------------------------------*/
382 /* pic16_emitDebuggerSymbol - associate the current code location */
383 /* with a debugger symbol */
384 /*-----------------------------------------------------------------*/
386 pic16_emitDebuggerSymbol (char * debugSym)
389 pic16_emitcode (";", "%s ==.", debugSym);
394 /*-----------------------------------------------------------------*/
395 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
396 /*-----------------------------------------------------------------*/
397 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
399 // bool r0iu = FALSE , r1iu = FALSE;
400 // bool r0ou = FALSE , r1ou = FALSE;
401 bool fsr0iu = FALSE, fsr0ou;
402 bool fsr2iu = FALSE, fsr2ou;
404 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
407 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
408 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
410 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
411 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
413 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
414 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
415 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
418 if(!fsr0iu && !fsr0ou) {
419 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
420 (*aopp)->type = AOP_FSR0;
422 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
424 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
428 /* no usage of FSR2 */
429 if(!fsr2iu && !fsr2ou) {
430 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
431 (*aopp)->type = AOP_FSR2;
433 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
437 /* now we know they both have usage */
438 /* if fsr0 not used in this instruction */
440 if (!_G.fsr0Pushed) {
441 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
442 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
446 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
447 (*aopp)->type = AOP_FSR0;
449 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
451 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
455 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
460 /* the logic: if r0 & r1 used in the instruction
461 then we are in trouble otherwise */
463 /* first check if r0 & r1 are used by this
464 instruction, in which case we are in trouble */
465 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
466 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
471 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
472 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
474 /* if no usage of r0 then return it */
475 if (!r0iu && !r0ou) {
476 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
477 (*aopp)->type = AOP_R0;
479 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
482 /* if no usage of r1 then return it */
483 if (!r1iu && !r1ou) {
484 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
485 (*aopp)->type = AOP_R1;
487 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
490 /* now we know they both have usage */
491 /* if r0 not used in this instruction */
493 /* push it if not already pushed */
495 //pic16_emitcode ("push","%s",
496 // pic16_regWithIdx(R0_IDX)->dname);
500 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
501 (*aopp)->type = AOP_R0;
503 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
506 /* if r1 not used then */
509 /* push it if not already pushed */
511 //pic16_emitcode ("push","%s",
512 // pic16_regWithIdx(R1_IDX)->dname);
516 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
517 (*aopp)->type = AOP_R1;
518 return pic16_regWithIdx(R1_IDX);
522 /* I said end of world but not quite end of world yet */
523 /* if this is a result then we can push it on the stack*/
525 (*aopp)->type = AOP_STK;
529 /* other wise this is true end of the world */
530 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
531 "getFreePtr should never reach here");
536 /*-----------------------------------------------------------------*/
537 /* newAsmop - creates a new asmOp */
538 /*-----------------------------------------------------------------*/
539 static asmop *newAsmop (short type)
543 aop = Safe_calloc(1,sizeof(asmop));
548 static void genSetDPTR(int n)
552 pic16_emitcode(";", "Select standard DPTR");
553 pic16_emitcode("mov", "dps, #0x00");
557 pic16_emitcode(";", "Select alternate DPTR");
558 pic16_emitcode("mov", "dps, #0x01");
562 /*-----------------------------------------------------------------*/
563 /* resolveIfx - converts an iCode ifx into a form more useful for */
564 /* generating code */
565 /*-----------------------------------------------------------------*/
566 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
570 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
576 resIfx->condition = 1; /* assume that the ifx is true */
577 resIfx->generated = 0; /* indicate that the ifx has not been used */
580 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
583 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
584 __FUNCTION__,__LINE__,resIfx->lbl->key);
589 resIfx->lbl = IC_TRUE(ifx);
591 resIfx->lbl = IC_FALSE(ifx);
592 resIfx->condition = 0;
597 DEBUGpic16_emitcode("; +++","ifx true is non-null");
599 DEBUGpic16_emitcode("; +++","ifx true is null");
601 DEBUGpic16_emitcode("; +++","ifx false is non-null");
603 DEBUGpic16_emitcode("; +++","ifx false is null");
607 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
611 /*-----------------------------------------------------------------*/
612 /* pointerCode - returns the code for a pointer type */
613 /*-----------------------------------------------------------------*/
614 static int pointerCode (sym_link *etype)
617 return PTR_TYPE(SPEC_OCLS(etype));
622 /*-----------------------------------------------------------------*/
623 /* aopForSym - for a true symbol */
624 /*-----------------------------------------------------------------*/
625 static asmop *aopForSym (iCode *ic, operand *op, bool result)
627 symbol *sym=OP_SYMBOL(op);
629 memmap *space= SPEC_OCLS(sym->etype);
633 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
635 // sym = OP_SYMBOL(op);
637 /* if already has one */
639 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
644 /* if symbol was initially placed onStack then we must re-place it
645 * to direct memory, since pic16 does not have a specific stack */
647 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
652 /* assign depending on the storage class */
653 /* if it is on the stack or indirectly addressable */
654 /* space we need to assign either r0 or r1 to it */
655 if (sym->onStack || sym->iaccess) {
659 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
660 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
662 /* acquire a temporary register -- it is saved in function */
664 sym->aop = aop = newAsmop(AOP_STA);
665 aop->aopu.stk.stk = sym->stack;
666 aop->size = getSize(sym->type);
669 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
670 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
671 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
672 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
674 for(i=0;i<aop->size;i++)
675 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
676 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
678 for(i=0;i<aop->size;i++) {
679 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
680 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
684 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
687 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
690 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
693 for(i=0;i<aop->size;i++) {
695 /* initialise for stack access via frame pointer */
696 // operands on stack are accessible via "FSR2 + index" with index
697 // starting at 2 for arguments and growing from 0 downwards for
698 // local variables (index == 0 is not assigned so we add one here)
700 int soffs = sym->stack;
705 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
706 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
707 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
712 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
719 /* now assign the address of the variable to
720 the pointer register */
721 if (aop->type != AOP_STK) {
725 pic16_emitcode("push","acc");
727 pic16_emitcode("mov","a,_bp");
728 pic16_emitcode("add","a,#0x%02x",
730 ((char)(sym->stack - _G.nRegsSaved )) :
731 ((char)sym->stack)) & 0xff);
732 pic16_emitcode("mov","%s,a",
733 aop->aopu.aop_ptr->name);
736 pic16_emitcode("pop","acc");
738 pic16_emitcode("mov","%s,#%s",
739 aop->aopu.aop_ptr->name,
741 aop->paged = space->paged;
743 aop->aopu.aop_stk = sym->stack;
751 if (sym->onStack && options.stack10bit)
753 /* It's on the 10 bit stack, which is located in
757 //DEBUGpic16_emitcode(";","%d",__LINE__);
760 pic16_emitcode("push","acc");
762 pic16_emitcode("mov","a,_bp");
763 pic16_emitcode("add","a,#0x%02x",
765 ((char)(sym->stack - _G.nRegsSaved )) :
766 ((char)sym->stack)) & 0xff);
769 pic16_emitcode ("mov","dpx1,#0x40");
770 pic16_emitcode ("mov","dph1,#0x00");
771 pic16_emitcode ("mov","dpl1, a");
775 pic16_emitcode("pop","acc");
777 sym->aop = aop = newAsmop(AOP_DPTR2);
778 aop->size = getSize(sym->type);
784 /* special case for a function */
785 if (IS_FUNC(sym->type)) {
786 sym->aop = aop = newAsmop(AOP_PCODE);
787 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
788 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
789 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
790 PCOI(aop->aopu.pcop)->index = 0;
791 aop->size = FPTRSIZE;
792 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
799 //DEBUGpic16_emitcode(";","%d",__LINE__);
800 /* if in bit space */
801 if (IN_BITSPACE(space)) {
802 sym->aop = aop = newAsmop (AOP_CRY);
803 aop->aopu.aop_dir = sym->rname ;
804 aop->size = getSize(sym->type);
805 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
808 /* if it is in direct space */
809 if (IN_DIRSPACE(space)) {
810 sym->aop = aop = newAsmop (AOP_DIR);
811 aop->aopu.aop_dir = sym->rname ;
812 aop->size = getSize(sym->type);
813 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
814 pic16_allocDirReg( IC_LEFT(ic) );
819 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
820 sym->aop = aop = newAsmop (AOP_DIR);
821 aop->aopu.aop_dir = sym->rname ;
822 aop->size = getSize(sym->type);
823 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
824 pic16_allocDirReg( IC_LEFT(ic) );
829 /* only remaining is far space */
830 sym->aop = aop = newAsmop(AOP_PCODE);
832 /* change the next if to 1 to revert to good old immediate code */
833 if(IN_CODESPACE(space)) {
834 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
835 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
836 PCOI(aop->aopu.pcop)->index = 0;
838 /* try to allocate via direct register */
839 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
840 // aop->size = getSize( sym->type );
843 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
844 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
847 if(!pic16_allocDirReg (IC_LEFT(ic)))
851 if(IN_DIRSPACE( space ))
853 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
854 aop->size = FPTRSIZE;
855 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
856 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
857 else if(sym->onStack) {
863 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
865 /* if it is in code space */
866 if (IN_CODESPACE(space))
872 /*-----------------------------------------------------------------*/
873 /* aopForRemat - rematerialzes an object */
874 /*-----------------------------------------------------------------*/
875 static asmop *aopForRemat (operand *op) // x symbol *sym)
877 symbol *sym = OP_SYMBOL(op);
879 iCode *ic = NULL, *oldic;
880 asmop *aop = newAsmop(AOP_PCODE);
887 ic = sym->rematiCode;
889 if(IS_OP_POINTER(op)) {
890 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
896 // pic16_emitpcomment("ic: %s\n", printILine(ic));
899 val += (int) operandLitValue(IC_RIGHT(ic));
900 } else if (ic->op == '-') {
901 val -= (int) operandLitValue(IC_RIGHT(ic));
905 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
908 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
911 if(!op->isaddr)viaimmd++; else viaimmd=0;
913 /* set the following if to 1 to revert to good old immediate code */
914 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
917 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
919 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
922 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
924 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
927 PCOI(aop->aopu.pcop)->index = val;
929 aop->size = getSize( sym->type );
931 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
933 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
934 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
936 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
940 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
941 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
943 val, IS_PTR_CONST(operandType(op)));
945 val, IS_CODEPTR(operandType(op)));
948 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
950 pic16_allocDirReg (IC_LEFT(ic));
952 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
959 static int aopIdx (asmop *aop, int offset)
964 if(aop->type != AOP_REG)
967 return aop->aopu.aop_reg[offset]->rIdx;
972 /*-----------------------------------------------------------------*/
973 /* regsInCommon - two operands have some registers in common */
974 /*-----------------------------------------------------------------*/
975 static bool regsInCommon (operand *op1, operand *op2)
980 /* if they have registers in common */
981 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
984 sym1 = OP_SYMBOL(op1);
985 sym2 = OP_SYMBOL(op2);
987 if (sym1->nRegs == 0 || sym2->nRegs == 0)
990 for (i = 0 ; i < sym1->nRegs ; i++) {
995 for (j = 0 ; j < sym2->nRegs ;j++ ) {
999 if (sym2->regs[j] == sym1->regs[i])
1007 /*-----------------------------------------------------------------*/
1008 /* operandsEqu - equivalent */
1009 /*-----------------------------------------------------------------*/
1010 static bool operandsEqu ( operand *op1, operand *op2)
1012 symbol *sym1, *sym2;
1014 /* if they not symbols */
1015 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1018 sym1 = OP_SYMBOL(op1);
1019 sym2 = OP_SYMBOL(op2);
1021 /* if both are itemps & one is spilt
1022 and the other is not then false */
1023 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1024 sym1->isspilt != sym2->isspilt )
1027 /* if they are the same */
1031 if (sym1->rname[0] && sym2->rname[0]
1032 && strcmp (sym1->rname, sym2->rname) == 0)
1036 /* if left is a tmp & right is not */
1037 if (IS_ITEMP(op1) &&
1040 (sym1->usl.spillLoc == sym2))
1043 if (IS_ITEMP(op2) &&
1047 (sym2->usl.spillLoc == sym1))
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_sameRegs - two asmops have the same registers */
1055 /*-----------------------------------------------------------------*/
1056 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1063 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1064 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1066 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1068 if (aop1->type != AOP_REG ||
1069 aop2->type != AOP_REG )
1072 /* This is a bit too restrictive if one is a subset of the other...
1073 if (aop1->size != aop2->size )
1077 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1078 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1080 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1081 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1088 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1090 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1091 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1093 if(aop1 == aop2)return TRUE;
1094 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1096 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1102 /*-----------------------------------------------------------------*/
1103 /* pic16_aopOp - allocates an asmop for an operand : */
1104 /*-----------------------------------------------------------------*/
1105 void pic16_aopOp (operand *op, iCode *ic, bool result)
1114 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1116 /* if this a literal */
1117 if (IS_OP_LITERAL(op)) {
1118 op->aop = aop = newAsmop(AOP_LIT);
1119 aop->aopu.aop_lit = op->operand.valOperand;
1120 aop->size = getSize(operandType(op));
1125 sym_link *type = operandType(op);
1127 if(IS_PTR_CONST(type))
1129 if(IS_CODEPTR(type))
1131 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1134 /* if already has a asmop then continue */
1138 /* if the underlying symbol has a aop */
1139 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1140 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1141 op->aop = OP_SYMBOL(op)->aop;
1145 /* if this is a true symbol */
1146 if (IS_TRUE_SYMOP(op)) {
1147 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1148 op->aop = aopForSym(ic, op, result);
1152 /* this is a temporary : this has
1158 e) can be a return use only */
1160 sym = OP_SYMBOL(op);
1162 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1163 /* if the type is a conditional */
1164 if (sym->regType == REG_CND) {
1165 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1170 /* if it is spilt then two situations
1172 b) has a spill location */
1173 if (sym->isspilt || sym->nRegs == 0) {
1175 DEBUGpic16_emitcode(";","%d",__LINE__);
1176 /* rematerialize it NOW */
1179 sym->aop = op->aop = aop = aopForRemat (op);
1180 // aop->size = getSize(sym->type);
1181 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1188 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1189 aop->size = getSize(sym->type);
1190 for ( i = 0 ; i < 1 ; i++ ) {
1191 aop->aopu.aop_str[i] = accUse[i];
1192 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1194 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1195 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1203 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1204 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1205 //pic16_allocDirReg (IC_LEFT(ic));
1206 aop->size = getSize(sym->type);
1211 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1212 aop->size = getSize(sym->type);
1213 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1214 aop->aopu.aop_str[i] = fReturn[i];
1216 DEBUGpic16_emitcode(";","%d",__LINE__);
1220 /* else spill location */
1221 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1222 /* force a new aop if sizes differ */
1223 sym->usl.spillLoc->aop = NULL;
1227 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1228 __FUNCTION__,__LINE__,
1229 sym->usl.spillLoc->rname,
1230 sym->rname, sym->usl.spillLoc->offset);
1233 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1234 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1235 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1237 sym->usl.spillLoc->offset, op);
1238 aop->size = getSize(sym->type);
1244 sym_link *type = operandType(op);
1246 if(IS_PTR_CONST(type))
1248 if(IS_CODEPTR(type))
1250 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1253 /* must be in a register */
1254 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1255 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1256 aop->size = sym->nRegs;
1257 for ( i = 0 ; i < sym->nRegs ;i++)
1258 aop->aopu.aop_reg[i] = sym->regs[i];
1261 /*-----------------------------------------------------------------*/
1262 /* pic16_freeAsmop - free up the asmop given to an operand */
1263 /*----------------------------------------------------------------*/
1264 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1281 /* depending on the asmop type only three cases need work AOP_RO
1282 , AOP_R1 && AOP_STK */
1284 switch (aop->type) {
1286 if (_G.fsr0Pushed ) {
1288 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1289 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1290 // pic16_emitcode ("pop","ar0");
1294 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1298 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1304 pic16_emitcode ("pop","ar0");
1308 bitVectUnSetBit(ic->rUsed,R0_IDX);
1314 pic16_emitcode ("pop","ar1");
1318 bitVectUnSetBit(ic->rUsed,R1_IDX);
1325 /* we must store the result on stack */
1326 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1327 // operands on stack are accessible via "FSR2 + index" with index
1328 // starting at 2 for arguments and growing from 0 downwards for
1329 // local variables (index == 0 is not assigned so we add one here)
1330 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1335 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1336 for(i=0;i<aop->size;i++) {
1337 /* initialise for stack access via frame pointer */
1338 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1339 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1340 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1343 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1347 for(i=0;i<aop->size;i++)
1348 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1357 int stk = aop->aopu.aop_stk + aop->size;
1358 bitVectUnSetBit(ic->rUsed,R0_IDX);
1359 bitVectUnSetBit(ic->rUsed,R1_IDX);
1361 getFreePtr(ic,&aop,FALSE);
1363 if (options.stack10bit)
1365 /* I'm not sure what to do here yet... */
1368 "*** Warning: probably generating bad code for "
1369 "10 bit stack mode.\n");
1373 pic16_emitcode ("mov","a,_bp");
1374 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1375 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1377 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1381 pic16_emitcode("pop","acc");
1382 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1384 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1387 pic16_freeAsmop(op,NULL,ic,TRUE);
1389 pic16_emitcode("pop","ar0");
1394 pic16_emitcode("pop","ar1");
1404 /* all other cases just dealloc */
1408 OP_SYMBOL(op)->aop = NULL;
1409 /* if the symbol has a spill */
1411 SPIL_LOC(op)->aop = NULL;
1416 /*-----------------------------------------------------------------*/
1417 /* pic16_aopGet - for fetching value of the aop */
1418 /*-----------------------------------------------------------------*/
1419 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1424 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1426 /* offset is greater than size then zero */
1427 if (offset > (aop->size - 1) &&
1428 aop->type != AOP_LIT)
1431 /* depending on type */
1432 switch (aop->type) {
1436 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1437 rs = Safe_calloc(1, strlen(s)+1);
1442 /* if we need to increment it */
1443 while (offset > aop->coff)
1445 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1449 while (offset < aop->coff)
1451 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1457 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1458 return (dname ? "acc" : "a");
1460 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1461 rs = Safe_calloc (1, strlen (s) + 1);
1469 sprintf (s,"%s",aop->aopu.aop_immd);
1472 sprintf(s,"(%s >> %d)",
1477 aop->aopu.aop_immd);
1478 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1479 rs = Safe_calloc(1,strlen(s)+1);
1485 sprintf(s,"(%s + %d)",
1488 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1490 sprintf(s,"%s",aop->aopu.aop_dir);
1491 rs = Safe_calloc(1,strlen(s)+1);
1497 // return aop->aopu.aop_reg[offset]->dname;
1499 return aop->aopu.aop_reg[offset]->name;
1502 //pic16_emitcode(";","%d",__LINE__);
1503 return aop->aopu.aop_dir;
1506 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1507 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1509 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1510 rs = Safe_strdup("WREG");
1514 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1515 rs = Safe_calloc(1,strlen(s)+1);
1520 aop->coff = offset ;
1521 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1524 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1526 return aop->aopu.aop_str[offset];
1530 pCodeOp *pcop = aop->aopu.pcop;
1531 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1533 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1534 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1536 sprintf(s,"(%s + %d)", pcop->name, offset);
1538 sprintf(s,"%s", pcop->name);
1541 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1544 rs = Safe_calloc(1,strlen(s)+1);
1549 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1553 // pCodeOp *pcop = aop->aop
1558 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1559 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1560 "aopget got unsupported aop->type");
1566 /* lock has the following meaning: When allocating temporary registers
1567 * for stack variables storage, the value of the temporary register is
1568 * saved on stack. Its value is restored at the end. This procedure is
1569 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1570 * a possibility that before a call to pic16_aopOp, a temporary register
1571 * is allocated for a while and it is freed after some time, this will
1572 * mess the stack and values will not be restored properly. So use lock=1
1573 * to allocate temporary registers used internally by the programmer, and
1574 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1575 * to inform the compiler developer about a possible bug. This is an internal
1576 * feature for developing the compiler -- VR */
1578 int _TempReg_lock = 0;
1579 /*-----------------------------------------------------------------*/
1580 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1581 /*-----------------------------------------------------------------*/
1582 pCodeOp *pic16_popGetTempReg(int lock)
1587 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1589 // werror(W_POSSBUG2, __FILE__, __LINE__);
1592 _TempReg_lock += lock;
1597 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1598 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1599 PCOR(pcop)->r->wasUsed=1;
1600 PCOR(pcop)->r->isFree=0;
1602 /* push value on stack */
1603 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1611 /*-----------------------------------------------------------------*/
1612 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1613 /* don't save if inside v */
1614 /*-----------------------------------------------------------------*/
1615 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1620 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1623 // werror(W_POSSBUG2, __FILE__, __LINE__);
1626 _TempReg_lock += lock;
1631 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1632 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1633 PCOR(pcop)->r->wasUsed=1;
1634 PCOR(pcop)->r->isFree=0;
1636 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1637 /* push value on stack */
1638 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1648 /*-----------------------------------------------------------------*/
1649 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1650 /*-----------------------------------------------------------------*/
1651 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1653 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1655 _TempReg_lock -= lock;
1657 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1658 PCOR(pcop)->r->isFree = 1;
1659 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1662 /*-----------------------------------------------------------------*/
1663 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1664 /*-----------------------------------------------------------------*/
1665 pCodeOp *pic16_popGetLabel(unsigned int key)
1668 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1673 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1676 /*-----------------------------------------------------------------*/
1677 /* pic16_popCopyReg - copy a pcode operator */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1683 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1684 pcor->pcop.type = pc->pcop.type;
1686 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1687 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1689 pcor->pcop.name = NULL;
1692 pcor->rIdx = pc->rIdx;
1694 pcor->instance = pc->instance;
1696 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1701 /*-----------------------------------------------------------------*/
1702 /* pic16_popGetLit - asm operator to pcode operator conversion */
1703 /*-----------------------------------------------------------------*/
1704 pCodeOp *pic16_popGetLit(int lit)
1706 return pic16_newpCodeOpLit(lit);
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1711 /*-----------------------------------------------------------------*/
1712 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1714 return pic16_newpCodeOpLit2(lit, arg2);
1718 /*-----------------------------------------------------------------*/
1719 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1720 /*-----------------------------------------------------------------*/
1721 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1723 return pic16_newpCodeOpImmd(name, offset,index, 0);
1727 /*-----------------------------------------------------------------*/
1728 /* pic16_popGet - asm operator to pcode operator conversion */
1729 /*-----------------------------------------------------------------*/
1730 pCodeOp *pic16_popGetWithString(char *str)
1736 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1740 pcop = pic16_newpCodeOp(str,PO_STR);
1745 /*-----------------------------------------------------------------*/
1746 /* pic16_popRegFromString - */
1747 /*-----------------------------------------------------------------*/
1748 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1751 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1752 pcop->type = PO_DIR;
1754 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1755 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1760 pcop->name = Safe_calloc(1,strlen(str)+1);
1761 strcpy(pcop->name,str);
1763 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1765 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1767 /* make sure that register doesn't exist,
1768 * and operand isn't NULL
1769 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1770 if((PCOR(pcop)->r == NULL)
1772 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1773 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1774 // __FUNCTION__, __LINE__, str, size, offset);
1776 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1777 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1780 PCOR(pcop)->instance = offset;
1785 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1789 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1791 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1792 PCOR(pcop)->rIdx = rIdx;
1793 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1795 PCOR(pcop)->r->isFree = 0;
1796 PCOR(pcop)->r->wasUsed = 1;
1798 pcop->type = PCOR(pcop)->r->pc_type;
1803 /*---------------------------------------------------------------------------------*/
1804 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1806 /*---------------------------------------------------------------------------------*/
1807 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1812 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1814 /* comment the following check, so errors to throw up */
1815 // if(!pcop2)return NULL;
1817 temp = pic16_popGet(aop_dst, offset);
1818 pcop2->pcop2 = temp;
1825 /*--------------------------------------------------------------------------------.-*/
1826 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1827 /* VR 030601 , adapted by Hans Dorn */
1828 /*--------------------------------------------------------------------------------.-*/
1829 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1833 pcop2 = (pCodeOpReg2 *)src;
1841 /*---------------------------------------------------------------------------------*/
1842 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1843 /* movff instruction */
1844 /*---------------------------------------------------------------------------------*/
1845 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1850 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1851 pcop2->pcop2 = pic16_popCopyReg(dst);
1853 /* the pCodeOp may be already allocated */
1854 pcop2 = (pCodeOpReg2 *)(src);
1855 pcop2->pcop2 = (pCodeOp *)(dst);
1862 /*-----------------------------------------------------------------*/
1863 /* pic16_popGet - asm operator to pcode operator conversion */
1864 /*-----------------------------------------------------------------*/
1865 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1867 //char *s = buffer ;
1872 /* offset is greater than
1875 // if (offset > (aop->size - 1) &&
1876 // aop->type != AOP_LIT)
1877 // return NULL; //zero;
1879 /* depending on type */
1880 switch (aop->type) {
1886 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1887 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1894 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1895 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1896 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1897 PCOR(pcop)->r->wasUsed = 1;
1898 PCOR(pcop)->r->isFree = 0;
1900 PCOR(pcop)->instance = offset;
1901 pcop->type = PCOR(pcop)->r->pc_type;
1905 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1906 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1909 /* pCodeOp is already allocated from aopForSym */
1910 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1911 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1917 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1919 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1921 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1923 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1924 PCOR(pcop)->rIdx = rIdx;
1925 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1926 PCOR(pcop)->r->wasUsed=1;
1927 PCOR(pcop)->r->isFree=0;
1929 PCOR(pcop)->instance = offset;
1930 pcop->type = PCOR(pcop)->r->pc_type;
1931 // rs = aop->aopu.aop_reg[offset]->name;
1932 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1936 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1937 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1943 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1944 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1949 assert (aop && aop->aopu.aop_reg[offset] != NULL);
1950 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1952 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1954 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1955 // pcop->type = PO_GPR_REGISTER;
1956 PCOR(pcop)->rIdx = rIdx;
1957 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1958 PCOR(pcop)->r->wasUsed=1;
1959 PCOR(pcop)->r->isFree=0;
1961 PCOR(pcop)->instance = offset;
1962 pcop->type = PCOR(pcop)->r->pc_type;
1964 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1965 rs = aop->aopu.aop_reg[offset]->name;
1966 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1971 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1973 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1974 PCOR(pcop)->instance = offset;
1975 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1976 //if(PCOR(pcop)->r == NULL)
1977 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1981 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1982 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1985 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1986 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1989 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1990 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1991 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1992 pcop->type = PCOR(pcop)->r->pc_type;
1993 pcop->name = PCOR(pcop)->r->name;
1999 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2001 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2002 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2003 switch( aop->aopu.pcop->type ) {
2004 case PO_DIR: PCOR(pcop)->instance += offset; break;
2005 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2007 assert( 0 ); /* should never reach here */;
2012 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2013 "pic16_popGet got unsupported aop->type");
2016 /*-----------------------------------------------------------------*/
2017 /* pic16_aopPut - puts a string for a aop */
2018 /*-----------------------------------------------------------------*/
2019 void pic16_aopPut (asmop *aop, char *s, int offset)
2026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2028 if (aop->size && offset > ( aop->size - 1)) {
2029 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2030 "pic16_aopPut got offset > aop->size");
2034 /* will assign value to value */
2035 /* depending on where it is ofcourse */
2036 switch (aop->type) {
2039 sprintf(d,"(%s + %d)",
2040 aop->aopu.aop_dir,offset);
2041 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2044 sprintf(d,"%s",aop->aopu.aop_dir);
2047 DEBUGpic16_emitcode(";","%d",__LINE__);
2049 pic16_emitcode("movf","%s,w",s);
2050 pic16_emitcode("movwf","%s",d);
2053 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2054 if(offset >= aop->size) {
2055 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2058 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2061 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2068 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2069 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2072 strcmp(s,"r0") == 0 ||
2073 strcmp(s,"r1") == 0 ||
2074 strcmp(s,"r2") == 0 ||
2075 strcmp(s,"r3") == 0 ||
2076 strcmp(s,"r4") == 0 ||
2077 strcmp(s,"r5") == 0 ||
2078 strcmp(s,"r6") == 0 ||
2079 strcmp(s,"r7") == 0 )
2080 pic16_emitcode("mov","%s,%s ; %d",
2081 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2085 if(strcmp(s,"W")==0 )
2086 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2088 pic16_emitcode("movwf","%s",
2089 aop->aopu.aop_reg[offset]->name);
2091 if(strcmp(s,zero)==0) {
2092 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2094 } else if(strcmp(s,"W")==0) {
2095 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2096 pcop->type = PO_GPR_REGISTER;
2098 PCOR(pcop)->rIdx = -1;
2099 PCOR(pcop)->r = NULL;
2101 DEBUGpic16_emitcode(";","%d",__LINE__);
2102 pcop->name = Safe_strdup(s);
2103 pic16_emitpcode(POC_MOVFW,pcop);
2104 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2105 } else if(strcmp(s,one)==0) {
2106 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2107 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2109 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2117 if (aop->type == AOP_DPTR2)
2123 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2124 "pic16_aopPut writting to code space");
2128 while (offset > aop->coff) {
2130 pic16_emitcode ("inc","dptr");
2133 while (offset < aop->coff) {
2135 pic16_emitcode("lcall","__decdptr");
2140 /* if not in accumulater */
2143 pic16_emitcode ("movx","@dptr,a");
2145 if (aop->type == AOP_DPTR2)
2153 while (offset > aop->coff) {
2155 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2157 while (offset < aop->coff) {
2159 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2165 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2170 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2172 if (strcmp(s,"r0") == 0 ||
2173 strcmp(s,"r1") == 0 ||
2174 strcmp(s,"r2") == 0 ||
2175 strcmp(s,"r3") == 0 ||
2176 strcmp(s,"r4") == 0 ||
2177 strcmp(s,"r5") == 0 ||
2178 strcmp(s,"r6") == 0 ||
2179 strcmp(s,"r7") == 0 ) {
2181 sprintf(buffer,"a%s",s);
2182 pic16_emitcode("mov","@%s,%s",
2183 aop->aopu.aop_ptr->name,buffer);
2185 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2190 if (strcmp(s,"a") == 0)
2191 pic16_emitcode("push","acc");
2193 pic16_emitcode("push","%s",s);
2198 /* if bit variable */
2199 if (!aop->aopu.aop_dir) {
2200 pic16_emitcode("clr","a");
2201 pic16_emitcode("rlc","a");
2204 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2207 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2210 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2212 lbl = newiTempLabel(NULL);
2214 if (strcmp(s,"a")) {
2217 pic16_emitcode("clr","c");
2218 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2219 pic16_emitcode("cpl","c");
2220 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2221 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2228 if (strcmp(aop->aopu.aop_str[offset],s))
2229 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2234 if (!offset && (strcmp(s,"acc") == 0))
2237 if (strcmp(aop->aopu.aop_str[offset],s))
2238 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2242 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2243 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2244 // "pic16_aopPut got unsupported aop->type");
2250 /*-----------------------------------------------------------------*/
2251 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2252 /*-----------------------------------------------------------------*/
2253 void pic16_mov2w (asmop *aop, int offset)
2255 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2258 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2260 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2263 static void mov2f(asmop *dst, asmop *src, int offset)
2265 if(is_LitAOp(src)) {
2266 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2267 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2269 if(pic16_sameRegsOfs(src, dst, offset))return;
2270 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2271 pic16_popGet(dst, offset)));
2275 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2277 if(is_LitAOp(src)) {
2278 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2279 pic16_emitpcode(POC_MOVWF, dst);
2281 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2285 void pic16_testStackOverflow(void)
2287 #define GSTACK_TEST_NAME "__gstack_test"
2289 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2294 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2295 strcpy(sym->rname, GSTACK_TEST_NAME);
2296 checkAddSym(&externs, sym);
2301 /* push pcop into stack */
2302 void pic16_pushpCodeOp(pCodeOp *pcop)
2304 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2305 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2306 if(pic16_options.gstack)
2307 pic16_testStackOverflow();
2311 /* pop pcop from stack */
2312 void pic16_poppCodeOp(pCodeOp *pcop)
2314 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2315 if(pic16_options.gstack)
2316 pic16_testStackOverflow();
2320 /*-----------------------------------------------------------------*/
2321 /* pushw - pushes wreg to stack */
2322 /*-----------------------------------------------------------------*/
2325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2326 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2327 if(pic16_options.gstack)
2328 pic16_testStackOverflow();
2332 /*-----------------------------------------------------------------*/
2333 /* pushaop - pushes aop to stack */
2334 /*-----------------------------------------------------------------*/
2335 void pushaop(asmop *aop, int offset)
2337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2339 if(is_LitAOp(aop)) {
2340 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2341 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2343 pic16_emitpcode(POC_MOVFF,
2344 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2347 if(pic16_options.gstack)
2348 pic16_testStackOverflow();
2351 /*-----------------------------------------------------------------*/
2352 /* popaop - pops aop from stack */
2353 /*-----------------------------------------------------------------*/
2354 void popaop(asmop *aop, int offset)
2356 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2357 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2358 if(pic16_options.gstack)
2359 pic16_testStackOverflow();
2362 void popaopidx(asmop *aop, int offset, int index)
2366 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2368 if(STACK_MODEL_LARGE)ofs++;
2370 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2371 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2372 if(pic16_options.gstack)
2373 pic16_testStackOverflow();
2376 #if !(USE_GENERIC_SIGNED_SHIFT)
2377 /*-----------------------------------------------------------------*/
2378 /* reAdjustPreg - points a register back to where it should */
2379 /*-----------------------------------------------------------------*/
2380 static void reAdjustPreg (asmop *aop)
2384 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2386 if ((size = aop->size) <= 1)
2389 switch (aop->type) {
2393 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2397 if (aop->type == AOP_DPTR2)
2403 pic16_emitcode("lcall","__decdptr");
2406 if (aop->type == AOP_DPTR2)
2418 /*-----------------------------------------------------------------*/
2419 /* opIsGptr: returns non-zero if the passed operand is */
2420 /* a generic pointer type. */
2421 /*-----------------------------------------------------------------*/
2422 static int opIsGptr(operand *op)
2424 sym_link *type = operandType(op);
2426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2427 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2435 /*-----------------------------------------------------------------*/
2436 /* pic16_getDataSize - get the operand data size */
2437 /*-----------------------------------------------------------------*/
2438 int pic16_getDataSize(operand *op)
2440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2443 return AOP_SIZE(op);
2445 // tsd- in the pic port, the genptr size is 1, so this code here
2446 // fails. ( in the 8051 port, the size was 4).
2449 size = AOP_SIZE(op);
2450 if (size == GPTRSIZE)
2452 sym_link *type = operandType(op);
2453 if (IS_GENPTR(type))
2455 /* generic pointer; arithmetic operations
2456 * should ignore the high byte (pointer type).
2459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2466 /*-----------------------------------------------------------------*/
2467 /* pic16_outAcc - output Acc */
2468 /*-----------------------------------------------------------------*/
2469 void pic16_outAcc(operand *result)
2472 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2473 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2476 size = pic16_getDataSize(result);
2478 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2481 /* unsigned or positive */
2483 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2488 /*-----------------------------------------------------------------*/
2489 /* pic16_outBitC - output a bit C */
2490 /* Move to result the value of Carry flag -- VR */
2491 /*-----------------------------------------------------------------*/
2492 void pic16_outBitC(operand *result)
2496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2498 /* if the result is bit */
2499 if (AOP_TYPE(result) == AOP_CRY) {
2500 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2501 pic16_aopPut(AOP(result),"c",0);
2504 i = AOP_SIZE(result);
2506 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2508 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2512 /*-----------------------------------------------------------------*/
2513 /* pic16_outBitOp - output a bit from Op */
2514 /* Move to result the value of set/clr op -- VR */
2515 /*-----------------------------------------------------------------*/
2516 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2522 /* if the result is bit */
2523 if (AOP_TYPE(result) == AOP_CRY) {
2524 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2525 pic16_aopPut(AOP(result),"c",0);
2528 i = AOP_SIZE(result);
2530 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2532 pic16_emitpcode(POC_RRCF, pcop);
2533 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2537 /*-----------------------------------------------------------------*/
2538 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2539 /*-----------------------------------------------------------------*/
2540 void pic16_toBoolean(operand *oper)
2542 int size = AOP_SIZE(oper) - 1;
2545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2547 if ( AOP_TYPE(oper) != AOP_ACC) {
2548 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2551 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2556 #if !defined(GEN_Not)
2557 /*-----------------------------------------------------------------*/
2558 /* genNot - generate code for ! operation */
2559 /*-----------------------------------------------------------------*/
2560 static void pic16_genNot (iCode *ic)
2566 /* assign asmOps to operand & result */
2567 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2568 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2570 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2571 /* if in bit space then a special case */
2572 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2573 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2574 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2575 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2577 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2578 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2579 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2584 size = AOP_SIZE(IC_LEFT(ic));
2586 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2587 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2588 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2591 pic16_toBoolean(IC_LEFT(ic));
2593 tlbl = newiTempLabel(NULL);
2594 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2595 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2596 pic16_outBitC(IC_RESULT(ic));
2599 /* release the aops */
2600 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2601 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2606 #if !defined(GEN_Cpl)
2607 /*-----------------------------------------------------------------*/
2608 /* genCpl - generate code for complement */
2609 /*-----------------------------------------------------------------*/
2610 static void pic16_genCpl (iCode *ic)
2616 /* assign asmOps to operand & result */
2617 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2618 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2620 /* if both are in bit space then
2622 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2623 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2625 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2626 pic16_emitcode("cpl","c");
2627 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2631 size = AOP_SIZE(IC_RESULT(ic));
2634 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2636 pic16_emitcode("cpl","a");
2637 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2639 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2640 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2642 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2651 /* release the aops */
2652 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2653 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2657 /*-----------------------------------------------------------------*/
2658 /* genUminusFloat - unary minus for floating points */
2659 /*-----------------------------------------------------------------*/
2660 static void genUminusFloat(operand *op,operand *result)
2662 int size ,offset =0 ;
2665 /* for this we just need to flip the
2666 first it then copy the rest in place */
2667 size = AOP_SIZE(op);
2670 mov2f(AOP(result), AOP(op), offset);
2674 /* toggle the MSB's highest bit */
2675 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2678 /*-----------------------------------------------------------------*/
2679 /* genUminus - unary minus code generation */
2680 /*-----------------------------------------------------------------*/
2681 static void genUminus (iCode *ic)
2684 sym_link *optype, *rtype;
2691 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2692 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2694 /* if both in bit space then special case */
2695 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2696 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2698 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2699 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2700 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2704 optype = operandType(IC_LEFT(ic));
2705 rtype = operandType(IC_RESULT(ic));
2707 /* if float then do float stuff */
2708 if (IS_FLOAT(optype)) {
2709 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2713 /* otherwise subtract from zero by taking the 2's complement */
2714 size = AOP_SIZE(IC_LEFT(ic));
2715 label = newiTempLabel ( NULL );
2717 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2718 for (i=size-1; i > 0; i--) {
2719 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2721 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2722 for (i=1; i < size; i++) {
2723 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2724 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2727 for (i=size-1; i >= 0; i--) {
2728 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2729 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2732 for (i=0; i < size-2; i++) {
2733 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2734 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2736 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2738 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2741 pic16_emitpLabel (label->key);
2744 /* release the aops */
2745 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2746 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2750 /*-----------------------------------------------------------------*/
2751 /* saveRegisters - will look for a call and save the registers */
2752 /*-----------------------------------------------------------------*/
2753 static void saveRegisters(iCode *lic)
2760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2762 for (ic = lic ; ic ; ic = ic->next)
2763 if (ic->op == CALL || ic->op == PCALL)
2767 fprintf(stderr,"found parameter push with no function call\n");
2771 /* if the registers have been saved already then
2773 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2776 /* find the registers in use at this time
2777 and push them away to safety */
2778 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2782 if (options.useXstack) {
2783 if (bitVectBitValue(rsave,R0_IDX))
2784 pic16_emitcode("mov","b,r0");
2785 pic16_emitcode("mov","r0,%s",spname);
2786 for (i = 0 ; i < pic16_nRegs ; i++) {
2787 if (bitVectBitValue(rsave,i)) {
2789 pic16_emitcode("mov","a,b");
2791 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2792 pic16_emitcode("movx","@r0,a");
2793 pic16_emitcode("inc","r0");
2796 pic16_emitcode("mov","%s,r0",spname);
2797 if (bitVectBitValue(rsave,R0_IDX))
2798 pic16_emitcode("mov","r0,b");
2800 //for (i = 0 ; i < pic16_nRegs ; i++) {
2801 // if (bitVectBitValue(rsave,i))
2802 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2805 dtype = operandType(IC_LEFT(ic));
2806 if (currFunc && dtype &&
2807 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2808 IFFUNC_ISISR(currFunc->type) &&
2811 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2814 /*-----------------------------------------------------------------*/
2815 /* unsaveRegisters - pop the pushed registers */
2816 /*-----------------------------------------------------------------*/
2817 static void unsaveRegisters (iCode *ic)
2822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2823 /* find the registers in use at this time
2824 and push them away to safety */
2825 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2828 if (options.useXstack) {
2829 pic16_emitcode("mov","r0,%s",spname);
2830 for (i = pic16_nRegs ; i >= 0 ; i--) {
2831 if (bitVectBitValue(rsave,i)) {
2832 pic16_emitcode("dec","r0");
2833 pic16_emitcode("movx","a,@r0");
2835 pic16_emitcode("mov","b,a");
2837 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2841 pic16_emitcode("mov","%s,r0",spname);
2842 if (bitVectBitValue(rsave,R0_IDX))
2843 pic16_emitcode("mov","r0,b");
2845 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2846 // if (bitVectBitValue(rsave,i))
2847 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2854 /*-----------------------------------------------------------------*/
2856 /*-----------------------------------------------------------------*/
2857 static void pushSide(operand * oper, int size)
2860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2862 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2863 if (AOP_TYPE(oper) != AOP_REG &&
2864 AOP_TYPE(oper) != AOP_DIR &&
2866 pic16_emitcode("mov","a,%s",l);
2867 pic16_emitcode("push","acc");
2869 pic16_emitcode("push","%s",l);
2874 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2876 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2877 pic16_emitpcode(POC_MOVFW, src);
2878 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2880 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2881 src, pic16_popGet(AOP(op), offset)));
2886 /*-----------------------------------------------------------------*/
2887 /* assignResultValue - assign results to oper, rescall==1 is */
2888 /* called from genCall() or genPcall() */
2889 /*-----------------------------------------------------------------*/
2890 static void assignResultValue(operand * oper, int rescall)
2892 int size = AOP_SIZE(oper);
2896 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2897 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2900 /* assign result from a call/pcall function() */
2902 /* function results are stored in a special order,
2903 * see top of file with Function return policy, or manual */
2906 /* 8-bits, result in WREG */
2907 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2910 /* 16-bits, result in PRODL:WREG */
2911 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2915 /* 24-bits, result in PRODH:PRODL:WREG */
2916 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2920 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2921 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2925 /* >32-bits, result on stack, and FSR0 points to beginning.
2926 * Fix stack when done */
2928 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2930 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2931 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2933 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2938 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2939 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2940 if(STACK_MODEL_LARGE) {
2942 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2946 int areg = 0; /* matching argument register */
2948 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2949 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2952 /* its called from genReceive (probably) -- VR */
2953 /* I hope this code will not be called from somewhere else in the future!
2954 * We manually set the pseudo stack pointer in genReceive. - dw
2956 if(!GpsuedoStkPtr && _G.useWreg) {
2957 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2959 /* The last byte in the assignment is in W */
2960 if(areg <= GpsuedoStkPtr) {
2962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2964 // debugf("receive from WREG\n", 0);
2966 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2969 _G.stack_lat = AOP_SIZE(oper)-1;
2974 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2975 // debugf("receive from STACK\n", 0);
2982 /*-----------------------------------------------------------------*/
2983 /* genIpush - generate code for pushing this gets a little complex */
2984 /*-----------------------------------------------------------------*/
2985 static void genIpush (iCode *ic)
2987 // int size, offset=0;
2990 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2993 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2995 /* send to stack as normal */
2996 addSet(&_G.sendSet,ic);
2997 // addSetHead(&_G.sendSet,ic);
2998 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3003 int size, offset = 0 ;
3007 /* if this is not a parm push : ie. it is spill push
3008 and spill push is always done on the local stack */
3009 if (!ic->parmPush) {
3011 /* and the item is spilt then do nothing */
3012 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3015 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3016 size = AOP_SIZE(IC_LEFT(ic));
3017 /* push it on the stack */
3019 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3024 pic16_emitcode("push","%s",l);
3029 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3033 /*-----------------------------------------------------------------*/
3034 /* genIpop - recover the registers: can happen only for spilling */
3035 /*-----------------------------------------------------------------*/
3036 static void genIpop (iCode *ic)
3039 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3044 /* if the temp was not pushed then */
3045 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3048 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3049 size = AOP_SIZE(IC_LEFT(ic));
3052 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3055 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3060 /*-----------------------------------------------------------------*/
3061 /* unsaverbank - restores the resgister bank from stack */
3062 /*-----------------------------------------------------------------*/
3063 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3065 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3071 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3073 if (options.useXstack) {
3075 r = getFreePtr(ic,&aop,FALSE);
3078 pic16_emitcode("mov","%s,_spx",r->name);
3079 pic16_emitcode("movx","a,@%s",r->name);
3080 pic16_emitcode("mov","psw,a");
3081 pic16_emitcode("dec","%s",r->name);
3084 pic16_emitcode ("pop","psw");
3087 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3088 if (options.useXstack) {
3089 pic16_emitcode("movx","a,@%s",r->name);
3090 //pic16_emitcode("mov","(%s+%d),a",
3091 // regspic16[i].base,8*bank+regspic16[i].offset);
3092 pic16_emitcode("dec","%s",r->name);
3095 pic16_emitcode("pop",""); //"(%s+%d)",
3096 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3099 if (options.useXstack) {
3101 pic16_emitcode("mov","_spx,%s",r->name);
3102 pic16_freeAsmop(NULL,aop,ic,TRUE);
3108 /*-----------------------------------------------------------------*/
3109 /* saverbank - saves an entire register bank on the stack */
3110 /*-----------------------------------------------------------------*/
3111 static void saverbank (int bank, iCode *ic, bool pushPsw)
3113 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3119 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3120 if (options.useXstack) {
3123 r = getFreePtr(ic,&aop,FALSE);
3124 pic16_emitcode("mov","%s,_spx",r->name);
3128 for (i = 0 ; i < pic16_nRegs ;i++) {
3129 if (options.useXstack) {
3130 pic16_emitcode("inc","%s",r->name);
3131 //pic16_emitcode("mov","a,(%s+%d)",
3132 // regspic16[i].base,8*bank+regspic16[i].offset);
3133 pic16_emitcode("movx","@%s,a",r->name);
3135 pic16_emitcode("push","");// "(%s+%d)",
3136 //regspic16[i].base,8*bank+regspic16[i].offset);
3140 if (options.useXstack) {
3141 pic16_emitcode("mov","a,psw");
3142 pic16_emitcode("movx","@%s,a",r->name);
3143 pic16_emitcode("inc","%s",r->name);
3144 pic16_emitcode("mov","_spx,%s",r->name);
3145 pic16_freeAsmop (NULL,aop,ic,TRUE);
3148 pic16_emitcode("push","psw");
3150 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3158 static int wparamCmp(void *p1, void *p2)
3160 return (!strcmp((char *)p1, (char *)p2));
3163 int inWparamList(char *s)
3165 return isinSetWith(wparamList, s, wparamCmp);
3169 /*-----------------------------------------------------------------*/
3170 /* genCall - generates a call statement */
3171 /*-----------------------------------------------------------------*/
3172 static void genCall (iCode *ic)
3182 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3183 /* if caller saves & we have not saved then */
3184 // if (!ic->regsSaved)
3185 // saveRegisters(ic);
3187 /* initialise stackParms for IPUSH pushes */
3188 // stackParms = psuedoStkPtr;
3189 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3190 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3191 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3194 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3197 /* if send set is not empty the assign */
3200 int psuedoStkPtr=-1;
3201 int firstTimeThruLoop = 1;
3204 /* reverse sendSet if function is not reentrant */
3205 if(!IFFUNC_ISREENT(ftype))
3206 _G.sendSet = reverseSet(_G.sendSet);
3208 /* First figure how many parameters are getting passed */
3212 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3216 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3217 size = AOP_SIZE(IC_LEFT(sic));
3221 /* pass the last byte through WREG */
3225 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3226 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3227 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3229 if(!firstTimeThruLoop) {
3230 /* If this is not the first time we've been through the loop
3231 * then we need to save the parameter in a temporary
3232 * register. The last byte of the last parameter is
3236 // --psuedoStkPtr; // sanity check
3240 firstTimeThruLoop=0;
3242 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3247 /* all arguments are passed via stack */
3251 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3252 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3253 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3255 // pushaop(AOP(IC_LEFT(sic)), size);
3256 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3261 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3265 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3266 pushw(); /* save last parameter to stack if functions has varargs */
3270 } else use_wreg = 0;
3272 _G.stackRegSet = _G.sendSet;
3277 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3281 /* if we need to assign a result value */
3282 if ((IS_ITEMP(IC_RESULT(ic))
3283 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3284 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3285 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3288 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3291 assignResultValue(IC_RESULT(ic), 1);
3293 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3294 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3296 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3299 if(!stackParms && ic->parmBytes) {
3300 stackParms = ic->parmBytes;
3303 stackParms -= use_wreg;
3306 if(stackParms == 1) {
3307 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3309 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3310 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3312 if(STACK_MODEL_LARGE) {
3314 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3319 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3322 /* adjust the stack for parameters if required */
3323 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3326 /* if register bank was saved then pop them */
3328 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3330 /* if we hade saved some registers then unsave them */
3331 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3332 unsaveRegisters (ic);
3338 /*-----------------------------------------------------------------*/
3339 /* genPcall - generates a call by pointer statement */
3340 /* new version, created from genCall - HJD */
3341 /*-----------------------------------------------------------------*/
3342 static void genPcall (iCode *ic)
3344 sym_link *ftype, *fntype;
3346 symbol *retlbl = newiTempLabel(NULL);
3347 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3351 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3352 fntype = operandType( IC_LEFT(ic) )->next;
3354 /* if send set is not empty the assign */
3357 int psuedoStkPtr=-1;
3359 /* reverse sendSet if function is not reentrant */
3360 if(!IFFUNC_ISREENT(fntype))
3361 _G.sendSet = reverseSet(_G.sendSet);
3365 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3368 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3369 size = AOP_SIZE(IC_LEFT(sic));
3372 /* all parameters are passed via stack, since WREG is clobbered
3373 * by the calling sequence */
3375 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3376 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3377 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3379 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3383 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3386 _G.stackRegSet = _G.sendSet;
3390 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3392 // push return address
3393 // push $ on return stack, then replace with retlbl
3395 pic16_emitpcodeNULLop(POC_PUSH);
3397 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3398 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3399 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3400 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3401 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3402 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3404 /* make the call by writing the pointer into pc */
3405 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3408 // note: MOVFF to PCL not allowed
3409 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3410 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3413 /* return address is here: (X) */
3414 pic16_emitpLabelFORCE(retlbl->key);
3416 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3419 /* if we need assign a result value */
3420 if ((IS_ITEMP(IC_RESULT(ic))
3421 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3422 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3423 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3426 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3429 assignResultValue(IC_RESULT(ic), 1);
3431 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3432 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3434 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3437 // stackParms -= use_wreg;
3440 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3441 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3442 if(STACK_MODEL_LARGE) {
3444 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3449 /*-----------------------------------------------------------------*/
3450 /* resultRemat - result is rematerializable */
3451 /*-----------------------------------------------------------------*/
3452 static int resultRemat (iCode *ic)
3454 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3455 if (SKIP_IC(ic) || ic->op == IFX)
3458 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3459 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3460 if (sym->remat && !POINTER_SET(ic))
3467 #if defined(__BORLANDC__) || defined(_MSC_VER)
3468 #define STRCASECMP stricmp
3470 #define STRCASECMP strcasecmp
3474 /*-----------------------------------------------------------------*/
3475 /* inExcludeList - return 1 if the string is in exclude Reg list */
3476 /*-----------------------------------------------------------------*/
3477 static bool inExcludeList(char *s)
3479 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3482 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3483 if (options.excludeRegs[i] &&
3484 STRCASECMP(options.excludeRegs[i],"none") == 0)
3487 for ( i = 0 ; options.excludeRegs[i]; i++) {
3488 if (options.excludeRegs[i] &&
3489 STRCASECMP(s,options.excludeRegs[i]) == 0)
3496 /*-----------------------------------------------------------------*/
3497 /* genFunction - generated code for function entry */
3498 /*-----------------------------------------------------------------*/
3499 static void genFunction (iCode *ic)
3505 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3507 pic16_labelOffset += (max_key+4);
3512 ftype = operandType(IC_LEFT(ic));
3513 sym = OP_SYMBOL(IC_LEFT(ic));
3515 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3516 /* create an absolute section at the interrupt vector:
3517 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3525 sym = OP_SYMBOL( IC_LEFT(ic));
3527 if(interrupts[i]->name
3528 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3535 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3536 __FILE__, __LINE__, sym->name);
3539 _G.interruptvector = found;
3542 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3543 asym = newSymbol(asymname, 0);
3545 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3546 pic16_addpBlock( apb );
3548 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3549 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3550 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3552 /* mark the end of this tiny function */
3553 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3558 abSym = Safe_calloc(1, sizeof(absSym));
3559 strcpy(abSym->name, asymname);
3561 switch( _G.interruptvector ) {
3562 case 0: abSym->address = 0x000000; break;
3563 case 1: abSym->address = 0x000008; break;
3564 case 2: abSym->address = 0x000018; break;
3567 /* relocate interrupt vectors if needed */
3568 abSym->address += pic16_options.ivt_loc;
3570 addSet(&absSymSet, abSym);
3574 /* create the function header */
3575 pic16_emitcode(";","-----------------------------------------");
3576 pic16_emitcode(";"," function %s",sym->name);
3577 pic16_emitcode(";","-----------------------------------------");
3579 pic16_emitcode("","%s:",sym->rname);
3580 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3586 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3587 if(!strcmp(ab->name, sym->rname)) {
3588 pic16_pBlockConvert2Absolute(pb);
3595 if(IFFUNC_ISNAKED(ftype)) {
3596 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3600 /* if critical function then turn interrupts off */
3601 if (IFFUNC_ISCRITICAL(ftype)) {
3602 //pic16_emitcode("clr","ea");
3605 _G.fregsUsed = sym->regsUsed;
3607 /* if this is an interrupt service routine then
3608 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3609 if (IFFUNC_ISISR(sym->type)) {
3610 _G.usefastretfie = 1; /* use shadow registers by default */
3612 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3613 if(!(_G.interruptvector == 1)) {
3614 /* do not save WREG,STATUS,BSR for high priority interrupts
3615 * because they are stored in the hardware shadow registers already */
3616 _G.usefastretfie = 0;
3617 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3618 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3619 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3622 /* these should really be optimized somehow, because not all
3623 * interrupt handlers modify them */
3624 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3625 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3626 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3627 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3629 // pic16_pBlockConvert2ISR(pb);
3633 /* emit code to setup stack frame if user enabled,
3634 * and function is not main() */
3636 //fprintf(stderr, "function name: %s\n", sym->name);
3637 if(strcmp(sym->name, "main")) {
3638 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3639 /* setup the stack frame */
3640 if(STACK_MODEL_LARGE)
3641 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3642 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3644 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3645 if(STACK_MODEL_LARGE)
3646 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3650 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3653 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3655 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3656 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3658 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3661 if(inWparamList(sym->name)) {
3662 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3669 /* if callee-save to be used for this function
3670 * then save the registers being used in this function */
3671 // if (IFFUNC_CALLEESAVES(sym->type))
3675 /* if any registers used */
3676 if (sym->regsUsed) {
3677 /* save the registers used */
3678 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3679 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3680 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3681 if (bitVectBitValue(sym->regsUsed,i)) {
3682 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3685 if(!pic16_regWithIdx(i)->wasUsed) {
3686 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3687 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3688 pic16_regWithIdx(i)->wasUsed = 1;
3692 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3696 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3697 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3700 /*-----------------------------------------------------------------*/
3701 /* genEndFunction - generates epilogue for functions */
3702 /*-----------------------------------------------------------------*/
3703 static void genEndFunction (iCode *ic)
3705 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3709 if(IFFUNC_ISNAKED(sym->type)) {
3710 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3716 /* add code for ISCRITICAL */
3717 if(IFFUNC_ISCRITICAL(sym->type)) {
3718 /* if critical function, turn on interrupts */
3720 /* TODO: add code here -- VR */
3723 // sym->regsUsed = _G.fregsUsed;
3725 /* now we need to restore the registers */
3726 /* if any registers used */
3727 if (sym->regsUsed) {
3730 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3731 /* restore registers used */
3732 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3733 for ( i = sym->regsUsed->size; i >= 0; i--) {
3734 if (bitVectBitValue(sym->regsUsed,i)) {
3735 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3739 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3743 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3745 if (sym->stack == 1) {
3746 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3747 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3749 // we have to add more than one...
3750 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3751 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3752 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3754 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3755 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3756 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3760 if(strcmp(sym->name, "main")) {
3761 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3762 /* restore stack frame */
3763 if(STACK_MODEL_LARGE)
3764 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3765 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3771 if (IFFUNC_ISISR(sym->type)) {
3772 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3773 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3774 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3775 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3777 if(!(_G.interruptvector == 1)) {
3778 /* do not restore interrupt vector for WREG,STATUS,BSR
3779 * for high priority interrupt, see genFunction */
3780 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3781 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3782 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3784 _G.interruptvector = 0; /* sanity check */
3787 /* if debug then send end of function */
3788 /* if (options.debug && currFunc) */
3790 debugFile->writeEndFunction (currFunc, ic, 1);
3793 if(_G.usefastretfie)
3794 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3796 pic16_emitpcodeNULLop(POC_RETFIE);
3798 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3800 _G.usefastretfie = 0;
3804 if (IFFUNC_ISCRITICAL(sym->type)) {
3805 pic16_emitcode("setb","ea");
3808 /* if debug then send end of function */
3810 debugFile->writeEndFunction (currFunc, ic, 1);
3813 /* insert code to restore stack frame, if user enabled it
3814 * and function is not main() */
3817 pic16_emitpcodeNULLop(POC_RETURN);
3819 /* Mark the end of a function */
3820 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3824 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3827 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3829 pic16_emitpcode(POC_CLRF, dest);
3831 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3832 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3835 if(dest->type == PO_WREG && (offset == 0)) {
3836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3839 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3843 /*-----------------------------------------------------------------*/
3844 /* genRet - generate code for return statement */
3845 /*-----------------------------------------------------------------*/
3846 static void genRet (iCode *ic)
3852 /* if we have no return value then
3853 * just generate the "ret" */
3858 /* we have something to return then
3859 * move the return value into place */
3860 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3861 size = AOP_SIZE(IC_LEFT(ic));
3865 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3866 // pic16_emitpcode(POC_MOVFF,
3867 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3870 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3871 // pic16_emitpcode(POC_MOVFF,
3872 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3875 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3876 // pic16_emitpcode(POC_MOVFF,
3877 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3880 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3882 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3883 // pic16_emitpcode(POC_MOVFF,
3884 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3887 /* >32-bits, setup stack and FSR0 */
3889 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3890 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3892 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3894 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3899 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3900 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3902 if(STACK_MODEL_LARGE) {
3903 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3904 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3906 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3911 /* old code, left here for reference -- VR */
3915 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3917 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3918 pic16_emitpcomment("push %s",l);
3921 DEBUGpic16_emitcode(";", "%d", __LINE__);
3922 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3923 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3925 if (strcmp(fReturn[offset],l)) {
3926 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3927 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3928 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3930 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3934 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3944 if (strcmp(fReturn[pushed],"a"))
3945 pic16_emitcode("pop",fReturn[pushed]);
3947 pic16_emitcode("pop","acc");
3953 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3956 /* generate a jump to the return label
3957 * if the next is not the return statement */
3958 if (!(ic->next && ic->next->op == LABEL
3959 && IC_LABEL(ic->next) == returnLabel)) {
3961 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3962 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3966 /*-----------------------------------------------------------------*/
3967 /* genLabel - generates a label */
3968 /*-----------------------------------------------------------------*/
3969 static void genLabel (iCode *ic)
3973 /* special case never generate */
3974 if (IC_LABEL(ic) == entryLabel)
3977 pic16_emitpLabel(IC_LABEL(ic)->key);
3978 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3981 /*-----------------------------------------------------------------*/
3982 /* genGoto - generates a goto */
3983 /*-----------------------------------------------------------------*/
3985 static void genGoto (iCode *ic)
3988 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3989 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3993 /*-----------------------------------------------------------------*/
3994 /* genMultbits :- multiplication of bits */
3995 /*-----------------------------------------------------------------*/
3996 static void genMultbits (operand *left,
4002 if(!pic16_sameRegs(AOP(result),AOP(right)))
4003 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4005 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4006 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4007 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4012 /*-----------------------------------------------------------------*/
4013 /* genMultOneByte : 8 bit multiplication & division */
4014 /*-----------------------------------------------------------------*/
4015 static void genMultOneByte (operand *left,
4021 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4022 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4024 /* (if two literals, the value is computed before) */
4025 /* if one literal, literal on the right */
4026 if (AOP_TYPE(left) == AOP_LIT){
4032 /* size is already checked in genMult == 1 */
4033 // size = AOP_SIZE(result);
4035 if (AOP_TYPE(right) == AOP_LIT){
4036 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4037 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4038 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4039 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4041 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4042 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4043 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4044 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4047 pic16_genMult8X8_8 (left, right,result);
4050 /*-----------------------------------------------------------------*/
4051 /* genMultOneWord : 16 bit multiplication */
4052 /*-----------------------------------------------------------------*/
4053 static void genMultOneWord (operand *left,
4058 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4059 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4061 /* (if two literals, the value is computed before)
4062 * if one literal, literal on the right */
4063 if (AOP_TYPE(left) == AOP_LIT){
4069 /* size is checked already == 2 */
4070 // size = AOP_SIZE(result);
4072 if (AOP_TYPE(right) == AOP_LIT) {
4073 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4074 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4075 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4076 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4078 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4079 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4080 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4081 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4084 pic16_genMult16X16_16(left, right,result);
4087 /*-----------------------------------------------------------------*/
4088 /* genMultOneLong : 32 bit multiplication */
4089 /*-----------------------------------------------------------------*/
4090 static void genMultOneLong (operand *left,
4095 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4096 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4098 /* (if two literals, the value is computed before)
4099 * if one literal, literal on the right */
4100 if (AOP_TYPE(left) == AOP_LIT){
4106 /* size is checked already == 4 */
4107 // size = AOP_SIZE(result);
4109 if (AOP_TYPE(right) == AOP_LIT) {
4110 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4111 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4112 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4113 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4115 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4116 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4117 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4118 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4121 pic16_genMult32X32_32(left, right,result);
4126 /*-----------------------------------------------------------------*/
4127 /* genMult - generates code for multiplication */
4128 /*-----------------------------------------------------------------*/
4129 static void genMult (iCode *ic)
4131 operand *left = IC_LEFT(ic);
4132 operand *right = IC_RIGHT(ic);
4133 operand *result= IC_RESULT(ic);
4136 /* assign the amsops */
4137 pic16_aopOp (left,ic,FALSE);
4138 pic16_aopOp (right,ic,FALSE);
4139 pic16_aopOp (result,ic,TRUE);
4141 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4143 /* special cases first *
4145 if (AOP_TYPE(left) == AOP_CRY
4146 && AOP_TYPE(right)== AOP_CRY) {
4147 genMultbits(left,right,result);
4151 /* if both are of size == 1 */
4152 if(AOP_SIZE(left) == 1
4153 && AOP_SIZE(right) == 1) {
4154 genMultOneByte(left,right,result);
4158 /* if both are of size == 2 */
4159 if(AOP_SIZE(left) == 2
4160 && AOP_SIZE(right) == 2) {
4161 genMultOneWord(left, right, result);
4165 /* if both are of size == 4 */
4166 if(AOP_SIZE(left) == 4
4167 && AOP_SIZE(right) == 4) {
4168 genMultOneLong(left, right, result);
4172 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4175 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4176 /* should have been converted to function call */
4180 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4181 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4182 pic16_freeAsmop(result,NULL,ic,TRUE);
4185 /*-----------------------------------------------------------------*/
4186 /* genDivbits :- division of bits */
4187 /*-----------------------------------------------------------------*/
4188 static void genDivbits (operand *left,
4195 /* the result must be bit */
4196 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4197 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4201 pic16_emitcode("div","ab");
4202 pic16_emitcode("rrc","a");
4203 pic16_aopPut(AOP(result),"c",0);
4206 /*-----------------------------------------------------------------*/
4207 /* genDivOneByte : 8 bit division */
4208 /*-----------------------------------------------------------------*/
4209 static void genDivOneByte (operand *left,
4213 sym_link *opetype = operandType(result);
4218 /* result = divident / divisor
4219 * - divident may be a register or a literal,
4220 * - divisor may be a register or a literal,
4221 * so there are 3 cases (literal / literal is optimized
4222 * by the front-end) to handle.
4223 * In addition we must handle signed and unsigned, which
4224 * result in 6 final different cases -- VR */
4228 size = AOP_SIZE(result) - 1;
4230 /* signed or unsigned */
4231 if (SPEC_USIGN(opetype)) {
4232 pCodeOp *pct1, /* count */
4235 symbol *label1, *label2, *label3;;
4238 /* unsigned is easy */
4240 pct1 = pic16_popGetTempReg(1);
4241 pct2 = pic16_popGetTempReg(1);
4242 pct3 = pic16_popGetTempReg(1);
4244 label1 = newiTempLabel(NULL);
4245 label2 = newiTempLabel(NULL);
4246 label3 = newiTempLabel(NULL);
4248 /* the following algorithm is extracted from divuint.c */
4250 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4251 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4253 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4255 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4257 pic16_emitpLabel(label1->key);
4260 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4264 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4268 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4270 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4271 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4273 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4274 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4275 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4277 pic16_emitpLabel( label3->key );
4278 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4279 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4283 pic16_emitpLabel(label2->key);
4284 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4285 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4286 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4288 /* result is in wreg */
4289 if(AOP_TYPE(result) != AOP_ACC)
4290 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4292 pic16_popReleaseTempReg( pct3, 1);
4293 pic16_popReleaseTempReg( pct2, 1);
4294 pic16_popReleaseTempReg( pct1, 1);
4299 /* signed is a little bit more difficult */
4301 /* save the signs of the operands */
4302 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4304 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4305 pic16_emitcode("push","acc"); /* save it on the stack */
4307 /* now sign adjust for both left & right */
4308 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4310 lbl = newiTempLabel(NULL);
4311 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4312 pic16_emitcode("cpl","a");
4313 pic16_emitcode("inc","a");
4314 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4315 pic16_emitcode("mov","b,a");
4317 /* sign adjust left side */
4318 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4321 lbl = newiTempLabel(NULL);
4322 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4323 pic16_emitcode("cpl","a");
4324 pic16_emitcode("inc","a");
4325 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4327 /* now the division */
4328 pic16_emitcode("div","ab");
4329 /* we are interested in the lower order
4331 pic16_emitcode("mov","b,a");
4332 lbl = newiTempLabel(NULL);
4333 pic16_emitcode("pop","acc");
4334 /* if there was an over flow we don't
4335 adjust the sign of the result */
4336 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4337 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4339 pic16_emitcode("clr","a");
4340 pic16_emitcode("subb","a,b");
4341 pic16_emitcode("mov","b,a");
4342 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4344 /* now we are done */
4345 pic16_aopPut(AOP(result),"b",0);
4347 pic16_emitcode("mov","c,b.7");
4348 pic16_emitcode("subb","a,acc");
4351 pic16_aopPut(AOP(result),"a",offset++);
4355 /*-----------------------------------------------------------------*/
4356 /* genDiv - generates code for division */
4357 /*-----------------------------------------------------------------*/
4358 static void genDiv (iCode *ic)
4360 operand *left = IC_LEFT(ic);
4361 operand *right = IC_RIGHT(ic);
4362 operand *result= IC_RESULT(ic);
4365 /* Division is a very lengthy algorithm, so it is better
4366 * to call support routines than inlining algorithm.
4367 * Division functions written here just in case someone
4368 * wants to inline and not use the support libraries -- VR */
4372 /* assign the amsops */
4373 pic16_aopOp (left,ic,FALSE);
4374 pic16_aopOp (right,ic,FALSE);
4375 pic16_aopOp (result,ic,TRUE);
4377 /* special cases first */
4379 if (AOP_TYPE(left) == AOP_CRY &&
4380 AOP_TYPE(right)== AOP_CRY) {
4381 genDivbits(left,right,result);
4385 /* if both are of size == 1 */
4386 if (AOP_SIZE(left) == 1 &&
4387 AOP_SIZE(right) == 1 ) {
4388 genDivOneByte(left,right,result);
4392 /* should have been converted to function call */
4395 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4396 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4397 pic16_freeAsmop(result,NULL,ic,TRUE);
4400 /*-----------------------------------------------------------------*/
4401 /* genModbits :- modulus of bits */
4402 /*-----------------------------------------------------------------*/
4403 static void genModbits (operand *left,
4411 werror(W_POSSBUG2, __FILE__, __LINE__);
4412 /* the result must be bit */
4413 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4414 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4418 pic16_emitcode("div","ab");
4419 pic16_emitcode("mov","a,b");
4420 pic16_emitcode("rrc","a");
4421 pic16_aopPut(AOP(result),"c",0);
4424 /*-----------------------------------------------------------------*/
4425 /* genModOneByte : 8 bit modulus */
4426 /*-----------------------------------------------------------------*/
4427 static void genModOneByte (operand *left,
4431 sym_link *opetype = operandType(result);
4436 werror(W_POSSBUG2, __FILE__, __LINE__);
4438 /* signed or unsigned */
4439 if (SPEC_USIGN(opetype)) {
4440 /* unsigned is easy */
4441 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4442 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4444 pic16_emitcode("div","ab");
4445 pic16_aopPut(AOP(result),"b",0);
4449 /* signed is a little bit more difficult */
4451 /* save the signs of the operands */
4452 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4455 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4456 pic16_emitcode("push","acc"); /* save it on the stack */
4458 /* now sign adjust for both left & right */
4459 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4462 lbl = newiTempLabel(NULL);
4463 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4464 pic16_emitcode("cpl","a");
4465 pic16_emitcode("inc","a");
4466 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4467 pic16_emitcode("mov","b,a");
4469 /* sign adjust left side */
4470 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4473 lbl = newiTempLabel(NULL);
4474 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4475 pic16_emitcode("cpl","a");
4476 pic16_emitcode("inc","a");
4477 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4479 /* now the multiplication */
4480 pic16_emitcode("div","ab");
4481 /* we are interested in the lower order
4483 lbl = newiTempLabel(NULL);
4484 pic16_emitcode("pop","acc");
4485 /* if there was an over flow we don't
4486 adjust the sign of the result */
4487 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4488 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4490 pic16_emitcode("clr","a");
4491 pic16_emitcode("subb","a,b");
4492 pic16_emitcode("mov","b,a");
4493 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4495 /* now we are done */
4496 pic16_aopPut(AOP(result),"b",0);
4500 /*-----------------------------------------------------------------*/
4501 /* genMod - generates code for division */
4502 /*-----------------------------------------------------------------*/
4503 static void genMod (iCode *ic)
4505 operand *left = IC_LEFT(ic);
4506 operand *right = IC_RIGHT(ic);
4507 operand *result= IC_RESULT(ic);
4511 /* assign the amsops */
4512 pic16_aopOp (left,ic,FALSE);
4513 pic16_aopOp (right,ic,FALSE);
4514 pic16_aopOp (result,ic,TRUE);
4516 /* special cases first */
4518 if (AOP_TYPE(left) == AOP_CRY &&
4519 AOP_TYPE(right)== AOP_CRY) {
4520 genModbits(left,right,result);
4524 /* if both are of size == 1 */
4525 if (AOP_SIZE(left) == 1 &&
4526 AOP_SIZE(right) == 1 ) {
4527 genModOneByte(left,right,result);
4531 /* should have been converted to function call */
4535 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4536 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4537 pic16_freeAsmop(result,NULL,ic,TRUE);
4540 /*-----------------------------------------------------------------*/
4541 /* genIfxJump :- will create a jump depending on the ifx */
4542 /*-----------------------------------------------------------------*/
4544 note: May need to add parameter to indicate when a variable is in bit space.
4546 static void genIfxJump (iCode *ic, char *jval)
4550 /* if true label then we jump if condition
4552 if ( IC_TRUE(ic) ) {
4554 if(strcmp(jval,"a") == 0)
4556 else if (strcmp(jval,"c") == 0)
4559 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4560 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4563 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4564 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4568 /* false label is present */
4569 if(strcmp(jval,"a") == 0)
4571 else if (strcmp(jval,"c") == 0)
4574 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4575 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4578 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4579 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4584 /* mark the icode as generated */
4588 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4592 /* if true label then we jump if condition
4594 if ( IC_TRUE(ic) ) {
4595 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4596 pic16_emitpcode(POC_BTFSC, jop);
4598 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4599 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4602 /* false label is present */
4603 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4604 pic16_emitpcode(POC_BTFSS, jop);
4606 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4607 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4611 /* mark the icode as generated */
4618 /*-----------------------------------------------------------------*/
4620 /*-----------------------------------------------------------------*/
4621 static void genSkip(iCode *ifx,int status_bit)
4623 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4627 if ( IC_TRUE(ifx) ) {
4628 switch(status_bit) {
4643 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4644 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4648 switch(status_bit) {
4662 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4663 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4670 /*-----------------------------------------------------------------*/
4672 /*-----------------------------------------------------------------*/
4673 static void genSkipc(resolvedIfx *rifx)
4675 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4685 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4686 rifx->generated = 1;
4689 #if !(USE_SIMPLE_GENCMP)
4690 /*-----------------------------------------------------------------*/
4692 /*-----------------------------------------------------------------*/
4693 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4695 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4700 if( (rifx->condition ^ invert_condition) & 1)
4705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4706 rifx->generated = 1;
4711 /*-----------------------------------------------------------------*/
4713 /*-----------------------------------------------------------------*/
4714 static void genSkipz(iCode *ifx, int condition)
4725 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4727 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4730 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4732 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4737 #if !(USE_SIMPLE_GENCMP)
4738 /*-----------------------------------------------------------------*/
4740 /*-----------------------------------------------------------------*/
4741 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4747 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4749 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4752 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4753 rifx->generated = 1;
4758 /*-----------------------------------------------------------------*/
4759 /* genChkZeroes :- greater or less than comparison */
4760 /* For each byte in a literal that is zero, inclusive or the */
4761 /* the corresponding byte in the operand with W */
4762 /* returns true if any of the bytes are zero */
4763 /*-----------------------------------------------------------------*/
4764 static int genChkZeroes(operand *op, int lit, int size)
4771 i = (lit >> (size*8)) & 0xff;
4775 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4777 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4786 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4787 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4789 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4790 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4792 /*-----------------------------------------------------------------*/
4793 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4794 /* aop (if it's NOT a literal) or from lit (if */
4795 /* aop is a literal) */
4796 /*-----------------------------------------------------------------*/
4797 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4798 if (aop->type == AOP_LIT) {
4799 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4801 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4805 /*-----------------------------------------------------------------*/
4806 /* genCmp :- greater or less than comparison */
4807 /*-----------------------------------------------------------------*/
4809 #if USE_SIMPLE_GENCMP
4811 /* genCmp performs a left < right comparison, stores
4812 * the outcome in result (if != NULL) and generates
4813 * control flow code for the ifx (if != NULL).
4815 * This version leaves in sequences like
4816 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4817 * which should be optmized by the peephole
4818 * optimizer - RN 2005-01-01 */
4819 static void genCmp (operand *left,operand *right,
4820 operand *result, iCode *ifx, int sign)
4833 assert (AOP_SIZE(left) == AOP_SIZE(right));
4834 assert (left && right);
4836 size = AOP_SIZE(right) - 1;
4837 mask = (0x100UL << (size*8)) - 1;
4838 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4843 resolveIfx (&rIfx, ifx);
4845 /**********************************************************************
4846 * handle bits - bit compares are promoted to int compares seemingly! *
4847 **********************************************************************/
4849 // THIS IS COMPLETELY UNTESTED!
4850 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4851 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4852 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4853 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4856 // 1 < {0,1} is false --> clear C by skipping the next instruction
4857 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4858 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4859 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4860 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4861 emitCLRC; // only skipped for left=0 && right=1
4863 goto correct_result_in_carry;
4867 /*************************************************
4868 * make sure that left is register (or the like) *
4869 *************************************************/
4870 if (!isAOP_REGlike(left)) {
4871 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4872 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4874 assert (isAOP_LIT(left));
4875 assert (isAOP_REGlike(right));
4876 // swap left and right
4877 // left < right <==> right > left <==> (right >= left + 1)
4878 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4880 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4881 // MAXVALUE < right? always false
4882 if (performedLt) emitCLRC; else emitSETC;
4883 goto correct_result_in_carry;
4886 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4887 // that's we handled it above.
4894 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4895 } else if (isAOP_LIT(right)) {
4896 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4899 assert (isAOP_REGlike(left)); // left must be register or the like
4900 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4902 /*************************************************
4903 * special cases go here *
4904 *************************************************/
4906 if (isAOP_LIT(right)) {
4908 // unsigned comparison to a literal
4909 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4910 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4913 // unsigned left < 0? always false
4914 if (performedLt) emitCLRC; else emitSETC;
4915 goto correct_result_in_carry;
4918 // signed comparison to a literal
4919 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4920 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4922 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4923 // signed left < 0x80000000? always false
4924 if (performedLt) emitCLRC; else emitSETC;
4925 goto correct_result_in_carry;
4926 } else if (lit == 0) {
4927 // compare left < 0; set CARRY if SIGNBIT(left) is set
4928 if (performedLt) emitSETC; else emitCLRC;
4929 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4930 if (performedLt) emitCLRC; else emitSETC;
4931 goto correct_result_in_carry;
4934 } // right is literal
4936 /*************************************************
4937 * perform a general case comparison *
4938 * make sure we get CARRY==1 <==> left >= right *
4939 *************************************************/
4940 // compare most significant bytes
4941 //DEBUGpc ("comparing bytes at offset %d", size);
4943 // unsigned comparison
4944 mov2w_regOrLit (AOP(right), lit, size);
4945 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4947 // signed comparison
4948 // (add 2^n to both operands then perform an unsigned comparison)
4949 if (isAOP_LIT(right)) {
4950 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4951 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4953 if (litbyte == 0x80) {
4954 // left >= 0x80 -- always true, but more bytes to come
4955 pic16_mov2w (AOP(left), size);
4956 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4959 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4960 pic16_mov2w (AOP(left), size);
4961 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4962 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4965 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4966 //pCodeOp *pctemp = pic16_popGetTempReg(1);
4967 pic16_mov2w (AOP(left), size);
4968 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4969 pic16_emitpcode (POC_MOVWF, pctemp);
4970 pic16_mov2w (AOP(right), size);
4971 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4972 pic16_emitpcode (POC_SUBFW, pctemp);
4973 //pic16_popReleaseTempReg(pctemp, 1);
4977 // compare remaining bytes (treat as unsigned case from above)
4978 templbl = newiTempLabel ( NULL );
4981 //DEBUGpc ("comparing bytes at offset %d", offs);
4982 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4983 mov2w_regOrLit (AOP(right), lit, offs);
4984 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4986 pic16_emitpLabel (templbl->key);
4987 goto result_in_carry;
4991 /****************************************************
4992 * now CARRY contains the result of the comparison: *
4993 * SUBWF sets CARRY iff *
4994 * F-W >= 0 <==> F >= W <==> !(F < W) *
4996 ****************************************************/
4999 if (result && AOP_TYPE(result) != AOP_CRY) {
5000 // value will be stored
5003 // value wil only be used in the following genSkipc()
5004 rIfx.condition ^= 1;
5008 correct_result_in_carry:
5010 // assign result to variable (if neccessary)
5011 if (result && AOP_TYPE(result) != AOP_CRY) {
5012 //DEBUGpc ("assign result");
5013 size = AOP_SIZE(result);
5015 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5017 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5020 // perform conditional jump
5021 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5023 //DEBUGpc ("generate control flow");
5024 rIfx.condition ^= 1;
5033 static void genCmp (operand *left,operand *right,
5034 operand *result, iCode *ifx, int sign)
5036 int size; //, offset = 0 ;
5037 unsigned long lit = 0L,i = 0;
5038 resolvedIfx rFalseIfx;
5039 // resolvedIfx rTrueIfx;
5041 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5044 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5045 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5051 resolveIfx(&rFalseIfx,ifx);
5052 truelbl = newiTempLabel(NULL);
5053 size = max(AOP_SIZE(left),AOP_SIZE(right));
5055 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5059 /* if literal is on the right then swap with left */
5060 if ((AOP_TYPE(right) == AOP_LIT)) {
5061 operand *tmp = right ;
5062 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5063 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5066 lit = (lit - 1) & mask;
5069 rFalseIfx.condition ^= 1;
5072 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5073 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5077 //if(IC_TRUE(ifx) == NULL)
5078 /* if left & right are bit variables */
5079 if (AOP_TYPE(left) == AOP_CRY &&
5080 AOP_TYPE(right) == AOP_CRY ) {
5081 assert (0 && "bit variables used in genCmp");
5082 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5083 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5085 /* subtract right from left if at the
5086 end the carry flag is set then we know that
5087 left is greater than right */
5089 symbol *lbl = newiTempLabel(NULL);
5092 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5093 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5097 if(AOP_TYPE(right) == AOP_LIT) {
5099 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5101 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5108 genSkipCond(&rFalseIfx,left,size-1,7);
5110 /* no need to compare to 0...*/
5111 /* NOTE: this is a de-generate compare that most certainly
5112 * creates some dead code. */
5113 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5115 if(ifx) ifx->generated = 1;
5122 //i = (lit >> (size*8)) & 0xff;
5123 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5125 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5127 i = ((0-lit) & 0xff);
5130 /* lit is 0x7f, all signed chars are less than
5131 * this except for 0x7f itself */
5132 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5133 genSkipz2(&rFalseIfx,0);
5135 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5136 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5137 genSkipc(&rFalseIfx);
5142 genSkipz2(&rFalseIfx,1);
5144 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5145 genSkipc(&rFalseIfx);
5149 if(ifx) ifx->generated = 1;
5153 /* chars are out of the way. now do ints and longs */
5156 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5163 genSkipCond(&rFalseIfx,left,size,7);
5164 if(ifx) ifx->generated = 1;
5169 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5171 //rFalseIfx.condition ^= 1;
5172 //genSkipCond(&rFalseIfx,left,size,7);
5173 //rFalseIfx.condition ^= 1;
5175 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5176 if(rFalseIfx.condition)
5177 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5179 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5181 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5182 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5183 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5186 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5188 if(rFalseIfx.condition) {
5190 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5196 genSkipc(&rFalseIfx);
5197 pic16_emitpLabel(truelbl->key);
5198 if(ifx) ifx->generated = 1;
5205 if( (lit & 0xff) == 0) {
5206 /* lower byte is zero */
5207 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5208 i = ((lit >> 8) & 0xff) ^0x80;
5209 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5210 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5211 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5212 genSkipc(&rFalseIfx);
5215 if(ifx) ifx->generated = 1;
5220 /* Special cases for signed longs */
5221 if( (lit & 0xffffff) == 0) {
5222 /* lower byte is zero */
5223 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5224 i = ((lit >> 8*3) & 0xff) ^0x80;
5225 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5226 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5228 genSkipc(&rFalseIfx);
5231 if(ifx) ifx->generated = 1;
5239 if(lit & (0x80 << (size*8))) {
5240 /* lit is negative */
5241 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5243 //genSkipCond(&rFalseIfx,left,size,7);
5245 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5247 if(rFalseIfx.condition)
5248 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5250 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5254 /* lit is positive */
5255 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5256 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5257 if(rFalseIfx.condition)
5258 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5260 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5265 This works, but is only good for ints.
5266 It also requires a "known zero" register.
5267 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5268 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5269 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5270 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5271 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5272 genSkipc(&rFalseIfx);
5274 pic16_emitpLabel(truelbl->key);
5275 if(ifx) ifx->generated = 1;
5279 /* There are no more special cases, so perform a general compare */
5281 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5282 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5286 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5288 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5290 //rFalseIfx.condition ^= 1;
5291 genSkipc(&rFalseIfx);
5293 pic16_emitpLabel(truelbl->key);
5295 if(ifx) ifx->generated = 1;
5302 /* sign is out of the way. So now do an unsigned compare */
5303 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5306 /* General case - compare to an unsigned literal on the right.*/
5308 i = (lit >> (size*8)) & 0xff;
5309 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5310 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5312 i = (lit >> (size*8)) & 0xff;
5315 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5317 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5319 /* this byte of the lit is zero,
5320 *if it's not the last then OR in the variable */
5322 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5327 pic16_emitpLabel(lbl->key);
5328 // pic16_emitpLabel(truelbl->key);
5329 //if(emitFinalCheck)
5330 genSkipc(&rFalseIfx);
5332 pic16_emitpLabel(truelbl->key);
5334 if(ifx) ifx->generated = 1;
5341 if(AOP_TYPE(left) == AOP_LIT) {
5342 //symbol *lbl = newiTempLabel(NULL);
5344 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5347 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5350 if((lit == 0) && (sign == 0)){
5353 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5355 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5357 genSkipz2(&rFalseIfx,0);
5358 if(ifx) ifx->generated = 1;
5365 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5366 /* degenerate compare can never be true */
5367 if(rFalseIfx.condition == 0)
5368 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5370 if(ifx) ifx->generated = 1;
5375 /* signed comparisons to a literal byte */
5377 int lp1 = (lit+1) & 0xff;
5379 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5382 rFalseIfx.condition ^= 1;
5383 genSkipCond(&rFalseIfx,right,0,7);
5386 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5387 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5388 genSkipz2(&rFalseIfx,1);
5391 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5392 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5393 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5394 rFalseIfx.condition ^= 1;
5395 genSkipc(&rFalseIfx);
5399 /* unsigned comparisons to a literal byte */
5401 switch(lit & 0xff ) {
5403 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5404 genSkipz2(&rFalseIfx,0);
5407 rFalseIfx.condition ^= 1;
5408 genSkipCond(&rFalseIfx,right,0,7);
5412 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5413 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5414 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5415 rFalseIfx.condition ^= 1;
5416 if (AOP_TYPE(result) == AOP_CRY)
5417 genSkipc(&rFalseIfx);
5419 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5420 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5426 if(ifx) ifx->generated = 1;
5427 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5433 /* Size is greater than 1 */
5441 /* this means lit = 0xffffffff, or -1 */
5444 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5445 rFalseIfx.condition ^= 1;
5446 genSkipCond(&rFalseIfx,right,size,7);
5447 if(ifx) ifx->generated = 1;
5449 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5458 if(rFalseIfx.condition) {
5459 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5460 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5463 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5465 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5469 if(rFalseIfx.condition) {
5470 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5471 pic16_emitpLabel(truelbl->key);
5473 rFalseIfx.condition ^= 1;
5474 genSkipCond(&rFalseIfx,right,s,7);
5477 if(ifx) ifx->generated = 1;
5479 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5485 if((size == 1) && (0 == (lp1&0xff))) {
5486 /* lower byte of signed word is zero */
5487 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5488 i = ((lp1 >> 8) & 0xff) ^0x80;
5489 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5490 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5491 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5493 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5495 if(ifx) ifx->generated = 1;
5498 rFalseIfx.condition ^= 1;
5499 genSkipc(&rFalseIfx);
5500 if(ifx) ifx->generated = 1;
5506 if(lit & (0x80 << (size*8))) {
5507 /* Lit is less than zero */
5508 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5509 //rFalseIfx.condition ^= 1;
5510 //genSkipCond(&rFalseIfx,left,size,7);
5511 //rFalseIfx.condition ^= 1;
5512 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5513 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5515 if(rFalseIfx.condition)
5516 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5518 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5522 /* Lit is greater than or equal to zero */
5523 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5524 //rFalseIfx.condition ^= 1;
5525 //genSkipCond(&rFalseIfx,right,size,7);
5526 //rFalseIfx.condition ^= 1;
5528 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5529 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5531 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5532 if(rFalseIfx.condition)
5533 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5535 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5539 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5540 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5544 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5546 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5548 rFalseIfx.condition ^= 1;
5549 //rFalseIfx.condition = 1;
5550 genSkipc(&rFalseIfx);
5552 pic16_emitpLabel(truelbl->key);
5554 if(ifx) ifx->generated = 1;
5557 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5564 /* compare word or long to an unsigned literal on the right.*/
5569 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5572 break; /* handled above */
5575 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5577 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5578 genSkipz2(&rFalseIfx,0);
5582 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5584 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5587 if(rFalseIfx.condition)
5588 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5590 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5593 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5594 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5596 rFalseIfx.condition ^= 1;
5597 genSkipc(&rFalseIfx);
5600 pic16_emitpLabel(truelbl->key);
5602 if(ifx) ifx->generated = 1;
5604 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5612 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5613 i = (lit >> (size*8)) & 0xff;
5615 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5616 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5619 i = (lit >> (size*8)) & 0xff;
5622 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5624 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5626 /* this byte of the lit is zero,
5627 * if it's not the last then OR in the variable */
5629 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5634 pic16_emitpLabel(lbl->key);
5636 rFalseIfx.condition ^= 1;
5638 genSkipc(&rFalseIfx);
5642 pic16_emitpLabel(truelbl->key);
5643 if(ifx) ifx->generated = 1;
5645 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5651 /* Compare two variables */
5653 DEBUGpic16_emitcode(";sign","%d",sign);
5657 /* Sigh. thus sucks... */
5661 pctemp = pic16_popGetTempReg(1);
5662 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5663 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5664 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5665 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5666 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5667 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5668 pic16_popReleaseTempReg(pctemp, 1);
5670 /* Signed char comparison */
5671 /* Special thanks to Nikolai Golovchenko for this snippet */
5672 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5673 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5674 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5675 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5676 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5677 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5679 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5680 genSkipc(&rFalseIfx);
5682 if(ifx) ifx->generated = 1;
5684 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5692 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5693 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5697 /* The rest of the bytes of a multi-byte compare */
5701 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5704 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5705 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5710 pic16_emitpLabel(lbl->key);
5712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5713 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5714 (AOP_TYPE(result) == AOP_REG)) {
5715 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5716 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5718 genSkipc(&rFalseIfx);
5720 //genSkipc(&rFalseIfx);
5721 if(ifx) ifx->generated = 1;
5724 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5732 if ((AOP_TYPE(result) != AOP_CRY)
5733 && AOP_SIZE(result)) {
5734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5736 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5738 pic16_outBitC(result);
5740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5741 /* if the result is used in the next
5742 ifx conditional branch then generate
5743 code a little differently */
5745 genIfxJump (ifx,"c");
5747 pic16_outBitC(result);
5748 /* leave the result in acc */
5753 #else /* old version of genCmp() */ /* } else { */
5755 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5756 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5757 operand *result, int offset, int invert_op)
5761 /* check condition, > or < ?? */
5762 if(rIfx->condition != 0)invert_op ^= 1;
5764 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5766 if(!ifx)invert_op ^= 1;
5768 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5769 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5772 if(!invert_op)return POC_CPFSGT;
5773 else return POC_CPFSLT;
5776 static int compareAopfirstpass=1;
5778 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5779 operand *oper, int offset, operand *result,
5780 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5786 /* invert if there is a result to be loaded, in order to fit,
5787 * SETC/CLRC sequence */
5788 if(AOP_SIZE(result))invert_op ^= 1;
5790 // if(sign && !offset)invert_op ^= 1;
5792 // if(sign)invert_op ^= 1;
5794 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5796 if(AOP_SIZE(result) && compareAopfirstpass) {
5799 pic16_emitpcode(POC_SETF, pcop2);
5804 pic16_emitpcode(POC_CLRF, pcop2);
5810 compareAopfirstpass = 0;
5812 /* there is a bug when comparing operands with size > 1,
5813 * because higher bytes can be equal and test should be performed
5814 * to the next lower byte, current algorithm, considers operands
5815 * inequal in these cases! -- VR 20041107 */
5819 pic16_emitpcode(op, pcop);
5821 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5824 if((!sign || !offset) && AOP_SIZE(result)) {
5827 pic16_emitpcode(POC_CLRF, pcop2);
5832 pic16_emitpcode(POC_SETF, pcop2);
5837 /* don't emit final branch (offset == 0) */
5841 pic16_emitpcode(POC_RRCF, pcop2);
5843 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5846 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5847 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5848 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5850 truelbl = newiTempLabel( NULL );
5851 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5852 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5853 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5855 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5856 pic16_emitpLabel(truelbl->key);
5858 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5867 static void genCmp (operand *left, operand *right,
5868 operand *result, iCode *ifx, int sign)
5872 resolvedIfx rFalseIfx;
5873 symbol *falselbl, *tlbl;
5877 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5879 resolveIfx(&rFalseIfx, ifx);
5880 size = max(AOP_SIZE(left), AOP_SIZE(right));
5882 /* if left & right are bit variables */
5883 if(AOP_TYPE(left) == AOP_CRY
5884 && AOP_TYPE(right) == AOP_CRY ) {
5886 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5887 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5889 werror(W_POSSBUG2, __FILE__, __LINE__);
5893 /* if literal is on the right then swap with left */
5894 if((AOP_TYPE(right) == AOP_LIT)) {
5895 operand *tmp = right ;
5896 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5898 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5900 // lit = (lit - 1) & mask;
5903 rFalseIfx.condition ^= 1; /* reverse compare */
5905 if ((AOP_TYPE(left) == AOP_LIT)) {
5906 /* float compares are handled by support functions */
5907 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5910 /* actual comparing algorithm */
5911 // size = AOP_SIZE( right );
5913 falselbl = newiTempLabel( NULL );
5914 if(AOP_TYPE(left) == AOP_LIT) {
5915 /* compare to literal */
5916 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5919 pCodeOp *pct, *pct2;
5922 /* signed compare */
5923 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5925 pct = pic16_popCopyReg(&pic16_pc_prodl);
5926 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5927 tlbl = newiTempLabel( NULL );
5929 /* first compare signs:
5930 * a. if both are positive, compare just like unsigned
5931 * b. if both are negative, invert cmpop, compare just like unsigned
5932 * c. if different signs, determine the result directly */
5938 tlbl1 = newiTempLabel( NULL );
5939 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5943 /* literal is zero or positive:
5944 * a. if carry is zero, too, continue compare,
5945 * b. if carry is set, then continue depending on cmpop ^ condition:
5946 * 1. '<' return false (literal < variable),
5947 * 2. '>' return true (literal > variable) */
5948 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5949 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5952 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5953 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5957 /* literal is negative:
5958 * a. if carry is set, too, continue compare,
5959 * b. if carry is zero, then continue depending on cmpop ^ condition:
5960 * 1. '<' return true (literal < variable),
5961 * 2. '>' return false (literal > variable) */
5962 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5963 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5965 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5966 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5971 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5973 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5974 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5979 pic16_emitpLabel( tlbl1->key );
5982 compareAopfirstpass=1;
5983 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5984 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5985 // pic16_emitpcode(POC_MOVWF, pct);
5987 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5988 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5989 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5990 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5994 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5995 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5996 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5997 // pic16_emitpcode(POC_MOVWF, pct);
5999 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6000 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6001 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6002 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6003 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6007 if(ifx)ifx->generated = 1;
6009 if(AOP_SIZE(result)) {
6010 pic16_emitpLabel(tlbl->key);
6011 pic16_emitpLabel(falselbl->key);
6012 pic16_outBitOp( result, pct2 );
6014 pic16_emitpLabel(tlbl->key);
6019 /* unsigned compare */
6020 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6022 compareAopfirstpass=1;
6025 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6026 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6030 if(ifx)ifx->generated = 1;
6033 if(AOP_SIZE(result)) {
6034 pic16_emitpLabel(falselbl->key);
6035 pic16_outBitC( result );
6040 /* compare registers */
6041 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6045 pCodeOp *pct, *pct2;
6047 /* signed compare */
6048 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6050 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6051 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6052 tlbl = newiTempLabel( NULL );
6054 compareAopfirstpass=1;
6057 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6058 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6059 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6060 pic16_emitpcode(POC_MOVWF, pct);
6062 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6063 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6064 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6066 /* WREG already holds left + 0x80 */
6067 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6070 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6071 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6072 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6073 pic16_emitpcode(POC_MOVWF, pct);
6075 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6076 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6077 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6079 /* WREG already holds left + 0x80 */
6080 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6081 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6084 if(ifx)ifx->generated = 1;
6086 if(AOP_SIZE(result)) {
6087 pic16_emitpLabel(tlbl->key);
6088 pic16_emitpLabel(falselbl->key);
6089 pic16_outBitOp( result, pct2 );
6091 pic16_emitpLabel(tlbl->key);
6095 /* unsigned compare */
6096 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6098 compareAopfirstpass=1;
6101 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6102 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6106 if(ifx)ifx->generated = 1;
6107 if(AOP_SIZE(result)) {
6109 pic16_emitpLabel(falselbl->key);
6110 pic16_outBitC( result );
6117 #else /* } else { */
6119 /* new version of genCmp -- VR 20041012 */
6120 static void genCmp (operand *left,operand *right,
6121 operand *result, iCode *ifx, int sign)
6123 int size; //, offset = 0 ;
6124 unsigned long lit = 0L,i = 0;
6125 resolvedIfx rFalseIfx;
6126 int willCheckCarry=0;
6127 // resolvedIfx rTrueIfx;
6133 * subtract right from left if at the end the carry flag is set then we
6134 * know that left is greater than right */
6136 resolveIfx(&rFalseIfx,ifx);
6137 truelbl = newiTempLabel(NULL);
6138 size = max(AOP_SIZE(left),AOP_SIZE(right));
6140 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6142 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6143 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6146 /* if literal is on the right then swap with left */
6147 if ((AOP_TYPE(right) == AOP_LIT)) {
6148 operand *tmp = right ;
6149 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6151 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6153 // lit = (lit - 1) & mask;
6156 rFalseIfx.condition ^= 1; /* reverse compare */
6158 if ((AOP_TYPE(left) == AOP_LIT)) {
6159 /* float compares are handled by support functions */
6160 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6164 //if(IC_TRUE(ifx) == NULL)
6165 /* if left & right are bit variables */
6166 if (AOP_TYPE(left) == AOP_CRY &&
6167 AOP_TYPE(right) == AOP_CRY ) {
6169 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6170 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6173 symbol *lbl = newiTempLabel(NULL);
6175 if(AOP_TYPE(left) == AOP_LIT) {
6176 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6178 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6180 else willCheckCarry = 0;
6183 if((lit == 0) && (sign == 0)) {
6184 /* unsigned compare to 0 */
6185 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6188 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6190 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6192 genSkipz2(&rFalseIfx,0);
6193 if(ifx)ifx->generated = 1;
6200 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6201 /* degenerate compare can never be true */
6202 if(rFalseIfx.condition == 0)
6203 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6205 if(ifx) ifx->generated = 1;
6210 /* signed comparisons to a literal byte */
6211 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6213 int lp1 = (lit+1) & 0xff;
6215 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6218 rFalseIfx.condition ^= 1;
6219 genSkipCond(&rFalseIfx,right,0,7);
6222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6223 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6224 genSkipz2(&rFalseIfx,1);
6227 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6229 if(rFalseIfx.condition)
6230 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6232 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6234 if(willCheckCarry) {
6235 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6236 else { emitSETC; emitCLRC; }
6239 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6242 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6243 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6244 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6245 rFalseIfx.condition ^= 1;
6246 genSkipc(&rFalseIfx);
6251 /* unsigned comparisons to a literal byte */
6252 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6254 switch(lit & 0xff ) {
6257 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6258 genSkipz2(&rFalseIfx,0);
6261 rFalseIfx.condition ^= 1;
6262 genSkipCond(&rFalseIfx,right,0,7);
6265 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6266 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6267 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6268 rFalseIfx.condition ^= 1;
6269 if (AOP_TYPE(result) == AOP_CRY)
6270 genSkipc(&rFalseIfx);
6272 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6273 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6279 if(ifx) ifx->generated = 1;
6280 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6286 /* Size is greater than 1 */
6294 /* this means lit = 0xffffffff, or -1 */
6297 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6298 rFalseIfx.condition ^= 1;
6299 genSkipCond(&rFalseIfx,right,size,7);
6300 if(ifx) ifx->generated = 1;
6307 if(rFalseIfx.condition) {
6308 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6309 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6312 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6314 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6318 if(rFalseIfx.condition) {
6319 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6320 pic16_emitpLabel(truelbl->key);
6322 rFalseIfx.condition ^= 1;
6323 genSkipCond(&rFalseIfx,right,s,7);
6326 if(ifx) ifx->generated = 1;
6330 if((size == 1) && (0 == (lp1&0xff))) {
6331 /* lower byte of signed word is zero */
6332 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6333 i = ((lp1 >> 8) & 0xff) ^0x80;
6334 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6336 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6337 rFalseIfx.condition ^= 1;
6338 genSkipc(&rFalseIfx);
6341 if(ifx) ifx->generated = 1;
6345 if(lit & (0x80 << (size*8))) {
6346 /* Lit is less than zero */
6347 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6348 //rFalseIfx.condition ^= 1;
6349 //genSkipCond(&rFalseIfx,left,size,7);
6350 //rFalseIfx.condition ^= 1;
6351 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6352 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6354 if(rFalseIfx.condition)
6355 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6357 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6361 /* Lit is greater than or equal to zero */
6362 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6363 //rFalseIfx.condition ^= 1;
6364 //genSkipCond(&rFalseIfx,right,size,7);
6365 //rFalseIfx.condition ^= 1;
6367 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6368 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6370 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6371 if(rFalseIfx.condition)
6372 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6374 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6379 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6380 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6384 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6386 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6388 rFalseIfx.condition ^= 1;
6389 //rFalseIfx.condition = 1;
6390 genSkipc(&rFalseIfx);
6392 pic16_emitpLabel(truelbl->key);
6394 if(ifx) ifx->generated = 1;
6399 /* compare word or long to an unsigned literal on the right.*/
6404 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6407 break; /* handled above */
6410 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6412 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6413 genSkipz2(&rFalseIfx,0);
6417 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6419 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6422 if(rFalseIfx.condition)
6423 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6425 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6428 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6429 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6431 rFalseIfx.condition ^= 1;
6432 genSkipc(&rFalseIfx);
6435 pic16_emitpLabel(truelbl->key);
6437 if(ifx) ifx->generated = 1;
6443 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6444 i = (lit >> (size*8)) & 0xff;
6446 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6447 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6450 i = (lit >> (size*8)) & 0xff;
6453 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6455 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6457 /* this byte of the lit is zero,
6458 * if it's not the last then OR in the variable */
6460 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6465 pic16_emitpLabel(lbl->key);
6467 rFalseIfx.condition ^= 1;
6469 genSkipc(&rFalseIfx);
6473 pic16_emitpLabel(truelbl->key);
6474 if(ifx) ifx->generated = 1;
6478 /* Compare two variables */
6480 DEBUGpic16_emitcode(";sign","%d",sign);
6484 /* Sigh. thus sucks... */
6488 pctemp = pic16_popGetTempReg(1);
6489 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6490 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6491 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6492 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6493 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6494 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6495 pic16_popReleaseTempReg(pctemp, 1);
6497 /* Signed char comparison */
6498 /* Special thanks to Nikolai Golovchenko for this snippet */
6499 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6500 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6501 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6502 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6503 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6504 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6506 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6507 genSkipc(&rFalseIfx);
6509 if(ifx) ifx->generated = 1;
6515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6516 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6520 /* The rest of the bytes of a multi-byte compare */
6524 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6527 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6528 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6533 pic16_emitpLabel(lbl->key);
6535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6536 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6537 (AOP_TYPE(result) == AOP_REG)) {
6538 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6539 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6541 genSkipc(&rFalseIfx);
6543 //genSkipc(&rFalseIfx);
6544 if(ifx) ifx->generated = 1;
6551 if ((AOP_TYPE(result) != AOP_CRY)
6552 && AOP_SIZE(result)) {
6553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6555 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6557 pic16_outBitC(result);
6559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6560 /* if the result is used in the next
6561 ifx conditional branch then generate
6562 code a little differently */
6564 genIfxJump (ifx,"c");
6566 pic16_outBitC(result);
6567 /* leave the result in acc */
6578 /*-----------------------------------------------------------------*/
6579 /* genCmpGt :- greater than comparison */
6580 /*-----------------------------------------------------------------*/
6581 static void genCmpGt (iCode *ic, iCode *ifx)
6583 operand *left, *right, *result;
6584 sym_link *letype , *retype;
6590 right= IC_RIGHT(ic);
6591 result = IC_RESULT(ic);
6593 letype = getSpec(operandType(left));
6594 retype =getSpec(operandType(right));
6595 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6596 /* assign the amsops */
6597 pic16_aopOp (left,ic,FALSE);
6598 pic16_aopOp (right,ic,FALSE);
6599 pic16_aopOp (result,ic,TRUE);
6601 genCmp(right, left, result, ifx, sign);
6603 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6604 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6605 pic16_freeAsmop(result,NULL,ic,TRUE);
6608 /*-----------------------------------------------------------------*/
6609 /* genCmpLt - less than comparisons */
6610 /*-----------------------------------------------------------------*/
6611 static void genCmpLt (iCode *ic, iCode *ifx)
6613 operand *left, *right, *result;
6614 sym_link *letype , *retype;
6620 right= IC_RIGHT(ic);
6621 result = IC_RESULT(ic);
6623 letype = getSpec(operandType(left));
6624 retype =getSpec(operandType(right));
6625 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6627 /* assign the amsops */
6628 pic16_aopOp (left,ic,FALSE);
6629 pic16_aopOp (right,ic,FALSE);
6630 pic16_aopOp (result,ic,TRUE);
6632 genCmp(left, right, result, ifx, sign);
6634 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6635 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6636 pic16_freeAsmop(result,NULL,ic,TRUE);
6641 // FIXME reenable literal optimisation when the pic16 port is stable
6643 /*-----------------------------------------------------------------*/
6644 /* genc16bit2lit - compare a 16 bit value to a literal */
6645 /*-----------------------------------------------------------------*/
6646 static void genc16bit2lit(operand *op, int lit, int offset)
6650 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6651 if( (lit&0xff) == 0)
6656 switch( BYTEofLONG(lit,i)) {
6658 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6661 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6664 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6667 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6668 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6673 switch( BYTEofLONG(lit,i)) {
6675 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6679 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6683 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6686 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6688 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6697 /*-----------------------------------------------------------------*/
6698 /* gencjneshort - compare and jump if not equal */
6699 /*-----------------------------------------------------------------*/
6700 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6702 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6704 int res_offset = 0; /* the result may be a different size then left or right */
6705 int res_size = AOP_SIZE(result);
6707 symbol *lbl, *lbl_done;
6709 unsigned long lit = 0L;
6710 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6713 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6715 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6716 resolveIfx(&rIfx,ifx);
6717 lbl = newiTempLabel(NULL);
6718 lbl_done = newiTempLabel(NULL);
6721 /* if the left side is a literal or
6722 if the right is in a pointer register and left
6724 if ((AOP_TYPE(left) == AOP_LIT) ||
6725 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6730 if(AOP_TYPE(right) == AOP_LIT)
6731 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6733 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6734 preserve_result = 1;
6736 if(result && !preserve_result)
6739 for(i = 0; i < AOP_SIZE(result); i++)
6740 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6744 /* if the right side is a literal then anything goes */
6745 if (AOP_TYPE(right) == AOP_LIT &&
6746 AOP_TYPE(left) != AOP_DIR ) {
6749 genc16bit2lit(left, lit, 0);
6751 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6754 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6757 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6758 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6760 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6764 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6766 if(res_offset < res_size-1)
6774 /* if the right side is in a register or in direct space or
6775 if the left is a pointer register & right is not */
6776 else if (AOP_TYPE(right) == AOP_REG ||
6777 AOP_TYPE(right) == AOP_DIR ||
6778 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6779 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6780 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6781 int lbl_key = lbl->key;
6784 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6785 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6787 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6788 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6789 __FUNCTION__,__LINE__);
6793 /* switch(size) { */
6795 /* genc16bit2lit(left, lit, 0); */
6797 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6802 if((AOP_TYPE(left) == AOP_DIR) &&
6803 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6805 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6806 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6808 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6810 switch (lit & 0xff) {
6812 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6815 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6816 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6817 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6821 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6822 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6823 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6824 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6828 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6829 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6834 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6837 if(AOP_TYPE(result) == AOP_CRY) {
6838 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6843 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6845 /* fix me. probably need to check result size too */
6846 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6851 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6852 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6859 if(res_offset < res_size-1)
6864 } else if(AOP_TYPE(right) == AOP_REG &&
6865 AOP_TYPE(left) != AOP_DIR){
6868 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6869 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6870 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6877 if(res_offset < res_size-1)
6882 /* right is a pointer reg need both a & b */
6884 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6886 pic16_emitcode("mov","b,%s",l);
6887 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6888 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6893 if(result && preserve_result)
6896 for(i = 0; i < AOP_SIZE(result); i++)
6897 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6900 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6902 if(result && preserve_result)
6903 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6906 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6908 pic16_emitpLabel(lbl->key);
6910 if(result && preserve_result)
6913 for(i = 0; i < AOP_SIZE(result); i++)
6914 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6916 pic16_emitpLabel(lbl_done->key);
6919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6927 /*-----------------------------------------------------------------*/
6928 /* gencjne - compare and jump if not equal */
6929 /*-----------------------------------------------------------------*/
6930 static void gencjne(operand *left, operand *right, iCode *ifx)
6932 symbol *tlbl = newiTempLabel(NULL);
6934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6935 gencjneshort(left, right, lbl);
6937 pic16_emitcode("mov","a,%s",one);
6938 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6939 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6940 pic16_emitcode("clr","a");
6941 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6943 pic16_emitpLabel(lbl->key);
6944 pic16_emitpLabel(tlbl->key);
6950 /*-----------------------------------------------------------------*/
6951 /* is_LitOp - check if operand has to be treated as literal */
6952 /*-----------------------------------------------------------------*/
6953 static bool is_LitOp(operand *op)
6955 return ((AOP_TYPE(op) == AOP_LIT)
6956 || ( (AOP_TYPE(op) == AOP_PCODE)
6957 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6958 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6961 /*-----------------------------------------------------------------*/
6962 /* is_LitAOp - check if operand has to be treated as literal */
6963 /*-----------------------------------------------------------------*/
6964 static bool is_LitAOp(asmop *aop)
6966 return ((aop->type == AOP_LIT)
6967 || ( (aop->type == AOP_PCODE)
6968 && ( (aop->aopu.pcop->type == PO_LITERAL)
6969 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6974 /*-----------------------------------------------------------------*/
6975 /* genCmpEq - generates code for equal to */
6976 /*-----------------------------------------------------------------*/
6977 static void genCmpEq (iCode *ic, iCode *ifx)
6979 operand *left, *right, *result;
6980 symbol *falselbl = newiTempLabel(NULL);
6981 symbol *donelbl = newiTempLabel(NULL);
6983 int preserve_result = 0;
6984 int generate_result = 0;
6989 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6990 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6991 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6993 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6995 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6997 werror(W_POSSBUG2, __FILE__, __LINE__);
6998 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6999 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7003 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7005 operand *tmp = right ;
7010 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7011 preserve_result = 1;
7013 if(result && AOP_SIZE(result))
7014 generate_result = 1;
7016 if(generate_result && !preserve_result)
7018 for(i = 0; i < AOP_SIZE(result); i++)
7019 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7022 for(i=0; i < AOP_SIZE(left); i++)
7024 if(AOP_TYPE(left) != AOP_ACC)
7027 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7029 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7032 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7034 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7036 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7041 if(generate_result && preserve_result)
7043 for(i = 0; i < AOP_SIZE(result); i++)
7044 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7048 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7050 if(generate_result && preserve_result)
7051 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7053 if(ifx && IC_TRUE(ifx))
7054 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7056 if(ifx && IC_FALSE(ifx))
7057 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7059 pic16_emitpLabel(falselbl->key);
7063 if(ifx && IC_FALSE(ifx))
7064 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7066 if(generate_result && preserve_result)
7068 for(i = 0; i < AOP_SIZE(result); i++)
7069 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7072 pic16_emitpLabel(donelbl->key);
7078 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7079 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7080 pic16_freeAsmop(result,NULL,ic,TRUE);
7086 // old version kept for reference
7088 /*-----------------------------------------------------------------*/
7089 /* genCmpEq - generates code for equal to */
7090 /*-----------------------------------------------------------------*/
7091 static void genCmpEq (iCode *ic, iCode *ifx)
7093 operand *left, *right, *result;
7094 unsigned long lit = 0L;
7096 symbol *falselbl = newiTempLabel(NULL);
7099 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7102 DEBUGpic16_emitcode ("; ifx is non-null","");
7104 DEBUGpic16_emitcode ("; ifx is null","");
7106 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7107 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7108 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7110 size = max(AOP_SIZE(left),AOP_SIZE(right));
7112 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7114 /* if literal, literal on the right or
7115 if the right is in a pointer register and left
7117 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7118 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7119 operand *tmp = right ;
7125 if(ifx && !AOP_SIZE(result)){
7127 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7128 /* if they are both bit variables */
7129 if (AOP_TYPE(left) == AOP_CRY &&
7130 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7131 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7132 if(AOP_TYPE(right) == AOP_LIT){
7133 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7135 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7136 pic16_emitcode("cpl","c");
7137 } else if(lit == 1L) {
7138 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7140 pic16_emitcode("clr","c");
7142 /* AOP_TYPE(right) == AOP_CRY */
7144 symbol *lbl = newiTempLabel(NULL);
7145 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7146 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7147 pic16_emitcode("cpl","c");
7148 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7150 /* if true label then we jump if condition
7152 tlbl = newiTempLabel(NULL);
7153 if ( IC_TRUE(ifx) ) {
7154 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7155 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7157 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7158 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7160 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7163 /* left and right are both bit variables, result is carry */
7166 resolveIfx(&rIfx,ifx);
7168 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7169 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7170 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7171 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7176 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7178 /* They're not both bit variables. Is the right a literal? */
7179 if(AOP_TYPE(right) == AOP_LIT) {
7180 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7185 switch(lit & 0xff) {
7187 if ( IC_TRUE(ifx) ) {
7188 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7190 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7192 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7193 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7197 if ( IC_TRUE(ifx) ) {
7198 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7200 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7202 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7203 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7207 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7209 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7214 /* end of size == 1 */
7218 genc16bit2lit(left,lit,offset);
7221 /* end of size == 2 */
7226 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7227 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7228 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7229 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7232 /* search for patterns that can be optimized */
7234 genc16bit2lit(left,lit,0);
7238 emitSKPZ; // if hi word unequal
7240 emitSKPNZ; // if hi word equal
7242 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7243 genc16bit2lit(left,lit,2);
7246 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7247 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7251 pic16_emitpLabel(falselbl->key);
7260 } else if(AOP_TYPE(right) == AOP_CRY ) {
7261 /* we know the left is not a bit, but that the right is */
7262 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7263 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7264 pic16_popGet(AOP(right),offset));
7265 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7267 /* if the two are equal, then W will be 0 and the Z bit is set
7268 * we could test Z now, or go ahead and check the high order bytes if
7269 * the variable we're comparing is larger than a byte. */
7272 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7274 if ( IC_TRUE(ifx) ) {
7276 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7277 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7280 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7281 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7285 /* They're both variables that are larger than bits */
7288 tlbl = newiTempLabel(NULL);
7291 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7292 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7294 if ( IC_TRUE(ifx) ) {
7298 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7300 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7301 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7305 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7308 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7309 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7314 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7316 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7317 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7321 if(s>1 && IC_TRUE(ifx)) {
7322 pic16_emitpLabel(tlbl->key);
7323 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7327 /* mark the icode as generated */
7332 /* if they are both bit variables */
7333 if (AOP_TYPE(left) == AOP_CRY &&
7334 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7335 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7336 if(AOP_TYPE(right) == AOP_LIT){
7337 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7339 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7340 pic16_emitcode("cpl","c");
7341 } else if(lit == 1L) {
7342 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7344 pic16_emitcode("clr","c");
7346 /* AOP_TYPE(right) == AOP_CRY */
7348 symbol *lbl = newiTempLabel(NULL);
7349 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7350 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7351 pic16_emitcode("cpl","c");
7352 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7355 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7356 pic16_outBitC(result);
7360 genIfxJump (ifx,"c");
7363 /* if the result is used in an arithmetic operation
7364 then put the result in place */
7365 pic16_outBitC(result);
7368 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7369 gencjne(left,right,result,ifx);
7372 gencjne(left,right,newiTempLabel(NULL));
7374 if(IC_TRUE(ifx)->key)
7375 gencjne(left,right,IC_TRUE(ifx)->key);
7377 gencjne(left,right,IC_FALSE(ifx)->key);
7381 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7382 pic16_aopPut(AOP(result),"a",0);
7387 genIfxJump (ifx,"a");
7391 /* if the result is used in an arithmetic operation
7392 then put the result in place */
7394 if (AOP_TYPE(result) != AOP_CRY)
7395 pic16_outAcc(result);
7397 /* leave the result in acc */
7401 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7402 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7403 pic16_freeAsmop(result,NULL,ic,TRUE);
7407 /*-----------------------------------------------------------------*/
7408 /* ifxForOp - returns the icode containing the ifx for operand */
7409 /*-----------------------------------------------------------------*/
7410 static iCode *ifxForOp ( operand *op, iCode *ic )
7414 /* if true symbol then needs to be assigned */
7415 if (IS_TRUE_SYMOP(op))
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
7426 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7432 ic->next->op == IFX &&
7433 IC_COND(ic->next)->key == op->key) {
7434 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7439 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7441 ic->next->op == IFX)
7442 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7445 ic->next->op == IFX &&
7446 IC_COND(ic->next)->key == op->key) {
7447 DEBUGpic16_emitcode ("; "," key is okay");
7448 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7449 OP_SYMBOL(op)->liveTo,
7454 /* the code below is completely untested
7455 * it just allows ulong2fs.c compile -- VR */
7458 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7459 __FILE__, __FUNCTION__, __LINE__);
7461 /* if this has register type condition and
7462 the next instruction is ifx with the same operand
7463 and live to of the operand is upto the ifx only then */
7465 ic->next->op == IFX &&
7466 IC_COND(ic->next)->key == op->key &&
7467 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7471 ic->next->op == IFX &&
7472 IC_COND(ic->next)->key == op->key) {
7473 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7477 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7478 __FILE__, __FUNCTION__, __LINE__);
7480 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7485 /*-----------------------------------------------------------------*/
7486 /* genAndOp - for && operation */
7487 /*-----------------------------------------------------------------*/
7488 static void genAndOp (iCode *ic)
7490 operand *left,*right, *result;
7495 /* note here that && operations that are in an
7496 if statement are taken away by backPatchLabels
7497 only those used in arthmetic operations remain */
7498 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7499 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7500 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7502 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7504 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7505 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7506 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7508 /* if both are bit variables */
7509 /* if (AOP_TYPE(left) == AOP_CRY && */
7510 /* AOP_TYPE(right) == AOP_CRY ) { */
7511 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7512 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7513 /* pic16_outBitC(result); */
7515 /* tlbl = newiTempLabel(NULL); */
7516 /* pic16_toBoolean(left); */
7517 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7518 /* pic16_toBoolean(right); */
7519 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7520 /* pic16_outBitAcc(result); */
7523 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7524 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7525 pic16_freeAsmop(result,NULL,ic,TRUE);
7529 /*-----------------------------------------------------------------*/
7530 /* genOrOp - for || operation */
7531 /*-----------------------------------------------------------------*/
7534 modified this code, but it doesn't appear to ever get called
7537 static void genOrOp (iCode *ic)
7539 operand *left,*right, *result;
7544 /* note here that || operations that are in an
7545 if statement are taken away by backPatchLabels
7546 only those used in arthmetic operations remain */
7547 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7548 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7549 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7551 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7553 /* if both are bit variables */
7554 if (AOP_TYPE(left) == AOP_CRY &&
7555 AOP_TYPE(right) == AOP_CRY ) {
7556 pic16_emitcode("clrc","");
7557 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7558 AOP(left)->aopu.aop_dir,
7559 AOP(left)->aopu.aop_dir);
7560 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7561 AOP(right)->aopu.aop_dir,
7562 AOP(right)->aopu.aop_dir);
7563 pic16_emitcode("setc","");
7566 tlbl = newiTempLabel(NULL);
7567 pic16_toBoolean(left);
7569 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7570 pic16_toBoolean(right);
7571 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7573 pic16_outBitAcc(result);
7576 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7577 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7578 pic16_freeAsmop(result,NULL,ic,TRUE);
7581 /*-----------------------------------------------------------------*/
7582 /* isLiteralBit - test if lit == 2^n */
7583 /*-----------------------------------------------------------------*/
7584 static int isLiteralBit(unsigned long lit)
7586 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7587 0x100L,0x200L,0x400L,0x800L,
7588 0x1000L,0x2000L,0x4000L,0x8000L,
7589 0x10000L,0x20000L,0x40000L,0x80000L,
7590 0x100000L,0x200000L,0x400000L,0x800000L,
7591 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7592 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7596 for(idx = 0; idx < 32; idx++)
7602 /*-----------------------------------------------------------------*/
7603 /* continueIfTrue - */
7604 /*-----------------------------------------------------------------*/
7605 static void continueIfTrue (iCode *ic)
7609 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7613 /*-----------------------------------------------------------------*/
7615 /*-----------------------------------------------------------------*/
7616 static void jumpIfTrue (iCode *ic)
7620 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7624 /*-----------------------------------------------------------------*/
7625 /* jmpTrueOrFalse - */
7626 /*-----------------------------------------------------------------*/
7627 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7629 // ugly but optimized by peephole
7632 symbol *nlbl = newiTempLabel(NULL);
7633 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7634 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7635 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7636 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7638 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7639 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7644 /*-----------------------------------------------------------------*/
7645 /* genAnd - code for and */
7646 /*-----------------------------------------------------------------*/
7647 static void genAnd (iCode *ic, iCode *ifx)
7649 operand *left, *right, *result;
7651 unsigned long lit = 0L;
7657 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7658 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7659 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7661 resolveIfx(&rIfx,ifx);
7663 /* if left is a literal & right is not then exchange them */
7664 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7665 AOP_NEEDSACC(left)) {
7666 operand *tmp = right ;
7671 /* if result = right then exchange them */
7672 if(pic16_sameRegs(AOP(result),AOP(right))){
7673 operand *tmp = right ;
7678 /* if right is bit then exchange them */
7679 if (AOP_TYPE(right) == AOP_CRY &&
7680 AOP_TYPE(left) != AOP_CRY){
7681 operand *tmp = right ;
7685 if(AOP_TYPE(right) == AOP_LIT)
7686 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7688 size = AOP_SIZE(result);
7690 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7693 // result = bit & yy;
7694 if (AOP_TYPE(left) == AOP_CRY){
7695 // c = bit & literal;
7696 if(AOP_TYPE(right) == AOP_LIT){
7698 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7701 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7704 if(size && (AOP_TYPE(result) == AOP_CRY)){
7705 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7708 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7712 pic16_emitcode("clr","c");
7715 if (AOP_TYPE(right) == AOP_CRY){
7717 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7718 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7721 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7723 pic16_emitcode("rrc","a");
7724 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7730 pic16_outBitC(result);
7732 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7733 genIfxJump(ifx, "c");
7737 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7738 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7739 if((AOP_TYPE(right) == AOP_LIT) &&
7740 (AOP_TYPE(result) == AOP_CRY) &&
7741 (AOP_TYPE(left) != AOP_CRY)){
7742 int posbit = isLiteralBit(lit);
7746 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7749 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7755 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7756 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7758 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7762 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7763 size = AOP_SIZE(left);
7766 int bp = posbit, ofs=0;
7773 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7774 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7778 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7779 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7781 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7788 symbol *tlbl = newiTempLabel(NULL);
7789 int sizel = AOP_SIZE(left);
7795 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7797 /* patch provided by Aaron Colwell */
7798 if((posbit = isLiteralBit(bytelit)) != 0) {
7799 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7800 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7801 (posbit-1),0, PO_GPR_REGISTER));
7803 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7804 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7806 if (bytelit == 0xff) {
7807 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7808 * a peephole could optimize it out -- VR */
7809 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7811 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7812 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7815 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7816 pic16_popGetLabel(tlbl->key));
7820 /* old code, left here for reference -- VR 09/2004 */
7821 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7823 if((posbit = isLiteralBit(bytelit)) != 0)
7824 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7826 if(bytelit != 0x0FFL)
7827 pic16_emitcode("anl","a,%s",
7828 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7829 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7835 // bit = left & literal
7838 pic16_emitpLabel(tlbl->key);
7840 // if(left & literal)
7843 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7846 pic16_emitpLabel(tlbl->key);
7851 pic16_outBitC(result);
7855 /* if left is same as result */
7856 if(pic16_sameRegs(AOP(result),AOP(left))){
7858 for(;size--; offset++,lit>>=8) {
7859 if(AOP_TYPE(right) == AOP_LIT){
7860 switch(lit & 0xff) {
7862 /* and'ing with 0 has clears the result */
7863 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7864 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7867 /* and'ing with 0xff is a nop when the result and left are the same */
7872 int p = pic16_my_powof2( (~lit) & 0xff );
7874 /* only one bit is set in the literal, so use a bcf instruction */
7875 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7876 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7879 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7880 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7881 if(know_W != (lit&0xff))
7882 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7884 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7889 if (AOP_TYPE(left) == AOP_ACC) {
7890 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7892 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7893 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7900 // left & result in different registers
7901 if(AOP_TYPE(result) == AOP_CRY){
7903 // if(size), result in bit
7904 // if(!size && ifx), conditional oper: if(left & right)
7905 symbol *tlbl = newiTempLabel(NULL);
7906 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7908 pic16_emitcode("setb","c");
7910 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7911 pic16_emitcode("anl","a,%s",
7912 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7913 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7918 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7919 pic16_outBitC(result);
7921 jmpTrueOrFalse(ifx, tlbl);
7923 for(;(size--);offset++) {
7925 // result = left & right
7926 if(AOP_TYPE(right) == AOP_LIT){
7927 int t = (lit >> (offset*8)) & 0x0FFL;
7930 pic16_emitcode("clrf","%s",
7931 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7932 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7935 pic16_emitcode("movf","%s,w",
7936 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7937 pic16_emitcode("movwf","%s",
7938 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7939 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7940 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7943 pic16_emitcode("movlw","0x%x",t);
7944 pic16_emitcode("andwf","%s,w",
7945 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7946 pic16_emitcode("movwf","%s",
7947 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7950 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7951 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7956 if (AOP_TYPE(left) == AOP_ACC) {
7957 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7958 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7960 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7961 pic16_emitcode("andwf","%s,w",
7962 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7963 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7964 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7966 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7967 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7973 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7974 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7975 pic16_freeAsmop(result,NULL,ic,TRUE);
7978 /*-----------------------------------------------------------------*/
7979 /* genOr - code for or */
7980 /*-----------------------------------------------------------------*/
7981 static void genOr (iCode *ic, iCode *ifx)
7983 operand *left, *right, *result;
7985 unsigned long lit = 0L;
7987 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7989 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7990 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7991 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7993 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7995 /* if left is a literal & right is not then exchange them */
7996 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7997 AOP_NEEDSACC(left)) {
7998 operand *tmp = right ;
8003 /* if result = right then exchange them */
8004 if(pic16_sameRegs(AOP(result),AOP(right))){
8005 operand *tmp = right ;
8010 /* if right is bit then exchange them */
8011 if (AOP_TYPE(right) == AOP_CRY &&
8012 AOP_TYPE(left) != AOP_CRY){
8013 operand *tmp = right ;
8018 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8020 if(AOP_TYPE(right) == AOP_LIT)
8021 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8023 size = AOP_SIZE(result);
8027 if (AOP_TYPE(left) == AOP_CRY){
8028 if(AOP_TYPE(right) == AOP_LIT){
8029 // c = bit & literal;
8031 // lit != 0 => result = 1
8032 if(AOP_TYPE(result) == AOP_CRY){
8034 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8035 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8036 // AOP(result)->aopu.aop_dir,
8037 // AOP(result)->aopu.aop_dir);
8039 continueIfTrue(ifx);
8043 // lit == 0 => result = left
8044 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8046 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8049 if (AOP_TYPE(right) == AOP_CRY){
8050 if(pic16_sameRegs(AOP(result),AOP(left))){
8052 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8053 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8054 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8056 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8057 AOP(result)->aopu.aop_dir,
8058 AOP(result)->aopu.aop_dir);
8059 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8060 AOP(right)->aopu.aop_dir,
8061 AOP(right)->aopu.aop_dir);
8062 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8063 AOP(result)->aopu.aop_dir,
8064 AOP(result)->aopu.aop_dir);
8066 if( AOP_TYPE(result) == AOP_ACC) {
8067 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8068 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8069 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8074 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8075 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8076 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8077 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8079 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8080 AOP(result)->aopu.aop_dir,
8081 AOP(result)->aopu.aop_dir);
8082 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8083 AOP(right)->aopu.aop_dir,
8084 AOP(right)->aopu.aop_dir);
8085 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8086 AOP(left)->aopu.aop_dir,
8087 AOP(left)->aopu.aop_dir);
8088 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8089 AOP(result)->aopu.aop_dir,
8090 AOP(result)->aopu.aop_dir);
8095 symbol *tlbl = newiTempLabel(NULL);
8096 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8099 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8100 if( AOP_TYPE(right) == AOP_ACC) {
8101 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8103 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8104 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8109 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8110 pic16_emitcode(";XXX setb","c");
8111 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8112 AOP(left)->aopu.aop_dir,tlbl->key+100);
8113 pic16_toBoolean(right);
8114 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8115 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8116 jmpTrueOrFalse(ifx, tlbl);
8120 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8127 pic16_outBitC(result);
8129 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8130 genIfxJump(ifx, "c");
8134 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8135 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8136 if((AOP_TYPE(right) == AOP_LIT) &&
8137 (AOP_TYPE(result) == AOP_CRY) &&
8138 (AOP_TYPE(left) != AOP_CRY)){
8140 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8143 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8145 continueIfTrue(ifx);
8148 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8149 // lit = 0, result = boolean(left)
8151 pic16_emitcode(";XXX setb","c");
8152 pic16_toBoolean(right);
8154 symbol *tlbl = newiTempLabel(NULL);
8155 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8157 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8159 genIfxJump (ifx,"a");
8163 pic16_outBitC(result);
8167 /* if left is same as result */
8168 if(pic16_sameRegs(AOP(result),AOP(left))){
8170 for(;size--; offset++,lit>>=8) {
8171 if(AOP_TYPE(right) == AOP_LIT){
8172 if((lit & 0xff) == 0)
8173 /* or'ing with 0 has no effect */
8176 int p = pic16_my_powof2(lit & 0xff);
8178 /* only one bit is set in the literal, so use a bsf instruction */
8179 pic16_emitpcode(POC_BSF,
8180 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8182 if(know_W != (lit & 0xff))
8183 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8184 know_W = lit & 0xff;
8185 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8190 if (AOP_TYPE(left) == AOP_ACC) {
8191 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8192 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8194 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8195 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8197 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8198 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8204 // left & result in different registers
8205 if(AOP_TYPE(result) == AOP_CRY){
8207 // if(size), result in bit
8208 // if(!size && ifx), conditional oper: if(left | right)
8209 symbol *tlbl = newiTempLabel(NULL);
8210 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8211 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8215 pic16_emitcode(";XXX setb","c");
8217 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8218 pic16_emitcode(";XXX orl","a,%s",
8219 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8220 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8225 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8226 pic16_outBitC(result);
8228 jmpTrueOrFalse(ifx, tlbl);
8229 } else for(;(size--);offset++){
8231 // result = left & right
8232 if(AOP_TYPE(right) == AOP_LIT){
8233 int t = (lit >> (offset*8)) & 0x0FFL;
8236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8239 pic16_emitcode("movf","%s,w",
8240 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8241 pic16_emitcode("movwf","%s",
8242 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8245 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8246 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8249 pic16_emitcode("movlw","0x%x",t);
8250 pic16_emitcode("iorwf","%s,w",
8251 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8252 pic16_emitcode("movwf","%s",
8253 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8259 // faster than result <- left, anl result,right
8260 // and better if result is SFR
8261 if (AOP_TYPE(left) == AOP_ACC) {
8262 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8263 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8265 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8266 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8268 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8269 pic16_emitcode("iorwf","%s,w",
8270 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8272 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8273 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8278 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8279 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8280 pic16_freeAsmop(result,NULL,ic,TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genXor - code for xclusive or */
8285 /*-----------------------------------------------------------------*/
8286 static void genXor (iCode *ic, iCode *ifx)
8288 operand *left, *right, *result;
8290 unsigned long lit = 0L;
8292 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8294 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8295 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8296 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8298 /* if left is a literal & right is not ||
8299 if left needs acc & right does not */
8300 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8301 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8302 operand *tmp = right ;
8307 /* if result = right then exchange them */
8308 if(pic16_sameRegs(AOP(result),AOP(right))){
8309 operand *tmp = right ;
8314 /* if right is bit then exchange them */
8315 if (AOP_TYPE(right) == AOP_CRY &&
8316 AOP_TYPE(left) != AOP_CRY){
8317 operand *tmp = right ;
8321 if(AOP_TYPE(right) == AOP_LIT)
8322 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8324 size = AOP_SIZE(result);
8328 if (AOP_TYPE(left) == AOP_CRY){
8329 if(AOP_TYPE(right) == AOP_LIT){
8330 // c = bit & literal;
8332 // lit>>1 != 0 => result = 1
8333 if(AOP_TYPE(result) == AOP_CRY){
8335 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8336 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8338 continueIfTrue(ifx);
8341 pic16_emitcode("setb","c");
8345 // lit == 0, result = left
8346 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8348 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8350 // lit == 1, result = not(left)
8351 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8352 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8353 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8354 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8357 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8358 pic16_emitcode("cpl","c");
8365 symbol *tlbl = newiTempLabel(NULL);
8366 if (AOP_TYPE(right) == AOP_CRY){
8368 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8371 int sizer = AOP_SIZE(right);
8373 // if val>>1 != 0, result = 1
8374 pic16_emitcode("setb","c");
8376 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8378 // test the msb of the lsb
8379 pic16_emitcode("anl","a,#0xfe");
8380 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8384 pic16_emitcode("rrc","a");
8386 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8387 pic16_emitcode("cpl","c");
8388 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8393 pic16_outBitC(result);
8395 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8396 genIfxJump(ifx, "c");
8400 if(pic16_sameRegs(AOP(result),AOP(left))){
8401 /* if left is same as result */
8402 for(;size--; offset++) {
8403 if(AOP_TYPE(right) == AOP_LIT){
8404 int t = (lit >> (offset*8)) & 0x0FFL;
8408 if (IS_AOP_PREG(left)) {
8409 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8410 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8411 pic16_aopPut(AOP(result),"a",offset);
8413 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8414 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8415 pic16_emitcode("xrl","%s,%s",
8416 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8417 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8420 if (AOP_TYPE(left) == AOP_ACC)
8421 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8423 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8424 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8426 if (IS_AOP_PREG(left)) {
8427 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8428 pic16_aopPut(AOP(result),"a",offset);
8430 pic16_emitcode("xrl","%s,a",
8431 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8437 // left & result in different registers
8438 if(AOP_TYPE(result) == AOP_CRY){
8440 // if(size), result in bit
8441 // if(!size && ifx), conditional oper: if(left ^ right)
8442 symbol *tlbl = newiTempLabel(NULL);
8443 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8445 pic16_emitcode("setb","c");
8447 if((AOP_TYPE(right) == AOP_LIT) &&
8448 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8449 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8451 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8452 pic16_emitcode("xrl","a,%s",
8453 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8455 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8460 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8461 pic16_outBitC(result);
8463 jmpTrueOrFalse(ifx, tlbl);
8464 } else for(;(size--);offset++){
8466 // result = left & right
8467 if(AOP_TYPE(right) == AOP_LIT){
8468 int t = (lit >> (offset*8)) & 0x0FFL;
8471 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8472 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8473 pic16_emitcode("movf","%s,w",
8474 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8475 pic16_emitcode("movwf","%s",
8476 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8479 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8480 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8481 pic16_emitcode("comf","%s,w",
8482 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8483 pic16_emitcode("movwf","%s",
8484 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8487 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8488 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8489 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8490 pic16_emitcode("movlw","0x%x",t);
8491 pic16_emitcode("xorwf","%s,w",
8492 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8493 pic16_emitcode("movwf","%s",
8494 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8500 // faster than result <- left, anl result,right
8501 // and better if result is SFR
8502 if (AOP_TYPE(left) == AOP_ACC) {
8503 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8504 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8506 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8507 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8508 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8509 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8511 if ( AOP_TYPE(result) != AOP_ACC){
8512 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8513 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8519 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8520 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8521 pic16_freeAsmop(result,NULL,ic,TRUE);
8524 /*-----------------------------------------------------------------*/
8525 /* genInline - write the inline code out */
8526 /*-----------------------------------------------------------------*/
8527 static void genInline (iCode *ic)
8529 char *buffer, *bp, *bp1;
8531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8533 _G.inLine += (!options.asmpeep);
8535 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8536 strcpy(buffer,IC_INLINE(ic));
8538 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8540 /* emit each line as a code */
8546 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8554 /* print label, use this special format with NULL directive
8555 * to denote that the argument should not be indented with tab */
8556 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8563 if ((bp1 != bp) && *bp1)
8564 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8569 _G.inLine -= (!options.asmpeep);
8572 /*-----------------------------------------------------------------*/
8573 /* genRRC - rotate right with carry */
8574 /*-----------------------------------------------------------------*/
8575 static void genRRC (iCode *ic)
8577 operand *left , *result ;
8578 int size, offset = 0, same;
8580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8582 /* rotate right with carry */
8584 result=IC_RESULT(ic);
8585 pic16_aopOp (left,ic,FALSE);
8586 pic16_aopOp (result,ic,FALSE);
8588 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8590 same = pic16_sameRegs(AOP(result),AOP(left));
8592 size = AOP_SIZE(result);
8594 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8596 /* get the lsb and put it into the carry */
8597 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8604 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8606 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8607 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8613 pic16_freeAsmop(left,NULL,ic,TRUE);
8614 pic16_freeAsmop(result,NULL,ic,TRUE);
8617 /*-----------------------------------------------------------------*/
8618 /* genRLC - generate code for rotate left with carry */
8619 /*-----------------------------------------------------------------*/
8620 static void genRLC (iCode *ic)
8622 operand *left , *result ;
8623 int size, offset = 0;
8626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8627 /* rotate right with carry */
8629 result=IC_RESULT(ic);
8630 pic16_aopOp (left,ic,FALSE);
8631 pic16_aopOp (result,ic,FALSE);
8633 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8635 same = pic16_sameRegs(AOP(result),AOP(left));
8637 /* move it to the result */
8638 size = AOP_SIZE(result);
8640 /* get the msb and put it into the carry */
8641 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8648 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8650 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8651 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8658 pic16_freeAsmop(left,NULL,ic,TRUE);
8659 pic16_freeAsmop(result,NULL,ic,TRUE);
8663 /* gpasm can get the highest order bit with HIGH/UPPER
8664 * so the following probably is not needed -- VR */
8666 /*-----------------------------------------------------------------*/
8667 /* genGetHbit - generates code get highest order bit */
8668 /*-----------------------------------------------------------------*/
8669 static void genGetHbit (iCode *ic)
8671 operand *left, *result;
8673 result=IC_RESULT(ic);
8674 pic16_aopOp (left,ic,FALSE);
8675 pic16_aopOp (result,ic,FALSE);
8677 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8678 /* get the highest order byte into a */
8679 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8680 if(AOP_TYPE(result) == AOP_CRY){
8681 pic16_emitcode("rlc","a");
8682 pic16_outBitC(result);
8685 pic16_emitcode("rl","a");
8686 pic16_emitcode("anl","a,#0x01");
8687 pic16_outAcc(result);
8691 pic16_freeAsmop(left,NULL,ic,TRUE);
8692 pic16_freeAsmop(result,NULL,ic,TRUE);
8696 /*-----------------------------------------------------------------*/
8697 /* AccRol - rotate left accumulator by known count */
8698 /*-----------------------------------------------------------------*/
8699 static void AccRol (int shCount)
8701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8702 shCount &= 0x0007; // shCount : 0..7
8707 pic16_emitcode("rl","a");
8710 pic16_emitcode("rl","a");
8711 pic16_emitcode("rl","a");
8714 pic16_emitcode("swap","a");
8715 pic16_emitcode("rr","a");
8718 pic16_emitcode("swap","a");
8721 pic16_emitcode("swap","a");
8722 pic16_emitcode("rl","a");
8725 pic16_emitcode("rr","a");
8726 pic16_emitcode("rr","a");
8729 pic16_emitcode("rr","a");
8735 /*-----------------------------------------------------------------*/
8736 /* AccLsh - left shift accumulator by known count */
8737 /*-----------------------------------------------------------------*/
8738 static void AccLsh (int shCount)
8740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8746 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8749 pic16_emitpcode(POC_RLNCFW,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));
8754 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8757 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8760 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8761 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8764 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8765 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8768 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8772 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8775 /*-----------------------------------------------------------------*/
8776 /* AccRsh - right shift accumulator by known count */
8777 /*-----------------------------------------------------------------*/
8778 static void AccRsh (int shCount, int andmask)
8780 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8785 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8788 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8792 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8793 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8796 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8799 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8800 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8803 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8804 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8807 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8814 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8818 /*-----------------------------------------------------------------*/
8819 /* AccSRsh - signed right shift accumulator by known count */
8820 /*-----------------------------------------------------------------*/
8821 static void AccSRsh (int shCount)
8824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8827 pic16_emitcode("mov","c,acc.7");
8828 pic16_emitcode("rrc","a");
8829 } else if(shCount == 2){
8830 pic16_emitcode("mov","c,acc.7");
8831 pic16_emitcode("rrc","a");
8832 pic16_emitcode("mov","c,acc.7");
8833 pic16_emitcode("rrc","a");
8835 tlbl = newiTempLabel(NULL);
8836 /* rotate right accumulator */
8837 AccRol(8 - shCount);
8838 /* and kill the higher order bits */
8839 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8840 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8841 pic16_emitcode("orl","a,#0x%02x",
8842 (unsigned char)~SRMask[shCount]);
8843 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8849 /*-----------------------------------------------------------------*/
8850 /* shiftR1Left2Result - shift right one byte from left to result */
8851 /*-----------------------------------------------------------------*/
8852 static void shiftR1Left2ResultSigned (operand *left, int offl,
8853 operand *result, int offr,
8858 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8860 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8864 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8866 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8869 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8877 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8880 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8883 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8889 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8892 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8895 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8896 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8899 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8900 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8907 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8908 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8909 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8910 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8914 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8916 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8920 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8921 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8922 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8928 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8929 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8930 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8931 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8932 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8936 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8937 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8939 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8945 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8946 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8952 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8960 /*-----------------------------------------------------------------*/
8961 /* shiftR1Left2Result - shift right one byte from left to result */
8962 /*-----------------------------------------------------------------*/
8963 static void shiftR1Left2Result (operand *left, int offl,
8964 operand *result, int offr,
8965 int shCount, int sign)
8969 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8971 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8973 /* Copy the msb into the carry if signed. */
8975 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8985 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8987 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8988 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9005 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9011 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9012 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9013 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9014 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9019 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9025 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9034 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9035 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9036 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9043 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9053 /*-----------------------------------------------------------------*/
9054 /* shiftL1Left2Result - shift left one byte from left to result */
9055 /*-----------------------------------------------------------------*/
9056 static void shiftL1Left2Result (operand *left, int offl,
9057 operand *result, int offr, int shCount)
9062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9064 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9065 DEBUGpic16_emitcode ("; ***","same = %d",same);
9066 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9068 /* shift left accumulator */
9069 //AccLsh(shCount); // don't comment out just yet...
9070 // pic16_aopPut(AOP(result),"a",offr);
9074 /* Shift left 1 bit position */
9075 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9077 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9079 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9080 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9084 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9085 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9086 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9087 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9090 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9091 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9092 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9098 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9099 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9102 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9103 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9104 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9108 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9109 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9110 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9116 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9117 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9121 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9126 /*-----------------------------------------------------------------*/
9127 /* movLeft2Result - move byte from left to result */
9128 /*-----------------------------------------------------------------*/
9129 static void movLeft2Result (operand *left, int offl,
9130 operand *result, int offr)
9133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9134 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9135 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9137 if (*l == '@' && (IS_AOP_PREG(result))) {
9138 pic16_emitcode("mov","a,%s",l);
9139 pic16_aopPut(AOP(result),"a",offr);
9141 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9142 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9147 /*-----------------------------------------------------------------*/
9148 /* shiftL2Left2Result - shift left two bytes from left to result */
9149 /*-----------------------------------------------------------------*/
9150 static void shiftL2Left2Result (operand *left, int offl,
9151 operand *result, int offr, int shCount)
9153 int same = pic16_sameRegs(AOP(result), AOP(left));
9156 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9158 if (same && (offl != offr)) { // shift bytes
9161 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9164 } else { // just treat as different later on
9177 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9178 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9179 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9183 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9184 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9190 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9191 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9192 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9193 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9194 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9195 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9196 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9198 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9199 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9203 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9204 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9205 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9206 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9207 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9208 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9209 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9210 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9211 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9212 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9215 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9216 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9217 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9218 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9219 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9229 /* note, use a mov/add for the shift since the mov has a
9230 chance of getting optimized out */
9231 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9232 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9233 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9234 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9235 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9239 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9240 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9246 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9247 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9248 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9249 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9250 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9251 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9252 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9253 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9257 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9258 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9262 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9263 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9264 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9267 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9268 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9269 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9270 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9271 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9272 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9273 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9274 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9277 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9278 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9279 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9280 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9281 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9286 /*-----------------------------------------------------------------*/
9287 /* shiftR2Left2Result - shift right two bytes from left to result */
9288 /*-----------------------------------------------------------------*/
9289 static void shiftR2Left2Result (operand *left, int offl,
9290 operand *result, int offr,
9291 int shCount, int sign)
9293 int same = pic16_sameRegs(AOP(result), AOP(left));
9295 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9297 if (same && (offl != offr)) { // shift right bytes
9300 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9303 } else { // just treat as different later on
9315 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9320 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9321 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9323 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9324 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9325 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9326 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9331 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9334 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9335 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9342 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9343 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9344 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9346 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9347 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9348 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9349 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9351 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9352 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9353 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9355 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9357 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9358 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9359 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9363 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9364 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9368 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9369 pic16_emitpcode(POC_BTFSC,
9370 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9371 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9379 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9380 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9382 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9383 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9384 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9385 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9387 pic16_emitpcode(POC_BTFSC,
9388 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9389 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9391 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9392 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9393 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9394 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9396 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9397 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9398 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9399 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9400 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9401 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9402 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9403 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9405 pic16_emitpcode(POC_BTFSC,
9406 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9407 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9409 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9410 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9417 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9418 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9419 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9420 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9425 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9430 /*-----------------------------------------------------------------*/
9431 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9432 /*-----------------------------------------------------------------*/
9433 static void shiftLLeftOrResult (operand *left, int offl,
9434 operand *result, int offr, int shCount)
9436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9438 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9439 /* shift left accumulator */
9441 /* or with result */
9442 /* back to result */
9443 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9446 /*-----------------------------------------------------------------*/
9447 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9448 /*-----------------------------------------------------------------*/
9449 static void shiftRLeftOrResult (operand *left, int offl,
9450 operand *result, int offr, int shCount)
9452 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9454 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9455 /* shift right accumulator */
9457 /* or with result */
9458 /* back to result */
9459 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9462 /*-----------------------------------------------------------------*/
9463 /* genlshOne - left shift a one byte quantity by known count */
9464 /*-----------------------------------------------------------------*/
9465 static void genlshOne (operand *result, operand *left, int shCount)
9467 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9468 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9471 /*-----------------------------------------------------------------*/
9472 /* genlshTwo - left shift two bytes by known amount != 0 */
9473 /*-----------------------------------------------------------------*/
9474 static void genlshTwo (operand *result,operand *left, int shCount)
9478 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9479 size = pic16_getDataSize(result);
9481 /* if shCount >= 8 */
9487 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9489 movLeft2Result(left, LSB, result, MSB16);
9491 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9494 /* 1 <= shCount <= 7 */
9497 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9499 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9503 /*-----------------------------------------------------------------*/
9504 /* shiftLLong - shift left one long from left to result */
9505 /* offr = LSB or MSB16 */
9506 /*-----------------------------------------------------------------*/
9507 static void shiftLLong (operand *left, operand *result, int offr )
9509 int size = AOP_SIZE(result);
9510 int same = pic16_sameRegs(AOP(left),AOP(result));
9513 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9515 if (same && (offr == MSB16)) { //shift one byte
9516 for(i=size-1;i>=MSB16;i--) {
9517 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9518 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9521 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9524 if (size > LSB+offr ){
9526 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9528 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9529 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9533 if(size > MSB16+offr){
9535 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9537 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9538 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9542 if(size > MSB24+offr){
9544 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9546 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9547 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9551 if(size > MSB32+offr){
9553 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9555 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9556 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9560 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9564 /*-----------------------------------------------------------------*/
9565 /* genlshFour - shift four byte by a known amount != 0 */
9566 /*-----------------------------------------------------------------*/
9567 static void genlshFour (operand *result, operand *left, int shCount)
9571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9572 size = AOP_SIZE(result);
9574 /* if shifting more that 3 bytes */
9575 if (shCount >= 24 ) {
9578 /* lowest order of left goes to the highest
9579 order of the destination */
9580 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9582 movLeft2Result(left, LSB, result, MSB32);
9584 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9585 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9586 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9591 /* more than two bytes */
9592 else if ( shCount >= 16 ) {
9593 /* lower order two bytes goes to higher order two bytes */
9595 /* if some more remaining */
9597 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9599 movLeft2Result(left, MSB16, result, MSB32);
9600 movLeft2Result(left, LSB, result, MSB24);
9602 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9603 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9607 /* if more than 1 byte */
9608 else if ( shCount >= 8 ) {
9609 /* lower order three bytes goes to higher order three bytes */
9613 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9615 movLeft2Result(left, LSB, result, MSB16);
9617 else{ /* size = 4 */
9619 movLeft2Result(left, MSB24, result, MSB32);
9620 movLeft2Result(left, MSB16, result, MSB24);
9621 movLeft2Result(left, LSB, result, MSB16);
9622 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9624 else if(shCount == 1)
9625 shiftLLong(left, result, MSB16);
9627 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9628 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9629 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9630 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9635 /* 1 <= shCount <= 7 */
9636 else if(shCount <= 3)
9638 shiftLLong(left, result, LSB);
9639 while(--shCount >= 1)
9640 shiftLLong(result, result, LSB);
9642 /* 3 <= shCount <= 7, optimize */
9644 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9645 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9646 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9650 /*-----------------------------------------------------------------*/
9651 /* genLeftShiftLiteral - left shifting by known count */
9652 /*-----------------------------------------------------------------*/
9653 void pic16_genLeftShiftLiteral (operand *left,
9658 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9662 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9663 pic16_freeAsmop(right,NULL,ic,TRUE);
9665 pic16_aopOp(left,ic,FALSE);
9666 pic16_aopOp(result,ic,FALSE);
9668 size = getSize(operandType(result));
9671 pic16_emitcode("; shift left ","result %d, left %d",size,
9675 /* I suppose that the left size >= result size */
9678 movLeft2Result(left, size, result, size);
9682 else if(shCount >= (size * 8))
9684 pic16_aopPut(AOP(result),zero,size);
9688 genlshOne (result,left,shCount);
9693 genlshTwo (result,left,shCount);
9697 genlshFour (result,left,shCount);
9701 pic16_freeAsmop(left,NULL,ic,TRUE);
9702 pic16_freeAsmop(result,NULL,ic,TRUE);
9705 /*-----------------------------------------------------------------*
9706 * genMultiAsm - repeat assembly instruction for size of register.
9707 * if endian == 1, then the high byte (i.e base address + size of
9708 * register) is used first else the low byte is used first;
9709 *-----------------------------------------------------------------*/
9710 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9715 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9728 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9734 #if !(USE_GENERIC_SIGNED_SHIFT)
9735 /*-----------------------------------------------------------------*/
9736 /* genLeftShift - generates code for left shifting */
9737 /*-----------------------------------------------------------------*/
9738 static void genLeftShift (iCode *ic)
9740 operand *left,*right, *result;
9743 symbol *tlbl , *tlbl1;
9746 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9748 right = IC_RIGHT(ic);
9750 result = IC_RESULT(ic);
9752 pic16_aopOp(right,ic,FALSE);
9754 /* if the shift count is known then do it
9755 as efficiently as possible */
9756 if (AOP_TYPE(right) == AOP_LIT) {
9757 pic16_genLeftShiftLiteral (left,right,result,ic);
9761 /* shift count is unknown then we have to form
9762 * a loop. Get the loop count in WREG : Note: we take
9763 * only the lower order byte since shifting
9764 * more than 32 bits make no sense anyway, ( the
9765 * largest size of an object can be only 32 bits ) */
9767 pic16_aopOp(left,ic,FALSE);
9768 pic16_aopOp(result,ic,FALSE);
9770 /* now move the left to the result if they are not the
9771 * same, and if size > 1,
9772 * and if right is not same to result (!!!) -- VR */
9773 if (!pic16_sameRegs(AOP(left),AOP(result))
9774 && (AOP_SIZE(result) > 1)) {
9776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9778 size = AOP_SIZE(result);
9783 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9784 if (*l == '@' && (IS_AOP_PREG(result))) {
9786 pic16_emitcode("mov","a,%s",l);
9787 pic16_aopPut(AOP(result),"a",offset);
9791 /* we don't know if left is a literal or a register, take care -- VR */
9792 mov2f(AOP(result), AOP(left), offset);
9798 size = AOP_SIZE(result);
9800 /* if it is only one byte then */
9802 if(optimized_for_speed) {
9803 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9804 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9805 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9806 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9807 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9808 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9809 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9810 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9811 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9812 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9813 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9814 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9819 tlbl = newiTempLabel(NULL);
9822 /* this is already done, why change it? */
9823 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9824 mov2f(AOP(result), AOP(left), 0);
9828 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9829 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9830 pic16_emitpLabel(tlbl->key);
9831 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9832 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9834 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9839 if (pic16_sameRegs(AOP(left),AOP(result))) {
9841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9843 tlbl = newiTempLabel(NULL);
9844 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9845 genMultiAsm(POC_RRCF, result, size,1);
9846 pic16_emitpLabel(tlbl->key);
9847 genMultiAsm(POC_RLCF, result, size,0);
9848 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9850 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9854 //tlbl = newiTempLabel(NULL);
9856 //tlbl1 = newiTempLabel(NULL);
9858 //reAdjustPreg(AOP(result));
9860 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9861 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9862 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9864 //pic16_emitcode("add","a,acc");
9865 //pic16_aopPut(AOP(result),"a",offset++);
9867 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9869 // pic16_emitcode("rlc","a");
9870 // pic16_aopPut(AOP(result),"a",offset++);
9872 //reAdjustPreg(AOP(result));
9874 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9875 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9878 tlbl = newiTempLabel(NULL);
9879 tlbl1= newiTempLabel(NULL);
9881 size = AOP_SIZE(result);
9884 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9886 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9888 /* offset should be 0, 1 or 3 */
9890 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9892 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9894 pic16_emitpcode(POC_MOVWF, pctemp);
9897 pic16_emitpLabel(tlbl->key);
9900 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9902 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9904 pic16_emitpcode(POC_DECFSZ, pctemp);
9905 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9906 pic16_emitpLabel(tlbl1->key);
9908 pic16_popReleaseTempReg(pctemp,1);
9912 pic16_freeAsmop (right,NULL,ic,TRUE);
9913 pic16_freeAsmop(left,NULL,ic,TRUE);
9914 pic16_freeAsmop(result,NULL,ic,TRUE);
9920 #error old code (left here for reference)
9921 /*-----------------------------------------------------------------*/
9922 /* genLeftShift - generates code for left shifting */
9923 /*-----------------------------------------------------------------*/
9924 static void genLeftShift (iCode *ic)
9926 operand *left,*right, *result;
9929 symbol *tlbl , *tlbl1;
9932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9934 right = IC_RIGHT(ic);
9936 result = IC_RESULT(ic);
9938 pic16_aopOp(right,ic,FALSE);
9940 /* if the shift count is known then do it
9941 as efficiently as possible */
9942 if (AOP_TYPE(right) == AOP_LIT) {
9943 pic16_genLeftShiftLiteral (left,right,result,ic);
9947 /* shift count is unknown then we have to form
9948 a loop get the loop count in B : Note: we take
9949 only the lower order byte since shifting
9950 more that 32 bits make no sense anyway, ( the
9951 largest size of an object can be only 32 bits ) */
9954 pic16_aopOp(left,ic,FALSE);
9955 pic16_aopOp(result,ic,FALSE);
9957 /* now move the left to the result if they are not the
9959 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9960 AOP_SIZE(result) > 1) {
9962 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9964 size = AOP_SIZE(result);
9967 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9968 if (*l == '@' && (IS_AOP_PREG(result))) {
9970 pic16_emitcode("mov","a,%s",l);
9971 pic16_aopPut(AOP(result),"a",offset);
9974 /* we don't know if left is a literal or a register, take care -- VR */
9975 mov2f(AOP(result), AOP(left), offset);
9981 size = AOP_SIZE(result);
9983 /* if it is only one byte then */
9985 if(optimized_for_speed) {
9986 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9987 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9988 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9989 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9990 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9991 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9992 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9993 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9994 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9995 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9996 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9997 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10002 tlbl = newiTempLabel(NULL);
10003 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10004 mov2f(AOP(result), AOP(left), 0);
10006 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10007 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10010 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10011 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10012 pic16_emitpLabel(tlbl->key);
10013 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10014 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10021 if (pic16_sameRegs(AOP(left),AOP(result))) {
10023 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10025 tlbl = newiTempLabel(NULL);
10026 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10027 genMultiAsm(POC_RRCF, result, size,1);
10028 pic16_emitpLabel(tlbl->key);
10029 genMultiAsm(POC_RLCF, result, size,0);
10030 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10032 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10036 //tlbl = newiTempLabel(NULL);
10038 //tlbl1 = newiTempLabel(NULL);
10040 //reAdjustPreg(AOP(result));
10042 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10043 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10044 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10046 //pic16_emitcode("add","a,acc");
10047 //pic16_aopPut(AOP(result),"a",offset++);
10049 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10051 // pic16_emitcode("rlc","a");
10052 // pic16_aopPut(AOP(result),"a",offset++);
10054 //reAdjustPreg(AOP(result));
10056 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10057 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10060 tlbl = newiTempLabel(NULL);
10061 tlbl1= newiTempLabel(NULL);
10063 size = AOP_SIZE(result);
10066 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10068 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10070 /* offset should be 0, 1 or 3 */
10072 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10074 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10076 pic16_emitpcode(POC_MOVWF, pctemp);
10079 pic16_emitpLabel(tlbl->key);
10082 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10084 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10086 pic16_emitpcode(POC_DECFSZ, pctemp);
10087 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10088 pic16_emitpLabel(tlbl1->key);
10090 pic16_popReleaseTempReg(pctemp,1);
10094 pic16_freeAsmop (right,NULL,ic,TRUE);
10095 pic16_freeAsmop(left,NULL,ic,TRUE);
10096 pic16_freeAsmop(result,NULL,ic,TRUE);
10100 /*-----------------------------------------------------------------*/
10101 /* genrshOne - right shift a one byte quantity by known count */
10102 /*-----------------------------------------------------------------*/
10103 static void genrshOne (operand *result, operand *left,
10104 int shCount, int sign)
10106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10107 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10110 /*-----------------------------------------------------------------*/
10111 /* genrshTwo - right shift two bytes by known amount != 0 */
10112 /*-----------------------------------------------------------------*/
10113 static void genrshTwo (operand *result,operand *left,
10114 int shCount, int sign)
10116 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10117 /* if shCount >= 8 */
10118 if (shCount >= 8) {
10121 shiftR1Left2Result(left, MSB16, result, LSB,
10124 movLeft2Result(left, MSB16, result, LSB);
10126 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10129 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10130 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10134 /* 1 <= shCount <= 7 */
10136 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10139 /*-----------------------------------------------------------------*/
10140 /* shiftRLong - shift right one long from left to result */
10141 /* offl = LSB or MSB16 */
10142 /*-----------------------------------------------------------------*/
10143 static void shiftRLong (operand *left, int offl,
10144 operand *result, int sign)
10146 int size = AOP_SIZE(result);
10147 int same = pic16_sameRegs(AOP(left),AOP(result));
10149 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10151 if (same && (offl == MSB16)) { //shift one byte right
10152 for(i=MSB16;i<size;i++) {
10153 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10159 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10165 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10167 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10168 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10171 if(offl == MSB16) {
10172 /* add sign of "a" */
10173 pic16_addSign(result, MSB32, sign);
10177 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10179 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10180 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10184 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10186 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10191 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10194 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10195 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10200 /*-----------------------------------------------------------------*/
10201 /* genrshFour - shift four byte by a known amount != 0 */
10202 /*-----------------------------------------------------------------*/
10203 static void genrshFour (operand *result, operand *left,
10204 int shCount, int sign)
10206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10207 /* if shifting more that 3 bytes */
10208 if(shCount >= 24 ) {
10211 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10213 movLeft2Result(left, MSB32, result, LSB);
10215 pic16_addSign(result, MSB16, sign);
10217 else if(shCount >= 16){
10220 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10222 movLeft2Result(left, MSB24, result, LSB);
10223 movLeft2Result(left, MSB32, result, MSB16);
10225 pic16_addSign(result, MSB24, sign);
10227 else if(shCount >= 8){
10230 shiftRLong(left, MSB16, result, sign);
10231 else if(shCount == 0){
10232 movLeft2Result(left, MSB16, result, LSB);
10233 movLeft2Result(left, MSB24, result, MSB16);
10234 movLeft2Result(left, MSB32, result, MSB24);
10235 pic16_addSign(result, MSB32, sign);
10237 else{ //shcount >= 2
10238 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10239 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10240 /* the last shift is signed */
10241 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10242 pic16_addSign(result, MSB32, sign);
10245 else{ /* 1 <= shCount <= 7 */
10247 shiftRLong(left, LSB, result, sign);
10249 shiftRLong(result, LSB, result, sign);
10252 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10253 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10254 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10259 /*-----------------------------------------------------------------*/
10260 /* genRightShiftLiteral - right shifting by known count */
10261 /*-----------------------------------------------------------------*/
10262 static void genRightShiftLiteral (operand *left,
10268 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10269 int lsize,res_size;
10271 pic16_freeAsmop(right,NULL,ic,TRUE);
10273 pic16_aopOp(left,ic,FALSE);
10274 pic16_aopOp(result,ic,FALSE);
10276 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10279 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10283 lsize = pic16_getDataSize(left);
10284 res_size = pic16_getDataSize(result);
10285 /* test the LEFT size !!! */
10287 /* I suppose that the left size >= result size */
10290 movLeft2Result(left, lsize, result, res_size);
10293 else if(shCount >= (lsize * 8)){
10295 if(res_size == 1) {
10296 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10298 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10299 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10304 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10305 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10306 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10308 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10313 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10318 switch (res_size) {
10320 genrshOne (result,left,shCount,sign);
10324 genrshTwo (result,left,shCount,sign);
10328 genrshFour (result,left,shCount,sign);
10336 pic16_freeAsmop(left,NULL,ic,TRUE);
10337 pic16_freeAsmop(result,NULL,ic,TRUE);
10340 #if !(USE_GENERIC_SIGNED_SHIFT)
10341 /*-----------------------------------------------------------------*/
10342 /* genSignedRightShift - right shift of signed number */
10343 /*-----------------------------------------------------------------*/
10344 static void genSignedRightShift (iCode *ic)
10346 operand *right, *left, *result;
10349 symbol *tlbl, *tlbl1 ;
10352 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10354 /* we do it the hard way put the shift count in b
10355 and loop thru preserving the sign */
10356 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10358 right = IC_RIGHT(ic);
10359 left = IC_LEFT(ic);
10360 result = IC_RESULT(ic);
10362 pic16_aopOp(right,ic,FALSE);
10363 pic16_aopOp(left,ic,FALSE);
10364 pic16_aopOp(result,ic,FALSE);
10367 if ( AOP_TYPE(right) == AOP_LIT) {
10368 genRightShiftLiteral (left,right,result,ic,1);
10371 /* shift count is unknown then we have to form
10372 a loop get the loop count in B : Note: we take
10373 only the lower order byte since shifting
10374 more that 32 bits make no sense anyway, ( the
10375 largest size of an object can be only 32 bits ) */
10377 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10378 //pic16_emitcode("inc","b");
10379 //pic16_freeAsmop (right,NULL,ic,TRUE);
10380 //pic16_aopOp(left,ic,FALSE);
10381 //pic16_aopOp(result,ic,FALSE);
10383 /* now move the left to the result if they are not the
10385 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10386 AOP_SIZE(result) > 1) {
10388 size = AOP_SIZE(result);
10392 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10393 if (*l == '@' && IS_AOP_PREG(result)) {
10395 pic16_emitcode("mov","a,%s",l);
10396 pic16_aopPut(AOP(result),"a",offset);
10398 pic16_aopPut(AOP(result),l,offset);
10400 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10401 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10407 /* mov the highest order bit to OVR */
10408 tlbl = newiTempLabel(NULL);
10409 tlbl1= newiTempLabel(NULL);
10411 size = AOP_SIZE(result);
10414 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10416 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10418 /* offset should be 0, 1 or 3 */
10419 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10421 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10423 pic16_emitpcode(POC_MOVWF, pctemp);
10426 pic16_emitpLabel(tlbl->key);
10428 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10429 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10432 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10435 pic16_emitpcode(POC_DECFSZ, pctemp);
10436 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10437 pic16_emitpLabel(tlbl1->key);
10439 pic16_popReleaseTempReg(pctemp,1);
10441 size = AOP_SIZE(result);
10443 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10444 pic16_emitcode("rlc","a");
10445 pic16_emitcode("mov","ov,c");
10446 /* if it is only one byte then */
10448 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10450 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10451 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10452 pic16_emitcode("mov","c,ov");
10453 pic16_emitcode("rrc","a");
10454 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10455 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10456 pic16_aopPut(AOP(result),"a",0);
10460 reAdjustPreg(AOP(result));
10461 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10462 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10463 pic16_emitcode("mov","c,ov");
10465 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10467 pic16_emitcode("rrc","a");
10468 pic16_aopPut(AOP(result),"a",offset--);
10470 reAdjustPreg(AOP(result));
10471 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10472 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10477 pic16_freeAsmop(left,NULL,ic,TRUE);
10478 pic16_freeAsmop(result,NULL,ic,TRUE);
10479 pic16_freeAsmop(right,NULL,ic,TRUE);
10483 #if !(USE_GENERIC_SIGNED_SHIFT)
10484 #warning This implementation of genRightShift() is incomplete!
10485 /*-----------------------------------------------------------------*/
10486 /* genRightShift - generate code for right shifting */
10487 /*-----------------------------------------------------------------*/
10488 static void genRightShift (iCode *ic)
10490 operand *right, *left, *result;
10494 symbol *tlbl, *tlbl1 ;
10496 /* if signed then we do it the hard way preserve the
10497 sign bit moving it inwards */
10498 letype = getSpec(operandType(IC_LEFT(ic)));
10499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10501 if (!SPEC_USIGN(letype)) {
10502 genSignedRightShift (ic);
10506 /* signed & unsigned types are treated the same : i.e. the
10507 signed is NOT propagated inwards : quoting from the
10508 ANSI - standard : "for E1 >> E2, is equivalent to division
10509 by 2**E2 if unsigned or if it has a non-negative value,
10510 otherwise the result is implementation defined ", MY definition
10511 is that the sign does not get propagated */
10513 right = IC_RIGHT(ic);
10514 left = IC_LEFT(ic);
10515 result = IC_RESULT(ic);
10517 pic16_aopOp(right,ic,FALSE);
10519 /* if the shift count is known then do it
10520 as efficiently as possible */
10521 if (AOP_TYPE(right) == AOP_LIT) {
10522 genRightShiftLiteral (left,right,result,ic, 0);
10526 /* shift count is unknown then we have to form
10527 a loop get the loop count in B : Note: we take
10528 only the lower order byte since shifting
10529 more that 32 bits make no sense anyway, ( the
10530 largest size of an object can be only 32 bits ) */
10532 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10533 pic16_emitcode("inc","b");
10534 pic16_aopOp(left,ic,FALSE);
10535 pic16_aopOp(result,ic,FALSE);
10537 /* now move the left to the result if they are not the
10539 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10540 AOP_SIZE(result) > 1) {
10542 size = AOP_SIZE(result);
10545 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10546 if (*l == '@' && IS_AOP_PREG(result)) {
10548 pic16_emitcode("mov","a,%s",l);
10549 pic16_aopPut(AOP(result),"a",offset);
10551 pic16_aopPut(AOP(result),l,offset);
10556 tlbl = newiTempLabel(NULL);
10557 tlbl1= newiTempLabel(NULL);
10558 size = AOP_SIZE(result);
10561 /* if it is only one byte then */
10564 tlbl = newiTempLabel(NULL);
10565 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10566 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10570 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10571 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10572 pic16_emitpLabel(tlbl->key);
10573 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10574 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10576 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10581 reAdjustPreg(AOP(result));
10582 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10583 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10586 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10588 pic16_emitcode("rrc","a");
10589 pic16_aopPut(AOP(result),"a",offset--);
10591 reAdjustPreg(AOP(result));
10593 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10594 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10597 pic16_freeAsmop(left,NULL,ic,TRUE);
10598 pic16_freeAsmop (right,NULL,ic,TRUE);
10599 pic16_freeAsmop(result,NULL,ic,TRUE);
10603 #if (USE_GENERIC_SIGNED_SHIFT)
10604 /*-----------------------------------------------------------------*/
10605 /* genGenericShift - generates code for left or right shifting */
10606 /*-----------------------------------------------------------------*/
10607 static void genGenericShift (iCode *ic, int isShiftLeft) {
10608 operand *left,*right, *result;
10610 int sign, signedCount;
10611 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10612 PIC_OPCODE pos_shift, neg_shift;
10616 right = IC_RIGHT(ic);
10617 left = IC_LEFT(ic);
10618 result = IC_RESULT(ic);
10620 pic16_aopOp(right,ic,FALSE);
10621 pic16_aopOp(left,ic,FALSE);
10622 pic16_aopOp(result,ic,FALSE);
10624 sign = !SPEC_USIGN(operandType (left));
10625 signedCount = !SPEC_USIGN(operandType (right));
10627 /* if the shift count is known then do it
10628 as efficiently as possible */
10629 if (AOP_TYPE(right) == AOP_LIT) {
10630 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10631 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10632 // we should modify right->aopu.aop_lit here!
10633 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10634 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10636 pic16_genLeftShiftLiteral (left,right,result,ic);
10638 genRightShiftLiteral (left,right,result,ic, sign);
10641 } // if (right is literal)
10643 /* shift count is unknown then we have to form a loop.
10644 * Note: we take only the lower order byte since shifting
10645 * more than 32 bits make no sense anyway, ( the
10646 * largest size of an object can be only 32 bits )
10647 * Note: we perform arithmetic shifts if the left operand is
10648 * signed and we do an (effective) right shift, i. e. we
10649 * shift in the sign bit from the left. */
10651 label_complete = newiTempLabel ( NULL );
10652 label_loop_pos = newiTempLabel ( NULL );
10653 label_loop_neg = NULL;
10654 label_negative = NULL;
10655 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10656 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10659 // additional labels needed
10660 label_loop_neg = newiTempLabel ( NULL );
10661 label_negative = newiTempLabel ( NULL );
10664 // copy source to result -- this will effectively truncate the left operand to the size of result!
10665 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10666 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10667 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10668 mov2f (AOP(result),AOP(left), offset);
10671 // if result is longer than left, fill with zeros (or sign)
10672 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10673 if (sign && AOP_SIZE(left) > 0) {
10674 // shift signed operand -- fill with sign
10675 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10676 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10677 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10678 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10679 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10682 // shift unsigned operand -- fill result with zeros
10683 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10684 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10687 } // if (size mismatch)
10689 pic16_mov2w (AOP(right), 0);
10690 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10691 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10694 // perform a shift by one (shift count is positive)
10695 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10696 // 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])
10697 pic16_emitpLabel (label_loop_pos->key);
10699 if (sign && (pos_shift == POC_RRCF)) {
10700 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10703 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10704 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10705 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10707 // perform a shift by one (shift count is positive)
10708 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10709 // 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])
10710 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10711 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10713 pic16_emitpLabel (label_loop_pos->key);
10714 if (sign && (pos_shift == POC_RRCF)) {
10715 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10718 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10719 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10720 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10721 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10725 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10727 pic16_emitpLabel (label_negative->key);
10728 // perform a shift by -1 (shift count is negative)
10729 // 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)
10731 pic16_emitpLabel (label_loop_neg->key);
10732 if (sign && (neg_shift == POC_RRCF)) {
10733 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10736 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10737 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10738 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10739 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10740 } // if (signedCount)
10742 pic16_emitpLabel (label_complete->key);
10745 pic16_freeAsmop (right,NULL,ic,TRUE);
10746 pic16_freeAsmop(left,NULL,ic,TRUE);
10747 pic16_freeAsmop(result,NULL,ic,TRUE);
10750 static void genLeftShift (iCode *ic) {
10751 genGenericShift (ic, 1);
10754 static void genRightShift (iCode *ic) {
10755 genGenericShift (ic, 0);
10760 void pic16_loadFSR0(operand *op)
10762 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10765 /*-----------------------------------------------------------------*/
10766 /* genUnpackBits - generates code for unpacking bits */
10767 /*-----------------------------------------------------------------*/
10768 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10772 sym_link *etype, *letype;
10773 int blen=0, bstr=0;
10777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10778 etype = getSpec(operandType(result));
10779 letype = getSpec(operandType(left));
10781 // if(IS_BITFIELD(etype)) {
10782 blen = SPEC_BLEN(etype);
10783 bstr = SPEC_BSTR(etype);
10786 lbstr = SPEC_BSTR( letype );
10789 if((blen == 1) && (bstr < 8)) {
10790 /* it is a single bit, so use the appropriate bit instructions */
10791 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10793 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10795 if((ptype == POINTER) && (result)) {
10796 /* workaround to reduce the extra lfsr instruction */
10797 pic16_emitpcode(POC_BTFSC,
10798 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10800 pic16_emitpcode(POC_BTFSC,
10801 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10804 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10806 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10812 /* the following call to pic16_loadFSR0 is temporary until
10813 * optimization to handle single bit assignments is added
10814 * to the function. Until then use the old safe way! -- VR */
10815 pic16_loadFSR0( left );
10817 /* read the first byte */
10824 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10827 pic16_emitcode("clr","a");
10828 pic16_emitcode("movc","a","@a+dptr");
10833 /* if we have bitdisplacement then it fits */
10834 /* into this byte completely or if length is */
10835 /* less than a byte */
10836 if ((shCnt = SPEC_BSTR(etype)) ||
10837 (SPEC_BLEN(etype) <= 8)) {
10839 /* shift right acc */
10842 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10843 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10845 /* VR -- normally I would use the following, but since we use the hack,
10846 * to avoid the masking from AccRsh, why not mask it right now? */
10849 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10852 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10858 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10859 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10862 /* bit field did not fit in a byte */
10863 rlen = SPEC_BLEN(etype) - 8;
10864 pic16_aopPut(AOP(result),"a",offset++);
10871 pic16_emitcode("inc","%s",rname);
10872 pic16_emitcode("mov","a,@%s",rname);
10876 pic16_emitcode("inc","%s",rname);
10877 pic16_emitcode("movx","a,@%s",rname);
10881 pic16_emitcode("inc","dptr");
10882 pic16_emitcode("movx","a,@dptr");
10886 pic16_emitcode("clr","a");
10887 pic16_emitcode("inc","dptr");
10888 pic16_emitcode("movc","a","@a+dptr");
10892 pic16_emitcode("inc","dptr");
10893 pic16_emitcode("lcall","__gptrget");
10898 /* if we are done */
10902 pic16_aopPut(AOP(result),"a",offset++);
10907 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10908 pic16_aopPut(AOP(result),"a",offset);
10915 static void genDataPointerGet(operand *left,
10919 int size, offset = 0, leoffset=0 ;
10921 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10922 pic16_aopOp(result, ic, FALSE);
10924 size = AOP_SIZE(result);
10925 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10929 /* The following tests may save a redudant movff instruction when
10930 * accessing unions */
10932 /* if they are the same */
10933 if (operandsEqu (left, result)) {
10934 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10940 /* if they are the same registers */
10941 if (pic16_sameRegs(AOP(left),AOP(result))) {
10942 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10948 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10949 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10950 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10957 if ( AOP_TYPE(left) == AOP_PCODE) {
10958 fprintf(stderr,"genDataPointerGet %s, %d\n",
10959 AOP(left)->aopu.pcop->name,
10960 (AOP(left)->aopu.pcop->type == PO_DIR)?
10961 PCOR(AOP(left)->aopu.pcop)->instance:
10962 PCOI(AOP(left)->aopu.pcop)->offset);
10966 if(AOP(left)->aopu.pcop->type == PO_DIR)
10967 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10969 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10972 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10974 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10975 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10976 pic16_mov2w(AOP(left), offset); // patch 8
10977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10979 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10980 pic16_popGet(AOP(left), offset), //patch 8
10981 pic16_popGet(AOP(result), offset)));
10989 pic16_freeAsmop(result,NULL,ic,TRUE);
10994 /*-----------------------------------------------------------------*/
10995 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10996 /*-----------------------------------------------------------------*/
10997 static void genNearPointerGet (operand *left,
11002 //regs *preg = NULL ;
11003 sym_link *rtype, *retype;
11004 sym_link *ltype = operandType(left);
11008 rtype = operandType(result);
11009 retype= getSpec(rtype);
11011 pic16_aopOp(left,ic,FALSE);
11013 // pic16_DumpOp("(left)",left);
11014 // pic16_DumpOp("(result)",result);
11016 /* if left is rematerialisable and
11017 * result is not bit variable type and
11018 * the left is pointer to data space i.e
11019 * lower 128 bytes of space */
11021 if (AOP_TYPE(left) == AOP_PCODE
11022 && !IS_BITFIELD(retype)
11023 && DCL_TYPE(ltype) == POINTER) {
11025 genDataPointerGet (left,result,ic);
11026 pic16_freeAsmop(left, NULL, ic, TRUE);
11030 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11031 pic16_aopOp (result,ic,FALSE);
11033 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11036 if(IS_BITFIELD( retype )
11037 && (SPEC_BLEN(operandType(result))==1)
11041 int bitstrt, bytestrt;
11043 /* if this is bitfield of size 1, see if we are checking the value
11044 * of a single bit in an if-statement,
11045 * if yes, then don't generate usual code, but execute the
11046 * genIfx directly -- VR */
11050 /* CHECK: if next iCode is IFX
11051 * and current result operand is nextic's conditional operand
11052 * and current result operand live ranges ends at nextic's key number
11054 if((nextic->op == IFX)
11055 && (result == IC_COND(nextic))
11056 && (OP_LIVETO(result) == nextic->seq)
11058 /* everything is ok then */
11059 /* find a way to optimize the genIfx iCode */
11061 bytestrt = SPEC_BSTR(operandType(result))/8;
11062 bitstrt = SPEC_BSTR(operandType(result))%8;
11064 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11066 genIfxpCOpJump(nextic, jop);
11068 pic16_freeAsmop(left, NULL, ic, TRUE);
11069 pic16_freeAsmop(result, NULL, ic, TRUE);
11076 /* if the value is already in a pointer register
11077 * then don't need anything more */
11078 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11079 /* otherwise get a free pointer register */
11080 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11082 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11083 /* bitfields will be handled by genUnpackBits */
11084 if(!IS_BITFIELD(retype)) {
11086 if(is_LitAOp( AOP(left) )) {
11087 pic16_loadFSR0( left );
11089 // set up FSR0 with address from left
11090 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11091 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11096 /* if bitfield then unpack the bits */
11097 if (IS_BITFIELD(retype))
11098 genUnpackBits (result, left, NULL, POINTER);
11100 /* we have can just get the values */
11101 int size = AOP_SIZE(result);
11104 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11106 /* fsr0 is loaded already -- VR */
11107 // pic16_loadFSR0( left );
11109 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11110 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11114 pic16_popGet(AOP(result), offset++)));
11116 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11117 pic16_popGet(AOP(result), offset++)));
11121 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11122 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11124 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11128 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11130 pic16_emitcode("mov","a,@%s",rname);
11131 pic16_aopPut(AOP(result),"a",offset);
11133 sprintf(buffer,"@%s",rname);
11134 pic16_aopPut(AOP(result),buffer,offset);
11138 pic16_emitcode("inc","%s",rname);
11143 /* now some housekeeping stuff */
11145 /* we had to allocate for this iCode */
11146 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
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 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11155 if (AOP_SIZE(result) > 1
11156 && !OP_SYMBOL(left)->remat
11157 && ( OP_SYMBOL(left)->liveTo > ic->seq
11159 // int size = AOP_SIZE(result) - 1;
11161 // pic16_emitcode("dec","%s",rname);
11166 pic16_freeAsmop(left,NULL,ic,TRUE);
11167 pic16_freeAsmop(result,NULL,ic,TRUE);
11170 /*-----------------------------------------------------------------*/
11171 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11172 /*-----------------------------------------------------------------*/
11173 static void genPagedPointerGet (operand *left,
11178 regs *preg = NULL ;
11180 sym_link *rtype, *retype;
11182 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11184 rtype = operandType(result);
11185 retype= getSpec(rtype);
11187 pic16_aopOp(left,ic,FALSE);
11189 /* if the value is already in a pointer register
11190 then don't need anything more */
11191 if (!AOP_INPREG(AOP(left))) {
11192 /* otherwise get a free pointer register */
11194 preg = getFreePtr(ic,&aop,FALSE);
11195 pic16_emitcode("mov","%s,%s",
11197 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11198 rname = preg->name ;
11200 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11202 pic16_freeAsmop(left,NULL,ic,TRUE);
11203 pic16_aopOp (result,ic,FALSE);
11205 /* if bitfield then unpack the bits */
11206 if (IS_BITFIELD(retype))
11207 genUnpackBits (result,left,rname,PPOINTER);
11209 /* we have can just get the values */
11210 int size = AOP_SIZE(result);
11215 pic16_emitcode("movx","a,@%s",rname);
11216 pic16_aopPut(AOP(result),"a",offset);
11221 pic16_emitcode("inc","%s",rname);
11225 /* now some housekeeping stuff */
11227 /* we had to allocate for this iCode */
11228 pic16_freeAsmop(NULL,aop,ic,TRUE);
11230 /* we did not allocate which means left
11231 already in a pointer register, then
11232 if size > 0 && this could be used again
11233 we have to point it back to where it
11235 if (AOP_SIZE(result) > 1 &&
11236 !OP_SYMBOL(left)->remat &&
11237 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11239 int size = AOP_SIZE(result) - 1;
11241 pic16_emitcode("dec","%s",rname);
11246 pic16_freeAsmop(result,NULL,ic,TRUE);
11251 /*-----------------------------------------------------------------*/
11252 /* genFarPointerGet - gget value from far space */
11253 /*-----------------------------------------------------------------*/
11254 static void genFarPointerGet (operand *left,
11255 operand *result, iCode *ic)
11258 sym_link *retype = getSpec(operandType(result));
11260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11262 pic16_aopOp(left,ic,FALSE);
11264 /* if the operand is already in dptr
11265 then we do nothing else we move the value to dptr */
11266 if (AOP_TYPE(left) != AOP_STR) {
11267 /* if this is remateriazable */
11268 if (AOP_TYPE(left) == AOP_IMMD)
11269 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11270 else { /* we need to get it byte by byte */
11271 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11272 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11273 if (options.model == MODEL_FLAT24)
11275 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11279 /* so dptr know contains the address */
11280 pic16_freeAsmop(left,NULL,ic,TRUE);
11281 pic16_aopOp(result,ic,FALSE);
11283 /* if bit then unpack */
11284 if (IS_BITFIELD(retype))
11285 genUnpackBits(result,left,"dptr",FPOINTER);
11287 size = AOP_SIZE(result);
11291 pic16_emitcode("movx","a,@dptr");
11292 pic16_aopPut(AOP(result),"a",offset++);
11294 pic16_emitcode("inc","dptr");
11298 pic16_freeAsmop(result,NULL,ic,TRUE);
11302 /*-----------------------------------------------------------------*/
11303 /* genCodePointerGet - get value from code space */
11304 /*-----------------------------------------------------------------*/
11305 static void genCodePointerGet (operand *left,
11306 operand *result, iCode *ic)
11309 sym_link *retype = getSpec(operandType(result));
11311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11313 pic16_aopOp(left,ic,FALSE);
11315 /* if the operand is already in dptr
11316 then we do nothing else we move the value to dptr */
11317 if (AOP_TYPE(left) != AOP_STR) {
11318 /* if this is remateriazable */
11319 if (AOP_TYPE(left) == AOP_IMMD)
11320 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11321 else { /* we need to get it byte by byte */
11322 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11323 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11324 if (options.model == MODEL_FLAT24)
11326 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11330 /* so dptr know contains the address */
11331 pic16_freeAsmop(left,NULL,ic,TRUE);
11332 pic16_aopOp(result,ic,FALSE);
11334 /* if bit then unpack */
11335 if (IS_BITFIELD(retype))
11336 genUnpackBits(result,left,"dptr",CPOINTER);
11338 size = AOP_SIZE(result);
11342 pic16_emitcode("clr","a");
11343 pic16_emitcode("movc","a,@a+dptr");
11344 pic16_aopPut(AOP(result),"a",offset++);
11346 pic16_emitcode("inc","dptr");
11350 pic16_freeAsmop(result,NULL,ic,TRUE);
11355 /*-----------------------------------------------------------------*/
11356 /* genGenPointerGet - gget value from generic pointer space */
11357 /*-----------------------------------------------------------------*/
11358 static void genGenPointerGet (operand *left,
11359 operand *result, iCode *ic)
11361 int size, offset, lit;
11362 sym_link *retype = getSpec(operandType(result));
11364 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11365 pic16_aopOp(left,ic,FALSE);
11366 pic16_aopOp(result,ic,FALSE);
11367 size = AOP_SIZE(result);
11369 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11371 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11373 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11374 // load FSR0 from immediate
11375 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11377 // pic16_loadFSR0( left );
11382 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11391 else { /* we need to get it byte by byte */
11392 // set up FSR0 with address from left
11393 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11394 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11400 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11402 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
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);
11421 /*-----------------------------------------------------------------*/
11422 /* genGenPointerGet - gget value from generic pointer space */
11423 /*-----------------------------------------------------------------*/
11424 static void genGenPointerGet (operand *left,
11425 operand *result, iCode *ic)
11427 int size, offset, lit;
11428 sym_link *retype = getSpec(operandType(result));
11431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11432 pic16_aopOp(left,ic,FALSE);
11433 pic16_aopOp(result,ic,FALSE);
11434 size = AOP_SIZE(result);
11436 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11438 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11440 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11441 // load FSR0 from immediate
11442 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11444 werror(W_POSSBUG2, __FILE__, __LINE__);
11449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11451 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11458 } else { /* we need to get it byte by byte */
11460 /* set up WREG:PRODL:FSR0L with address from left */
11461 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11462 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11463 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11466 case 1: strcpy(fgptrget, "__gptrget1"); break;
11467 case 2: strcpy(fgptrget, "__gptrget2"); break;
11468 case 3: strcpy(fgptrget, "__gptrget3"); break;
11469 case 4: strcpy(fgptrget, "__gptrget4"); break;
11471 werror(W_POSSBUG2, __FILE__, __LINE__);
11475 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11477 assignResultValue(result, 1);
11482 sym = newSymbol( fgptrget, 0 );
11483 strcpy(sym->rname, fgptrget);
11484 checkAddSym(&externs, sym);
11486 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11492 /* if bit then unpack */
11493 if (IS_BITFIELD(retype))
11494 genUnpackBits(result,left,"BAD",GPOINTER);
11497 pic16_freeAsmop(left,NULL,ic,TRUE);
11498 pic16_freeAsmop(result,NULL,ic,TRUE);
11501 /*-----------------------------------------------------------------*/
11502 /* genConstPointerGet - get value from const generic pointer space */
11503 /*-----------------------------------------------------------------*/
11504 static void genConstPointerGet (operand *left,
11505 operand *result, iCode *ic)
11507 //sym_link *retype = getSpec(operandType(result));
11508 // symbol *albl = newiTempLabel(NULL); // patch 15
11509 // symbol *blbl = newiTempLabel(NULL); //
11510 // PIC_OPCODE poc; // patch 15
11514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11515 pic16_aopOp(left,ic,FALSE);
11516 pic16_aopOp(result,ic,TRUE);
11517 size = AOP_SIZE(result);
11519 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11521 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11523 // set up table pointer
11524 if( (AOP_TYPE(left) == AOP_PCODE)
11525 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11526 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11528 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11529 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11530 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11531 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11532 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11533 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11535 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11536 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11537 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11541 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11542 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11546 pic16_freeAsmop(left,NULL,ic,TRUE);
11547 pic16_freeAsmop(result,NULL,ic,TRUE);
11551 /*-----------------------------------------------------------------*/
11552 /* genPointerGet - generate code for pointer get */
11553 /*-----------------------------------------------------------------*/
11554 static void genPointerGet (iCode *ic)
11556 operand *left, *result ;
11557 sym_link *type, *etype;
11562 left = IC_LEFT(ic);
11563 result = IC_RESULT(ic) ;
11565 /* depending on the type of pointer we need to
11566 move it to the correct pointer register */
11567 type = operandType(left);
11568 etype = getSpec(type);
11571 if (IS_PTR_CONST(type))
11573 if (IS_CODEPTR(type))
11575 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11577 /* if left is of type of pointer then it is simple */
11578 if (IS_PTR(type) && !IS_FUNC(type->next))
11579 p_type = DCL_TYPE(type);
11581 /* we have to go by the storage class */
11582 p_type = PTR_TYPE(SPEC_OCLS(etype));
11584 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11586 if (SPEC_OCLS(etype)->codesp ) {
11587 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11588 //p_type = CPOINTER ;
11590 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11591 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11592 /*p_type = FPOINTER ;*/
11594 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11595 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11596 /* p_type = PPOINTER; */
11598 if (SPEC_OCLS(etype) == idata ) {
11599 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11600 /* p_type = IPOINTER; */
11602 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11603 /* p_type = POINTER ; */
11607 /* now that we have the pointer type we assign
11608 the pointer values */
11612 genNearPointerGet (left,result,ic);
11616 genPagedPointerGet(left,result,ic);
11620 genFarPointerGet (left,result,ic);
11624 genConstPointerGet (left,result,ic);
11625 //pic16_emitcodePointerGet (left,result,ic);
11630 if (IS_PTR_CONST(type))
11631 genConstPointerGet (left,result,ic);
11634 genGenPointerGet (left,result,ic);
11638 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11639 "genPointerGet: illegal pointer type");
11644 /*-----------------------------------------------------------------*/
11645 /* genPackBits - generates code for packed bit storage */
11646 /*-----------------------------------------------------------------*/
11647 static void genPackBits (sym_link *etype , operand *result,
11649 char *rname, int p_type)
11658 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11659 blen = SPEC_BLEN(etype);
11660 bstr = SPEC_BSTR(etype);
11662 retype = getSpec(operandType(right));
11664 if(AOP_TYPE(right) == AOP_LIT) {
11665 if((blen == 1) && (bstr < 8)) {
11667 /* it is a single bit, so use the appropriate bit instructions */
11669 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11671 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11672 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11673 if((p_type == POINTER) && (result)) {
11674 /* workaround to reduce the extra lfsr instruction */
11676 pic16_emitpcode(POC_BSF,
11677 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11679 pic16_emitpcode(POC_BCF,
11680 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11683 pic16_loadFSR0( result );
11685 pic16_emitpcode(POC_BSF,
11686 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11688 pic16_emitpcode(POC_BCF,
11689 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11696 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11699 if(IS_BITFIELD(retype)
11700 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11704 rblen = SPEC_BLEN( retype );
11705 rbstr = SPEC_BSTR( retype );
11708 if(IS_BITFIELD(etype)) {
11709 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11710 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11712 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11715 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11717 if(IS_BITFIELD(etype)) {
11718 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11720 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11723 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11727 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11729 /* if the bit lenth is less than or */
11730 /* it exactly fits a byte then */
11731 if((shCnt=SPEC_BSTR(etype))
11732 || SPEC_BLEN(etype) <= 8 ) {
11734 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11736 /* shift left acc */
11739 /* using PRODL as a temporary register here */
11740 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11745 pic16_loadFSR0( result );
11746 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11747 // pic16_emitcode ("mov","b,a");
11748 // pic16_emitcode("mov","a,@%s",rname);
11752 werror(W_POSSBUG2, __FILE__, __LINE__);
11757 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11758 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11759 (unsigned char)(0xff >> (8-bstr))) ));
11760 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11761 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11768 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11769 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11774 if ( SPEC_BLEN(etype) <= 8 )
11777 pic16_emitcode("inc","%s",rname);
11778 rLen = SPEC_BLEN(etype) ;
11782 /* now generate for lengths greater than one byte */
11785 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11795 pic16_emitcode("mov","@%s,a",rname);
11797 pic16_emitcode("mov","@%s,%s",rname,l);
11802 pic16_emitcode("movx","@dptr,a");
11807 DEBUGpic16_emitcode(";lcall","__gptrput");
11810 pic16_emitcode ("inc","%s",rname);
11815 /* last last was not complete */
11817 /* save the byte & read byte */
11820 pic16_emitcode ("mov","b,a");
11821 pic16_emitcode("mov","a,@%s",rname);
11825 pic16_emitcode ("mov","b,a");
11826 pic16_emitcode("movx","a,@dptr");
11830 pic16_emitcode ("push","b");
11831 pic16_emitcode ("push","acc");
11832 pic16_emitcode ("lcall","__gptrget");
11833 pic16_emitcode ("pop","b");
11837 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11838 pic16_emitcode ("orl","a,b");
11841 if (p_type == GPOINTER)
11842 pic16_emitcode("pop","b");
11847 pic16_emitcode("mov","@%s,a",rname);
11851 pic16_emitcode("movx","@dptr,a");
11855 DEBUGpic16_emitcode(";lcall","__gptrput");
11859 /*-----------------------------------------------------------------*/
11860 /* genDataPointerSet - remat pointer to data space */
11861 /*-----------------------------------------------------------------*/
11862 static void genDataPointerSet(operand *right,
11866 int size, offset = 0, resoffset=0 ;
11868 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11869 pic16_aopOp(right,ic,FALSE);
11871 size = AOP_SIZE(right);
11873 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11876 if ( AOP_TYPE(result) == AOP_PCODE) {
11877 fprintf(stderr,"genDataPointerSet %s, %d\n",
11878 AOP(result)->aopu.pcop->name,
11879 (AOP(result)->aopu.pcop->type == PO_DIR)?
11880 PCOR(AOP(result)->aopu.pcop)->instance:
11881 PCOI(AOP(result)->aopu.pcop)->offset);
11885 if(AOP(result)->aopu.pcop->type == PO_DIR)
11886 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11889 if (AOP_TYPE(right) == AOP_LIT) {
11892 if(!IS_FLOAT(operandType( right )))
11893 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11896 unsigned long lit_int;
11900 /* take care if literal is a float */
11901 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11902 lit = info.lit_int;
11905 lit = lit >> (8*offset);
11907 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11910 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11913 pic16_mov2w(AOP(right), offset);
11914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11920 pic16_freeAsmop(right,NULL,ic,TRUE);
11925 /*-----------------------------------------------------------------*/
11926 /* genNearPointerSet - pic16_emitcode for near pointer put */
11927 /*-----------------------------------------------------------------*/
11928 static void genNearPointerSet (operand *right,
11935 sym_link *ptype = operandType(result);
11936 sym_link *resetype;
11938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11939 retype= getSpec(operandType(right));
11940 resetype = getSpec(operandType(result));
11942 pic16_aopOp(result,ic,FALSE);
11944 /* if the result is rematerializable &
11945 * in data space & not a bit variable */
11947 /* and result is not a bit variable */
11948 if (AOP_TYPE(result) == AOP_PCODE
11949 // && AOP_TYPE(result) == AOP_IMMD
11950 && DCL_TYPE(ptype) == POINTER
11951 && !IS_BITFIELD(retype)
11952 && !IS_BITFIELD(resetype)) {
11954 genDataPointerSet (right,result,ic);
11955 pic16_freeAsmop(result,NULL,ic,TRUE);
11959 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11960 pic16_aopOp(right,ic,FALSE);
11961 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11963 /* if the value is already in a pointer register
11964 * then don't need anything more */
11965 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11966 /* otherwise get a free pointer register */
11967 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11969 // if( (AOP_TYPE(result) == AOP_PCODE)
11970 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11971 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11972 if(is_LitAOp( AOP(result) ))
11974 if(!IS_BITFIELD(resetype))
11975 pic16_loadFSR0( result ); // patch 10
11977 if(!IS_BITFIELD(resetype)) {
11978 // set up FSR0 with address of result
11979 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11980 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11986 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11990 // pic16_loadFSR0( result );
11992 /* if bitfield then unpack the bits */
11993 if (IS_BITFIELD(resetype)) {
11994 genPackBits (resetype, result, right, NULL, POINTER);
11996 /* we have can just get the values */
11997 int size = AOP_SIZE(right);
12000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12002 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12005 //pic16_emitcode("mov","@%s,a",rname);
12006 pic16_emitcode("movf","indf0,w ;1");
12009 if (AOP_TYPE(right) == AOP_LIT) {
12010 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12012 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12014 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12016 } else { // no literal
12018 pic16_emitpcode(POC_MOVFF,
12019 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12020 pic16_popCopyReg(&pic16_pc_postinc0)));
12022 pic16_emitpcode(POC_MOVFF,
12023 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12024 pic16_popCopyReg(&pic16_pc_indf0)));
12032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12033 /* now some housekeeping stuff */
12035 /* we had to allocate for this iCode */
12036 pic16_freeAsmop(NULL,aop,ic,TRUE);
12038 /* we did not allocate which means left
12039 * already in a pointer register, then
12040 * if size > 0 && this could be used again
12041 * we have to point it back to where it
12043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12044 if (AOP_SIZE(right) > 1
12045 && !OP_SYMBOL(result)->remat
12046 && ( OP_SYMBOL(result)->liveTo > ic->seq
12049 int size = AOP_SIZE(right) - 1;
12052 pic16_emitcode("decf","fsr0,f");
12053 //pic16_emitcode("dec","%s",rname);
12057 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12060 pic16_freeAsmop(right,NULL,ic,TRUE);
12061 pic16_freeAsmop(result,NULL,ic,TRUE);
12064 /*-----------------------------------------------------------------*/
12065 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12066 /*-----------------------------------------------------------------*/
12067 static void genPagedPointerSet (operand *right,
12072 regs *preg = NULL ;
12076 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12078 retype= getSpec(operandType(right));
12080 pic16_aopOp(result,ic,FALSE);
12082 /* if the value is already in a pointer register
12083 then don't need anything more */
12084 if (!AOP_INPREG(AOP(result))) {
12085 /* otherwise get a free pointer register */
12087 preg = getFreePtr(ic,&aop,FALSE);
12088 pic16_emitcode("mov","%s,%s",
12090 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12091 rname = preg->name ;
12093 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12095 pic16_freeAsmop(result,NULL,ic,TRUE);
12096 pic16_aopOp (right,ic,FALSE);
12098 /* if bitfield then unpack the bits */
12099 if (IS_BITFIELD(retype))
12100 genPackBits (retype,result,right,rname,PPOINTER);
12102 /* we have can just get the values */
12103 int size = AOP_SIZE(right);
12107 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12110 pic16_emitcode("movx","@%s,a",rname);
12113 pic16_emitcode("inc","%s",rname);
12119 /* now some housekeeping stuff */
12121 /* we had to allocate for this iCode */
12122 pic16_freeAsmop(NULL,aop,ic,TRUE);
12124 /* we did not allocate which means left
12125 already in a pointer register, then
12126 if size > 0 && this could be used again
12127 we have to point it back to where it
12129 if (AOP_SIZE(right) > 1 &&
12130 !OP_SYMBOL(result)->remat &&
12131 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12133 int size = AOP_SIZE(right) - 1;
12135 pic16_emitcode("dec","%s",rname);
12140 pic16_freeAsmop(right,NULL,ic,TRUE);
12145 /*-----------------------------------------------------------------*/
12146 /* genFarPointerSet - set value from far space */
12147 /*-----------------------------------------------------------------*/
12148 static void genFarPointerSet (operand *right,
12149 operand *result, iCode *ic)
12152 sym_link *retype = getSpec(operandType(right));
12154 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12155 pic16_aopOp(result,ic,FALSE);
12157 /* if the operand is already in dptr
12158 then we do nothing else we move the value to dptr */
12159 if (AOP_TYPE(result) != AOP_STR) {
12160 /* if this is remateriazable */
12161 if (AOP_TYPE(result) == AOP_IMMD)
12162 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12163 else { /* we need to get it byte by byte */
12164 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12165 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12166 if (options.model == MODEL_FLAT24)
12168 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12172 /* so dptr know contains the address */
12173 pic16_freeAsmop(result,NULL,ic,TRUE);
12174 pic16_aopOp(right,ic,FALSE);
12176 /* if bit then unpack */
12177 if (IS_BITFIELD(retype))
12178 genPackBits(retype,result,right,"dptr",FPOINTER);
12180 size = AOP_SIZE(right);
12184 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12186 pic16_emitcode("movx","@dptr,a");
12188 pic16_emitcode("inc","dptr");
12192 pic16_freeAsmop(right,NULL,ic,TRUE);
12195 /*-----------------------------------------------------------------*/
12196 /* genGenPointerSet - set value from generic pointer space */
12197 /*-----------------------------------------------------------------*/
12199 static void genGenPointerSet (operand *right,
12200 operand *result, iCode *ic)
12202 int i, size, offset, lit;
12203 sym_link *retype = getSpec(operandType(right));
12205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12207 pic16_aopOp(result,ic,FALSE);
12208 pic16_aopOp(right,ic,FALSE);
12209 size = AOP_SIZE(right);
12212 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12214 /* if the operand is already in dptr
12215 then we do nothing else we move the value to dptr */
12216 if (AOP_TYPE(result) != AOP_STR) {
12217 /* if this is remateriazable */
12218 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12219 // WARNING: anythig until "else" is untested!
12220 if (AOP_TYPE(result) == AOP_IMMD) {
12221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12222 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12223 // load FSR0 from immediate
12224 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12228 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12230 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12236 else { /* we need to get it byte by byte */
12237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12238 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12240 // set up FSR0 with address of result
12241 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12242 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12244 /* hack hack! see if this the FSR. If so don't load W */
12245 if(AOP_TYPE(right) != AOP_ACC) {
12247 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12249 if(AOP_TYPE(right) == AOP_LIT)
12252 // note: pic16_popGet handles sign extension
12253 for(i=0;i<size;i++) {
12254 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12256 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12258 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12263 for(i=0;i<size;i++) {
12265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12266 pic16_popCopyReg(&pic16_pc_postinc0)));
12268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12269 pic16_popCopyReg(&pic16_pc_indf0)));
12275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12276 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12278 } // if (AOP_TYPE(result) != AOP_IMMD)
12280 } // if (AOP_TYPE(result) != AOP_STR)
12281 /* so dptr know contains the address */
12284 /* if bit then unpack */
12285 if (IS_BITFIELD(retype))
12286 genPackBits(retype,result,right,"dptr",GPOINTER);
12288 size = AOP_SIZE(right);
12291 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12293 // set up FSR0 with address of result
12294 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12295 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12298 if (AOP_TYPE(right) == AOP_LIT) {
12299 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12301 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12303 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12305 } else { // no literal
12307 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12309 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12317 pic16_freeAsmop(right,NULL,ic,TRUE);
12318 pic16_freeAsmop(result,NULL,ic,TRUE);
12322 static void genGenPointerSet (operand *right,
12323 operand *result, iCode *ic)
12326 sym_link *retype = getSpec(operandType(right));
12329 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12331 pic16_aopOp(result,ic,FALSE);
12332 pic16_aopOp(right,ic,FALSE);
12333 size = AOP_SIZE(right);
12335 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12338 /* if bit then unpack */
12339 if (IS_BITFIELD(retype)) {
12340 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12341 genPackBits(retype,result,right,"dptr",GPOINTER);
12345 size = AOP_SIZE(right);
12347 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12351 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12353 /* value of right+0 is placed on stack, which will be retrieved
12354 * by the support function this restoring the stack. The important
12355 * thing is that there is no need to manually restore stack pointer
12357 pushaop(AOP(right), 0);
12358 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12359 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12360 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12361 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12363 /* load address to write to in WREG:FSR0H:FSR0L */
12364 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12365 pic16_popCopyReg(&pic16_pc_fsr0l)));
12366 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12367 pic16_popCopyReg(&pic16_pc_prodl)));
12368 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12371 /* put code here */
12373 case 1: strcpy(fgptrput, "__gptrput1"); break;
12374 case 2: strcpy(fgptrput, "__gptrput2"); break;
12375 case 3: strcpy(fgptrput, "__gptrput3"); break;
12376 case 4: strcpy(fgptrput, "__gptrput4"); break;
12378 werror(W_POSSBUG2, __FILE__, __LINE__);
12382 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12387 sym = newSymbol( fgptrput, 0 );
12388 strcpy(sym->rname, fgptrput);
12389 checkAddSym(&externs, sym);
12393 pic16_freeAsmop(right,NULL,ic,TRUE);
12394 pic16_freeAsmop(result,NULL,ic,TRUE);
12397 /*-----------------------------------------------------------------*/
12398 /* genPointerSet - stores the value into a pointer location */
12399 /*-----------------------------------------------------------------*/
12400 static void genPointerSet (iCode *ic)
12402 operand *right, *result ;
12403 sym_link *type, *etype;
12408 right = IC_RIGHT(ic);
12409 result = IC_RESULT(ic) ;
12411 /* depending on the type of pointer we need to
12412 move it to the correct pointer register */
12413 type = operandType(result);
12414 etype = getSpec(type);
12415 /* if left is of type of pointer then it is simple */
12416 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12417 p_type = DCL_TYPE(type);
12420 /* we have to go by the storage class */
12421 p_type = PTR_TYPE(SPEC_OCLS(etype));
12423 /* if (SPEC_OCLS(etype)->codesp ) { */
12424 /* p_type = CPOINTER ; */
12427 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12428 /* p_type = FPOINTER ; */
12430 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12431 /* p_type = PPOINTER ; */
12433 /* if (SPEC_OCLS(etype) == idata ) */
12434 /* p_type = IPOINTER ; */
12436 /* p_type = POINTER ; */
12439 /* now that we have the pointer type we assign
12440 the pointer values */
12444 genNearPointerSet (right,result,ic);
12448 genPagedPointerSet (right,result,ic);
12452 genFarPointerSet (right,result,ic);
12456 genGenPointerSet (right,result,ic);
12460 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12461 "genPointerSet: illegal pointer type");
12465 /*-----------------------------------------------------------------*/
12466 /* genIfx - generate code for Ifx statement */
12467 /*-----------------------------------------------------------------*/
12468 static void genIfx (iCode *ic, iCode *popIc)
12470 operand *cond = IC_COND(ic);
12475 pic16_aopOp(cond,ic,FALSE);
12477 /* get the value into acc */
12478 if (AOP_TYPE(cond) != AOP_CRY)
12479 pic16_toBoolean(cond);
12482 /* the result is now in the accumulator */
12483 pic16_freeAsmop(cond,NULL,ic,TRUE);
12485 /* if there was something to be popped then do it */
12489 /* if the condition is a bit variable */
12490 if (isbit && IS_ITEMP(cond) &&
12492 genIfxJump(ic,"c");
12493 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12495 if (isbit && !IS_ITEMP(cond))
12496 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12498 genIfxJump(ic,"a");
12503 /*-----------------------------------------------------------------*/
12504 /* genAddrOf - generates code for address of */
12505 /*-----------------------------------------------------------------*/
12506 static void genAddrOf (iCode *ic)
12508 operand *result, *left;
12510 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12511 pCodeOp *pcop0, *pcop1, *pcop2;
12515 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12517 sym = OP_SYMBOL( IC_LEFT(ic) );
12520 /* get address of symbol on stack */
12521 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12523 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12524 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12527 // operands on stack are accessible via "FSR2 + index" with index
12528 // starting at 2 for arguments and growing from 0 downwards for
12529 // local variables (index == 0 is not assigned so we add one here)
12531 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12533 assert (soffs < 0);
12536 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12537 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12538 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12539 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12540 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12541 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12542 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12548 // if(pic16_debug_verbose) {
12549 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12550 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12553 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12554 size = AOP_SIZE(IC_RESULT(ic));
12556 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12557 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12558 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12561 pic16_emitpcode(POC_MOVLW, pcop0);
12562 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12563 pic16_emitpcode(POC_MOVLW, pcop1);
12564 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12565 pic16_emitpcode(POC_MOVLW, pcop2);
12566 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12569 pic16_emitpcode(POC_MOVLW, pcop0);
12570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12571 pic16_emitpcode(POC_MOVLW, pcop1);
12572 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12574 pic16_emitpcode(POC_MOVLW, pcop0);
12575 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12578 pic16_freeAsmop(left, NULL, ic, FALSE);
12580 pic16_freeAsmop(result,NULL,ic,TRUE);
12585 /*-----------------------------------------------------------------*/
12586 /* genFarFarAssign - assignment when both are in far space */
12587 /*-----------------------------------------------------------------*/
12588 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12590 int size = AOP_SIZE(right);
12593 /* first push the right side on to the stack */
12595 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12597 pic16_emitcode ("push","acc");
12600 pic16_freeAsmop(right,NULL,ic,FALSE);
12601 /* now assign DPTR to result */
12602 pic16_aopOp(result,ic,FALSE);
12603 size = AOP_SIZE(result);
12605 pic16_emitcode ("pop","acc");
12606 pic16_aopPut(AOP(result),"a",--offset);
12608 pic16_freeAsmop(result,NULL,ic,FALSE);
12613 /*-----------------------------------------------------------------*/
12614 /* genAssign - generate code for assignment */
12615 /*-----------------------------------------------------------------*/
12616 static void genAssign (iCode *ic)
12618 operand *result, *right;
12619 int size, offset,know_W;
12620 unsigned long lit = 0L;
12622 result = IC_RESULT(ic);
12623 right = IC_RIGHT(ic) ;
12627 /* if they are the same */
12628 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12631 /* reversed order operands are aopOp'ed so that result operand
12632 * is effective in case right is a stack symbol. This maneauver
12633 * allows to use the _G.resDirect flag later */
12634 pic16_aopOp(result,ic,TRUE);
12635 pic16_aopOp(right,ic,FALSE);
12637 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12639 /* if they are the same registers */
12640 if (pic16_sameRegs(AOP(right),AOP(result)))
12643 /* if the result is a bit */
12644 if (AOP_TYPE(result) == AOP_CRY) {
12645 /* if the right size is a literal then
12646 we know what the value is */
12647 if (AOP_TYPE(right) == AOP_LIT) {
12649 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12650 pic16_popGet(AOP(result),0));
12652 if (((int) operandLitValue(right)))
12653 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12654 AOP(result)->aopu.aop_dir,
12655 AOP(result)->aopu.aop_dir);
12657 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12658 AOP(result)->aopu.aop_dir,
12659 AOP(result)->aopu.aop_dir);
12663 /* the right is also a bit variable */
12664 if (AOP_TYPE(right) == AOP_CRY) {
12665 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12666 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12667 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12669 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12670 AOP(result)->aopu.aop_dir,
12671 AOP(result)->aopu.aop_dir);
12672 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12673 AOP(right)->aopu.aop_dir,
12674 AOP(right)->aopu.aop_dir);
12675 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12676 AOP(result)->aopu.aop_dir,
12677 AOP(result)->aopu.aop_dir);
12681 /* we need to or */
12682 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12683 pic16_toBoolean(right);
12685 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12686 //pic16_aopPut(AOP(result),"a",0);
12690 /* bit variables done */
12692 size = AOP_SIZE(result);
12695 if(AOP_TYPE(right) == AOP_LIT) {
12696 if(!IS_FLOAT(operandType( right )))
12697 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12700 unsigned long lit_int;
12704 /* take care if literal is a float */
12705 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12706 lit = info.lit_int;
12710 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12711 // sizeof(unsigned long int), sizeof(float));
12714 if (AOP_TYPE(right) == AOP_REG) {
12715 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12718 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12723 if(AOP_TYPE(right) != AOP_LIT
12724 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12725 && !IS_FUNC(OP_SYM_TYPE(right))
12727 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12728 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12730 // set up table pointer
12731 if(is_LitOp(right)) {
12732 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12733 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12734 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12735 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12736 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12737 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12738 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12740 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12741 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12742 pic16_popCopyReg(&pic16_pc_tblptrl)));
12743 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12744 pic16_popCopyReg(&pic16_pc_tblptrh)));
12745 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12746 pic16_popCopyReg(&pic16_pc_tblptru)));
12749 size = min(AOP_SIZE(right), AOP_SIZE(result));
12751 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12752 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12753 pic16_popGet(AOP(result),offset)));
12757 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12758 size = AOP_SIZE(result) - AOP_SIZE(right);
12760 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12770 /* VR - What is this?! */
12771 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12772 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12773 if(aopIdx(AOP(result),0) == 4) {
12775 /* this is a workaround to save value of right into wreg too,
12776 * value of wreg is going to be used later */
12777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12778 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12779 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12783 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12789 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12790 if(AOP_TYPE(right) == AOP_LIT) {
12792 if(know_W != (lit&0xff))
12793 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12795 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12797 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12801 } else if (AOP_TYPE(right) == AOP_CRY) {
12802 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12804 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12805 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12806 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12808 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12809 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12810 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12814 if(!_G.resDirect) /* use this aopForSym feature */
12815 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12822 pic16_freeAsmop (right,NULL,ic,FALSE);
12823 pic16_freeAsmop (result,NULL,ic,TRUE);
12826 /*-----------------------------------------------------------------*/
12827 /* genJumpTab - generates code for jump table */
12828 /*-----------------------------------------------------------------*/
12829 static void genJumpTab (iCode *ic)
12834 pCodeOp *jt_offs_hi;
12839 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12840 /* get the condition into accumulator */
12841 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12843 /* multiply by three */
12844 pic16_emitcode("add","a,acc");
12845 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12847 jtab = newiTempLabel(NULL);
12848 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12849 pic16_emitcode("jmp","@a+dptr");
12850 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12853 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12854 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12856 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12857 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12858 pic16_emitpLabel(jtab->key);
12862 jt_offs = pic16_popGetTempReg(0);
12863 jt_offs_hi = pic16_popGetTempReg(1);
12864 jt_label = pic16_popGetLabel (jtab->key);
12865 //fprintf (stderr, "Creating jump table...\n");
12867 // calculate offset into jump table (idx * sizeof (GOTO))
12868 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12869 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12870 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12871 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12872 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12873 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12874 pic16_emitpcode(POC_MOVWF , jt_offs);
12876 // prepare PCLATx (set to first entry in jump table)
12877 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12878 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12879 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12880 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12881 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12883 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12884 pic16_emitpcode(POC_ADDWF , jt_offs);
12885 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12886 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12888 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12890 // release temporaries and prepare jump into table (new PCL --> WREG)
12891 pic16_emitpcode(POC_MOVFW , jt_offs);
12892 pic16_popReleaseTempReg (jt_offs_hi, 1);
12893 pic16_popReleaseTempReg (jt_offs, 0);
12895 // jump into the table
12896 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12898 pic16_emitpLabelFORCE(jtab->key);
12901 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12903 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12904 /* now generate the jump labels */
12905 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12906 jtab = setNextItem(IC_JTLABELS(ic))) {
12907 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12911 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12915 /*-----------------------------------------------------------------*/
12916 /* genMixedOperation - gen code for operators between mixed types */
12917 /*-----------------------------------------------------------------*/
12919 TSD - Written for the PIC port - but this unfortunately is buggy.
12920 This routine is good in that it is able to efficiently promote
12921 types to different (larger) sizes. Unfortunately, the temporary
12922 variables that are optimized out by this routine are sometimes
12923 used in other places. So until I know how to really parse the
12924 iCode tree, I'm going to not be using this routine :(.
12926 static int genMixedOperation (iCode *ic)
12929 operand *result = IC_RESULT(ic);
12930 sym_link *ctype = operandType(IC_LEFT(ic));
12931 operand *right = IC_RIGHT(ic);
12937 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12939 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12945 nextright = IC_RIGHT(nextic);
12946 nextleft = IC_LEFT(nextic);
12947 nextresult = IC_RESULT(nextic);
12949 pic16_aopOp(right,ic,FALSE);
12950 pic16_aopOp(result,ic,FALSE);
12951 pic16_aopOp(nextright, nextic, FALSE);
12952 pic16_aopOp(nextleft, nextic, FALSE);
12953 pic16_aopOp(nextresult, nextic, FALSE);
12955 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12957 operand *t = right;
12961 pic16_emitcode(";remove right +","");
12963 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12965 operand *t = right;
12969 pic16_emitcode(";remove left +","");
12973 big = AOP_SIZE(nextleft);
12974 small = AOP_SIZE(nextright);
12976 switch(nextic->op) {
12979 pic16_emitcode(";optimize a +","");
12980 /* if unsigned or not an integral type */
12981 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12982 pic16_emitcode(";add a bit to something","");
12985 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12987 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12988 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12989 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12991 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12999 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13000 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13001 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13004 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13006 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13007 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13008 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13009 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13010 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13013 pic16_emitcode("rlf","known_zero,w");
13020 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13021 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13022 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13024 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13034 pic16_freeAsmop(right,NULL,ic,TRUE);
13035 pic16_freeAsmop(result,NULL,ic,TRUE);
13036 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13037 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13039 nextic->generated = 1;
13046 /*-----------------------------------------------------------------*/
13047 /* genCast - gen code for casting */
13048 /*-----------------------------------------------------------------*/
13049 static void genCast (iCode *ic)
13051 operand *result = IC_RESULT(ic);
13052 sym_link *ctype = operandType(IC_LEFT(ic));
13053 sym_link *rtype = operandType(IC_RIGHT(ic));
13054 sym_link *restype = operandType(IC_RESULT(ic));
13055 operand *right = IC_RIGHT(ic);
13061 /* if they are equivalent then do nothing */
13062 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13065 pic16_aopOp(right,ic,FALSE) ;
13066 pic16_aopOp(result,ic,FALSE);
13068 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13071 /* if the result is a bit */
13072 if (AOP_TYPE(result) == AOP_CRY) {
13074 /* if the right size is a literal then
13075 * we know what the value is */
13076 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13078 if (AOP_TYPE(right) == AOP_LIT) {
13079 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13080 pic16_popGet(AOP(result),0));
13082 if (((int) operandLitValue(right)))
13083 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13084 AOP(result)->aopu.aop_dir,
13085 AOP(result)->aopu.aop_dir);
13087 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13088 AOP(result)->aopu.aop_dir,
13089 AOP(result)->aopu.aop_dir);
13093 /* the right is also a bit variable */
13094 if (AOP_TYPE(right) == AOP_CRY) {
13096 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13098 pic16_emitcode("clrc","");
13099 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13100 AOP(right)->aopu.aop_dir,
13101 AOP(right)->aopu.aop_dir);
13102 pic16_aopPut(AOP(result),"c",0);
13106 /* we need to or */
13107 if (AOP_TYPE(right) == AOP_REG) {
13108 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13109 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13110 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13112 pic16_toBoolean(right);
13113 pic16_aopPut(AOP(result),"a",0);
13117 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13120 size = AOP_SIZE(result);
13122 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13124 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13125 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13126 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13129 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13134 if(IS_BITFIELD(getSpec(restype))
13135 && IS_BITFIELD(getSpec(rtype))) {
13136 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13139 /* if they are the same size : or less */
13140 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13142 /* if they are in the same place */
13143 if (pic16_sameRegs(AOP(right),AOP(result)))
13146 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13148 if (IS_PTR_CONST(rtype))
13150 if (IS_CODEPTR(rtype))
13152 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13155 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13157 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13159 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13162 if(AOP_TYPE(right) == AOP_IMMD) {
13163 pCodeOp *pcop0, *pcop1, *pcop2;
13164 symbol *sym = OP_SYMBOL( right );
13166 size = AOP_SIZE(result);
13168 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13170 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13172 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13175 pic16_emitpcode(POC_MOVLW, pcop0);
13176 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13177 pic16_emitpcode(POC_MOVLW, pcop1);
13178 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13179 pic16_emitpcode(POC_MOVLW, pcop2);
13180 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13183 pic16_emitpcode(POC_MOVLW, pcop0);
13184 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13185 pic16_emitpcode(POC_MOVLW, pcop1);
13186 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13188 pic16_emitpcode(POC_MOVLW, pcop0);
13189 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13193 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13194 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13195 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13196 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13197 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13198 if(AOP_SIZE(result) <2)
13199 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13201 /* if they in different places then copy */
13202 size = AOP_SIZE(result);
13205 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13206 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13213 /* if the result is of type pointer */
13214 if (IS_PTR(ctype)) {
13216 sym_link *type = operandType(right);
13217 sym_link *etype = getSpec(type);
13219 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13221 /* pointer to generic pointer */
13222 if (IS_GENPTR(ctype)) {
13226 p_type = DCL_TYPE(type);
13228 /* we have to go by the storage class */
13229 p_type = PTR_TYPE(SPEC_OCLS(etype));
13231 /* if (SPEC_OCLS(etype)->codesp ) */
13232 /* p_type = CPOINTER ; */
13234 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13235 /* p_type = FPOINTER ; */
13237 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13238 /* p_type = PPOINTER; */
13240 /* if (SPEC_OCLS(etype) == idata ) */
13241 /* p_type = IPOINTER ; */
13243 /* p_type = POINTER ; */
13246 /* the first two bytes are known */
13247 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13248 size = GPTRSIZE - 1;
13251 if(offset < AOP_SIZE(right)) {
13252 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13253 mov2f(AOP(result), AOP(right), offset);
13255 if ((AOP_TYPE(right) == AOP_PCODE) &&
13256 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13257 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13261 pic16_aopPut(AOP(result),
13262 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13267 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13270 /* the last byte depending on type */
13274 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13275 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13276 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13280 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13284 pic16_emitcode(";BUG!? ","%d",__LINE__);
13288 pic16_emitcode(";BUG!? ","%d",__LINE__);
13293 if (GPTRSIZE > AOP_SIZE(right)) {
13294 // assume data pointer... THIS MIGHT BE WRONG!
13295 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13296 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13298 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13303 /* this should never happen */
13304 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13305 "got unknown pointer type");
13308 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13312 /* just copy the pointers */
13313 size = AOP_SIZE(result);
13316 pic16_aopPut(AOP(result),
13317 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13326 /* so we now know that the size of destination is greater
13327 than the size of the source.
13328 Now, if the next iCode is an operator then we might be
13329 able to optimize the operation without performing a cast.
13331 if(genMixedOperation(ic))
13334 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13336 /* we move to result for the size of source */
13337 size = AOP_SIZE(right);
13340 mov2f(AOP(result), AOP(right), offset);
13344 /* now depending on the sign of the destination */
13345 size = AOP_SIZE(result) - AOP_SIZE(right);
13346 /* if unsigned or not an integral type */
13347 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13349 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13351 /* we need to extend the sign :( */
13354 /* Save one instruction of casting char to int */
13355 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13356 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13357 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13359 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13362 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13364 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13366 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13369 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13374 pic16_freeAsmop(right,NULL,ic,TRUE);
13375 pic16_freeAsmop(result,NULL,ic,TRUE);
13379 /*-----------------------------------------------------------------*/
13380 /* genDjnz - generate decrement & jump if not zero instrucion */
13381 /*-----------------------------------------------------------------*/
13382 static int genDjnz (iCode *ic, iCode *ifx)
13384 symbol *lbl, *lbl1;
13385 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13390 /* if the if condition has a false label
13391 then we cannot save */
13395 /* if the minus is not of the form
13397 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13398 !IS_OP_LITERAL(IC_RIGHT(ic)))
13401 if (operandLitValue(IC_RIGHT(ic)) != 1)
13404 /* if the size of this greater than one then no
13406 if (getSize(operandType(IC_RESULT(ic))) > 1)
13409 /* otherwise we can save BIG */
13410 lbl = newiTempLabel(NULL);
13411 lbl1= newiTempLabel(NULL);
13413 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13415 if (IS_AOP_PREG(IC_RESULT(ic))) {
13416 pic16_emitcode("dec","%s",
13417 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13418 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13419 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13423 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13424 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13426 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13427 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13431 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13432 ifx->generated = 1;
13436 /*-----------------------------------------------------------------*/
13437 /* genReceive - generate code for a receive iCode */
13438 /*-----------------------------------------------------------------*/
13439 static void genReceive (iCode *ic)
13445 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13446 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13448 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13450 if (isOperandInFarSpace(IC_RESULT(ic))
13451 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13452 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13454 int size = getSize(operandType(IC_RESULT(ic)));
13455 int offset = pic16_fReturnSizePic - size;
13459 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13460 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13464 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13466 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13467 size = AOP_SIZE(IC_RESULT(ic));
13470 pic16_emitcode ("pop","acc");
13471 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13474 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13476 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13479 /* set pseudo stack pointer to where it should be - dw*/
13480 GpsuedoStkPtr = ic->parmBytes;
13482 /* setting GpsuedoStkPtr has side effects here: */
13483 assignResultValue(IC_RESULT(ic), 0);
13486 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13489 /*-----------------------------------------------------------------*/
13490 /* genDummyRead - generate code for dummy read of volatiles */
13491 /*-----------------------------------------------------------------*/
13493 genDummyRead (iCode * ic)
13495 pic16_emitcode ("; genDummyRead","");
13496 pic16_emitcode ("; not implemented","");
13501 /*-----------------------------------------------------------------*/
13502 /* genpic16Code - generate code for pic16 based controllers */
13503 /*-----------------------------------------------------------------*/
13505 * At this point, ralloc.c has gone through the iCode and attempted
13506 * to optimize in a way suitable for a PIC. Now we've got to generate
13507 * PIC instructions that correspond to the iCode.
13509 * Once the instructions are generated, we'll pass through both the
13510 * peep hole optimizer and the pCode optimizer.
13511 *-----------------------------------------------------------------*/
13513 void genpic16Code (iCode *lic)
13518 lineHead = lineCurr = NULL;
13520 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13521 pic16_addpBlock(pb);
13524 /* if debug information required */
13525 if (options.debug && currFunc) {
13527 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13532 for (ic = lic ; ic ; ic = ic->next ) {
13534 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13535 if ( cln != ic->lineno ) {
13536 if ( options.debug ) {
13537 debugFile->writeCLine (ic);
13540 if(!options.noCcodeInAsm) {
13541 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13542 printCLine(ic->filename, ic->lineno)));
13548 if(options.iCodeInAsm) {
13551 /* insert here code to print iCode as comment */
13552 l = Safe_strdup(printILine(ic));
13553 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13556 /* if the result is marked as
13557 * spilt and rematerializable or code for
13558 * this has already been generated then
13560 if (resultRemat(ic) || ic->generated )
13563 /* depending on the operation */
13582 /* IPOP happens only when trying to restore a
13583 * spilt live range, if there is an ifx statement
13584 * following this pop then the if statement might
13585 * be using some of the registers being popped which
13586 * would destroy the contents of the register so
13587 * we need to check for this condition and handle it */
13589 && ic->next->op == IFX
13590 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13591 genIfx (ic->next,ic);
13609 genEndFunction (ic);
13625 pic16_genPlus (ic) ;
13629 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13630 pic16_genMinus (ic);
13646 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13650 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13656 /* note these two are xlated by algebraic equivalence
13657 * during parsing SDCC.y */
13658 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13659 "got '>=' or '<=' shouldn't have come here");
13663 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13675 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13679 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13683 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13707 genRightShift (ic);
13710 case GET_VALUE_AT_ADDRESS:
13715 if (POINTER_SET(ic))
13742 addSet(&_G.sendSet,ic);
13745 case DUMMY_READ_VOLATILE:
13755 /* now we are ready to call the
13756 peep hole optimizer */
13757 if (!options.nopeep)
13758 peepHole (&lineHead);
13760 /* now do the actual printing */
13761 printLine (lineHead, codeOutFile);
13764 DFPRINTF((stderr,"printing pBlock\n\n"));
13765 pic16_printpBlock(stdout,pb);