1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2f(asmop *dst, asmop *src, int offset);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
141 static char *accUse[] = {"WREG"};
143 //static short rbank = -1;
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);
655 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
657 sym->aop = aop = newAsmop (AOP_PAGED);
658 aop->aopu.aop_dir = sym->rname ;
659 aop->size = getSize(sym->type);
660 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
661 pic16_allocDirReg( IC_LEFT(ic) );
669 /* assign depending on the storage class */
670 /* if it is on the stack or indirectly addressable */
671 /* space we need to assign either r0 or r1 to it */
672 if (sym->onStack) // || sym->iaccess)
677 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
678 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
680 /* acquire a temporary register -- it is saved in function */
682 sym->aop = aop = newAsmop(AOP_STA);
683 aop->aopu.stk.stk = sym->stack;
684 aop->size = getSize(sym->type);
687 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
688 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
689 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
690 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
692 for(i=0;i<aop->size;i++)
693 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
694 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
696 for(i=0;i<aop->size;i++) {
697 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
698 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
702 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
705 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
708 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
711 for(i=0;i<aop->size;i++) {
713 /* initialise for stack access via frame pointer */
714 // operands on stack are accessible via "FSR2 + index" with index
715 // starting at 2 for arguments and growing from 0 downwards for
716 // local variables (index == 0 is not assigned so we add one here)
718 int soffs = sym->stack;
723 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
724 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
725 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
730 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
737 /* now assign the address of the variable to
738 the pointer register */
739 if (aop->type != AOP_STK) {
743 pic16_emitcode("push","acc");
745 pic16_emitcode("mov","a,_bp");
746 pic16_emitcode("add","a,#0x%02x",
748 ((char)(sym->stack - _G.nRegsSaved )) :
749 ((char)sym->stack)) & 0xff);
750 pic16_emitcode("mov","%s,a",
751 aop->aopu.aop_ptr->name);
754 pic16_emitcode("pop","acc");
756 pic16_emitcode("mov","%s,#%s",
757 aop->aopu.aop_ptr->name,
759 aop->paged = space->paged;
761 aop->aopu.aop_stk = sym->stack;
769 if (sym->onStack && options.stack10bit)
771 /* It's on the 10 bit stack, which is located in
775 //DEBUGpic16_emitcode(";","%d",__LINE__);
778 pic16_emitcode("push","acc");
780 pic16_emitcode("mov","a,_bp");
781 pic16_emitcode("add","a,#0x%02x",
783 ((char)(sym->stack - _G.nRegsSaved )) :
784 ((char)sym->stack)) & 0xff);
787 pic16_emitcode ("mov","dpx1,#0x40");
788 pic16_emitcode ("mov","dph1,#0x00");
789 pic16_emitcode ("mov","dpl1, a");
793 pic16_emitcode("pop","acc");
795 sym->aop = aop = newAsmop(AOP_DPTR2);
796 aop->size = getSize(sym->type);
802 /* special case for a function */
803 if (IS_FUNC(sym->type)) {
804 sym->aop = aop = newAsmop(AOP_PCODE);
805 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
806 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
807 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
808 PCOI(aop->aopu.pcop)->index = 0;
809 aop->size = FPTRSIZE;
810 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
817 //DEBUGpic16_emitcode(";","%d",__LINE__);
818 /* if in bit space */
819 if (IN_BITSPACE(space)) {
820 sym->aop = aop = newAsmop (AOP_CRY);
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);
826 /* if it is in direct space */
827 if (IN_DIRSPACE(space)) {
828 sym->aop = aop = newAsmop (AOP_DIR);
829 aop->aopu.aop_dir = sym->rname ;
830 aop->size = getSize(sym->type);
831 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
832 pic16_allocDirReg( IC_LEFT(ic) );
837 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
838 sym->aop = aop = newAsmop (AOP_DIR);
839 aop->aopu.aop_dir = sym->rname ;
840 aop->size = getSize(sym->type);
841 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
842 pic16_allocDirReg( IC_LEFT(ic) );
847 /* only remaining is far space */
848 sym->aop = aop = newAsmop(AOP_PCODE);
850 /* change the next if to 1 to revert to good old immediate code */
851 if(IN_CODESPACE(space)) {
852 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
853 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
854 PCOI(aop->aopu.pcop)->index = 0;
856 /* try to allocate via direct register */
857 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
858 // aop->size = getSize( sym->type );
861 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
862 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
865 if(!pic16_allocDirReg (IC_LEFT(ic)))
869 if(IN_DIRSPACE( space ))
871 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
872 aop->size = FPTRSIZE;
873 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
874 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
875 else if(sym->onStack) {
878 if(SPEC_SCLS(sym->etype) == S_PDATA) {
879 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
880 aop->size = FPTRSIZE;
885 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
887 /* if it is in code space */
888 if (IN_CODESPACE(space))
894 /*-----------------------------------------------------------------*/
895 /* aopForRemat - rematerialzes an object */
896 /*-----------------------------------------------------------------*/
897 static asmop *aopForRemat (operand *op) // x symbol *sym)
899 symbol *sym = OP_SYMBOL(op);
901 iCode *ic = NULL, *oldic;
902 asmop *aop = newAsmop(AOP_PCODE);
909 ic = sym->rematiCode;
911 if(IS_OP_POINTER(op)) {
912 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
918 // pic16_emitpcomment("ic: %s\n", printILine(ic));
921 val += (int) operandLitValue(IC_RIGHT(ic));
922 } else if (ic->op == '-') {
923 val -= (int) operandLitValue(IC_RIGHT(ic));
927 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
930 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
933 if(!op->isaddr)viaimmd++; else viaimmd=0;
935 /* set the following if to 1 to revert to good old immediate code */
936 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
939 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
941 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
944 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
946 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
949 PCOI(aop->aopu.pcop)->index = val;
951 aop->size = getSize( sym->type );
953 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
955 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
956 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
958 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
962 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
963 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
965 val, IS_PTR_CONST(operandType(op)));
967 val, IS_CODEPTR(operandType(op)));
970 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
972 pic16_allocDirReg (IC_LEFT(ic));
974 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
981 static int aopIdx (asmop *aop, int offset)
986 if(aop->type != AOP_REG)
989 return aop->aopu.aop_reg[offset]->rIdx;
994 /*-----------------------------------------------------------------*/
995 /* regsInCommon - two operands have some registers in common */
996 /*-----------------------------------------------------------------*/
997 static bool regsInCommon (operand *op1, operand *op2)
1002 /* if they have registers in common */
1003 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1006 sym1 = OP_SYMBOL(op1);
1007 sym2 = OP_SYMBOL(op2);
1009 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1012 for (i = 0 ; i < sym1->nRegs ; i++) {
1017 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1021 if (sym2->regs[j] == sym1->regs[i])
1029 /*-----------------------------------------------------------------*/
1030 /* operandsEqu - equivalent */
1031 /*-----------------------------------------------------------------*/
1032 static bool operandsEqu ( operand *op1, operand *op2)
1034 symbol *sym1, *sym2;
1036 /* if they not symbols */
1037 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1040 sym1 = OP_SYMBOL(op1);
1041 sym2 = OP_SYMBOL(op2);
1043 /* if both are itemps & one is spilt
1044 and the other is not then false */
1045 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1046 sym1->isspilt != sym2->isspilt )
1049 /* if they are the same */
1053 if (sym1->rname[0] && sym2->rname[0]
1054 && strcmp (sym1->rname, sym2->rname) == 0)
1058 /* if left is a tmp & right is not */
1059 if (IS_ITEMP(op1) &&
1062 (sym1->usl.spillLoc == sym2))
1065 if (IS_ITEMP(op2) &&
1069 (sym2->usl.spillLoc == sym1))
1075 /*-----------------------------------------------------------------*/
1076 /* pic16_sameRegs - two asmops have the same registers */
1077 /*-----------------------------------------------------------------*/
1078 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1085 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1086 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1088 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1090 if (aop1->type != AOP_REG ||
1091 aop2->type != AOP_REG )
1094 /* This is a bit too restrictive if one is a subset of the other...
1095 if (aop1->size != aop2->size )
1099 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1100 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1102 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1103 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1110 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1112 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1113 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1115 if(aop1 == aop2)return TRUE;
1116 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1118 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1124 /*-----------------------------------------------------------------*/
1125 /* pic16_aopOp - allocates an asmop for an operand : */
1126 /*-----------------------------------------------------------------*/
1127 void pic16_aopOp (operand *op, iCode *ic, bool result)
1136 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1138 /* if this a literal */
1139 if (IS_OP_LITERAL(op)) {
1140 op->aop = aop = newAsmop(AOP_LIT);
1141 aop->aopu.aop_lit = op->operand.valOperand;
1142 aop->size = getSize(operandType(op));
1147 sym_link *type = operandType(op);
1149 if(IS_PTR_CONST(type))
1151 if(IS_CODEPTR(type))
1153 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1156 /* if already has a asmop then continue */
1160 /* if the underlying symbol has a aop */
1161 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1162 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1163 op->aop = OP_SYMBOL(op)->aop;
1167 /* if this is a true symbol */
1168 if (IS_TRUE_SYMOP(op)) {
1169 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1170 op->aop = aopForSym(ic, op, result);
1174 /* this is a temporary : this has
1180 e) can be a return use only */
1182 sym = OP_SYMBOL(op);
1184 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1185 /* if the type is a conditional */
1186 if (sym->regType == REG_CND) {
1187 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1192 /* if it is spilt then two situations
1194 b) has a spill location */
1195 if (sym->isspilt || sym->nRegs == 0) {
1197 // debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
1198 DEBUGpic16_emitcode(";","%d",__LINE__);
1199 /* rematerialize it NOW */
1202 sym->aop = op->aop = aop = aopForRemat (op);
1203 // aop->size = getSize(sym->type);
1204 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1211 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1212 aop->size = getSize(sym->type);
1213 for ( i = 0 ; i < 1 ; i++ ) {
1214 aop->aopu.aop_str[i] = accUse[i];
1215 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1217 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1218 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1226 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1227 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1228 //pic16_allocDirReg (IC_LEFT(ic));
1229 aop->size = getSize(sym->type);
1234 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1235 aop->size = getSize(sym->type);
1236 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1237 aop->aopu.aop_str[i] = fReturn[i];
1239 DEBUGpic16_emitcode(";","%d",__LINE__);
1243 /* else spill location */
1244 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1245 /* force a new aop if sizes differ */
1246 sym->usl.spillLoc->aop = NULL;
1250 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1251 __FUNCTION__,__LINE__,
1252 sym->usl.spillLoc->rname,
1253 sym->rname, sym->usl.spillLoc->offset);
1256 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1257 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1258 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1260 sym->usl.spillLoc->offset, op);
1261 aop->size = getSize(sym->type);
1267 sym_link *type = operandType(op);
1269 if(IS_PTR_CONST(type))
1271 if(IS_CODEPTR(type))
1273 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1276 /* must be in a register */
1277 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1278 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1279 aop->size = sym->nRegs;
1280 for ( i = 0 ; i < sym->nRegs ;i++)
1281 aop->aopu.aop_reg[i] = sym->regs[i];
1284 /*-----------------------------------------------------------------*/
1285 /* pic16_freeAsmop - free up the asmop given to an operand */
1286 /*----------------------------------------------------------------*/
1287 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1304 /* depending on the asmop type only three cases need work AOP_RO
1305 , AOP_R1 && AOP_STK */
1307 switch (aop->type) {
1309 if (_G.fsr0Pushed ) {
1311 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1312 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1313 // pic16_emitcode ("pop","ar0");
1317 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1321 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1327 pic16_emitcode ("pop","ar0");
1331 bitVectUnSetBit(ic->rUsed,R0_IDX);
1337 pic16_emitcode ("pop","ar1");
1341 bitVectUnSetBit(ic->rUsed,R1_IDX);
1348 /* we must store the result on stack */
1349 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1350 // operands on stack are accessible via "FSR2 + index" with index
1351 // starting at 2 for arguments and growing from 0 downwards for
1352 // local variables (index == 0 is not assigned so we add one here)
1353 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1358 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1359 for(i=0;i<aop->size;i++) {
1360 /* initialise for stack access via frame pointer */
1361 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1362 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1363 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1366 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1370 for(i=0;i<aop->size;i++)
1371 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1380 int stk = aop->aopu.aop_stk + aop->size;
1381 bitVectUnSetBit(ic->rUsed,R0_IDX);
1382 bitVectUnSetBit(ic->rUsed,R1_IDX);
1384 getFreePtr(ic,&aop,FALSE);
1386 if (options.stack10bit)
1388 /* I'm not sure what to do here yet... */
1391 "*** Warning: probably generating bad code for "
1392 "10 bit stack mode.\n");
1396 pic16_emitcode ("mov","a,_bp");
1397 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1398 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1400 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1404 pic16_emitcode("pop","acc");
1405 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1407 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1410 pic16_freeAsmop(op,NULL,ic,TRUE);
1412 pic16_emitcode("pop","ar0");
1417 pic16_emitcode("pop","ar1");
1427 /* all other cases just dealloc */
1431 OP_SYMBOL(op)->aop = NULL;
1432 /* if the symbol has a spill */
1434 SPIL_LOC(op)->aop = NULL;
1439 /*-----------------------------------------------------------------*/
1440 /* pic16_aopGet - for fetching value of the aop */
1441 /*-----------------------------------------------------------------*/
1442 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1447 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1449 /* offset is greater than size then zero */
1450 if (offset > (aop->size - 1) &&
1451 aop->type != AOP_LIT)
1454 /* depending on type */
1455 switch (aop->type) {
1459 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1460 rs = Safe_calloc(1, strlen(s)+1);
1465 /* if we need to increment it */
1466 while (offset > aop->coff)
1468 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1472 while (offset < aop->coff)
1474 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1480 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1481 return (dname ? "acc" : "a");
1483 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1484 rs = Safe_calloc (1, strlen (s) + 1);
1492 sprintf (s,"%s",aop->aopu.aop_immd);
1495 sprintf(s,"(%s >> %d)",
1500 aop->aopu.aop_immd);
1501 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1502 rs = Safe_calloc(1,strlen(s)+1);
1508 sprintf(s,"(%s + %d)",
1511 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1513 sprintf(s,"%s",aop->aopu.aop_dir);
1514 rs = Safe_calloc(1,strlen(s)+1);
1520 // return aop->aopu.aop_reg[offset]->dname;
1522 return aop->aopu.aop_reg[offset]->name;
1525 //pic16_emitcode(";","%d",__LINE__);
1526 return aop->aopu.aop_dir;
1529 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1530 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1532 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1533 rs = Safe_strdup("WREG");
1537 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1538 rs = Safe_calloc(1,strlen(s)+1);
1543 aop->coff = offset ;
1544 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1547 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1549 return aop->aopu.aop_str[offset];
1553 pCodeOp *pcop = aop->aopu.pcop;
1554 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1556 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1557 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1559 sprintf(s,"(%s + %d)", pcop->name, offset);
1561 sprintf(s,"%s", pcop->name);
1564 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1567 rs = Safe_calloc(1,strlen(s)+1);
1573 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1575 sprintf(s,"(%s + %d)",
1579 sprintf(s,"%s",aop->aopu.aop_dir);
1580 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1581 rs = Safe_calloc(1,strlen(s)+1);
1587 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1591 // pCodeOp *pcop = aop->aop
1596 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1597 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1598 "aopget got unsupported aop->type");
1604 /* lock has the following meaning: When allocating temporary registers
1605 * for stack variables storage, the value of the temporary register is
1606 * saved on stack. Its value is restored at the end. This procedure is
1607 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1608 * a possibility that before a call to pic16_aopOp, a temporary register
1609 * is allocated for a while and it is freed after some time, this will
1610 * mess the stack and values will not be restored properly. So use lock=1
1611 * to allocate temporary registers used internally by the programmer, and
1612 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1613 * to inform the compiler developer about a possible bug. This is an internal
1614 * feature for developing the compiler -- VR */
1616 int _TempReg_lock = 0;
1617 /*-----------------------------------------------------------------*/
1618 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1619 /*-----------------------------------------------------------------*/
1620 pCodeOp *pic16_popGetTempReg(int lock)
1625 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1627 // werror(W_POSSBUG2, __FILE__, __LINE__);
1630 _TempReg_lock += lock;
1635 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1636 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1637 PCOR(pcop)->r->wasUsed=1;
1638 PCOR(pcop)->r->isFree=0;
1640 /* push value on stack */
1641 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1649 /*-----------------------------------------------------------------*/
1650 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1651 /* don't save if inside v */
1652 /*-----------------------------------------------------------------*/
1653 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1658 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1661 // werror(W_POSSBUG2, __FILE__, __LINE__);
1664 _TempReg_lock += lock;
1669 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1670 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1671 PCOR(pcop)->r->wasUsed=1;
1672 PCOR(pcop)->r->isFree=0;
1674 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1675 /* push value on stack */
1676 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1686 /*-----------------------------------------------------------------*/
1687 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1688 /*-----------------------------------------------------------------*/
1689 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1693 _TempReg_lock -= lock;
1695 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1696 PCOR(pcop)->r->isFree = 1;
1697 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1700 /*-----------------------------------------------------------------*/
1701 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1702 /*-----------------------------------------------------------------*/
1703 pCodeOp *pic16_popGetLabel(unsigned int key)
1706 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1711 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1714 /*-----------------------------------------------------------------*/
1715 /* pic16_popCopyReg - copy a pcode operator */
1716 /*-----------------------------------------------------------------*/
1717 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1721 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1722 pcor->pcop.type = pc->pcop.type;
1724 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1725 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1727 pcor->pcop.name = NULL;
1730 pcor->rIdx = pc->rIdx;
1732 pcor->instance = pc->instance;
1734 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1739 /*-----------------------------------------------------------------*/
1740 /* pic16_popGetLit - asm operator to pcode operator conversion */
1741 /*-----------------------------------------------------------------*/
1742 pCodeOp *pic16_popGetLit(int lit)
1744 return pic16_newpCodeOpLit(lit);
1747 /*-----------------------------------------------------------------*/
1748 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1749 /*-----------------------------------------------------------------*/
1750 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1752 return pic16_newpCodeOpLit2(lit, arg2);
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1758 /*-----------------------------------------------------------------*/
1759 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1761 return pic16_newpCodeOpImmd(name, offset,index, 0);
1765 /*-----------------------------------------------------------------*/
1766 /* pic16_popGet - asm operator to pcode operator conversion */
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *pic16_popGetWithString(char *str)
1774 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1778 pcop = pic16_newpCodeOp(str,PO_STR);
1783 /*-----------------------------------------------------------------*/
1784 /* pic16_popRegFromString - */
1785 /*-----------------------------------------------------------------*/
1786 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1789 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1790 pcop->type = PO_DIR;
1792 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1793 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1798 pcop->name = Safe_calloc(1,strlen(str)+1);
1799 strcpy(pcop->name,str);
1801 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1803 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1805 /* make sure that register doesn't exist,
1806 * and operand isn't NULL
1807 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1808 if((PCOR(pcop)->r == NULL)
1810 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1811 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1812 // __FUNCTION__, __LINE__, str, size, offset);
1814 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1815 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1818 PCOR(pcop)->instance = offset;
1823 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1827 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1829 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1830 PCOR(pcop)->rIdx = rIdx;
1831 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1833 PCOR(pcop)->r->isFree = 0;
1834 PCOR(pcop)->r->wasUsed = 1;
1836 pcop->type = PCOR(pcop)->r->pc_type;
1841 /*---------------------------------------------------------------------------------*/
1842 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1844 /*---------------------------------------------------------------------------------*/
1845 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1850 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1852 /* comment the following check, so errors to throw up */
1853 // if(!pcop2)return NULL;
1855 temp = pic16_popGet(aop_dst, offset);
1856 pcop2->pcop2 = temp;
1863 /*--------------------------------------------------------------------------------.-*/
1864 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1865 /* VR 030601 , adapted by Hans Dorn */
1866 /*--------------------------------------------------------------------------------.-*/
1867 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1871 pcop2 = (pCodeOpReg2 *)src;
1879 /*---------------------------------------------------------------------------------*/
1880 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1881 /* movff instruction */
1882 /*---------------------------------------------------------------------------------*/
1883 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1888 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1889 pcop2->pcop2 = pic16_popCopyReg(dst);
1891 /* the pCodeOp may be already allocated */
1892 pcop2 = (pCodeOpReg2 *)(src);
1893 pcop2->pcop2 = (pCodeOp *)(dst);
1900 /*-----------------------------------------------------------------*/
1901 /* pic16_popGet - asm operator to pcode operator conversion */
1902 /*-----------------------------------------------------------------*/
1903 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1905 //char *s = buffer ;
1910 /* offset is greater than
1913 // if (offset > (aop->size - 1) &&
1914 // aop->type != AOP_LIT)
1915 // return NULL; //zero;
1917 /* depending on type */
1918 switch (aop->type) {
1924 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1925 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1932 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1933 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1934 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1935 PCOR(pcop)->r->wasUsed = 1;
1936 PCOR(pcop)->r->isFree = 0;
1938 PCOR(pcop)->instance = offset;
1939 pcop->type = PCOR(pcop)->r->pc_type;
1943 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1944 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1947 /* pCodeOp is already allocated from aopForSym */
1948 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1949 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1955 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1957 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1959 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1961 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1962 PCOR(pcop)->rIdx = rIdx;
1963 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1964 PCOR(pcop)->r->wasUsed=1;
1965 PCOR(pcop)->r->isFree=0;
1967 PCOR(pcop)->instance = offset;
1968 pcop->type = PCOR(pcop)->r->pc_type;
1969 // rs = aop->aopu.aop_reg[offset]->name;
1970 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1974 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1975 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1981 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1982 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1986 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1987 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1993 assert (aop && aop->aopu.aop_reg[offset] != NULL);
1994 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1996 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1998 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1999 // pcop->type = PO_GPR_REGISTER;
2000 PCOR(pcop)->rIdx = rIdx;
2001 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2002 PCOR(pcop)->r->wasUsed=1;
2003 PCOR(pcop)->r->isFree=0;
2005 PCOR(pcop)->instance = offset;
2006 pcop->type = PCOR(pcop)->r->pc_type;
2008 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
2009 rs = aop->aopu.aop_reg[offset]->name;
2010 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2015 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2017 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2018 PCOR(pcop)->instance = offset;
2019 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2020 //if(PCOR(pcop)->r == NULL)
2021 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2025 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2026 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2029 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2030 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2033 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2034 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2035 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2036 pcop->type = PCOR(pcop)->r->pc_type;
2037 pcop->name = PCOR(pcop)->r->name;
2043 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2045 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2046 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2047 switch( aop->aopu.pcop->type ) {
2048 case PO_DIR: PCOR(pcop)->instance += offset; break;
2049 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2051 assert( 0 ); /* should never reach here */;
2056 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2057 "pic16_popGet got unsupported aop->type");
2060 /*-----------------------------------------------------------------*/
2061 /* pic16_aopPut - puts a string for a aop */
2062 /*-----------------------------------------------------------------*/
2063 void pic16_aopPut (asmop *aop, char *s, int offset)
2070 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2072 if (aop->size && offset > ( aop->size - 1)) {
2073 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2074 "pic16_aopPut got offset > aop->size");
2078 /* will assign value to value */
2079 /* depending on where it is ofcourse */
2080 switch (aop->type) {
2083 sprintf(d,"(%s + %d)",
2084 aop->aopu.aop_dir,offset);
2085 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2088 sprintf(d,"%s",aop->aopu.aop_dir);
2091 DEBUGpic16_emitcode(";","%d",__LINE__);
2093 pic16_emitcode("movf","%s,w",s);
2094 pic16_emitcode("movwf","%s",d);
2097 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2098 if(offset >= aop->size) {
2099 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2102 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2105 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2112 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2113 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2116 strcmp(s,"r0") == 0 ||
2117 strcmp(s,"r1") == 0 ||
2118 strcmp(s,"r2") == 0 ||
2119 strcmp(s,"r3") == 0 ||
2120 strcmp(s,"r4") == 0 ||
2121 strcmp(s,"r5") == 0 ||
2122 strcmp(s,"r6") == 0 ||
2123 strcmp(s,"r7") == 0 )
2124 pic16_emitcode("mov","%s,%s ; %d",
2125 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2129 if(strcmp(s,"W")==0 )
2130 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2132 pic16_emitcode("movwf","%s",
2133 aop->aopu.aop_reg[offset]->name);
2135 if(strcmp(s,zero)==0) {
2136 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2138 } else if(strcmp(s,"W")==0) {
2139 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2140 pcop->type = PO_GPR_REGISTER;
2142 PCOR(pcop)->rIdx = -1;
2143 PCOR(pcop)->r = NULL;
2145 DEBUGpic16_emitcode(";","%d",__LINE__);
2146 pcop->name = Safe_strdup(s);
2147 pic16_emitpcode(POC_MOVFW,pcop);
2148 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2149 } else if(strcmp(s,one)==0) {
2150 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2151 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2153 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2161 if (aop->type == AOP_DPTR2)
2167 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2168 "pic16_aopPut writting to code space");
2172 while (offset > aop->coff) {
2174 pic16_emitcode ("inc","dptr");
2177 while (offset < aop->coff) {
2179 pic16_emitcode("lcall","__decdptr");
2184 /* if not in accumulater */
2187 pic16_emitcode ("movx","@dptr,a");
2189 if (aop->type == AOP_DPTR2)
2197 while (offset > aop->coff) {
2199 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2201 while (offset < aop->coff) {
2203 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2209 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2214 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2216 if (strcmp(s,"r0") == 0 ||
2217 strcmp(s,"r1") == 0 ||
2218 strcmp(s,"r2") == 0 ||
2219 strcmp(s,"r3") == 0 ||
2220 strcmp(s,"r4") == 0 ||
2221 strcmp(s,"r5") == 0 ||
2222 strcmp(s,"r6") == 0 ||
2223 strcmp(s,"r7") == 0 ) {
2225 sprintf(buffer,"a%s",s);
2226 pic16_emitcode("mov","@%s,%s",
2227 aop->aopu.aop_ptr->name,buffer);
2229 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2234 if (strcmp(s,"a") == 0)
2235 pic16_emitcode("push","acc");
2237 pic16_emitcode("push","%s",s);
2242 /* if bit variable */
2243 if (!aop->aopu.aop_dir) {
2244 pic16_emitcode("clr","a");
2245 pic16_emitcode("rlc","a");
2248 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2251 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2254 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2256 lbl = newiTempLabel(NULL);
2258 if (strcmp(s,"a")) {
2261 pic16_emitcode("clr","c");
2262 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2263 pic16_emitcode("cpl","c");
2264 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2265 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2272 if (strcmp(aop->aopu.aop_str[offset],s))
2273 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2278 if (!offset && (strcmp(s,"acc") == 0))
2281 if (strcmp(aop->aopu.aop_str[offset],s))
2282 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2286 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2287 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2288 // "pic16_aopPut got unsupported aop->type");
2294 /*-----------------------------------------------------------------*/
2295 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2296 /*-----------------------------------------------------------------*/
2297 void pic16_mov2w (asmop *aop, int offset)
2299 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2302 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2304 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2307 static void mov2f(asmop *dst, asmop *src, int offset)
2309 if(is_LitAOp(src)) {
2310 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2311 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2313 if(pic16_sameRegsOfs(src, dst, offset))return;
2314 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2315 pic16_popGet(dst, offset)));
2319 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2321 if(is_LitAOp(src)) {
2322 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2323 pic16_emitpcode(POC_MOVWF, dst);
2325 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2329 void pic16_testStackOverflow(void)
2331 #define GSTACK_TEST_NAME "__gstack_test"
2333 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2338 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2339 strcpy(sym->rname, GSTACK_TEST_NAME);
2340 checkAddSym(&externs, sym);
2345 /* push pcop into stack */
2346 void pic16_pushpCodeOp(pCodeOp *pcop)
2348 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2349 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2350 if(pic16_options.gstack)
2351 pic16_testStackOverflow();
2355 /* pop pcop from stack */
2356 void pic16_poppCodeOp(pCodeOp *pcop)
2358 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2359 if(pic16_options.gstack)
2360 pic16_testStackOverflow();
2364 /*-----------------------------------------------------------------*/
2365 /* pushw - pushes wreg to stack */
2366 /*-----------------------------------------------------------------*/
2369 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2370 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2371 if(pic16_options.gstack)
2372 pic16_testStackOverflow();
2376 /*-----------------------------------------------------------------*/
2377 /* pushaop - pushes aop to stack */
2378 /*-----------------------------------------------------------------*/
2379 void pushaop(asmop *aop, int offset)
2381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2383 if(is_LitAOp(aop)) {
2384 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2385 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
2387 pic16_emitpcode(POC_MOVFF,
2388 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2391 if(pic16_options.gstack)
2392 pic16_testStackOverflow();
2395 /*-----------------------------------------------------------------*/
2396 /* popaop - pops aop from stack */
2397 /*-----------------------------------------------------------------*/
2398 void popaop(asmop *aop, int offset)
2400 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2401 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2402 if(pic16_options.gstack)
2403 pic16_testStackOverflow();
2406 void popaopidx(asmop *aop, int offset, int index)
2410 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2412 if(STACK_MODEL_LARGE)ofs++;
2414 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2415 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2416 if(pic16_options.gstack)
2417 pic16_testStackOverflow();
2420 #if !(USE_GENERIC_SIGNED_SHIFT)
2421 /*-----------------------------------------------------------------*/
2422 /* reAdjustPreg - points a register back to where it should */
2423 /*-----------------------------------------------------------------*/
2424 static void reAdjustPreg (asmop *aop)
2428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2430 if ((size = aop->size) <= 1)
2433 switch (aop->type) {
2437 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2441 if (aop->type == AOP_DPTR2)
2447 pic16_emitcode("lcall","__decdptr");
2450 if (aop->type == AOP_DPTR2)
2462 /*-----------------------------------------------------------------*/
2463 /* opIsGptr: returns non-zero if the passed operand is */
2464 /* a generic pointer type. */
2465 /*-----------------------------------------------------------------*/
2466 static int opIsGptr(operand *op)
2468 sym_link *type = operandType(op);
2470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2471 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2479 /*-----------------------------------------------------------------*/
2480 /* pic16_getDataSize - get the operand data size */
2481 /*-----------------------------------------------------------------*/
2482 int pic16_getDataSize(operand *op)
2484 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2487 return AOP_SIZE(op);
2489 // tsd- in the pic port, the genptr size is 1, so this code here
2490 // fails. ( in the 8051 port, the size was 4).
2493 size = AOP_SIZE(op);
2494 if (size == GPTRSIZE)
2496 sym_link *type = operandType(op);
2497 if (IS_GENPTR(type))
2499 /* generic pointer; arithmetic operations
2500 * should ignore the high byte (pointer type).
2503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2510 /*-----------------------------------------------------------------*/
2511 /* pic16_outAcc - output Acc */
2512 /*-----------------------------------------------------------------*/
2513 void pic16_outAcc(operand *result)
2516 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2517 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2520 size = pic16_getDataSize(result);
2522 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2525 /* unsigned or positive */
2527 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2532 /*-----------------------------------------------------------------*/
2533 /* pic16_outBitC - output a bit C */
2534 /* Move to result the value of Carry flag -- VR */
2535 /*-----------------------------------------------------------------*/
2536 void pic16_outBitC(operand *result)
2540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2542 /* if the result is bit */
2543 if (AOP_TYPE(result) == AOP_CRY) {
2544 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2545 pic16_aopPut(AOP(result),"c",0);
2548 i = AOP_SIZE(result);
2550 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2552 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2556 /*-----------------------------------------------------------------*/
2557 /* pic16_outBitOp - output a bit from Op */
2558 /* Move to result the value of set/clr op -- VR */
2559 /*-----------------------------------------------------------------*/
2560 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2566 /* if the result is bit */
2567 if (AOP_TYPE(result) == AOP_CRY) {
2568 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2569 pic16_aopPut(AOP(result),"c",0);
2572 i = AOP_SIZE(result);
2574 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2576 pic16_emitpcode(POC_RRCF, pcop);
2577 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2581 /*-----------------------------------------------------------------*/
2582 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2583 /*-----------------------------------------------------------------*/
2584 void pic16_toBoolean(operand *oper)
2586 int size = AOP_SIZE(oper) - 1;
2589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2591 if ( AOP_TYPE(oper) != AOP_ACC) {
2592 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2595 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2600 #if !defined(GEN_Not)
2601 /*-----------------------------------------------------------------*/
2602 /* genNot - generate code for ! operation */
2603 /*-----------------------------------------------------------------*/
2604 static void pic16_genNot (iCode *ic)
2610 /* assign asmOps to operand & result */
2611 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2612 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2614 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2615 /* if in bit space then a special case */
2616 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2617 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2618 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2619 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2621 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2622 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2623 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2628 size = AOP_SIZE(IC_LEFT(ic));
2630 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2631 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2632 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2635 pic16_toBoolean(IC_LEFT(ic));
2637 tlbl = newiTempLabel(NULL);
2638 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2639 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2640 pic16_outBitC(IC_RESULT(ic));
2643 /* release the aops */
2644 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2645 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2650 #if !defined(GEN_Cpl)
2651 /*-----------------------------------------------------------------*/
2652 /* genCpl - generate code for complement */
2653 /*-----------------------------------------------------------------*/
2654 static void pic16_genCpl (iCode *ic)
2660 /* assign asmOps to operand & result */
2661 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2662 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2664 /* if both are in bit space then
2666 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2667 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2669 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2670 pic16_emitcode("cpl","c");
2671 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2675 size = AOP_SIZE(IC_RESULT(ic));
2678 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2680 pic16_emitcode("cpl","a");
2681 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2683 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2684 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2686 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2695 /* release the aops */
2696 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2697 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2701 /*-----------------------------------------------------------------*/
2702 /* genUminusFloat - unary minus for floating points */
2703 /*-----------------------------------------------------------------*/
2704 static void genUminusFloat(operand *op,operand *result)
2706 int size ,offset =0 ;
2709 /* for this we just need to flip the
2710 first it then copy the rest in place */
2711 size = AOP_SIZE(op);
2714 mov2f(AOP(result), AOP(op), offset);
2718 /* toggle the MSB's highest bit */
2719 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2722 /*-----------------------------------------------------------------*/
2723 /* genUminus - unary minus code generation */
2724 /*-----------------------------------------------------------------*/
2725 static void genUminus (iCode *ic)
2728 sym_link *optype, *rtype;
2735 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2736 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2738 /* if both in bit space then special case */
2739 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2740 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2742 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2743 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2744 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2748 optype = operandType(IC_LEFT(ic));
2749 rtype = operandType(IC_RESULT(ic));
2751 /* if float then do float stuff */
2752 if (IS_FLOAT(optype)) {
2753 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2757 /* otherwise subtract from zero by taking the 2's complement */
2758 size = AOP_SIZE(IC_LEFT(ic));
2759 label = newiTempLabel ( NULL );
2761 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2762 for (i=size-1; i > 0; i--) {
2763 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2765 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2766 for (i=1; i < size; i++) {
2767 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2768 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2771 for (i=size-1; i >= 0; i--) {
2772 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2773 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2776 for (i=0; i < size-2; i++) {
2777 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2778 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2780 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2782 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2785 pic16_emitpLabel (label->key);
2788 /* release the aops */
2789 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2790 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2794 /*-----------------------------------------------------------------*/
2795 /* saveRegisters - will look for a call and save the registers */
2796 /*-----------------------------------------------------------------*/
2797 static void saveRegisters(iCode *lic)
2804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2806 for (ic = lic ; ic ; ic = ic->next)
2807 if (ic->op == CALL || ic->op == PCALL)
2811 fprintf(stderr,"found parameter push with no function call\n");
2815 /* if the registers have been saved already then
2817 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2820 /* find the registers in use at this time
2821 and push them away to safety */
2822 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2826 if (options.useXstack) {
2827 if (bitVectBitValue(rsave,R0_IDX))
2828 pic16_emitcode("mov","b,r0");
2829 pic16_emitcode("mov","r0,%s",spname);
2830 for (i = 0 ; i < pic16_nRegs ; i++) {
2831 if (bitVectBitValue(rsave,i)) {
2833 pic16_emitcode("mov","a,b");
2835 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2836 pic16_emitcode("movx","@r0,a");
2837 pic16_emitcode("inc","r0");
2840 pic16_emitcode("mov","%s,r0",spname);
2841 if (bitVectBitValue(rsave,R0_IDX))
2842 pic16_emitcode("mov","r0,b");
2844 //for (i = 0 ; i < pic16_nRegs ; i++) {
2845 // if (bitVectBitValue(rsave,i))
2846 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2849 dtype = operandType(IC_LEFT(ic));
2850 if (currFunc && dtype &&
2851 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2852 IFFUNC_ISISR(currFunc->type) &&
2855 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2858 /*-----------------------------------------------------------------*/
2859 /* unsaveRegisters - pop the pushed registers */
2860 /*-----------------------------------------------------------------*/
2861 static void unsaveRegisters (iCode *ic)
2866 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2867 /* find the registers in use at this time
2868 and push them away to safety */
2869 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2872 if (options.useXstack) {
2873 pic16_emitcode("mov","r0,%s",spname);
2874 for (i = pic16_nRegs ; i >= 0 ; i--) {
2875 if (bitVectBitValue(rsave,i)) {
2876 pic16_emitcode("dec","r0");
2877 pic16_emitcode("movx","a,@r0");
2879 pic16_emitcode("mov","b,a");
2881 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2885 pic16_emitcode("mov","%s,r0",spname);
2886 if (bitVectBitValue(rsave,R0_IDX))
2887 pic16_emitcode("mov","r0,b");
2889 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2890 // if (bitVectBitValue(rsave,i))
2891 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2898 /*-----------------------------------------------------------------*/
2900 /*-----------------------------------------------------------------*/
2901 static void pushSide(operand * oper, int size)
2904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2906 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2907 if (AOP_TYPE(oper) != AOP_REG &&
2908 AOP_TYPE(oper) != AOP_DIR &&
2910 pic16_emitcode("mov","a,%s",l);
2911 pic16_emitcode("push","acc");
2913 pic16_emitcode("push","%s",l);
2918 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2920 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2921 pic16_emitpcode(POC_MOVFW, src);
2922 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2924 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2925 src, pic16_popGet(AOP(op), offset)));
2930 /*-----------------------------------------------------------------*/
2931 /* assignResultValue - assign results to oper, rescall==1 is */
2932 /* called from genCall() or genPcall() */
2933 /*-----------------------------------------------------------------*/
2934 static void assignResultValue(operand * oper, int rescall)
2936 int size = AOP_SIZE(oper);
2940 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2941 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2944 /* assign result from a call/pcall function() */
2946 /* function results are stored in a special order,
2947 * see top of file with Function return policy, or manual */
2950 /* 8-bits, result in WREG */
2951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2954 /* 16-bits, result in PRODL:WREG */
2955 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2959 /* 24-bits, result in PRODH:PRODL:WREG */
2960 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2964 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2965 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2969 /* >32-bits, result on stack, and FSR0 points to beginning.
2970 * Fix stack when done */
2972 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2974 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2975 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2977 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2982 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2983 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2984 if(STACK_MODEL_LARGE) {
2986 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2990 int areg = 0; /* matching argument register */
2992 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2993 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2996 /* its called from genReceive (probably) -- VR */
2997 /* I hope this code will not be called from somewhere else in the future!
2998 * We manually set the pseudo stack pointer in genReceive. - dw
3000 if(!GpsuedoStkPtr && _G.useWreg) {
3001 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3003 /* The last byte in the assignment is in W */
3004 if(areg <= GpsuedoStkPtr) {
3006 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3008 // debugf("receive from WREG\n", 0);
3010 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3013 _G.stack_lat = AOP_SIZE(oper)-1;
3018 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3019 // debugf("receive from STACK\n", 0);
3026 /*-----------------------------------------------------------------*/
3027 /* genIpush - generate code for pushing this gets a little complex */
3028 /*-----------------------------------------------------------------*/
3029 static void genIpush (iCode *ic)
3031 // int size, offset=0;
3034 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3037 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3039 /* send to stack as normal */
3040 addSet(&_G.sendSet,ic);
3041 // addSetHead(&_G.sendSet,ic);
3042 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3047 int size, offset = 0 ;
3051 /* if this is not a parm push : ie. it is spill push
3052 and spill push is always done on the local stack */
3053 if (!ic->parmPush) {
3055 /* and the item is spilt then do nothing */
3056 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3059 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3060 size = AOP_SIZE(IC_LEFT(ic));
3061 /* push it on the stack */
3063 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3068 pic16_emitcode("push","%s",l);
3073 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3077 /*-----------------------------------------------------------------*/
3078 /* genIpop - recover the registers: can happen only for spilling */
3079 /*-----------------------------------------------------------------*/
3080 static void genIpop (iCode *ic)
3083 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3088 /* if the temp was not pushed then */
3089 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3092 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3093 size = AOP_SIZE(IC_LEFT(ic));
3096 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3099 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3104 /*-----------------------------------------------------------------*/
3105 /* unsaverbank - restores the resgister bank from stack */
3106 /*-----------------------------------------------------------------*/
3107 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3109 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3117 if (options.useXstack) {
3119 r = getFreePtr(ic,&aop,FALSE);
3122 pic16_emitcode("mov","%s,_spx",r->name);
3123 pic16_emitcode("movx","a,@%s",r->name);
3124 pic16_emitcode("mov","psw,a");
3125 pic16_emitcode("dec","%s",r->name);
3128 pic16_emitcode ("pop","psw");
3131 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3132 if (options.useXstack) {
3133 pic16_emitcode("movx","a,@%s",r->name);
3134 //pic16_emitcode("mov","(%s+%d),a",
3135 // regspic16[i].base,8*bank+regspic16[i].offset);
3136 pic16_emitcode("dec","%s",r->name);
3139 pic16_emitcode("pop",""); //"(%s+%d)",
3140 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3143 if (options.useXstack) {
3145 pic16_emitcode("mov","_spx,%s",r->name);
3146 pic16_freeAsmop(NULL,aop,ic,TRUE);
3152 /*-----------------------------------------------------------------*/
3153 /* saverbank - saves an entire register bank on the stack */
3154 /*-----------------------------------------------------------------*/
3155 static void saverbank (int bank, iCode *ic, bool pushPsw)
3157 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3164 if (options.useXstack) {
3167 r = getFreePtr(ic,&aop,FALSE);
3168 pic16_emitcode("mov","%s,_spx",r->name);
3172 for (i = 0 ; i < pic16_nRegs ;i++) {
3173 if (options.useXstack) {
3174 pic16_emitcode("inc","%s",r->name);
3175 //pic16_emitcode("mov","a,(%s+%d)",
3176 // regspic16[i].base,8*bank+regspic16[i].offset);
3177 pic16_emitcode("movx","@%s,a",r->name);
3179 pic16_emitcode("push","");// "(%s+%d)",
3180 //regspic16[i].base,8*bank+regspic16[i].offset);
3184 if (options.useXstack) {
3185 pic16_emitcode("mov","a,psw");
3186 pic16_emitcode("movx","@%s,a",r->name);
3187 pic16_emitcode("inc","%s",r->name);
3188 pic16_emitcode("mov","_spx,%s",r->name);
3189 pic16_freeAsmop (NULL,aop,ic,TRUE);
3192 pic16_emitcode("push","psw");
3194 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3202 static int wparamCmp(void *p1, void *p2)
3204 return (!strcmp((char *)p1, (char *)p2));
3207 int inWparamList(char *s)
3209 return isinSetWith(wparamList, s, wparamCmp);
3213 /*-----------------------------------------------------------------*/
3214 /* genCall - generates a call statement */
3215 /*-----------------------------------------------------------------*/
3216 static void genCall (iCode *ic)
3226 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3227 /* if caller saves & we have not saved then */
3228 // if (!ic->regsSaved)
3229 // saveRegisters(ic);
3231 /* initialise stackParms for IPUSH pushes */
3232 // stackParms = psuedoStkPtr;
3233 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3234 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3235 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3238 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3241 /* if send set is not empty the assign */
3244 int psuedoStkPtr=-1;
3245 int firstTimeThruLoop = 1;
3248 /* reverse sendSet if function is not reentrant */
3249 if(!IFFUNC_ISREENT(ftype))
3250 _G.sendSet = reverseSet(_G.sendSet);
3252 /* First figure how many parameters are getting passed */
3256 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3260 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3261 size = AOP_SIZE(IC_LEFT(sic));
3265 /* pass the last byte through WREG */
3269 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3270 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3271 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3273 if(!firstTimeThruLoop) {
3274 /* If this is not the first time we've been through the loop
3275 * then we need to save the parameter in a temporary
3276 * register. The last byte of the last parameter is
3280 // --psuedoStkPtr; // sanity check
3284 firstTimeThruLoop=0;
3286 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3291 /* all arguments are passed via stack */
3295 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3296 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3297 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3299 // pushaop(AOP(IC_LEFT(sic)), size);
3300 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3305 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3309 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3310 pushw(); /* save last parameter to stack if functions has varargs */
3314 } else use_wreg = 0;
3316 _G.stackRegSet = _G.sendSet;
3321 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3325 /* if we need to assign a result value */
3326 if ((IS_ITEMP(IC_RESULT(ic))
3327 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3328 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3329 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3332 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3335 assignResultValue(IC_RESULT(ic), 1);
3337 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3340 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3343 if(!stackParms && ic->parmBytes) {
3344 stackParms = ic->parmBytes;
3347 stackParms -= use_wreg;
3350 if(stackParms == 1) {
3351 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3353 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3354 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3356 if(STACK_MODEL_LARGE) {
3358 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3363 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3366 /* adjust the stack for parameters if required */
3367 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3370 /* if register bank was saved then pop them */
3372 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3374 /* if we hade saved some registers then unsave them */
3375 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3376 unsaveRegisters (ic);
3382 /*-----------------------------------------------------------------*/
3383 /* genPcall - generates a call by pointer statement */
3384 /* new version, created from genCall - HJD */
3385 /*-----------------------------------------------------------------*/
3386 static void genPcall (iCode *ic)
3388 sym_link *ftype, *fntype;
3390 symbol *retlbl = newiTempLabel(NULL);
3391 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3395 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3396 fntype = operandType( IC_LEFT(ic) )->next;
3398 /* if send set is not empty the assign */
3401 int psuedoStkPtr=-1;
3403 /* reverse sendSet if function is not reentrant */
3404 if(!IFFUNC_ISREENT(fntype))
3405 _G.sendSet = reverseSet(_G.sendSet);
3409 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3412 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3413 size = AOP_SIZE(IC_LEFT(sic));
3416 /* all parameters are passed via stack, since WREG is clobbered
3417 * by the calling sequence */
3419 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3420 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3421 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3423 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3427 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3430 _G.stackRegSet = _G.sendSet;
3434 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3436 // push return address
3437 // push $ on return stack, then replace with retlbl
3439 pic16_emitpcodeNULLop(POC_PUSH);
3441 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3442 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3443 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3444 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3445 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3446 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3448 /* make the call by writing the pointer into pc */
3449 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3450 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3452 // note: MOVFF to PCL not allowed
3453 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3454 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3457 /* return address is here: (X) */
3458 pic16_emitpLabelFORCE(retlbl->key);
3460 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3463 /* if we need assign a result value */
3464 if ((IS_ITEMP(IC_RESULT(ic))
3465 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3466 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3467 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3470 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3473 assignResultValue(IC_RESULT(ic), 1);
3475 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3476 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3478 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3481 // stackParms -= use_wreg;
3484 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3485 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3486 if(STACK_MODEL_LARGE) {
3488 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3493 /*-----------------------------------------------------------------*/
3494 /* resultRemat - result is rematerializable */
3495 /*-----------------------------------------------------------------*/
3496 static int resultRemat (iCode *ic)
3498 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3499 if (SKIP_IC(ic) || ic->op == IFX)
3502 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3503 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3504 if (sym->remat && !POINTER_SET(ic))
3511 #if defined(__BORLANDC__) || defined(_MSC_VER)
3512 #define STRCASECMP stricmp
3514 #define STRCASECMP strcasecmp
3518 /*-----------------------------------------------------------------*/
3519 /* inExcludeList - return 1 if the string is in exclude Reg list */
3520 /*-----------------------------------------------------------------*/
3521 static bool inExcludeList(char *s)
3523 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3526 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3527 if (options.excludeRegs[i] &&
3528 STRCASECMP(options.excludeRegs[i],"none") == 0)
3531 for ( i = 0 ; options.excludeRegs[i]; i++) {
3532 if (options.excludeRegs[i] &&
3533 STRCASECMP(s,options.excludeRegs[i]) == 0)
3540 /*-----------------------------------------------------------------*/
3541 /* genFunction - generated code for function entry */
3542 /*-----------------------------------------------------------------*/
3543 static void genFunction (iCode *ic)
3549 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3551 pic16_labelOffset += (max_key+4);
3556 ftype = operandType(IC_LEFT(ic));
3557 sym = OP_SYMBOL(IC_LEFT(ic));
3559 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3560 /* create an absolute section at the interrupt vector:
3561 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3569 sym = OP_SYMBOL( IC_LEFT(ic));
3571 if(interrupts[i]->name
3572 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3579 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3580 __FILE__, __LINE__, sym->name);
3583 _G.interruptvector = found;
3586 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3587 asym = newSymbol(asymname, 0);
3589 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3590 pic16_addpBlock( apb );
3592 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3593 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3594 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3596 /* mark the end of this tiny function */
3597 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3602 abSym = Safe_calloc(1, sizeof(absSym));
3603 strcpy(abSym->name, asymname);
3605 switch( _G.interruptvector ) {
3606 case 0: abSym->address = 0x000000; break;
3607 case 1: abSym->address = 0x000008; break;
3608 case 2: abSym->address = 0x000018; break;
3611 /* relocate interrupt vectors if needed */
3612 abSym->address += pic16_options.ivt_loc;
3614 addSet(&absSymSet, abSym);
3618 /* create the function header */
3619 pic16_emitcode(";","-----------------------------------------");
3620 pic16_emitcode(";"," function %s",sym->name);
3621 pic16_emitcode(";","-----------------------------------------");
3623 pic16_emitcode("","%s:",sym->rname);
3624 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3630 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3631 if(!strcmp(ab->name, sym->rname)) {
3632 pic16_pBlockConvert2Absolute(pb);
3639 if(IFFUNC_ISNAKED(ftype)) {
3640 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3644 /* if critical function then turn interrupts off */
3645 if (IFFUNC_ISCRITICAL(ftype)) {
3646 //pic16_emitcode("clr","ea");
3649 _G.fregsUsed = sym->regsUsed;
3651 /* if this is an interrupt service routine then
3652 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3653 if (IFFUNC_ISISR(sym->type)) {
3654 _G.usefastretfie = 1; /* use shadow registers by default */
3656 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3657 if(!(_G.interruptvector == 1)) {
3658 /* do not save WREG,STATUS,BSR for high priority interrupts
3659 * because they are stored in the hardware shadow registers already */
3660 _G.usefastretfie = 0;
3661 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3662 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3663 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3666 /* these should really be optimized somehow, because not all
3667 * interrupt handlers modify them */
3668 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3669 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3670 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3671 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3673 // pic16_pBlockConvert2ISR(pb);
3677 /* emit code to setup stack frame if user enabled,
3678 * and function is not main() */
3680 //fprintf(stderr, "function name: %s\n", sym->name);
3681 if(strcmp(sym->name, "main")) {
3682 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3683 /* setup the stack frame */
3684 if(STACK_MODEL_LARGE)
3685 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3686 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3688 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3689 if(STACK_MODEL_LARGE)
3690 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3694 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3697 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3700 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3702 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3705 if(inWparamList(sym->name)) {
3706 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3713 /* if callee-save to be used for this function
3714 * then save the registers being used in this function */
3715 // if (IFFUNC_CALLEESAVES(sym->type))
3719 /* if any registers used */
3720 if (sym->regsUsed) {
3721 /* save the registers used */
3722 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3723 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3724 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3725 if (bitVectBitValue(sym->regsUsed,i)) {
3726 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3729 if(!pic16_regWithIdx(i)->wasUsed) {
3730 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3731 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3732 pic16_regWithIdx(i)->wasUsed = 1;
3736 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3740 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3741 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3744 /*-----------------------------------------------------------------*/
3745 /* genEndFunction - generates epilogue for functions */
3746 /*-----------------------------------------------------------------*/
3747 static void genEndFunction (iCode *ic)
3749 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3753 if(IFFUNC_ISNAKED(sym->type)) {
3754 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3760 /* add code for ISCRITICAL */
3761 if(IFFUNC_ISCRITICAL(sym->type)) {
3762 /* if critical function, turn on interrupts */
3764 /* TODO: add code here -- VR */
3767 // sym->regsUsed = _G.fregsUsed;
3769 /* now we need to restore the registers */
3770 /* if any registers used */
3771 if (sym->regsUsed) {
3774 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3775 /* restore registers used */
3776 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3777 for ( i = sym->regsUsed->size; i >= 0; i--) {
3778 if (bitVectBitValue(sym->regsUsed,i)) {
3779 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3783 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3787 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3789 if (sym->stack == 1) {
3790 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3791 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3793 // we have to add more than one...
3794 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3795 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3796 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3798 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3799 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3800 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3804 if(strcmp(sym->name, "main")) {
3805 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3806 /* restore stack frame */
3807 if(STACK_MODEL_LARGE)
3808 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3809 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3815 if (IFFUNC_ISISR(sym->type)) {
3816 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3817 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3818 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3819 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3821 if(!(_G.interruptvector == 1)) {
3822 /* do not restore interrupt vector for WREG,STATUS,BSR
3823 * for high priority interrupt, see genFunction */
3824 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3825 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3826 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3828 _G.interruptvector = 0; /* sanity check */
3831 /* if debug then send end of function */
3832 /* if (options.debug && currFunc) */
3834 debugFile->writeEndFunction (currFunc, ic, 1);
3837 if(_G.usefastretfie)
3838 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3840 pic16_emitpcodeNULLop(POC_RETFIE);
3842 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3844 _G.usefastretfie = 0;
3848 if (IFFUNC_ISCRITICAL(sym->type)) {
3849 pic16_emitcode("setb","ea");
3852 /* if debug then send end of function */
3854 debugFile->writeEndFunction (currFunc, ic, 1);
3857 /* insert code to restore stack frame, if user enabled it
3858 * and function is not main() */
3861 pic16_emitpcodeNULLop(POC_RETURN);
3863 /* Mark the end of a function */
3864 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3868 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3871 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3873 pic16_emitpcode(POC_CLRF, dest);
3875 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3876 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3879 if(dest->type == PO_WREG && (offset == 0)) {
3880 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3883 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3887 /*-----------------------------------------------------------------*/
3888 /* genRet - generate code for return statement */
3889 /*-----------------------------------------------------------------*/
3890 static void genRet (iCode *ic)
3896 /* if we have no return value then
3897 * just generate the "ret" */
3902 /* we have something to return then
3903 * move the return value into place */
3904 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3905 size = AOP_SIZE(IC_LEFT(ic));
3909 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3910 // pic16_emitpcode(POC_MOVFF,
3911 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3914 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3915 // pic16_emitpcode(POC_MOVFF,
3916 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3919 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3920 // pic16_emitpcode(POC_MOVFF,
3921 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3924 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3926 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3927 // pic16_emitpcode(POC_MOVFF,
3928 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3931 /* >32-bits, setup stack and FSR0 */
3933 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3934 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3936 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3938 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3943 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3944 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3946 if(STACK_MODEL_LARGE) {
3947 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3948 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3950 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3955 /* old code, left here for reference -- VR */
3959 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3961 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3962 pic16_emitpcomment("push %s",l);
3965 DEBUGpic16_emitcode(";", "%d", __LINE__);
3966 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3967 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3969 if (strcmp(fReturn[offset],l)) {
3970 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3971 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3972 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3974 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3978 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3988 if (strcmp(fReturn[pushed],"a"))
3989 pic16_emitcode("pop",fReturn[pushed]);
3991 pic16_emitcode("pop","acc");
3997 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4000 /* generate a jump to the return label
4001 * if the next is not the return statement */
4002 if (!(ic->next && ic->next->op == LABEL
4003 && IC_LABEL(ic->next) == returnLabel)) {
4005 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4006 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4010 /*-----------------------------------------------------------------*/
4011 /* genLabel - generates a label */
4012 /*-----------------------------------------------------------------*/
4013 static void genLabel (iCode *ic)
4017 /* special case never generate */
4018 if (IC_LABEL(ic) == entryLabel)
4021 pic16_emitpLabel(IC_LABEL(ic)->key);
4022 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4025 /*-----------------------------------------------------------------*/
4026 /* genGoto - generates a goto */
4027 /*-----------------------------------------------------------------*/
4029 static void genGoto (iCode *ic)
4032 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4033 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4037 /*-----------------------------------------------------------------*/
4038 /* genMultbits :- multiplication of bits */
4039 /*-----------------------------------------------------------------*/
4040 static void genMultbits (operand *left,
4046 if(!pic16_sameRegs(AOP(result),AOP(right)))
4047 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4049 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4050 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4051 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4056 /*-----------------------------------------------------------------*/
4057 /* genMultOneByte : 8 bit multiplication & division */
4058 /*-----------------------------------------------------------------*/
4059 static void genMultOneByte (operand *left,
4065 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4066 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4068 /* (if two literals, the value is computed before) */
4069 /* if one literal, literal on the right */
4070 if (AOP_TYPE(left) == AOP_LIT){
4076 /* size is already checked in genMult == 1 */
4077 // size = AOP_SIZE(result);
4079 if (AOP_TYPE(right) == AOP_LIT){
4080 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4081 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4082 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4083 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4085 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4086 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4087 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4088 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4091 pic16_genMult8X8_8 (left, right,result);
4094 /*-----------------------------------------------------------------*/
4095 /* genMultOneWord : 16 bit multiplication */
4096 /*-----------------------------------------------------------------*/
4097 static void genMultOneWord (operand *left,
4102 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4103 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4105 /* (if two literals, the value is computed before)
4106 * if one literal, literal on the right */
4107 if (AOP_TYPE(left) == AOP_LIT){
4113 /* size is checked already == 2 */
4114 // size = AOP_SIZE(result);
4116 if (AOP_TYPE(right) == AOP_LIT) {
4117 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4118 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4119 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4120 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4122 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4123 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4124 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4125 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4128 pic16_genMult16X16_16(left, right,result);
4131 /*-----------------------------------------------------------------*/
4132 /* genMultOneLong : 32 bit multiplication */
4133 /*-----------------------------------------------------------------*/
4134 static void genMultOneLong (operand *left,
4139 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4140 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4142 /* (if two literals, the value is computed before)
4143 * if one literal, literal on the right */
4144 if (AOP_TYPE(left) == AOP_LIT){
4150 /* size is checked already == 4 */
4151 // size = AOP_SIZE(result);
4153 if (AOP_TYPE(right) == AOP_LIT) {
4154 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4155 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4156 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4157 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4159 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4160 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4161 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4162 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4165 pic16_genMult32X32_32(left, right,result);
4170 /*-----------------------------------------------------------------*/
4171 /* genMult - generates code for multiplication */
4172 /*-----------------------------------------------------------------*/
4173 static void genMult (iCode *ic)
4175 operand *left = IC_LEFT(ic);
4176 operand *right = IC_RIGHT(ic);
4177 operand *result= IC_RESULT(ic);
4180 /* assign the amsops */
4181 pic16_aopOp (left,ic,FALSE);
4182 pic16_aopOp (right,ic,FALSE);
4183 pic16_aopOp (result,ic,TRUE);
4185 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4187 /* special cases first *
4189 if (AOP_TYPE(left) == AOP_CRY
4190 && AOP_TYPE(right)== AOP_CRY) {
4191 genMultbits(left,right,result);
4195 /* if both are of size == 1 */
4196 if(AOP_SIZE(left) == 1
4197 && AOP_SIZE(right) == 1) {
4198 genMultOneByte(left,right,result);
4202 /* if both are of size == 2 */
4203 if(AOP_SIZE(left) == 2
4204 && AOP_SIZE(right) == 2) {
4205 genMultOneWord(left, right, result);
4209 /* if both are of size == 4 */
4210 if(AOP_SIZE(left) == 4
4211 && AOP_SIZE(right) == 4) {
4212 genMultOneLong(left, right, result);
4216 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4219 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4220 /* should have been converted to function call */
4224 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4225 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4226 pic16_freeAsmop(result,NULL,ic,TRUE);
4229 /*-----------------------------------------------------------------*/
4230 /* genDivbits :- division of bits */
4231 /*-----------------------------------------------------------------*/
4232 static void genDivbits (operand *left,
4239 /* the result must be bit */
4240 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4241 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4245 pic16_emitcode("div","ab");
4246 pic16_emitcode("rrc","a");
4247 pic16_aopPut(AOP(result),"c",0);
4250 /*-----------------------------------------------------------------*/
4251 /* genDivOneByte : 8 bit division */
4252 /*-----------------------------------------------------------------*/
4253 static void genDivOneByte (operand *left,
4257 sym_link *opetype = operandType(result);
4262 /* result = divident / divisor
4263 * - divident may be a register or a literal,
4264 * - divisor may be a register or a literal,
4265 * so there are 3 cases (literal / literal is optimized
4266 * by the front-end) to handle.
4267 * In addition we must handle signed and unsigned, which
4268 * result in 6 final different cases -- VR */
4272 size = AOP_SIZE(result) - 1;
4274 /* signed or unsigned */
4275 if (SPEC_USIGN(opetype)) {
4276 pCodeOp *pct1, /* count */
4279 symbol *label1, *label2, *label3;;
4282 /* unsigned is easy */
4284 pct1 = pic16_popGetTempReg(1);
4285 pct2 = pic16_popGetTempReg(1);
4286 pct3 = pic16_popGetTempReg(1);
4288 label1 = newiTempLabel(NULL);
4289 label2 = newiTempLabel(NULL);
4290 label3 = newiTempLabel(NULL);
4292 /* the following algorithm is extracted from divuint.c */
4294 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4295 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4297 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4299 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4301 pic16_emitpLabel(label1->key);
4304 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4308 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4312 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4314 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4315 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4317 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4318 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4319 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4321 pic16_emitpLabel( label3->key );
4322 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4323 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4327 pic16_emitpLabel(label2->key);
4328 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4329 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4330 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4332 /* result is in wreg */
4333 if(AOP_TYPE(result) != AOP_ACC)
4334 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4336 pic16_popReleaseTempReg( pct3, 1);
4337 pic16_popReleaseTempReg( pct2, 1);
4338 pic16_popReleaseTempReg( pct1, 1);
4343 /* signed is a little bit more difficult */
4345 /* save the signs of the operands */
4346 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4348 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4349 pic16_emitcode("push","acc"); /* save it on the stack */
4351 /* now sign adjust for both left & right */
4352 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4354 lbl = newiTempLabel(NULL);
4355 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4356 pic16_emitcode("cpl","a");
4357 pic16_emitcode("inc","a");
4358 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4359 pic16_emitcode("mov","b,a");
4361 /* sign adjust left side */
4362 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4365 lbl = newiTempLabel(NULL);
4366 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4367 pic16_emitcode("cpl","a");
4368 pic16_emitcode("inc","a");
4369 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4371 /* now the division */
4372 pic16_emitcode("div","ab");
4373 /* we are interested in the lower order
4375 pic16_emitcode("mov","b,a");
4376 lbl = newiTempLabel(NULL);
4377 pic16_emitcode("pop","acc");
4378 /* if there was an over flow we don't
4379 adjust the sign of the result */
4380 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4381 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4383 pic16_emitcode("clr","a");
4384 pic16_emitcode("subb","a,b");
4385 pic16_emitcode("mov","b,a");
4386 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4388 /* now we are done */
4389 pic16_aopPut(AOP(result),"b",0);
4391 pic16_emitcode("mov","c,b.7");
4392 pic16_emitcode("subb","a,acc");
4395 pic16_aopPut(AOP(result),"a",offset++);
4399 /*-----------------------------------------------------------------*/
4400 /* genDiv - generates code for division */
4401 /*-----------------------------------------------------------------*/
4402 static void genDiv (iCode *ic)
4404 operand *left = IC_LEFT(ic);
4405 operand *right = IC_RIGHT(ic);
4406 operand *result= IC_RESULT(ic);
4409 /* Division is a very lengthy algorithm, so it is better
4410 * to call support routines than inlining algorithm.
4411 * Division functions written here just in case someone
4412 * wants to inline and not use the support libraries -- VR */
4416 /* assign the amsops */
4417 pic16_aopOp (left,ic,FALSE);
4418 pic16_aopOp (right,ic,FALSE);
4419 pic16_aopOp (result,ic,TRUE);
4421 /* special cases first */
4423 if (AOP_TYPE(left) == AOP_CRY &&
4424 AOP_TYPE(right)== AOP_CRY) {
4425 genDivbits(left,right,result);
4429 /* if both are of size == 1 */
4430 if (AOP_SIZE(left) == 1 &&
4431 AOP_SIZE(right) == 1 ) {
4432 genDivOneByte(left,right,result);
4436 /* should have been converted to function call */
4439 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4440 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441 pic16_freeAsmop(result,NULL,ic,TRUE);
4444 /*-----------------------------------------------------------------*/
4445 /* genModbits :- modulus of bits */
4446 /*-----------------------------------------------------------------*/
4447 static void genModbits (operand *left,
4455 werror(W_POSSBUG2, __FILE__, __LINE__);
4456 /* the result must be bit */
4457 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4458 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4462 pic16_emitcode("div","ab");
4463 pic16_emitcode("mov","a,b");
4464 pic16_emitcode("rrc","a");
4465 pic16_aopPut(AOP(result),"c",0);
4468 /*-----------------------------------------------------------------*/
4469 /* genModOneByte : 8 bit modulus */
4470 /*-----------------------------------------------------------------*/
4471 static void genModOneByte (operand *left,
4475 sym_link *opetype = operandType(result);
4480 werror(W_POSSBUG2, __FILE__, __LINE__);
4482 /* signed or unsigned */
4483 if (SPEC_USIGN(opetype)) {
4484 /* unsigned is easy */
4485 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4486 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4488 pic16_emitcode("div","ab");
4489 pic16_aopPut(AOP(result),"b",0);
4493 /* signed is a little bit more difficult */
4495 /* save the signs of the operands */
4496 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4499 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4500 pic16_emitcode("push","acc"); /* save it on the stack */
4502 /* now sign adjust for both left & right */
4503 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4506 lbl = newiTempLabel(NULL);
4507 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4508 pic16_emitcode("cpl","a");
4509 pic16_emitcode("inc","a");
4510 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4511 pic16_emitcode("mov","b,a");
4513 /* sign adjust left side */
4514 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4517 lbl = newiTempLabel(NULL);
4518 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4519 pic16_emitcode("cpl","a");
4520 pic16_emitcode("inc","a");
4521 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4523 /* now the multiplication */
4524 pic16_emitcode("div","ab");
4525 /* we are interested in the lower order
4527 lbl = newiTempLabel(NULL);
4528 pic16_emitcode("pop","acc");
4529 /* if there was an over flow we don't
4530 adjust the sign of the result */
4531 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4532 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4534 pic16_emitcode("clr","a");
4535 pic16_emitcode("subb","a,b");
4536 pic16_emitcode("mov","b,a");
4537 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4539 /* now we are done */
4540 pic16_aopPut(AOP(result),"b",0);
4544 /*-----------------------------------------------------------------*/
4545 /* genMod - generates code for division */
4546 /*-----------------------------------------------------------------*/
4547 static void genMod (iCode *ic)
4549 operand *left = IC_LEFT(ic);
4550 operand *right = IC_RIGHT(ic);
4551 operand *result= IC_RESULT(ic);
4555 /* assign the amsops */
4556 pic16_aopOp (left,ic,FALSE);
4557 pic16_aopOp (right,ic,FALSE);
4558 pic16_aopOp (result,ic,TRUE);
4560 /* special cases first */
4562 if (AOP_TYPE(left) == AOP_CRY &&
4563 AOP_TYPE(right)== AOP_CRY) {
4564 genModbits(left,right,result);
4568 /* if both are of size == 1 */
4569 if (AOP_SIZE(left) == 1 &&
4570 AOP_SIZE(right) == 1 ) {
4571 genModOneByte(left,right,result);
4575 /* should have been converted to function call */
4579 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4580 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4581 pic16_freeAsmop(result,NULL,ic,TRUE);
4584 /*-----------------------------------------------------------------*/
4585 /* genIfxJump :- will create a jump depending on the ifx */
4586 /*-----------------------------------------------------------------*/
4588 note: May need to add parameter to indicate when a variable is in bit space.
4590 static void genIfxJump (iCode *ic, char *jval)
4594 /* if true label then we jump if condition
4596 if ( IC_TRUE(ic) ) {
4598 if(strcmp(jval,"a") == 0)
4600 else if (strcmp(jval,"c") == 0)
4603 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4604 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4607 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4608 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4612 /* false label is present */
4613 if(strcmp(jval,"a") == 0)
4615 else if (strcmp(jval,"c") == 0)
4618 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4619 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4622 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4623 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4628 /* mark the icode as generated */
4632 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4636 /* if true label then we jump if condition
4638 if ( IC_TRUE(ic) ) {
4639 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4640 pic16_emitpcode(POC_BTFSC, jop);
4642 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4643 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4646 /* false label is present */
4647 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4648 pic16_emitpcode(POC_BTFSS, jop);
4650 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4651 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4655 /* mark the icode as generated */
4662 /*-----------------------------------------------------------------*/
4664 /*-----------------------------------------------------------------*/
4665 static void genSkip(iCode *ifx,int status_bit)
4667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4671 if ( IC_TRUE(ifx) ) {
4672 switch(status_bit) {
4687 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4688 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4692 switch(status_bit) {
4706 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4707 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4714 /*-----------------------------------------------------------------*/
4716 /*-----------------------------------------------------------------*/
4717 static void genSkipc(resolvedIfx *rifx)
4719 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4729 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4730 rifx->generated = 1;
4733 #if !(USE_SIMPLE_GENCMP)
4734 /*-----------------------------------------------------------------*/
4736 /*-----------------------------------------------------------------*/
4737 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4739 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4744 if( (rifx->condition ^ invert_condition) & 1)
4749 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4750 rifx->generated = 1;
4755 /*-----------------------------------------------------------------*/
4757 /*-----------------------------------------------------------------*/
4758 static void genSkipz(iCode *ifx, int condition)
4769 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4771 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4774 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4776 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4781 #if !(USE_SIMPLE_GENCMP)
4782 /*-----------------------------------------------------------------*/
4784 /*-----------------------------------------------------------------*/
4785 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4791 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4793 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4796 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4797 rifx->generated = 1;
4802 /*-----------------------------------------------------------------*/
4803 /* genChkZeroes :- greater or less than comparison */
4804 /* For each byte in a literal that is zero, inclusive or the */
4805 /* the corresponding byte in the operand with W */
4806 /* returns true if any of the bytes are zero */
4807 /*-----------------------------------------------------------------*/
4808 static int genChkZeroes(operand *op, int lit, int size)
4815 i = (lit >> (size*8)) & 0xff;
4819 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4821 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4830 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4831 #define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
4833 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
4834 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
4836 /*-----------------------------------------------------------------*/
4837 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4838 /* aop (if it's NOT a literal) or from lit (if */
4839 /* aop is a literal) */
4840 /*-----------------------------------------------------------------*/
4841 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4842 if (aop->type == AOP_LIT) {
4843 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4845 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4849 /*-----------------------------------------------------------------*/
4850 /* genCmp :- greater or less than comparison */
4851 /*-----------------------------------------------------------------*/
4853 #if USE_SIMPLE_GENCMP
4855 /* genCmp performs a left < right comparison, stores
4856 * the outcome in result (if != NULL) and generates
4857 * control flow code for the ifx (if != NULL).
4859 * This version leaves in sequences like
4860 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4861 * which should be optmized by the peephole
4862 * optimizer - RN 2005-01-01 */
4863 static void genCmp (operand *left,operand *right,
4864 operand *result, iCode *ifx, int sign)
4877 assert (AOP_SIZE(left) == AOP_SIZE(right));
4878 assert (left && right);
4880 size = AOP_SIZE(right) - 1;
4881 mask = (0x100UL << (size*8)) - 1;
4882 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4887 resolveIfx (&rIfx, ifx);
4889 /**********************************************************************
4890 * handle bits - bit compares are promoted to int compares seemingly! *
4891 **********************************************************************/
4893 // THIS IS COMPLETELY UNTESTED!
4894 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4895 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4896 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4897 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4900 // 1 < {0,1} is false --> clear C by skipping the next instruction
4901 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4902 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4903 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4904 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4905 emitCLRC; // only skipped for left=0 && right=1
4907 goto correct_result_in_carry;
4911 /*************************************************
4912 * make sure that left is register (or the like) *
4913 *************************************************/
4914 if (!isAOP_REGlike(left)) {
4915 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4916 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4918 assert (isAOP_LIT(left));
4919 assert (isAOP_REGlike(right));
4920 // swap left and right
4921 // left < right <==> right > left <==> (right >= left + 1)
4922 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4924 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4925 // MAXVALUE < right? always false
4926 if (performedLt) emitCLRC; else emitSETC;
4927 goto correct_result_in_carry;
4930 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4931 // that's we handled it above.
4938 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
4939 } else if (isAOP_LIT(right)) {
4940 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4943 assert (isAOP_REGlike(left)); // left must be register or the like
4944 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4946 /*************************************************
4947 * special cases go here *
4948 *************************************************/
4950 if (isAOP_LIT(right)) {
4952 // unsigned comparison to a literal
4953 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4954 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4957 // unsigned left < 0? always false
4958 if (performedLt) emitCLRC; else emitSETC;
4959 goto correct_result_in_carry;
4962 // signed comparison to a literal
4963 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
4964 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4966 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4967 // signed left < 0x80000000? always false
4968 if (performedLt) emitCLRC; else emitSETC;
4969 goto correct_result_in_carry;
4970 } else if (lit == 0) {
4971 // compare left < 0; set CARRY if SIGNBIT(left) is set
4972 if (performedLt) emitSETC; else emitCLRC;
4973 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4974 if (performedLt) emitCLRC; else emitSETC;
4975 goto correct_result_in_carry;
4978 } // right is literal
4980 /*************************************************
4981 * perform a general case comparison *
4982 * make sure we get CARRY==1 <==> left >= right *
4983 *************************************************/
4984 // compare most significant bytes
4985 //DEBUGpc ("comparing bytes at offset %d", size);
4987 // unsigned comparison
4988 mov2w_regOrLit (AOP(right), lit, size);
4989 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4991 // signed comparison
4992 // (add 2^n to both operands then perform an unsigned comparison)
4993 if (isAOP_LIT(right)) {
4994 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4995 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4997 if (litbyte == 0x80) {
4998 // left >= 0x80 -- always true, but more bytes to come
4999 pic16_mov2w (AOP(left), size);
5000 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5003 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5004 pic16_mov2w (AOP(left), size);
5005 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5006 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5009 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5010 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5011 pic16_mov2w (AOP(left), size);
5012 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5013 pic16_emitpcode (POC_MOVWF, pctemp);
5014 pic16_mov2w (AOP(right), size);
5015 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5016 pic16_emitpcode (POC_SUBFW, pctemp);
5017 //pic16_popReleaseTempReg(pctemp, 1);
5021 // compare remaining bytes (treat as unsigned case from above)
5022 templbl = newiTempLabel ( NULL );
5025 //DEBUGpc ("comparing bytes at offset %d", offs);
5026 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5027 mov2w_regOrLit (AOP(right), lit, offs);
5028 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5030 pic16_emitpLabel (templbl->key);
5031 goto result_in_carry;
5035 /****************************************************
5036 * now CARRY contains the result of the comparison: *
5037 * SUBWF sets CARRY iff *
5038 * F-W >= 0 <==> F >= W <==> !(F < W) *
5040 ****************************************************/
5043 if (result && AOP_TYPE(result) != AOP_CRY) {
5044 // value will be stored
5047 // value wil only be used in the following genSkipc()
5048 rIfx.condition ^= 1;
5052 correct_result_in_carry:
5054 // assign result to variable (if neccessary)
5055 if (result && AOP_TYPE(result) != AOP_CRY) {
5056 //DEBUGpc ("assign result");
5057 size = AOP_SIZE(result);
5059 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5061 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5064 // perform conditional jump
5065 // genSkipc branches to rifx->label if (rifx->condition != CARRY)
5067 //DEBUGpc ("generate control flow");
5068 rIfx.condition ^= 1;
5077 static void genCmp (operand *left,operand *right,
5078 operand *result, iCode *ifx, int sign)
5080 int size; //, offset = 0 ;
5081 unsigned long lit = 0L,i = 0;
5082 resolvedIfx rFalseIfx;
5083 // resolvedIfx rTrueIfx;
5085 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5088 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5089 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5095 resolveIfx(&rFalseIfx,ifx);
5096 truelbl = newiTempLabel(NULL);
5097 size = max(AOP_SIZE(left),AOP_SIZE(right));
5099 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5103 /* if literal is on the right then swap with left */
5104 if ((AOP_TYPE(right) == AOP_LIT)) {
5105 operand *tmp = right ;
5106 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5107 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5110 lit = (lit - 1) & mask;
5113 rFalseIfx.condition ^= 1;
5116 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5117 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5121 //if(IC_TRUE(ifx) == NULL)
5122 /* if left & right are bit variables */
5123 if (AOP_TYPE(left) == AOP_CRY &&
5124 AOP_TYPE(right) == AOP_CRY ) {
5125 assert (0 && "bit variables used in genCmp");
5126 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5127 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5129 /* subtract right from left if at the
5130 end the carry flag is set then we know that
5131 left is greater than right */
5133 symbol *lbl = newiTempLabel(NULL);
5136 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5137 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5141 if(AOP_TYPE(right) == AOP_LIT) {
5143 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5145 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5152 genSkipCond(&rFalseIfx,left,size-1,7);
5154 /* no need to compare to 0...*/
5155 /* NOTE: this is a de-generate compare that most certainly
5156 * creates some dead code. */
5157 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5159 if(ifx) ifx->generated = 1;
5166 //i = (lit >> (size*8)) & 0xff;
5167 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5169 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5171 i = ((0-lit) & 0xff);
5174 /* lit is 0x7f, all signed chars are less than
5175 * this except for 0x7f itself */
5176 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5177 genSkipz2(&rFalseIfx,0);
5179 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5180 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5181 genSkipc(&rFalseIfx);
5186 genSkipz2(&rFalseIfx,1);
5188 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5189 genSkipc(&rFalseIfx);
5193 if(ifx) ifx->generated = 1;
5197 /* chars are out of the way. now do ints and longs */
5200 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5207 genSkipCond(&rFalseIfx,left,size,7);
5208 if(ifx) ifx->generated = 1;
5213 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5215 //rFalseIfx.condition ^= 1;
5216 //genSkipCond(&rFalseIfx,left,size,7);
5217 //rFalseIfx.condition ^= 1;
5219 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5220 if(rFalseIfx.condition)
5221 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5223 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5225 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5226 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5227 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5230 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5232 if(rFalseIfx.condition) {
5234 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5240 genSkipc(&rFalseIfx);
5241 pic16_emitpLabel(truelbl->key);
5242 if(ifx) ifx->generated = 1;
5249 if( (lit & 0xff) == 0) {
5250 /* lower byte is zero */
5251 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5252 i = ((lit >> 8) & 0xff) ^0x80;
5253 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5254 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5255 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5256 genSkipc(&rFalseIfx);
5259 if(ifx) ifx->generated = 1;
5264 /* Special cases for signed longs */
5265 if( (lit & 0xffffff) == 0) {
5266 /* lower byte is zero */
5267 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5268 i = ((lit >> 8*3) & 0xff) ^0x80;
5269 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5270 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5271 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5272 genSkipc(&rFalseIfx);
5275 if(ifx) ifx->generated = 1;
5283 if(lit & (0x80 << (size*8))) {
5284 /* lit is negative */
5285 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5287 //genSkipCond(&rFalseIfx,left,size,7);
5289 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5291 if(rFalseIfx.condition)
5292 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5294 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5298 /* lit is positive */
5299 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5300 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5301 if(rFalseIfx.condition)
5302 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5304 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5309 This works, but is only good for ints.
5310 It also requires a "known zero" register.
5311 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5312 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5313 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5314 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5315 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5316 genSkipc(&rFalseIfx);
5318 pic16_emitpLabel(truelbl->key);
5319 if(ifx) ifx->generated = 1;
5323 /* There are no more special cases, so perform a general compare */
5325 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5326 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5330 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5332 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5334 //rFalseIfx.condition ^= 1;
5335 genSkipc(&rFalseIfx);
5337 pic16_emitpLabel(truelbl->key);
5339 if(ifx) ifx->generated = 1;
5346 /* sign is out of the way. So now do an unsigned compare */
5347 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5350 /* General case - compare to an unsigned literal on the right.*/
5352 i = (lit >> (size*8)) & 0xff;
5353 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5354 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5356 i = (lit >> (size*8)) & 0xff;
5359 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5361 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5363 /* this byte of the lit is zero,
5364 *if it's not the last then OR in the variable */
5366 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5371 pic16_emitpLabel(lbl->key);
5372 // pic16_emitpLabel(truelbl->key);
5373 //if(emitFinalCheck)
5374 genSkipc(&rFalseIfx);
5376 pic16_emitpLabel(truelbl->key);
5378 if(ifx) ifx->generated = 1;
5385 if(AOP_TYPE(left) == AOP_LIT) {
5386 //symbol *lbl = newiTempLabel(NULL);
5388 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5391 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5394 if((lit == 0) && (sign == 0)){
5397 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5399 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5401 genSkipz2(&rFalseIfx,0);
5402 if(ifx) ifx->generated = 1;
5409 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5410 /* degenerate compare can never be true */
5411 if(rFalseIfx.condition == 0)
5412 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5414 if(ifx) ifx->generated = 1;
5419 /* signed comparisons to a literal byte */
5421 int lp1 = (lit+1) & 0xff;
5423 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5426 rFalseIfx.condition ^= 1;
5427 genSkipCond(&rFalseIfx,right,0,7);
5430 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5431 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5432 genSkipz2(&rFalseIfx,1);
5435 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5436 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5437 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5438 rFalseIfx.condition ^= 1;
5439 genSkipc(&rFalseIfx);
5443 /* unsigned comparisons to a literal byte */
5445 switch(lit & 0xff ) {
5447 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5448 genSkipz2(&rFalseIfx,0);
5451 rFalseIfx.condition ^= 1;
5452 genSkipCond(&rFalseIfx,right,0,7);
5456 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5457 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5458 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5459 rFalseIfx.condition ^= 1;
5460 if (AOP_TYPE(result) == AOP_CRY)
5461 genSkipc(&rFalseIfx);
5463 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5464 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5470 if(ifx) ifx->generated = 1;
5471 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5477 /* Size is greater than 1 */
5485 /* this means lit = 0xffffffff, or -1 */
5488 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5489 rFalseIfx.condition ^= 1;
5490 genSkipCond(&rFalseIfx,right,size,7);
5491 if(ifx) ifx->generated = 1;
5493 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5502 if(rFalseIfx.condition) {
5503 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5504 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5509 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5513 if(rFalseIfx.condition) {
5514 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5515 pic16_emitpLabel(truelbl->key);
5517 rFalseIfx.condition ^= 1;
5518 genSkipCond(&rFalseIfx,right,s,7);
5521 if(ifx) ifx->generated = 1;
5523 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5529 if((size == 1) && (0 == (lp1&0xff))) {
5530 /* lower byte of signed word is zero */
5531 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5532 i = ((lp1 >> 8) & 0xff) ^0x80;
5533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5534 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5535 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5537 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5539 if(ifx) ifx->generated = 1;
5542 rFalseIfx.condition ^= 1;
5543 genSkipc(&rFalseIfx);
5544 if(ifx) ifx->generated = 1;
5550 if(lit & (0x80 << (size*8))) {
5551 /* Lit is less than zero */
5552 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5553 //rFalseIfx.condition ^= 1;
5554 //genSkipCond(&rFalseIfx,left,size,7);
5555 //rFalseIfx.condition ^= 1;
5556 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5557 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5559 if(rFalseIfx.condition)
5560 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5562 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5566 /* Lit is greater than or equal to zero */
5567 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5568 //rFalseIfx.condition ^= 1;
5569 //genSkipCond(&rFalseIfx,right,size,7);
5570 //rFalseIfx.condition ^= 1;
5572 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5573 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5575 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5576 if(rFalseIfx.condition)
5577 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5579 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5583 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5584 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5588 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5590 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5592 rFalseIfx.condition ^= 1;
5593 //rFalseIfx.condition = 1;
5594 genSkipc(&rFalseIfx);
5596 pic16_emitpLabel(truelbl->key);
5598 if(ifx) ifx->generated = 1;
5601 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5608 /* compare word or long to an unsigned literal on the right.*/
5613 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5616 break; /* handled above */
5619 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5621 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5622 genSkipz2(&rFalseIfx,0);
5626 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5628 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5631 if(rFalseIfx.condition)
5632 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5634 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5637 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5638 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5640 rFalseIfx.condition ^= 1;
5641 genSkipc(&rFalseIfx);
5644 pic16_emitpLabel(truelbl->key);
5646 if(ifx) ifx->generated = 1;
5648 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5656 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5657 i = (lit >> (size*8)) & 0xff;
5659 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5660 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5663 i = (lit >> (size*8)) & 0xff;
5666 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5668 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5670 /* this byte of the lit is zero,
5671 * if it's not the last then OR in the variable */
5673 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5678 pic16_emitpLabel(lbl->key);
5680 rFalseIfx.condition ^= 1;
5682 genSkipc(&rFalseIfx);
5686 pic16_emitpLabel(truelbl->key);
5687 if(ifx) ifx->generated = 1;
5689 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5695 /* Compare two variables */
5697 DEBUGpic16_emitcode(";sign","%d",sign);
5701 /* Sigh. thus sucks... */
5705 pctemp = pic16_popGetTempReg(1);
5706 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5707 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5709 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5710 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5711 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5712 pic16_popReleaseTempReg(pctemp, 1);
5714 /* Signed char comparison */
5715 /* Special thanks to Nikolai Golovchenko for this snippet */
5716 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5717 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5718 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5719 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5720 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5721 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5724 genSkipc(&rFalseIfx);
5726 if(ifx) ifx->generated = 1;
5728 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5736 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5737 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5741 /* The rest of the bytes of a multi-byte compare */
5745 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5749 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5754 pic16_emitpLabel(lbl->key);
5756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5757 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5758 (AOP_TYPE(result) == AOP_REG)) {
5759 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5760 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5762 genSkipc(&rFalseIfx);
5764 //genSkipc(&rFalseIfx);
5765 if(ifx) ifx->generated = 1;
5768 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776 if ((AOP_TYPE(result) != AOP_CRY)
5777 && AOP_SIZE(result)) {
5778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5780 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5782 pic16_outBitC(result);
5784 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5785 /* if the result is used in the next
5786 ifx conditional branch then generate
5787 code a little differently */
5789 genIfxJump (ifx,"c");
5791 pic16_outBitC(result);
5792 /* leave the result in acc */
5797 #else /* old version of genCmp() */ /* } else { */
5799 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5800 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5801 operand *result, int offset, int invert_op)
5805 /* check condition, > or < ?? */
5806 if(rIfx->condition != 0)invert_op ^= 1;
5808 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5810 if(!ifx)invert_op ^= 1;
5812 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5813 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5816 if(!invert_op)return POC_CPFSGT;
5817 else return POC_CPFSLT;
5820 static int compareAopfirstpass=1;
5822 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5823 operand *oper, int offset, operand *result,
5824 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5830 /* invert if there is a result to be loaded, in order to fit,
5831 * SETC/CLRC sequence */
5832 if(AOP_SIZE(result))invert_op ^= 1;
5834 // if(sign && !offset)invert_op ^= 1;
5836 // if(sign)invert_op ^= 1;
5838 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5840 if(AOP_SIZE(result) && compareAopfirstpass) {
5843 pic16_emitpcode(POC_SETF, pcop2);
5848 pic16_emitpcode(POC_CLRF, pcop2);
5854 compareAopfirstpass = 0;
5856 /* there is a bug when comparing operands with size > 1,
5857 * because higher bytes can be equal and test should be performed
5858 * to the next lower byte, current algorithm, considers operands
5859 * inequal in these cases! -- VR 20041107 */
5863 pic16_emitpcode(op, pcop);
5865 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5868 if((!sign || !offset) && AOP_SIZE(result)) {
5871 pic16_emitpcode(POC_CLRF, pcop2);
5876 pic16_emitpcode(POC_SETF, pcop2);
5881 /* don't emit final branch (offset == 0) */
5885 pic16_emitpcode(POC_RRCF, pcop2);
5887 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5890 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5891 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5892 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5894 truelbl = newiTempLabel( NULL );
5895 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5896 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5897 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5899 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5900 pic16_emitpLabel(truelbl->key);
5902 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5911 static void genCmp (operand *left, operand *right,
5912 operand *result, iCode *ifx, int sign)
5916 resolvedIfx rFalseIfx;
5917 symbol *falselbl, *tlbl;
5921 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5923 resolveIfx(&rFalseIfx, ifx);
5924 size = max(AOP_SIZE(left), AOP_SIZE(right));
5926 /* if left & right are bit variables */
5927 if(AOP_TYPE(left) == AOP_CRY
5928 && AOP_TYPE(right) == AOP_CRY ) {
5930 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5931 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5933 werror(W_POSSBUG2, __FILE__, __LINE__);
5937 /* if literal is on the right then swap with left */
5938 if((AOP_TYPE(right) == AOP_LIT)) {
5939 operand *tmp = right ;
5940 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5942 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5944 // lit = (lit - 1) & mask;
5947 rFalseIfx.condition ^= 1; /* reverse compare */
5949 if ((AOP_TYPE(left) == AOP_LIT)) {
5950 /* float compares are handled by support functions */
5951 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5954 /* actual comparing algorithm */
5955 // size = AOP_SIZE( right );
5957 falselbl = newiTempLabel( NULL );
5958 if(AOP_TYPE(left) == AOP_LIT) {
5959 /* compare to literal */
5960 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5963 pCodeOp *pct, *pct2;
5966 /* signed compare */
5967 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5969 pct = pic16_popCopyReg(&pic16_pc_prodl);
5970 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5971 tlbl = newiTempLabel( NULL );
5973 /* first compare signs:
5974 * a. if both are positive, compare just like unsigned
5975 * b. if both are negative, invert cmpop, compare just like unsigned
5976 * c. if different signs, determine the result directly */
5982 tlbl1 = newiTempLabel( NULL );
5983 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5987 /* literal is zero or positive:
5988 * a. if carry is zero, too, continue compare,
5989 * b. if carry is set, then continue depending on cmpop ^ condition:
5990 * 1. '<' return false (literal < variable),
5991 * 2. '>' return true (literal > variable) */
5992 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5993 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5996 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5997 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6001 /* literal is negative:
6002 * a. if carry is set, too, continue compare,
6003 * b. if carry is zero, then continue depending on cmpop ^ condition:
6004 * 1. '<' return true (literal < variable),
6005 * 2. '>' return false (literal > variable) */
6006 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6007 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6009 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6010 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6015 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6017 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6018 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6023 pic16_emitpLabel( tlbl1->key );
6026 compareAopfirstpass=1;
6027 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6028 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6029 // pic16_emitpcode(POC_MOVWF, pct);
6031 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6033 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6034 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6038 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6039 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6040 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6041 // pic16_emitpcode(POC_MOVWF, pct);
6043 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6044 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6045 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6046 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6047 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6051 if(ifx)ifx->generated = 1;
6053 if(AOP_SIZE(result)) {
6054 pic16_emitpLabel(tlbl->key);
6055 pic16_emitpLabel(falselbl->key);
6056 pic16_outBitOp( result, pct2 );
6058 pic16_emitpLabel(tlbl->key);
6063 /* unsigned compare */
6064 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6066 compareAopfirstpass=1;
6069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6070 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6074 if(ifx)ifx->generated = 1;
6077 if(AOP_SIZE(result)) {
6078 pic16_emitpLabel(falselbl->key);
6079 pic16_outBitC( result );
6084 /* compare registers */
6085 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6089 pCodeOp *pct, *pct2;
6091 /* signed compare */
6092 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6094 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6095 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6096 tlbl = newiTempLabel( NULL );
6098 compareAopfirstpass=1;
6101 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6102 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6103 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6104 pic16_emitpcode(POC_MOVWF, pct);
6106 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6107 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6108 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6110 /* WREG already holds left + 0x80 */
6111 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6114 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6115 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6116 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6117 pic16_emitpcode(POC_MOVWF, pct);
6119 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6120 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6121 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6123 /* WREG already holds left + 0x80 */
6124 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6125 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6128 if(ifx)ifx->generated = 1;
6130 if(AOP_SIZE(result)) {
6131 pic16_emitpLabel(tlbl->key);
6132 pic16_emitpLabel(falselbl->key);
6133 pic16_outBitOp( result, pct2 );
6135 pic16_emitpLabel(tlbl->key);
6139 /* unsigned compare */
6140 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6142 compareAopfirstpass=1;
6145 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6146 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6150 if(ifx)ifx->generated = 1;
6151 if(AOP_SIZE(result)) {
6153 pic16_emitpLabel(falselbl->key);
6154 pic16_outBitC( result );
6161 #else /* } else { */
6163 /* new version of genCmp -- VR 20041012 */
6164 static void genCmp (operand *left,operand *right,
6165 operand *result, iCode *ifx, int sign)
6167 int size; //, offset = 0 ;
6168 unsigned long lit = 0L,i = 0;
6169 resolvedIfx rFalseIfx;
6170 int willCheckCarry=0;
6171 // resolvedIfx rTrueIfx;
6177 * subtract right from left if at the end the carry flag is set then we
6178 * know that left is greater than right */
6180 resolveIfx(&rFalseIfx,ifx);
6181 truelbl = newiTempLabel(NULL);
6182 size = max(AOP_SIZE(left),AOP_SIZE(right));
6184 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6186 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
6187 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
6190 /* if literal is on the right then swap with left */
6191 if ((AOP_TYPE(right) == AOP_LIT)) {
6192 operand *tmp = right ;
6193 unsigned long mask = (0x100 << (8*(size-1))) - 1;
6195 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6197 // lit = (lit - 1) & mask;
6200 rFalseIfx.condition ^= 1; /* reverse compare */
6202 if ((AOP_TYPE(left) == AOP_LIT)) {
6203 /* float compares are handled by support functions */
6204 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
6208 //if(IC_TRUE(ifx) == NULL)
6209 /* if left & right are bit variables */
6210 if (AOP_TYPE(left) == AOP_CRY &&
6211 AOP_TYPE(right) == AOP_CRY ) {
6213 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6214 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6217 symbol *lbl = newiTempLabel(NULL);
6219 if(AOP_TYPE(left) == AOP_LIT) {
6220 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
6222 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6224 else willCheckCarry = 0;
6227 if((lit == 0) && (sign == 0)) {
6228 /* unsigned compare to 0 */
6229 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
6232 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6234 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
6236 genSkipz2(&rFalseIfx,0);
6237 if(ifx)ifx->generated = 1;
6244 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
6245 /* degenerate compare can never be true */
6246 if(rFalseIfx.condition == 0)
6247 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
6249 if(ifx) ifx->generated = 1;
6254 /* signed comparisons to a literal byte */
6255 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6257 int lp1 = (lit+1) & 0xff;
6259 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
6262 rFalseIfx.condition ^= 1;
6263 genSkipCond(&rFalseIfx,right,0,7);
6266 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6267 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
6268 genSkipz2(&rFalseIfx,1);
6271 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
6273 if(rFalseIfx.condition)
6274 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
6276 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
6278 if(willCheckCarry) {
6279 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
6280 else { emitSETC; emitCLRC; }
6283 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6286 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6287 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6288 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
6289 rFalseIfx.condition ^= 1;
6290 genSkipc(&rFalseIfx);
6295 /* unsigned comparisons to a literal byte */
6296 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
6298 switch(lit & 0xff ) {
6301 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6302 genSkipz2(&rFalseIfx,0);
6305 rFalseIfx.condition ^= 1;
6306 genSkipCond(&rFalseIfx,right,0,7);
6309 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
6310 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6312 rFalseIfx.condition ^= 1;
6313 if (AOP_TYPE(result) == AOP_CRY)
6314 genSkipc(&rFalseIfx);
6316 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6317 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6323 if(ifx) ifx->generated = 1;
6324 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6330 /* Size is greater than 1 */
6338 /* this means lit = 0xffffffff, or -1 */
6341 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
6342 rFalseIfx.condition ^= 1;
6343 genSkipCond(&rFalseIfx,right,size,7);
6344 if(ifx) ifx->generated = 1;
6351 if(rFalseIfx.condition) {
6352 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6353 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6356 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6358 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6362 if(rFalseIfx.condition) {
6363 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6364 pic16_emitpLabel(truelbl->key);
6366 rFalseIfx.condition ^= 1;
6367 genSkipCond(&rFalseIfx,right,s,7);
6370 if(ifx) ifx->generated = 1;
6374 if((size == 1) && (0 == (lp1&0xff))) {
6375 /* lower byte of signed word is zero */
6376 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6377 i = ((lp1 >> 8) & 0xff) ^0x80;
6378 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6379 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6380 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6381 rFalseIfx.condition ^= 1;
6382 genSkipc(&rFalseIfx);
6385 if(ifx) ifx->generated = 1;
6389 if(lit & (0x80 << (size*8))) {
6390 /* Lit is less than zero */
6391 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6392 //rFalseIfx.condition ^= 1;
6393 //genSkipCond(&rFalseIfx,left,size,7);
6394 //rFalseIfx.condition ^= 1;
6395 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6396 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6398 if(rFalseIfx.condition)
6399 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6401 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6405 /* Lit is greater than or equal to zero */
6406 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6407 //rFalseIfx.condition ^= 1;
6408 //genSkipCond(&rFalseIfx,right,size,7);
6409 //rFalseIfx.condition ^= 1;
6411 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6412 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6414 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6415 if(rFalseIfx.condition)
6416 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6418 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6423 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6424 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6428 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6430 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6432 rFalseIfx.condition ^= 1;
6433 //rFalseIfx.condition = 1;
6434 genSkipc(&rFalseIfx);
6436 pic16_emitpLabel(truelbl->key);
6438 if(ifx) ifx->generated = 1;
6443 /* compare word or long to an unsigned literal on the right.*/
6448 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6451 break; /* handled above */
6454 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6456 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6457 genSkipz2(&rFalseIfx,0);
6461 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6463 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6466 if(rFalseIfx.condition)
6467 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6469 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6472 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6473 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6475 rFalseIfx.condition ^= 1;
6476 genSkipc(&rFalseIfx);
6479 pic16_emitpLabel(truelbl->key);
6481 if(ifx) ifx->generated = 1;
6487 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6488 i = (lit >> (size*8)) & 0xff;
6490 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6491 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6494 i = (lit >> (size*8)) & 0xff;
6497 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6499 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6501 /* this byte of the lit is zero,
6502 * if it's not the last then OR in the variable */
6504 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6509 pic16_emitpLabel(lbl->key);
6511 rFalseIfx.condition ^= 1;
6513 genSkipc(&rFalseIfx);
6517 pic16_emitpLabel(truelbl->key);
6518 if(ifx) ifx->generated = 1;
6522 /* Compare two variables */
6524 DEBUGpic16_emitcode(";sign","%d",sign);
6528 /* Sigh. thus sucks... */
6532 pctemp = pic16_popGetTempReg(1);
6533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6534 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6535 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6536 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6537 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6538 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6539 pic16_popReleaseTempReg(pctemp, 1);
6541 /* Signed char comparison */
6542 /* Special thanks to Nikolai Golovchenko for this snippet */
6543 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6544 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6545 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6546 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6547 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6548 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6550 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6551 genSkipc(&rFalseIfx);
6553 if(ifx) ifx->generated = 1;
6559 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6560 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6564 /* The rest of the bytes of a multi-byte compare */
6568 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6571 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6572 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6577 pic16_emitpLabel(lbl->key);
6579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6580 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6581 (AOP_TYPE(result) == AOP_REG)) {
6582 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6583 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6585 genSkipc(&rFalseIfx);
6587 //genSkipc(&rFalseIfx);
6588 if(ifx) ifx->generated = 1;
6595 if ((AOP_TYPE(result) != AOP_CRY)
6596 && AOP_SIZE(result)) {
6597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6599 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6601 pic16_outBitC(result);
6603 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6604 /* if the result is used in the next
6605 ifx conditional branch then generate
6606 code a little differently */
6608 genIfxJump (ifx,"c");
6610 pic16_outBitC(result);
6611 /* leave the result in acc */
6622 /*-----------------------------------------------------------------*/
6623 /* genCmpGt :- greater than comparison */
6624 /*-----------------------------------------------------------------*/
6625 static void genCmpGt (iCode *ic, iCode *ifx)
6627 operand *left, *right, *result;
6628 sym_link *letype , *retype;
6634 right= IC_RIGHT(ic);
6635 result = IC_RESULT(ic);
6637 letype = getSpec(operandType(left));
6638 retype =getSpec(operandType(right));
6639 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6640 /* assign the amsops */
6641 pic16_aopOp (left,ic,FALSE);
6642 pic16_aopOp (right,ic,FALSE);
6643 pic16_aopOp (result,ic,TRUE);
6645 genCmp(right, left, result, ifx, sign);
6647 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6648 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6649 pic16_freeAsmop(result,NULL,ic,TRUE);
6652 /*-----------------------------------------------------------------*/
6653 /* genCmpLt - less than comparisons */
6654 /*-----------------------------------------------------------------*/
6655 static void genCmpLt (iCode *ic, iCode *ifx)
6657 operand *left, *right, *result;
6658 sym_link *letype , *retype;
6664 right= IC_RIGHT(ic);
6665 result = IC_RESULT(ic);
6667 letype = getSpec(operandType(left));
6668 retype =getSpec(operandType(right));
6669 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6671 /* assign the amsops */
6672 pic16_aopOp (left,ic,FALSE);
6673 pic16_aopOp (right,ic,FALSE);
6674 pic16_aopOp (result,ic,TRUE);
6676 genCmp(left, right, result, ifx, sign);
6678 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6679 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6680 pic16_freeAsmop(result,NULL,ic,TRUE);
6685 // FIXME reenable literal optimisation when the pic16 port is stable
6687 /*-----------------------------------------------------------------*/
6688 /* genc16bit2lit - compare a 16 bit value to a literal */
6689 /*-----------------------------------------------------------------*/
6690 static void genc16bit2lit(operand *op, int lit, int offset)
6694 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6695 if( (lit&0xff) == 0)
6700 switch( BYTEofLONG(lit,i)) {
6702 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6705 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6708 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6711 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6712 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6717 switch( BYTEofLONG(lit,i)) {
6719 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6723 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6727 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6730 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6732 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6741 /*-----------------------------------------------------------------*/
6742 /* gencjneshort - compare and jump if not equal */
6743 /*-----------------------------------------------------------------*/
6744 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6746 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6748 int res_offset = 0; /* the result may be a different size then left or right */
6749 int res_size = AOP_SIZE(result);
6751 symbol *lbl, *lbl_done;
6753 unsigned long lit = 0L;
6754 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6757 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6759 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6760 resolveIfx(&rIfx,ifx);
6761 lbl = newiTempLabel(NULL);
6762 lbl_done = newiTempLabel(NULL);
6765 /* if the left side is a literal or
6766 if the right is in a pointer register and left
6768 if ((AOP_TYPE(left) == AOP_LIT) ||
6769 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6774 if(AOP_TYPE(right) == AOP_LIT)
6775 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6777 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6778 preserve_result = 1;
6780 if(result && !preserve_result)
6783 for(i = 0; i < AOP_SIZE(result); i++)
6784 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6788 /* if the right side is a literal then anything goes */
6789 if (AOP_TYPE(right) == AOP_LIT &&
6790 AOP_TYPE(left) != AOP_DIR ) {
6793 genc16bit2lit(left, lit, 0);
6795 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6798 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6801 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6802 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6804 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6808 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6810 if(res_offset < res_size-1)
6818 /* if the right side is in a register or in direct space or
6819 if the left is a pointer register & right is not */
6820 else if (AOP_TYPE(right) == AOP_REG ||
6821 AOP_TYPE(right) == AOP_DIR ||
6822 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6823 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6824 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6825 int lbl_key = lbl->key;
6828 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6829 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6831 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6832 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6833 __FUNCTION__,__LINE__);
6837 /* switch(size) { */
6839 /* genc16bit2lit(left, lit, 0); */
6841 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6846 if((AOP_TYPE(left) == AOP_DIR) &&
6847 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6849 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6850 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6852 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6854 switch (lit & 0xff) {
6856 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6859 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6860 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6861 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6865 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6866 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6867 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6868 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6872 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6873 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6878 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6881 if(AOP_TYPE(result) == AOP_CRY) {
6882 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6887 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6889 /* fix me. probably need to check result size too */
6890 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6896 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6903 if(res_offset < res_size-1)
6908 } else if(AOP_TYPE(right) == AOP_REG &&
6909 AOP_TYPE(left) != AOP_DIR){
6912 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6913 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6914 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6919 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6921 if(res_offset < res_size-1)
6926 /* right is a pointer reg need both a & b */
6928 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6930 pic16_emitcode("mov","b,%s",l);
6931 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6932 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6937 if(result && preserve_result)
6940 for(i = 0; i < AOP_SIZE(result); i++)
6941 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6944 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6946 if(result && preserve_result)
6947 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6950 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6952 pic16_emitpLabel(lbl->key);
6954 if(result && preserve_result)
6957 for(i = 0; i < AOP_SIZE(result); i++)
6958 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6960 pic16_emitpLabel(lbl_done->key);
6963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6971 /*-----------------------------------------------------------------*/
6972 /* gencjne - compare and jump if not equal */
6973 /*-----------------------------------------------------------------*/
6974 static void gencjne(operand *left, operand *right, iCode *ifx)
6976 symbol *tlbl = newiTempLabel(NULL);
6978 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6979 gencjneshort(left, right, lbl);
6981 pic16_emitcode("mov","a,%s",one);
6982 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6983 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6984 pic16_emitcode("clr","a");
6985 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6987 pic16_emitpLabel(lbl->key);
6988 pic16_emitpLabel(tlbl->key);
6994 /*-----------------------------------------------------------------*/
6995 /* is_LitOp - check if operand has to be treated as literal */
6996 /*-----------------------------------------------------------------*/
6997 static bool is_LitOp(operand *op)
6999 return ((AOP_TYPE(op) == AOP_LIT)
7000 || ( (AOP_TYPE(op) == AOP_PCODE)
7001 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
7002 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
7005 /*-----------------------------------------------------------------*/
7006 /* is_LitAOp - check if operand has to be treated as literal */
7007 /*-----------------------------------------------------------------*/
7008 static bool is_LitAOp(asmop *aop)
7010 return ((aop->type == AOP_LIT)
7011 || ( (aop->type == AOP_PCODE)
7012 && ( (aop->aopu.pcop->type == PO_LITERAL)
7013 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
7018 /*-----------------------------------------------------------------*/
7019 /* genCmpEq - generates code for equal to */
7020 /*-----------------------------------------------------------------*/
7021 static void genCmpEq (iCode *ic, iCode *ifx)
7023 operand *left, *right, *result;
7024 symbol *falselbl = newiTempLabel(NULL);
7025 symbol *donelbl = newiTempLabel(NULL);
7027 int preserve_result = 0;
7028 int generate_result = 0;
7033 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7034 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7035 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7037 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7039 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
7041 werror(W_POSSBUG2, __FILE__, __LINE__);
7042 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
7043 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
7047 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
7049 operand *tmp = right ;
7054 if ( regsInCommon(left, result) || regsInCommon(right, result) )
7055 preserve_result = 1;
7057 if(result && AOP_SIZE(result))
7058 generate_result = 1;
7060 if(generate_result && !preserve_result)
7062 for(i = 0; i < AOP_SIZE(result); i++)
7063 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7066 for(i=0; i < AOP_SIZE(left); i++)
7068 if(AOP_TYPE(left) != AOP_ACC)
7071 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
7073 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
7076 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
7078 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
7080 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
7085 if(generate_result && preserve_result)
7087 for(i = 0; i < AOP_SIZE(result); i++)
7088 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7092 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7094 if(generate_result && preserve_result)
7095 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7097 if(ifx && IC_TRUE(ifx))
7098 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7100 if(ifx && IC_FALSE(ifx))
7101 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7103 pic16_emitpLabel(falselbl->key);
7107 if(ifx && IC_FALSE(ifx))
7108 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7110 if(generate_result && preserve_result)
7112 for(i = 0; i < AOP_SIZE(result); i++)
7113 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7116 pic16_emitpLabel(donelbl->key);
7122 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7123 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7124 pic16_freeAsmop(result,NULL,ic,TRUE);
7130 // old version kept for reference
7132 /*-----------------------------------------------------------------*/
7133 /* genCmpEq - generates code for equal to */
7134 /*-----------------------------------------------------------------*/
7135 static void genCmpEq (iCode *ic, iCode *ifx)
7137 operand *left, *right, *result;
7138 unsigned long lit = 0L;
7140 symbol *falselbl = newiTempLabel(NULL);
7143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7146 DEBUGpic16_emitcode ("; ifx is non-null","");
7148 DEBUGpic16_emitcode ("; ifx is null","");
7150 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7151 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7152 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7154 size = max(AOP_SIZE(left),AOP_SIZE(right));
7156 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7158 /* if literal, literal on the right or
7159 if the right is in a pointer register and left
7161 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7162 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7163 operand *tmp = right ;
7169 if(ifx && !AOP_SIZE(result)){
7171 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
7172 /* if they are both bit variables */
7173 if (AOP_TYPE(left) == AOP_CRY &&
7174 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7175 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
7176 if(AOP_TYPE(right) == AOP_LIT){
7177 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7179 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7180 pic16_emitcode("cpl","c");
7181 } else if(lit == 1L) {
7182 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7184 pic16_emitcode("clr","c");
7186 /* AOP_TYPE(right) == AOP_CRY */
7188 symbol *lbl = newiTempLabel(NULL);
7189 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7190 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7191 pic16_emitcode("cpl","c");
7192 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7194 /* if true label then we jump if condition
7196 tlbl = newiTempLabel(NULL);
7197 if ( IC_TRUE(ifx) ) {
7198 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7199 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7201 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7202 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7204 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7207 /* left and right are both bit variables, result is carry */
7210 resolveIfx(&rIfx,ifx);
7212 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7213 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7214 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7215 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7220 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
7222 /* They're not both bit variables. Is the right a literal? */
7223 if(AOP_TYPE(right) == AOP_LIT) {
7224 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7229 switch(lit & 0xff) {
7231 if ( IC_TRUE(ifx) ) {
7232 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7234 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7236 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7237 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7241 if ( IC_TRUE(ifx) ) {
7242 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7244 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7246 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7247 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7251 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7253 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7258 /* end of size == 1 */
7262 genc16bit2lit(left,lit,offset);
7265 /* end of size == 2 */
7270 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7271 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7272 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7273 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7276 /* search for patterns that can be optimized */
7278 genc16bit2lit(left,lit,0);
7282 emitSKPZ; // if hi word unequal
7284 emitSKPNZ; // if hi word equal
7286 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7287 genc16bit2lit(left,lit,2);
7290 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7291 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7295 pic16_emitpLabel(falselbl->key);
7304 } else if(AOP_TYPE(right) == AOP_CRY ) {
7305 /* we know the left is not a bit, but that the right is */
7306 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7307 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7308 pic16_popGet(AOP(right),offset));
7309 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7311 /* if the two are equal, then W will be 0 and the Z bit is set
7312 * we could test Z now, or go ahead and check the high order bytes if
7313 * the variable we're comparing is larger than a byte. */
7316 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7318 if ( IC_TRUE(ifx) ) {
7320 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7321 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7324 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7325 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7329 /* They're both variables that are larger than bits */
7332 tlbl = newiTempLabel(NULL);
7335 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7336 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7338 if ( IC_TRUE(ifx) ) {
7342 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7344 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7345 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7349 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7352 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7353 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7358 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7360 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7361 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7365 if(s>1 && IC_TRUE(ifx)) {
7366 pic16_emitpLabel(tlbl->key);
7367 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7371 /* mark the icode as generated */
7376 /* if they are both bit variables */
7377 if (AOP_TYPE(left) == AOP_CRY &&
7378 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7379 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7380 if(AOP_TYPE(right) == AOP_LIT){
7381 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7383 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7384 pic16_emitcode("cpl","c");
7385 } else if(lit == 1L) {
7386 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7388 pic16_emitcode("clr","c");
7390 /* AOP_TYPE(right) == AOP_CRY */
7392 symbol *lbl = newiTempLabel(NULL);
7393 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7394 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7395 pic16_emitcode("cpl","c");
7396 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7399 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7400 pic16_outBitC(result);
7404 genIfxJump (ifx,"c");
7407 /* if the result is used in an arithmetic operation
7408 then put the result in place */
7409 pic16_outBitC(result);
7412 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7413 gencjne(left,right,result,ifx);
7416 gencjne(left,right,newiTempLabel(NULL));
7418 if(IC_TRUE(ifx)->key)
7419 gencjne(left,right,IC_TRUE(ifx)->key);
7421 gencjne(left,right,IC_FALSE(ifx)->key);
7425 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7426 pic16_aopPut(AOP(result),"a",0);
7431 genIfxJump (ifx,"a");
7435 /* if the result is used in an arithmetic operation
7436 then put the result in place */
7438 if (AOP_TYPE(result) != AOP_CRY)
7439 pic16_outAcc(result);
7441 /* leave the result in acc */
7445 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7446 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7447 pic16_freeAsmop(result,NULL,ic,TRUE);
7451 /*-----------------------------------------------------------------*/
7452 /* ifxForOp - returns the icode containing the ifx for operand */
7453 /*-----------------------------------------------------------------*/
7454 static iCode *ifxForOp ( operand *op, iCode *ic )
7458 /* if true symbol then needs to be assigned */
7459 if (IS_TRUE_SYMOP(op))
7462 /* if this has register type condition and
7463 the next instruction is ifx with the same operand
7464 and live to of the operand is upto the ifx only then */
7466 && ic->next->op == IFX
7467 && IC_COND(ic->next)->key == op->key
7468 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7470 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7476 ic->next->op == IFX &&
7477 IC_COND(ic->next)->key == op->key) {
7478 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7483 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7485 ic->next->op == IFX)
7486 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7489 ic->next->op == IFX &&
7490 IC_COND(ic->next)->key == op->key) {
7491 DEBUGpic16_emitcode ("; "," key is okay");
7492 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7493 OP_SYMBOL(op)->liveTo,
7498 /* the code below is completely untested
7499 * it just allows ulong2fs.c compile -- VR */
7502 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7503 __FILE__, __FUNCTION__, __LINE__);
7505 /* if this has register type condition and
7506 the next instruction is ifx with the same operand
7507 and live to of the operand is upto the ifx only then */
7509 ic->next->op == IFX &&
7510 IC_COND(ic->next)->key == op->key &&
7511 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7515 ic->next->op == IFX &&
7516 IC_COND(ic->next)->key == op->key) {
7517 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7521 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7522 __FILE__, __FUNCTION__, __LINE__);
7524 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7529 /*-----------------------------------------------------------------*/
7530 /* genAndOp - for && operation */
7531 /*-----------------------------------------------------------------*/
7532 static void genAndOp (iCode *ic)
7534 operand *left,*right, *result;
7539 /* note here that && operations that are in an
7540 if statement are taken away by backPatchLabels
7541 only those used in arthmetic operations remain */
7542 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7543 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7544 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7546 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7548 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7549 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7550 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7552 /* if both are bit variables */
7553 /* if (AOP_TYPE(left) == AOP_CRY && */
7554 /* AOP_TYPE(right) == AOP_CRY ) { */
7555 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7556 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7557 /* pic16_outBitC(result); */
7559 /* tlbl = newiTempLabel(NULL); */
7560 /* pic16_toBoolean(left); */
7561 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7562 /* pic16_toBoolean(right); */
7563 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7564 /* pic16_outBitAcc(result); */
7567 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7568 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7569 pic16_freeAsmop(result,NULL,ic,TRUE);
7573 /*-----------------------------------------------------------------*/
7574 /* genOrOp - for || operation */
7575 /*-----------------------------------------------------------------*/
7578 modified this code, but it doesn't appear to ever get called
7581 static void genOrOp (iCode *ic)
7583 operand *left,*right, *result;
7588 /* note here that || operations that are in an
7589 if statement are taken away by backPatchLabels
7590 only those used in arthmetic operations remain */
7591 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7592 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7593 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7595 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7597 /* if both are bit variables */
7598 if (AOP_TYPE(left) == AOP_CRY &&
7599 AOP_TYPE(right) == AOP_CRY ) {
7600 pic16_emitcode("clrc","");
7601 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7602 AOP(left)->aopu.aop_dir,
7603 AOP(left)->aopu.aop_dir);
7604 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7605 AOP(right)->aopu.aop_dir,
7606 AOP(right)->aopu.aop_dir);
7607 pic16_emitcode("setc","");
7610 tlbl = newiTempLabel(NULL);
7611 pic16_toBoolean(left);
7613 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7614 pic16_toBoolean(right);
7615 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7617 pic16_outBitAcc(result);
7620 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7621 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7622 pic16_freeAsmop(result,NULL,ic,TRUE);
7625 /*-----------------------------------------------------------------*/
7626 /* isLiteralBit - test if lit == 2^n */
7627 /*-----------------------------------------------------------------*/
7628 static int isLiteralBit(unsigned long lit)
7630 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7631 0x100L,0x200L,0x400L,0x800L,
7632 0x1000L,0x2000L,0x4000L,0x8000L,
7633 0x10000L,0x20000L,0x40000L,0x80000L,
7634 0x100000L,0x200000L,0x400000L,0x800000L,
7635 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7636 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7639 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7640 for(idx = 0; idx < 32; idx++)
7646 /*-----------------------------------------------------------------*/
7647 /* continueIfTrue - */
7648 /*-----------------------------------------------------------------*/
7649 static void continueIfTrue (iCode *ic)
7653 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7657 /*-----------------------------------------------------------------*/
7659 /*-----------------------------------------------------------------*/
7660 static void jumpIfTrue (iCode *ic)
7664 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7668 /*-----------------------------------------------------------------*/
7669 /* jmpTrueOrFalse - */
7670 /*-----------------------------------------------------------------*/
7671 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7673 // ugly but optimized by peephole
7676 symbol *nlbl = newiTempLabel(NULL);
7677 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7678 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7679 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7680 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7682 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7683 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7688 /*-----------------------------------------------------------------*/
7689 /* genAnd - code for and */
7690 /*-----------------------------------------------------------------*/
7691 static void genAnd (iCode *ic, iCode *ifx)
7693 operand *left, *right, *result;
7695 unsigned long lit = 0L;
7701 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7702 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7703 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7705 resolveIfx(&rIfx,ifx);
7707 /* if left is a literal & right is not then exchange them */
7708 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7709 AOP_NEEDSACC(left)) {
7710 operand *tmp = right ;
7715 /* if result = right then exchange them */
7716 if(pic16_sameRegs(AOP(result),AOP(right))){
7717 operand *tmp = right ;
7722 /* if right is bit then exchange them */
7723 if (AOP_TYPE(right) == AOP_CRY &&
7724 AOP_TYPE(left) != AOP_CRY){
7725 operand *tmp = right ;
7729 if(AOP_TYPE(right) == AOP_LIT)
7730 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7732 size = AOP_SIZE(result);
7734 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7737 // result = bit & yy;
7738 if (AOP_TYPE(left) == AOP_CRY){
7739 // c = bit & literal;
7740 if(AOP_TYPE(right) == AOP_LIT){
7742 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7745 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7748 if(size && (AOP_TYPE(result) == AOP_CRY)){
7749 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7752 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7756 pic16_emitcode("clr","c");
7759 if (AOP_TYPE(right) == AOP_CRY){
7761 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7762 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7765 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7767 pic16_emitcode("rrc","a");
7768 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7774 pic16_outBitC(result);
7776 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7777 genIfxJump(ifx, "c");
7781 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7782 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7783 if((AOP_TYPE(right) == AOP_LIT) &&
7784 (AOP_TYPE(result) == AOP_CRY) &&
7785 (AOP_TYPE(left) != AOP_CRY)){
7786 int posbit = isLiteralBit(lit);
7790 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7793 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7799 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7802 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7803 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7806 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7807 size = AOP_SIZE(left);
7810 int bp = posbit, ofs=0;
7817 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7818 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7822 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7823 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7832 symbol *tlbl = newiTempLabel(NULL);
7833 int sizel = AOP_SIZE(left);
7839 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7841 /* patch provided by Aaron Colwell */
7842 if((posbit = isLiteralBit(bytelit)) != 0) {
7843 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7844 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7845 (posbit-1),0, PO_GPR_REGISTER));
7847 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7848 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7850 if (bytelit == 0xff) {
7851 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7852 * a peephole could optimize it out -- VR */
7853 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7855 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7856 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7859 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7860 pic16_popGetLabel(tlbl->key));
7864 /* old code, left here for reference -- VR 09/2004 */
7865 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7867 if((posbit = isLiteralBit(bytelit)) != 0)
7868 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7870 if(bytelit != 0x0FFL)
7871 pic16_emitcode("anl","a,%s",
7872 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7873 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7879 // bit = left & literal
7882 pic16_emitpLabel(tlbl->key);
7884 // if(left & literal)
7887 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7890 pic16_emitpLabel(tlbl->key);
7895 pic16_outBitC(result);
7899 /* if left is same as result */
7900 if(pic16_sameRegs(AOP(result),AOP(left))){
7902 for(;size--; offset++,lit>>=8) {
7903 if(AOP_TYPE(right) == AOP_LIT){
7904 switch(lit & 0xff) {
7906 /* and'ing with 0 has clears the result */
7907 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7908 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7911 /* and'ing with 0xff is a nop when the result and left are the same */
7916 int p = pic16_my_powof2( (~lit) & 0xff );
7918 /* only one bit is set in the literal, so use a bcf instruction */
7919 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7920 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7923 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7924 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7925 if(know_W != (lit&0xff))
7926 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7928 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7933 if (AOP_TYPE(left) == AOP_ACC) {
7934 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7936 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7937 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7944 // left & result in different registers
7945 if(AOP_TYPE(result) == AOP_CRY){
7947 // if(size), result in bit
7948 // if(!size && ifx), conditional oper: if(left & right)
7949 symbol *tlbl = newiTempLabel(NULL);
7950 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7952 pic16_emitcode("setb","c");
7954 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7955 pic16_emitcode("anl","a,%s",
7956 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7957 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7962 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7963 pic16_outBitC(result);
7965 jmpTrueOrFalse(ifx, tlbl);
7967 for(;(size--);offset++) {
7969 // result = left & right
7970 if(AOP_TYPE(right) == AOP_LIT){
7971 int t = (lit >> (offset*8)) & 0x0FFL;
7974 pic16_emitcode("clrf","%s",
7975 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7976 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7979 pic16_emitcode("movf","%s,w",
7980 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7981 pic16_emitcode("movwf","%s",
7982 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7983 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7984 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7987 pic16_emitcode("movlw","0x%x",t);
7988 pic16_emitcode("andwf","%s,w",
7989 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7990 pic16_emitcode("movwf","%s",
7991 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7994 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7995 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8000 if (AOP_TYPE(left) == AOP_ACC) {
8001 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8002 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
8004 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8005 pic16_emitcode("andwf","%s,w",
8006 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8007 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8008 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
8010 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8011 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8017 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8018 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8019 pic16_freeAsmop(result,NULL,ic,TRUE);
8022 /*-----------------------------------------------------------------*/
8023 /* genOr - code for or */
8024 /*-----------------------------------------------------------------*/
8025 static void genOr (iCode *ic, iCode *ifx)
8027 operand *left, *right, *result;
8029 unsigned long lit = 0L;
8031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8033 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8034 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8035 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8037 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8039 /* if left is a literal & right is not then exchange them */
8040 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8041 AOP_NEEDSACC(left)) {
8042 operand *tmp = right ;
8047 /* if result = right then exchange them */
8048 if(pic16_sameRegs(AOP(result),AOP(right))){
8049 operand *tmp = right ;
8054 /* if right is bit then exchange them */
8055 if (AOP_TYPE(right) == AOP_CRY &&
8056 AOP_TYPE(left) != AOP_CRY){
8057 operand *tmp = right ;
8062 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
8064 if(AOP_TYPE(right) == AOP_LIT)
8065 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8067 size = AOP_SIZE(result);
8071 if (AOP_TYPE(left) == AOP_CRY){
8072 if(AOP_TYPE(right) == AOP_LIT){
8073 // c = bit & literal;
8075 // lit != 0 => result = 1
8076 if(AOP_TYPE(result) == AOP_CRY){
8078 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8079 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8080 // AOP(result)->aopu.aop_dir,
8081 // AOP(result)->aopu.aop_dir);
8083 continueIfTrue(ifx);
8087 // lit == 0 => result = left
8088 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8090 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8093 if (AOP_TYPE(right) == AOP_CRY){
8094 if(pic16_sameRegs(AOP(result),AOP(left))){
8096 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8097 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8098 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8100 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8101 AOP(result)->aopu.aop_dir,
8102 AOP(result)->aopu.aop_dir);
8103 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8104 AOP(right)->aopu.aop_dir,
8105 AOP(right)->aopu.aop_dir);
8106 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8107 AOP(result)->aopu.aop_dir,
8108 AOP(result)->aopu.aop_dir);
8110 if( AOP_TYPE(result) == AOP_ACC) {
8111 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8112 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8113 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8118 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8119 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8120 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8121 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8123 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8124 AOP(result)->aopu.aop_dir,
8125 AOP(result)->aopu.aop_dir);
8126 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8127 AOP(right)->aopu.aop_dir,
8128 AOP(right)->aopu.aop_dir);
8129 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8130 AOP(left)->aopu.aop_dir,
8131 AOP(left)->aopu.aop_dir);
8132 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8133 AOP(result)->aopu.aop_dir,
8134 AOP(result)->aopu.aop_dir);
8139 symbol *tlbl = newiTempLabel(NULL);
8140 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8143 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
8144 if( AOP_TYPE(right) == AOP_ACC) {
8145 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8147 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8148 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
8153 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8154 pic16_emitcode(";XXX setb","c");
8155 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8156 AOP(left)->aopu.aop_dir,tlbl->key+100);
8157 pic16_toBoolean(right);
8158 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8159 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8160 jmpTrueOrFalse(ifx, tlbl);
8164 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8171 pic16_outBitC(result);
8173 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8174 genIfxJump(ifx, "c");
8178 // if(val | 0xZZ) - size = 0, ifx != FALSE -
8179 // bit = val | 0xZZ - size = 1, ifx = FALSE -
8180 if((AOP_TYPE(right) == AOP_LIT) &&
8181 (AOP_TYPE(result) == AOP_CRY) &&
8182 (AOP_TYPE(left) != AOP_CRY)){
8184 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8187 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8189 continueIfTrue(ifx);
8192 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8193 // lit = 0, result = boolean(left)
8195 pic16_emitcode(";XXX setb","c");
8196 pic16_toBoolean(right);
8198 symbol *tlbl = newiTempLabel(NULL);
8199 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8201 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8203 genIfxJump (ifx,"a");
8207 pic16_outBitC(result);
8211 /* if left is same as result */
8212 if(pic16_sameRegs(AOP(result),AOP(left))){
8214 for(;size--; offset++,lit>>=8) {
8215 if(AOP_TYPE(right) == AOP_LIT){
8216 if((lit & 0xff) == 0)
8217 /* or'ing with 0 has no effect */
8220 int p = pic16_my_powof2(lit & 0xff);
8222 /* only one bit is set in the literal, so use a bsf instruction */
8223 pic16_emitpcode(POC_BSF,
8224 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8226 if(know_W != (lit & 0xff))
8227 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8228 know_W = lit & 0xff;
8229 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8234 if (AOP_TYPE(left) == AOP_ACC) {
8235 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
8236 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8238 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8239 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8241 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8242 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8248 // left & result in different registers
8249 if(AOP_TYPE(result) == AOP_CRY){
8251 // if(size), result in bit
8252 // if(!size && ifx), conditional oper: if(left | right)
8253 symbol *tlbl = newiTempLabel(NULL);
8254 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8255 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8259 pic16_emitcode(";XXX setb","c");
8261 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8262 pic16_emitcode(";XXX orl","a,%s",
8263 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8264 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8269 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8270 pic16_outBitC(result);
8272 jmpTrueOrFalse(ifx, tlbl);
8273 } else for(;(size--);offset++){
8275 // result = left & right
8276 if(AOP_TYPE(right) == AOP_LIT){
8277 int t = (lit >> (offset*8)) & 0x0FFL;
8280 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8283 pic16_emitcode("movf","%s,w",
8284 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8285 pic16_emitcode("movwf","%s",
8286 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8289 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8290 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8291 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8293 pic16_emitcode("movlw","0x%x",t);
8294 pic16_emitcode("iorwf","%s,w",
8295 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8296 pic16_emitcode("movwf","%s",
8297 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8303 // faster than result <- left, anl result,right
8304 // and better if result is SFR
8305 if (AOP_TYPE(left) == AOP_ACC) {
8306 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
8307 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8309 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8310 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
8312 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8313 pic16_emitcode("iorwf","%s,w",
8314 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8316 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8317 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8322 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8323 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8324 pic16_freeAsmop(result,NULL,ic,TRUE);
8327 /*-----------------------------------------------------------------*/
8328 /* genXor - code for xclusive or */
8329 /*-----------------------------------------------------------------*/
8330 static void genXor (iCode *ic, iCode *ifx)
8332 operand *left, *right, *result;
8334 unsigned long lit = 0L;
8336 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8338 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8339 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8340 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8342 /* if left is a literal & right is not ||
8343 if left needs acc & right does not */
8344 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8345 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8346 operand *tmp = right ;
8351 /* if result = right then exchange them */
8352 if(pic16_sameRegs(AOP(result),AOP(right))){
8353 operand *tmp = right ;
8358 /* if right is bit then exchange them */
8359 if (AOP_TYPE(right) == AOP_CRY &&
8360 AOP_TYPE(left) != AOP_CRY){
8361 operand *tmp = right ;
8365 if(AOP_TYPE(right) == AOP_LIT)
8366 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8368 size = AOP_SIZE(result);
8372 if (AOP_TYPE(left) == AOP_CRY){
8373 if(AOP_TYPE(right) == AOP_LIT){
8374 // c = bit & literal;
8376 // lit>>1 != 0 => result = 1
8377 if(AOP_TYPE(result) == AOP_CRY){
8379 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8380 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8382 continueIfTrue(ifx);
8385 pic16_emitcode("setb","c");
8389 // lit == 0, result = left
8390 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8392 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8394 // lit == 1, result = not(left)
8395 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8396 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8397 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8398 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8401 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8402 pic16_emitcode("cpl","c");
8409 symbol *tlbl = newiTempLabel(NULL);
8410 if (AOP_TYPE(right) == AOP_CRY){
8412 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8415 int sizer = AOP_SIZE(right);
8417 // if val>>1 != 0, result = 1
8418 pic16_emitcode("setb","c");
8420 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8422 // test the msb of the lsb
8423 pic16_emitcode("anl","a,#0xfe");
8424 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8428 pic16_emitcode("rrc","a");
8430 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8431 pic16_emitcode("cpl","c");
8432 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8437 pic16_outBitC(result);
8439 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8440 genIfxJump(ifx, "c");
8444 if(pic16_sameRegs(AOP(result),AOP(left))){
8445 /* if left is same as result */
8446 for(;size--; offset++) {
8447 if(AOP_TYPE(right) == AOP_LIT){
8448 int t = (lit >> (offset*8)) & 0x0FFL;
8452 if (IS_AOP_PREG(left)) {
8453 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8454 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8455 pic16_aopPut(AOP(result),"a",offset);
8457 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8458 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8459 pic16_emitcode("xrl","%s,%s",
8460 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8461 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8464 if (AOP_TYPE(left) == AOP_ACC)
8465 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8467 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8468 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8470 if (IS_AOP_PREG(left)) {
8471 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8472 pic16_aopPut(AOP(result),"a",offset);
8474 pic16_emitcode("xrl","%s,a",
8475 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8481 // left & result in different registers
8482 if(AOP_TYPE(result) == AOP_CRY){
8484 // if(size), result in bit
8485 // if(!size && ifx), conditional oper: if(left ^ right)
8486 symbol *tlbl = newiTempLabel(NULL);
8487 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8489 pic16_emitcode("setb","c");
8491 if((AOP_TYPE(right) == AOP_LIT) &&
8492 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8493 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8495 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8496 pic16_emitcode("xrl","a,%s",
8497 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8499 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8504 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8505 pic16_outBitC(result);
8507 jmpTrueOrFalse(ifx, tlbl);
8508 } else for(;(size--);offset++){
8510 // result = left & right
8511 if(AOP_TYPE(right) == AOP_LIT){
8512 int t = (lit >> (offset*8)) & 0x0FFL;
8515 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8516 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8517 pic16_emitcode("movf","%s,w",
8518 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8519 pic16_emitcode("movwf","%s",
8520 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8523 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8524 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8525 pic16_emitcode("comf","%s,w",
8526 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8527 pic16_emitcode("movwf","%s",
8528 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8531 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8532 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8533 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8534 pic16_emitcode("movlw","0x%x",t);
8535 pic16_emitcode("xorwf","%s,w",
8536 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8537 pic16_emitcode("movwf","%s",
8538 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8544 // faster than result <- left, anl result,right
8545 // and better if result is SFR
8546 if (AOP_TYPE(left) == AOP_ACC) {
8547 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8548 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8550 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8551 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8552 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8553 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8555 if ( AOP_TYPE(result) != AOP_ACC){
8556 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8557 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8563 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8564 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8565 pic16_freeAsmop(result,NULL,ic,TRUE);
8568 /*-----------------------------------------------------------------*/
8569 /* genInline - write the inline code out */
8570 /*-----------------------------------------------------------------*/
8571 static void genInline (iCode *ic)
8573 char *buffer, *bp, *bp1;
8575 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8577 _G.inLine += (!options.asmpeep);
8579 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8580 strcpy(buffer,IC_INLINE(ic));
8582 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8584 /* emit each line as a code */
8590 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8598 /* print label, use this special format with NULL directive
8599 * to denote that the argument should not be indented with tab */
8600 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8607 if ((bp1 != bp) && *bp1)
8608 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8613 _G.inLine -= (!options.asmpeep);
8616 /*-----------------------------------------------------------------*/
8617 /* genRRC - rotate right with carry */
8618 /*-----------------------------------------------------------------*/
8619 static void genRRC (iCode *ic)
8621 operand *left , *result ;
8622 int size, offset = 0, same;
8624 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8626 /* rotate right with carry */
8628 result=IC_RESULT(ic);
8629 pic16_aopOp (left,ic,FALSE);
8630 pic16_aopOp (result,ic,FALSE);
8632 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8634 same = pic16_sameRegs(AOP(result),AOP(left));
8636 size = AOP_SIZE(result);
8638 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8640 /* get the lsb and put it into the carry */
8641 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8648 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8650 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8651 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8657 pic16_freeAsmop(left,NULL,ic,TRUE);
8658 pic16_freeAsmop(result,NULL,ic,TRUE);
8661 /*-----------------------------------------------------------------*/
8662 /* genRLC - generate code for rotate left with carry */
8663 /*-----------------------------------------------------------------*/
8664 static void genRLC (iCode *ic)
8666 operand *left , *result ;
8667 int size, offset = 0;
8670 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8671 /* rotate right with carry */
8673 result=IC_RESULT(ic);
8674 pic16_aopOp (left,ic,FALSE);
8675 pic16_aopOp (result,ic,FALSE);
8677 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8679 same = pic16_sameRegs(AOP(result),AOP(left));
8681 /* move it to the result */
8682 size = AOP_SIZE(result);
8684 /* get the msb and put it into the carry */
8685 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8692 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8694 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8702 pic16_freeAsmop(left,NULL,ic,TRUE);
8703 pic16_freeAsmop(result,NULL,ic,TRUE);
8707 /* gpasm can get the highest order bit with HIGH/UPPER
8708 * so the following probably is not needed -- VR */
8710 /*-----------------------------------------------------------------*/
8711 /* genGetHbit - generates code get highest order bit */
8712 /*-----------------------------------------------------------------*/
8713 static void genGetHbit (iCode *ic)
8715 operand *left, *result;
8717 result=IC_RESULT(ic);
8718 pic16_aopOp (left,ic,FALSE);
8719 pic16_aopOp (result,ic,FALSE);
8721 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8722 /* get the highest order byte into a */
8723 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8724 if(AOP_TYPE(result) == AOP_CRY){
8725 pic16_emitcode("rlc","a");
8726 pic16_outBitC(result);
8729 pic16_emitcode("rl","a");
8730 pic16_emitcode("anl","a,#0x01");
8731 pic16_outAcc(result);
8735 pic16_freeAsmop(left,NULL,ic,TRUE);
8736 pic16_freeAsmop(result,NULL,ic,TRUE);
8740 /*-----------------------------------------------------------------*/
8741 /* AccRol - rotate left accumulator by known count */
8742 /*-----------------------------------------------------------------*/
8743 static void AccRol (int shCount)
8745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8746 shCount &= 0x0007; // shCount : 0..7
8751 pic16_emitcode("rl","a");
8754 pic16_emitcode("rl","a");
8755 pic16_emitcode("rl","a");
8758 pic16_emitcode("swap","a");
8759 pic16_emitcode("rr","a");
8762 pic16_emitcode("swap","a");
8765 pic16_emitcode("swap","a");
8766 pic16_emitcode("rl","a");
8769 pic16_emitcode("rr","a");
8770 pic16_emitcode("rr","a");
8773 pic16_emitcode("rr","a");
8779 /*-----------------------------------------------------------------*/
8780 /* AccLsh - left shift accumulator by known count */
8781 /*-----------------------------------------------------------------*/
8782 static void AccLsh (int shCount)
8784 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8790 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8793 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8794 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8797 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8798 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8801 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8804 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8805 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8808 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8809 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8816 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8819 /*-----------------------------------------------------------------*/
8820 /* AccRsh - right shift accumulator by known count */
8821 /*-----------------------------------------------------------------*/
8822 static void AccRsh (int shCount, int andmask)
8824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8829 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8832 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8836 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8837 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8840 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8843 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8844 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8847 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8848 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8851 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8856 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8858 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8862 /*-----------------------------------------------------------------*/
8863 /* AccSRsh - signed right shift accumulator by known count */
8864 /*-----------------------------------------------------------------*/
8865 static void AccSRsh (int shCount)
8868 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8871 pic16_emitcode("mov","c,acc.7");
8872 pic16_emitcode("rrc","a");
8873 } else if(shCount == 2){
8874 pic16_emitcode("mov","c,acc.7");
8875 pic16_emitcode("rrc","a");
8876 pic16_emitcode("mov","c,acc.7");
8877 pic16_emitcode("rrc","a");
8879 tlbl = newiTempLabel(NULL);
8880 /* rotate right accumulator */
8881 AccRol(8 - shCount);
8882 /* and kill the higher order bits */
8883 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8884 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8885 pic16_emitcode("orl","a,#0x%02x",
8886 (unsigned char)~SRMask[shCount]);
8887 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8893 /*-----------------------------------------------------------------*/
8894 /* shiftR1Left2Result - shift right one byte from left to result */
8895 /*-----------------------------------------------------------------*/
8896 static void shiftR1Left2ResultSigned (operand *left, int offl,
8897 operand *result, int offr,
8902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8904 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8908 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8910 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8912 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8921 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8923 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8924 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8926 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8927 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8940 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8943 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8944 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8950 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8951 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8952 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8953 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8961 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8965 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8966 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8973 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8974 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8975 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8976 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8981 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8983 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8989 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8990 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8991 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8996 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
9004 /*-----------------------------------------------------------------*/
9005 /* shiftR1Left2Result - shift right one byte from left to result */
9006 /*-----------------------------------------------------------------*/
9007 static void shiftR1Left2Result (operand *left, int offl,
9008 operand *result, int offr,
9009 int shCount, int sign)
9013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9015 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9017 /* Copy the msb into the carry if signed. */
9019 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9029 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9032 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9038 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9041 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
9056 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9057 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9058 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9063 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9068 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9069 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9070 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9072 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9077 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
9078 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9080 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9087 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9088 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9097 /*-----------------------------------------------------------------*/
9098 /* shiftL1Left2Result - shift left one byte from left to result */
9099 /*-----------------------------------------------------------------*/
9100 static void shiftL1Left2Result (operand *left, int offl,
9101 operand *result, int offr, int shCount)
9106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9108 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9109 DEBUGpic16_emitcode ("; ***","same = %d",same);
9110 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9112 /* shift left accumulator */
9113 //AccLsh(shCount); // don't comment out just yet...
9114 // pic16_aopPut(AOP(result),"a",offr);
9118 /* Shift left 1 bit position */
9119 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9121 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9123 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9124 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9128 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9129 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9130 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9134 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9135 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9136 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9137 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9138 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9142 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9143 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9147 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9148 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9149 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9153 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9160 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9165 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9170 /*-----------------------------------------------------------------*/
9171 /* movLeft2Result - move byte from left to result */
9172 /*-----------------------------------------------------------------*/
9173 static void movLeft2Result (operand *left, int offl,
9174 operand *result, int offr)
9177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9178 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9179 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9181 if (*l == '@' && (IS_AOP_PREG(result))) {
9182 pic16_emitcode("mov","a,%s",l);
9183 pic16_aopPut(AOP(result),"a",offr);
9185 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9186 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9191 /*-----------------------------------------------------------------*/
9192 /* shiftL2Left2Result - shift left two bytes from left to result */
9193 /*-----------------------------------------------------------------*/
9194 static void shiftL2Left2Result (operand *left, int offl,
9195 operand *result, int offr, int shCount)
9197 int same = pic16_sameRegs(AOP(result), AOP(left));
9200 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9202 if (same && (offl != offr)) { // shift bytes
9205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9206 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9208 } else { // just treat as different later on
9221 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9222 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9223 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9227 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9228 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9234 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9235 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9236 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9237 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9238 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9239 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9240 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9242 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9243 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9247 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9248 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9249 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9250 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9251 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9252 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9253 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9254 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9255 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9256 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9259 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9260 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9261 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9262 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9263 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9273 /* note, use a mov/add for the shift since the mov has a
9274 chance of getting optimized out */
9275 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9277 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9278 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9279 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9283 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9284 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9290 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9291 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9292 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9293 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9294 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9295 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9296 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9297 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9301 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9302 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9306 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9307 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9308 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9309 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9311 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9312 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9313 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9314 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9315 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9316 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9317 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9318 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9321 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9322 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9323 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9324 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9325 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9330 /*-----------------------------------------------------------------*/
9331 /* shiftR2Left2Result - shift right two bytes from left to result */
9332 /*-----------------------------------------------------------------*/
9333 static void shiftR2Left2Result (operand *left, int offl,
9334 operand *result, int offr,
9335 int shCount, int sign)
9337 int same = pic16_sameRegs(AOP(result), AOP(left));
9339 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9341 if (same && (offl != offr)) { // shift right bytes
9344 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9345 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9347 } else { // just treat as different later on
9359 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9364 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9365 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9367 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9368 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9370 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9375 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9378 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9379 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9386 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9387 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9388 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9390 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9391 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9392 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9393 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9395 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9396 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9397 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9399 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9400 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9401 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9402 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9403 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9407 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9408 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9412 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9413 pic16_emitpcode(POC_BTFSC,
9414 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9415 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9423 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9424 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9426 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9427 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9428 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9429 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9431 pic16_emitpcode(POC_BTFSC,
9432 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9433 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9435 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9436 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9437 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9438 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9440 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9441 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9442 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9443 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9444 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9445 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9446 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9447 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9449 pic16_emitpcode(POC_BTFSC,
9450 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9451 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9453 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9454 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9461 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9462 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9463 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9464 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9467 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9469 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9474 /*-----------------------------------------------------------------*/
9475 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9476 /*-----------------------------------------------------------------*/
9477 static void shiftLLeftOrResult (operand *left, int offl,
9478 operand *result, int offr, int shCount)
9480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9482 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9483 /* shift left accumulator */
9485 /* or with result */
9486 /* back to result */
9487 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9490 /*-----------------------------------------------------------------*/
9491 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9492 /*-----------------------------------------------------------------*/
9493 static void shiftRLeftOrResult (operand *left, int offl,
9494 operand *result, int offr, int shCount)
9496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9499 /* shift right accumulator */
9501 /* or with result */
9502 /* back to result */
9503 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9506 /*-----------------------------------------------------------------*/
9507 /* genlshOne - left shift a one byte quantity by known count */
9508 /*-----------------------------------------------------------------*/
9509 static void genlshOne (operand *result, operand *left, int shCount)
9511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9512 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9515 /*-----------------------------------------------------------------*/
9516 /* genlshTwo - left shift two bytes by known amount != 0 */
9517 /*-----------------------------------------------------------------*/
9518 static void genlshTwo (operand *result,operand *left, int shCount)
9522 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9523 size = pic16_getDataSize(result);
9525 /* if shCount >= 8 */
9531 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9533 movLeft2Result(left, LSB, result, MSB16);
9535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9538 /* 1 <= shCount <= 7 */
9541 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9543 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9547 /*-----------------------------------------------------------------*/
9548 /* shiftLLong - shift left one long from left to result */
9549 /* offr = LSB or MSB16 */
9550 /*-----------------------------------------------------------------*/
9551 static void shiftLLong (operand *left, operand *result, int offr )
9553 int size = AOP_SIZE(result);
9554 int same = pic16_sameRegs(AOP(left),AOP(result));
9557 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9559 if (same && (offr == MSB16)) { //shift one byte
9560 for(i=size-1;i>=MSB16;i--) {
9561 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9562 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9565 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9568 if (size > LSB+offr ){
9570 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9572 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9573 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9577 if(size > MSB16+offr){
9579 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9581 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9582 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9586 if(size > MSB24+offr){
9588 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9590 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9591 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9595 if(size > MSB32+offr){
9597 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9599 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9600 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9604 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9608 /*-----------------------------------------------------------------*/
9609 /* genlshFour - shift four byte by a known amount != 0 */
9610 /*-----------------------------------------------------------------*/
9611 static void genlshFour (operand *result, operand *left, int shCount)
9615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9616 size = AOP_SIZE(result);
9618 /* if shifting more that 3 bytes */
9619 if (shCount >= 24 ) {
9622 /* lowest order of left goes to the highest
9623 order of the destination */
9624 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9626 movLeft2Result(left, LSB, result, MSB32);
9628 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9629 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9630 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9635 /* more than two bytes */
9636 else if ( shCount >= 16 ) {
9637 /* lower order two bytes goes to higher order two bytes */
9639 /* if some more remaining */
9641 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9643 movLeft2Result(left, MSB16, result, MSB32);
9644 movLeft2Result(left, LSB, result, MSB24);
9646 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9647 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9651 /* if more than 1 byte */
9652 else if ( shCount >= 8 ) {
9653 /* lower order three bytes goes to higher order three bytes */
9657 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9659 movLeft2Result(left, LSB, result, MSB16);
9661 else{ /* size = 4 */
9663 movLeft2Result(left, MSB24, result, MSB32);
9664 movLeft2Result(left, MSB16, result, MSB24);
9665 movLeft2Result(left, LSB, result, MSB16);
9666 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668 else if(shCount == 1)
9669 shiftLLong(left, result, MSB16);
9671 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9672 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9673 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9674 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9679 /* 1 <= shCount <= 7 */
9680 else if(shCount <= 3)
9682 shiftLLong(left, result, LSB);
9683 while(--shCount >= 1)
9684 shiftLLong(result, result, LSB);
9686 /* 3 <= shCount <= 7, optimize */
9688 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9689 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9690 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9694 /*-----------------------------------------------------------------*/
9695 /* genLeftShiftLiteral - left shifting by known count */
9696 /*-----------------------------------------------------------------*/
9697 void pic16_genLeftShiftLiteral (operand *left,
9702 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9706 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9707 pic16_freeAsmop(right,NULL,ic,TRUE);
9709 pic16_aopOp(left,ic,FALSE);
9710 pic16_aopOp(result,ic,FALSE);
9712 size = getSize(operandType(result));
9715 pic16_emitcode("; shift left ","result %d, left %d",size,
9719 /* I suppose that the left size >= result size */
9722 movLeft2Result(left, size, result, size);
9726 else if(shCount >= (size * 8))
9728 pic16_aopPut(AOP(result),zero,size);
9732 genlshOne (result,left,shCount);
9737 genlshTwo (result,left,shCount);
9741 genlshFour (result,left,shCount);
9745 pic16_freeAsmop(left,NULL,ic,TRUE);
9746 pic16_freeAsmop(result,NULL,ic,TRUE);
9749 /*-----------------------------------------------------------------*
9750 * genMultiAsm - repeat assembly instruction for size of register.
9751 * if endian == 1, then the high byte (i.e base address + size of
9752 * register) is used first else the low byte is used first;
9753 *-----------------------------------------------------------------*/
9754 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9772 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9778 #if !(USE_GENERIC_SIGNED_SHIFT)
9779 /*-----------------------------------------------------------------*/
9780 /* genLeftShift - generates code for left shifting */
9781 /*-----------------------------------------------------------------*/
9782 static void genLeftShift (iCode *ic)
9784 operand *left,*right, *result;
9787 symbol *tlbl , *tlbl1;
9790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9792 right = IC_RIGHT(ic);
9794 result = IC_RESULT(ic);
9796 pic16_aopOp(right,ic,FALSE);
9798 /* if the shift count is known then do it
9799 as efficiently as possible */
9800 if (AOP_TYPE(right) == AOP_LIT) {
9801 pic16_genLeftShiftLiteral (left,right,result,ic);
9805 /* shift count is unknown then we have to form
9806 * a loop. Get the loop count in WREG : Note: we take
9807 * only the lower order byte since shifting
9808 * more than 32 bits make no sense anyway, ( the
9809 * largest size of an object can be only 32 bits ) */
9811 pic16_aopOp(left,ic,FALSE);
9812 pic16_aopOp(result,ic,FALSE);
9814 /* now move the left to the result if they are not the
9815 * same, and if size > 1,
9816 * and if right is not same to result (!!!) -- VR */
9817 if (!pic16_sameRegs(AOP(left),AOP(result))
9818 && (AOP_SIZE(result) > 1)) {
9820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9822 size = AOP_SIZE(result);
9827 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9828 if (*l == '@' && (IS_AOP_PREG(result))) {
9830 pic16_emitcode("mov","a,%s",l);
9831 pic16_aopPut(AOP(result),"a",offset);
9835 /* we don't know if left is a literal or a register, take care -- VR */
9836 mov2f(AOP(result), AOP(left), offset);
9842 size = AOP_SIZE(result);
9844 /* if it is only one byte then */
9846 if(optimized_for_speed) {
9847 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9848 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9849 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9850 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9851 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9852 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9853 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9854 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9855 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9856 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9857 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9858 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9863 tlbl = newiTempLabel(NULL);
9866 /* this is already done, why change it? */
9867 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9868 mov2f(AOP(result), AOP(left), 0);
9872 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9873 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9874 pic16_emitpLabel(tlbl->key);
9875 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9876 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9883 if (pic16_sameRegs(AOP(left),AOP(result))) {
9885 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9887 tlbl = newiTempLabel(NULL);
9888 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9889 genMultiAsm(POC_RRCF, result, size,1);
9890 pic16_emitpLabel(tlbl->key);
9891 genMultiAsm(POC_RLCF, result, size,0);
9892 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9898 //tlbl = newiTempLabel(NULL);
9900 //tlbl1 = newiTempLabel(NULL);
9902 //reAdjustPreg(AOP(result));
9904 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9905 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9906 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9908 //pic16_emitcode("add","a,acc");
9909 //pic16_aopPut(AOP(result),"a",offset++);
9911 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9913 // pic16_emitcode("rlc","a");
9914 // pic16_aopPut(AOP(result),"a",offset++);
9916 //reAdjustPreg(AOP(result));
9918 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9919 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9922 tlbl = newiTempLabel(NULL);
9923 tlbl1= newiTempLabel(NULL);
9925 size = AOP_SIZE(result);
9928 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9930 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9932 /* offset should be 0, 1 or 3 */
9934 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9936 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9938 pic16_emitpcode(POC_MOVWF, pctemp);
9941 pic16_emitpLabel(tlbl->key);
9944 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9948 pic16_emitpcode(POC_DECFSZ, pctemp);
9949 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9950 pic16_emitpLabel(tlbl1->key);
9952 pic16_popReleaseTempReg(pctemp,1);
9956 pic16_freeAsmop (right,NULL,ic,TRUE);
9957 pic16_freeAsmop(left,NULL,ic,TRUE);
9958 pic16_freeAsmop(result,NULL,ic,TRUE);
9964 #error old code (left here for reference)
9965 /*-----------------------------------------------------------------*/
9966 /* genLeftShift - generates code for left shifting */
9967 /*-----------------------------------------------------------------*/
9968 static void genLeftShift (iCode *ic)
9970 operand *left,*right, *result;
9973 symbol *tlbl , *tlbl1;
9976 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9978 right = IC_RIGHT(ic);
9980 result = IC_RESULT(ic);
9982 pic16_aopOp(right,ic,FALSE);
9984 /* if the shift count is known then do it
9985 as efficiently as possible */
9986 if (AOP_TYPE(right) == AOP_LIT) {
9987 pic16_genLeftShiftLiteral (left,right,result,ic);
9991 /* shift count is unknown then we have to form
9992 a loop get the loop count in B : Note: we take
9993 only the lower order byte since shifting
9994 more that 32 bits make no sense anyway, ( the
9995 largest size of an object can be only 32 bits ) */
9998 pic16_aopOp(left,ic,FALSE);
9999 pic16_aopOp(result,ic,FALSE);
10001 /* now move the left to the result if they are not the
10003 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10004 AOP_SIZE(result) > 1) {
10006 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10008 size = AOP_SIZE(result);
10011 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10012 if (*l == '@' && (IS_AOP_PREG(result))) {
10014 pic16_emitcode("mov","a,%s",l);
10015 pic16_aopPut(AOP(result),"a",offset);
10018 /* we don't know if left is a literal or a register, take care -- VR */
10019 mov2f(AOP(result), AOP(left), offset);
10025 size = AOP_SIZE(result);
10027 /* if it is only one byte then */
10029 if(optimized_for_speed) {
10030 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10031 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
10032 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10033 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10034 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10035 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10036 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10037 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
10038 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
10039 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
10040 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10041 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
10044 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10046 tlbl = newiTempLabel(NULL);
10047 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10048 mov2f(AOP(result), AOP(left), 0);
10050 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10051 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10054 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10055 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10056 pic16_emitpLabel(tlbl->key);
10057 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10058 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10060 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10065 if (pic16_sameRegs(AOP(left),AOP(result))) {
10067 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10069 tlbl = newiTempLabel(NULL);
10070 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10071 genMultiAsm(POC_RRCF, result, size,1);
10072 pic16_emitpLabel(tlbl->key);
10073 genMultiAsm(POC_RLCF, result, size,0);
10074 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10076 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10080 //tlbl = newiTempLabel(NULL);
10082 //tlbl1 = newiTempLabel(NULL);
10084 //reAdjustPreg(AOP(result));
10086 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10087 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10088 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10090 //pic16_emitcode("add","a,acc");
10091 //pic16_aopPut(AOP(result),"a",offset++);
10093 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10095 // pic16_emitcode("rlc","a");
10096 // pic16_aopPut(AOP(result),"a",offset++);
10098 //reAdjustPreg(AOP(result));
10100 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10101 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10104 tlbl = newiTempLabel(NULL);
10105 tlbl1= newiTempLabel(NULL);
10107 size = AOP_SIZE(result);
10110 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10112 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10114 /* offset should be 0, 1 or 3 */
10116 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10118 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10120 pic16_emitpcode(POC_MOVWF, pctemp);
10123 pic16_emitpLabel(tlbl->key);
10126 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10128 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
10130 pic16_emitpcode(POC_DECFSZ, pctemp);
10131 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10132 pic16_emitpLabel(tlbl1->key);
10134 pic16_popReleaseTempReg(pctemp,1);
10138 pic16_freeAsmop (right,NULL,ic,TRUE);
10139 pic16_freeAsmop(left,NULL,ic,TRUE);
10140 pic16_freeAsmop(result,NULL,ic,TRUE);
10144 /*-----------------------------------------------------------------*/
10145 /* genrshOne - right shift a one byte quantity by known count */
10146 /*-----------------------------------------------------------------*/
10147 static void genrshOne (operand *result, operand *left,
10148 int shCount, int sign)
10150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10151 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10154 /*-----------------------------------------------------------------*/
10155 /* genrshTwo - right shift two bytes by known amount != 0 */
10156 /*-----------------------------------------------------------------*/
10157 static void genrshTwo (operand *result,operand *left,
10158 int shCount, int sign)
10160 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10161 /* if shCount >= 8 */
10162 if (shCount >= 8) {
10165 shiftR1Left2Result(left, MSB16, result, LSB,
10168 movLeft2Result(left, MSB16, result, LSB);
10170 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
10173 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10174 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
10178 /* 1 <= shCount <= 7 */
10180 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10183 /*-----------------------------------------------------------------*/
10184 /* shiftRLong - shift right one long from left to result */
10185 /* offl = LSB or MSB16 */
10186 /*-----------------------------------------------------------------*/
10187 static void shiftRLong (operand *left, int offl,
10188 operand *result, int sign)
10190 int size = AOP_SIZE(result);
10191 int same = pic16_sameRegs(AOP(left),AOP(result));
10193 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10195 if (same && (offl == MSB16)) { //shift one byte right
10196 for(i=MSB16;i<size;i++) {
10197 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10198 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10203 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10209 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10211 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10212 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10215 if(offl == MSB16) {
10216 /* add sign of "a" */
10217 pic16_addSign(result, MSB32, sign);
10221 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10223 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10224 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10228 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10230 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10231 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10235 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10238 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10239 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10244 /*-----------------------------------------------------------------*/
10245 /* genrshFour - shift four byte by a known amount != 0 */
10246 /*-----------------------------------------------------------------*/
10247 static void genrshFour (operand *result, operand *left,
10248 int shCount, int sign)
10250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10251 /* if shifting more that 3 bytes */
10252 if(shCount >= 24 ) {
10255 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10257 movLeft2Result(left, MSB32, result, LSB);
10259 pic16_addSign(result, MSB16, sign);
10261 else if(shCount >= 16){
10264 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10266 movLeft2Result(left, MSB24, result, LSB);
10267 movLeft2Result(left, MSB32, result, MSB16);
10269 pic16_addSign(result, MSB24, sign);
10271 else if(shCount >= 8){
10274 shiftRLong(left, MSB16, result, sign);
10275 else if(shCount == 0){
10276 movLeft2Result(left, MSB16, result, LSB);
10277 movLeft2Result(left, MSB24, result, MSB16);
10278 movLeft2Result(left, MSB32, result, MSB24);
10279 pic16_addSign(result, MSB32, sign);
10281 else{ //shcount >= 2
10282 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10283 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10284 /* the last shift is signed */
10285 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10286 pic16_addSign(result, MSB32, sign);
10289 else{ /* 1 <= shCount <= 7 */
10291 shiftRLong(left, LSB, result, sign);
10293 shiftRLong(result, LSB, result, sign);
10296 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10297 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10298 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10303 /*-----------------------------------------------------------------*/
10304 /* genRightShiftLiteral - right shifting by known count */
10305 /*-----------------------------------------------------------------*/
10306 static void genRightShiftLiteral (operand *left,
10312 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10313 int lsize,res_size;
10315 pic16_freeAsmop(right,NULL,ic,TRUE);
10317 pic16_aopOp(left,ic,FALSE);
10318 pic16_aopOp(result,ic,FALSE);
10320 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10323 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10327 lsize = pic16_getDataSize(left);
10328 res_size = pic16_getDataSize(result);
10329 /* test the LEFT size !!! */
10331 /* I suppose that the left size >= result size */
10334 movLeft2Result(left, lsize, result, res_size);
10337 else if(shCount >= (lsize * 8)){
10339 if(res_size == 1) {
10340 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10342 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10343 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
10348 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10349 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10350 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10352 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10357 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10362 switch (res_size) {
10364 genrshOne (result,left,shCount,sign);
10368 genrshTwo (result,left,shCount,sign);
10372 genrshFour (result,left,shCount,sign);
10380 pic16_freeAsmop(left,NULL,ic,TRUE);
10381 pic16_freeAsmop(result,NULL,ic,TRUE);
10384 #if !(USE_GENERIC_SIGNED_SHIFT)
10385 /*-----------------------------------------------------------------*/
10386 /* genSignedRightShift - right shift of signed number */
10387 /*-----------------------------------------------------------------*/
10388 static void genSignedRightShift (iCode *ic)
10390 operand *right, *left, *result;
10393 symbol *tlbl, *tlbl1 ;
10396 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10398 /* we do it the hard way put the shift count in b
10399 and loop thru preserving the sign */
10400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10402 right = IC_RIGHT(ic);
10403 left = IC_LEFT(ic);
10404 result = IC_RESULT(ic);
10406 pic16_aopOp(right,ic,FALSE);
10407 pic16_aopOp(left,ic,FALSE);
10408 pic16_aopOp(result,ic,FALSE);
10411 if ( AOP_TYPE(right) == AOP_LIT) {
10412 genRightShiftLiteral (left,right,result,ic,1);
10415 /* shift count is unknown then we have to form
10416 a loop get the loop count in B : Note: we take
10417 only the lower order byte since shifting
10418 more that 32 bits make no sense anyway, ( the
10419 largest size of an object can be only 32 bits ) */
10421 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10422 //pic16_emitcode("inc","b");
10423 //pic16_freeAsmop (right,NULL,ic,TRUE);
10424 //pic16_aopOp(left,ic,FALSE);
10425 //pic16_aopOp(result,ic,FALSE);
10427 /* now move the left to the result if they are not the
10429 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10430 AOP_SIZE(result) > 1) {
10432 size = AOP_SIZE(result);
10436 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10437 if (*l == '@' && IS_AOP_PREG(result)) {
10439 pic16_emitcode("mov","a,%s",l);
10440 pic16_aopPut(AOP(result),"a",offset);
10442 pic16_aopPut(AOP(result),l,offset);
10444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10445 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10451 /* mov the highest order bit to OVR */
10452 tlbl = newiTempLabel(NULL);
10453 tlbl1= newiTempLabel(NULL);
10455 size = AOP_SIZE(result);
10458 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10460 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10462 /* offset should be 0, 1 or 3 */
10463 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10465 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10467 pic16_emitpcode(POC_MOVWF, pctemp);
10470 pic16_emitpLabel(tlbl->key);
10472 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10473 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10476 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10479 pic16_emitpcode(POC_DECFSZ, pctemp);
10480 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10481 pic16_emitpLabel(tlbl1->key);
10483 pic16_popReleaseTempReg(pctemp,1);
10485 size = AOP_SIZE(result);
10487 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10488 pic16_emitcode("rlc","a");
10489 pic16_emitcode("mov","ov,c");
10490 /* if it is only one byte then */
10492 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10494 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10495 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10496 pic16_emitcode("mov","c,ov");
10497 pic16_emitcode("rrc","a");
10498 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10499 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10500 pic16_aopPut(AOP(result),"a",0);
10504 reAdjustPreg(AOP(result));
10505 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10506 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10507 pic16_emitcode("mov","c,ov");
10509 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10511 pic16_emitcode("rrc","a");
10512 pic16_aopPut(AOP(result),"a",offset--);
10514 reAdjustPreg(AOP(result));
10515 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10516 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10521 pic16_freeAsmop(left,NULL,ic,TRUE);
10522 pic16_freeAsmop(result,NULL,ic,TRUE);
10523 pic16_freeAsmop(right,NULL,ic,TRUE);
10527 #if !(USE_GENERIC_SIGNED_SHIFT)
10528 #warning This implementation of genRightShift() is incomplete!
10529 /*-----------------------------------------------------------------*/
10530 /* genRightShift - generate code for right shifting */
10531 /*-----------------------------------------------------------------*/
10532 static void genRightShift (iCode *ic)
10534 operand *right, *left, *result;
10538 symbol *tlbl, *tlbl1 ;
10540 /* if signed then we do it the hard way preserve the
10541 sign bit moving it inwards */
10542 letype = getSpec(operandType(IC_LEFT(ic)));
10543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10545 if (!SPEC_USIGN(letype)) {
10546 genSignedRightShift (ic);
10550 /* signed & unsigned types are treated the same : i.e. the
10551 signed is NOT propagated inwards : quoting from the
10552 ANSI - standard : "for E1 >> E2, is equivalent to division
10553 by 2**E2 if unsigned or if it has a non-negative value,
10554 otherwise the result is implementation defined ", MY definition
10555 is that the sign does not get propagated */
10557 right = IC_RIGHT(ic);
10558 left = IC_LEFT(ic);
10559 result = IC_RESULT(ic);
10561 pic16_aopOp(right,ic,FALSE);
10563 /* if the shift count is known then do it
10564 as efficiently as possible */
10565 if (AOP_TYPE(right) == AOP_LIT) {
10566 genRightShiftLiteral (left,right,result,ic, 0);
10570 /* shift count is unknown then we have to form
10571 a loop get the loop count in B : Note: we take
10572 only the lower order byte since shifting
10573 more that 32 bits make no sense anyway, ( the
10574 largest size of an object can be only 32 bits ) */
10576 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10577 pic16_emitcode("inc","b");
10578 pic16_aopOp(left,ic,FALSE);
10579 pic16_aopOp(result,ic,FALSE);
10581 /* now move the left to the result if they are not the
10583 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10584 AOP_SIZE(result) > 1) {
10586 size = AOP_SIZE(result);
10589 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10590 if (*l == '@' && IS_AOP_PREG(result)) {
10592 pic16_emitcode("mov","a,%s",l);
10593 pic16_aopPut(AOP(result),"a",offset);
10595 pic16_aopPut(AOP(result),l,offset);
10600 tlbl = newiTempLabel(NULL);
10601 tlbl1= newiTempLabel(NULL);
10602 size = AOP_SIZE(result);
10605 /* if it is only one byte then */
10608 tlbl = newiTempLabel(NULL);
10609 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10610 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10611 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10614 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10615 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10616 pic16_emitpLabel(tlbl->key);
10617 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10618 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10620 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10625 reAdjustPreg(AOP(result));
10626 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10627 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10630 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10632 pic16_emitcode("rrc","a");
10633 pic16_aopPut(AOP(result),"a",offset--);
10635 reAdjustPreg(AOP(result));
10637 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10638 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10641 pic16_freeAsmop(left,NULL,ic,TRUE);
10642 pic16_freeAsmop (right,NULL,ic,TRUE);
10643 pic16_freeAsmop(result,NULL,ic,TRUE);
10647 #if (USE_GENERIC_SIGNED_SHIFT)
10648 /*-----------------------------------------------------------------*/
10649 /* genGenericShift - generates code for left or right shifting */
10650 /*-----------------------------------------------------------------*/
10651 static void genGenericShift (iCode *ic, int isShiftLeft) {
10652 operand *left,*right, *result;
10654 int sign, signedCount;
10655 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10656 PIC_OPCODE pos_shift, neg_shift;
10660 right = IC_RIGHT(ic);
10661 left = IC_LEFT(ic);
10662 result = IC_RESULT(ic);
10664 pic16_aopOp(right,ic,FALSE);
10665 pic16_aopOp(left,ic,FALSE);
10666 pic16_aopOp(result,ic,FALSE);
10668 sign = !SPEC_USIGN(operandType (left));
10669 signedCount = !SPEC_USIGN(operandType (right));
10671 /* if the shift count is known then do it
10672 as efficiently as possible */
10673 if (AOP_TYPE(right) == AOP_LIT) {
10674 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10675 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10676 // we should modify right->aopu.aop_lit here!
10677 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10678 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10680 pic16_genLeftShiftLiteral (left,right,result,ic);
10682 genRightShiftLiteral (left,right,result,ic, sign);
10685 } // if (right is literal)
10687 /* shift count is unknown then we have to form a loop.
10688 * Note: we take only the lower order byte since shifting
10689 * more than 32 bits make no sense anyway, ( the
10690 * largest size of an object can be only 32 bits )
10691 * Note: we perform arithmetic shifts if the left operand is
10692 * signed and we do an (effective) right shift, i. e. we
10693 * shift in the sign bit from the left. */
10695 label_complete = newiTempLabel ( NULL );
10696 label_loop_pos = newiTempLabel ( NULL );
10697 label_loop_neg = NULL;
10698 label_negative = NULL;
10699 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10700 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10703 // additional labels needed
10704 label_loop_neg = newiTempLabel ( NULL );
10705 label_negative = newiTempLabel ( NULL );
10708 // copy source to result -- this will effectively truncate the left operand to the size of result!
10709 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10710 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10711 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10712 mov2f (AOP(result),AOP(left), offset);
10715 // if result is longer than left, fill with zeros (or sign)
10716 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10717 if (sign && AOP_SIZE(left) > 0) {
10718 // shift signed operand -- fill with sign
10719 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10720 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10721 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10722 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10723 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10726 // shift unsigned operand -- fill result with zeros
10727 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10728 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10731 } // if (size mismatch)
10733 pic16_mov2w (AOP(right), 0);
10734 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10735 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10738 // perform a shift by one (shift count is positive)
10739 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10740 // 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])
10741 pic16_emitpLabel (label_loop_pos->key);
10743 if (sign && (pos_shift == POC_RRCF)) {
10744 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10747 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10748 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10749 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10751 // perform a shift by one (shift count is positive)
10752 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10753 // 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])
10754 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10755 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10757 pic16_emitpLabel (label_loop_pos->key);
10758 if (sign && (pos_shift == POC_RRCF)) {
10759 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10762 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10763 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10764 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10765 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10769 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10771 pic16_emitpLabel (label_negative->key);
10772 // perform a shift by -1 (shift count is negative)
10773 // 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)
10775 pic16_emitpLabel (label_loop_neg->key);
10776 if (sign && (neg_shift == POC_RRCF)) {
10777 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10780 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10781 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10782 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10783 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10784 } // if (signedCount)
10786 pic16_emitpLabel (label_complete->key);
10789 pic16_freeAsmop (right,NULL,ic,TRUE);
10790 pic16_freeAsmop(left,NULL,ic,TRUE);
10791 pic16_freeAsmop(result,NULL,ic,TRUE);
10794 static void genLeftShift (iCode *ic) {
10795 genGenericShift (ic, 1);
10798 static void genRightShift (iCode *ic) {
10799 genGenericShift (ic, 0);
10804 void pic16_loadFSR0(operand *op)
10806 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10809 /*-----------------------------------------------------------------*/
10810 /* genUnpackBits - generates code for unpacking bits */
10811 /*-----------------------------------------------------------------*/
10812 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10816 sym_link *etype, *letype;
10817 int blen=0, bstr=0;
10821 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10822 etype = getSpec(operandType(result));
10823 letype = getSpec(operandType(left));
10825 // if(IS_BITFIELD(etype)) {
10826 blen = SPEC_BLEN(etype);
10827 bstr = SPEC_BSTR(etype);
10830 lbstr = SPEC_BSTR( letype );
10833 if((blen == 1) && (bstr < 8)) {
10834 /* it is a single bit, so use the appropriate bit instructions */
10835 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10837 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10839 if((ptype == POINTER) && (result)) {
10840 /* workaround to reduce the extra lfsr instruction */
10841 pic16_emitpcode(POC_BTFSC,
10842 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10844 pic16_emitpcode(POC_BTFSC,
10845 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10848 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10850 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10856 /* the following call to pic16_loadFSR0 is temporary until
10857 * optimization to handle single bit assignments is added
10858 * to the function. Until then use the old safe way! -- VR */
10859 pic16_loadFSR0( left );
10861 /* read the first byte */
10868 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10871 pic16_emitcode("clr","a");
10872 pic16_emitcode("movc","a","@a+dptr");
10877 /* if we have bitdisplacement then it fits */
10878 /* into this byte completely or if length is */
10879 /* less than a byte */
10880 if ((shCnt = SPEC_BSTR(etype)) ||
10881 (SPEC_BLEN(etype) <= 8)) {
10883 /* shift right acc */
10886 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10887 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10889 /* VR -- normally I would use the following, but since we use the hack,
10890 * to avoid the masking from AccRsh, why not mask it right now? */
10893 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10896 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10902 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10903 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10906 /* bit field did not fit in a byte */
10907 rlen = SPEC_BLEN(etype) - 8;
10908 pic16_aopPut(AOP(result),"a",offset++);
10915 pic16_emitcode("inc","%s",rname);
10916 pic16_emitcode("mov","a,@%s",rname);
10920 pic16_emitcode("inc","%s",rname);
10921 pic16_emitcode("movx","a,@%s",rname);
10925 pic16_emitcode("inc","dptr");
10926 pic16_emitcode("movx","a,@dptr");
10930 pic16_emitcode("clr","a");
10931 pic16_emitcode("inc","dptr");
10932 pic16_emitcode("movc","a","@a+dptr");
10936 pic16_emitcode("inc","dptr");
10937 pic16_emitcode("lcall","__gptrget");
10942 /* if we are done */
10946 pic16_aopPut(AOP(result),"a",offset++);
10951 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10952 pic16_aopPut(AOP(result),"a",offset);
10959 static void genDataPointerGet(operand *left,
10963 int size, offset = 0, leoffset=0 ;
10965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10966 pic16_aopOp(result, ic, FALSE);
10968 size = AOP_SIZE(result);
10969 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10973 /* The following tests may save a redudant movff instruction when
10974 * accessing unions */
10976 /* if they are the same */
10977 if (operandsEqu (left, result)) {
10978 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10984 /* if they are the same registers */
10985 if (pic16_sameRegs(AOP(left),AOP(result))) {
10986 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10992 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10993 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10994 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11001 if ( AOP_TYPE(left) == AOP_PCODE) {
11002 fprintf(stderr,"genDataPointerGet %s, %d\n",
11003 AOP(left)->aopu.pcop->name,
11004 (AOP(left)->aopu.pcop->type == PO_DIR)?
11005 PCOR(AOP(left)->aopu.pcop)->instance:
11006 PCOI(AOP(left)->aopu.pcop)->offset);
11010 if(AOP(left)->aopu.pcop->type == PO_DIR)
11011 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11013 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11016 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11018 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
11019 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
11020 pic16_mov2w(AOP(left), offset); // patch 8
11021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11024 pic16_popGet(AOP(left), offset), //patch 8
11025 pic16_popGet(AOP(result), offset)));
11033 pic16_freeAsmop(result,NULL,ic,TRUE);
11038 /*-----------------------------------------------------------------*/
11039 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
11040 /*-----------------------------------------------------------------*/
11041 static void genNearPointerGet (operand *left,
11046 //regs *preg = NULL ;
11047 sym_link *rtype, *retype;
11048 sym_link *ltype = operandType(left);
11052 rtype = operandType(result);
11053 retype= getSpec(rtype);
11055 pic16_aopOp(left,ic,FALSE);
11057 // pic16_DumpOp("(left)",left);
11058 // pic16_DumpOp("(result)",result);
11060 /* if left is rematerialisable and
11061 * result is not bit variable type and
11062 * the left is pointer to data space i.e
11063 * lower 128 bytes of space */
11065 if (AOP_TYPE(left) == AOP_PCODE
11066 && !IS_BITFIELD(retype)
11067 && DCL_TYPE(ltype) == POINTER) {
11069 genDataPointerGet (left,result,ic);
11070 pic16_freeAsmop(left, NULL, ic, TRUE);
11074 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11075 pic16_aopOp (result,ic,FALSE);
11077 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11080 if(IS_BITFIELD( retype )
11081 && (SPEC_BLEN(operandType(result))==1)
11085 int bitstrt, bytestrt;
11087 /* if this is bitfield of size 1, see if we are checking the value
11088 * of a single bit in an if-statement,
11089 * if yes, then don't generate usual code, but execute the
11090 * genIfx directly -- VR */
11094 /* CHECK: if next iCode is IFX
11095 * and current result operand is nextic's conditional operand
11096 * and current result operand live ranges ends at nextic's key number
11098 if((nextic->op == IFX)
11099 && (result == IC_COND(nextic))
11100 && (OP_LIVETO(result) == nextic->seq)
11102 /* everything is ok then */
11103 /* find a way to optimize the genIfx iCode */
11105 bytestrt = SPEC_BSTR(operandType(result))/8;
11106 bitstrt = SPEC_BSTR(operandType(result))%8;
11108 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11110 genIfxpCOpJump(nextic, jop);
11112 pic16_freeAsmop(left, NULL, ic, TRUE);
11113 pic16_freeAsmop(result, NULL, ic, TRUE);
11120 /* if the value is already in a pointer register
11121 * then don't need anything more */
11122 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
11123 /* otherwise get a free pointer register */
11124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11126 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
11127 /* bitfields will be handled by genUnpackBits */
11128 if(!IS_BITFIELD(retype)) {
11130 if(is_LitAOp( AOP(left) )) {
11131 pic16_loadFSR0( left );
11133 // set up FSR0 with address from left
11134 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11135 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11140 /* if bitfield then unpack the bits */
11141 if (IS_BITFIELD(retype))
11142 genUnpackBits (result, left, NULL, POINTER);
11144 /* we have can just get the values */
11145 int size = AOP_SIZE(result);
11148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11150 /* fsr0 is loaded already -- VR */
11151 // pic16_loadFSR0( left );
11153 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
11154 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
11157 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11158 pic16_popGet(AOP(result), offset++)));
11160 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11161 pic16_popGet(AOP(result), offset++)));
11165 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
11166 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
11168 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
11172 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
11174 pic16_emitcode("mov","a,@%s",rname);
11175 pic16_aopPut(AOP(result),"a",offset);
11177 sprintf(buffer,"@%s",rname);
11178 pic16_aopPut(AOP(result),buffer,offset);
11182 pic16_emitcode("inc","%s",rname);
11187 /* now some housekeeping stuff */
11189 /* we had to allocate for this iCode */
11190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11191 pic16_freeAsmop(NULL,aop,ic,TRUE);
11193 /* we did not allocate which means left
11194 * already in a pointer register, then
11195 * if size > 0 && this could be used again
11196 * we have to point it back to where it
11198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11199 if (AOP_SIZE(result) > 1
11200 && !OP_SYMBOL(left)->remat
11201 && ( OP_SYMBOL(left)->liveTo > ic->seq
11203 // int size = AOP_SIZE(result) - 1;
11205 // pic16_emitcode("dec","%s",rname);
11210 pic16_freeAsmop(left,NULL,ic,TRUE);
11211 pic16_freeAsmop(result,NULL,ic,TRUE);
11214 /*-----------------------------------------------------------------*/
11215 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
11216 /*-----------------------------------------------------------------*/
11217 static void genPagedPointerGet (operand *left,
11222 regs *preg = NULL ;
11224 sym_link *rtype, *retype;
11226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11228 rtype = operandType(result);
11229 retype= getSpec(rtype);
11231 pic16_aopOp(left,ic,FALSE);
11233 /* if the value is already in a pointer register
11234 then don't need anything more */
11235 if (!AOP_INPREG(AOP(left))) {
11236 /* otherwise get a free pointer register */
11238 preg = getFreePtr(ic,&aop,FALSE);
11239 pic16_emitcode("mov","%s,%s",
11241 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11242 rname = preg->name ;
11244 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11246 pic16_freeAsmop(left,NULL,ic,TRUE);
11247 pic16_aopOp (result,ic,FALSE);
11249 /* if bitfield then unpack the bits */
11250 if (IS_BITFIELD(retype))
11251 genUnpackBits (result,left,rname,PPOINTER);
11253 /* we have can just get the values */
11254 int size = AOP_SIZE(result);
11259 pic16_emitcode("movx","a,@%s",rname);
11260 pic16_aopPut(AOP(result),"a",offset);
11265 pic16_emitcode("inc","%s",rname);
11269 /* now some housekeeping stuff */
11271 /* we had to allocate for this iCode */
11272 pic16_freeAsmop(NULL,aop,ic,TRUE);
11274 /* we did not allocate which means left
11275 already in a pointer register, then
11276 if size > 0 && this could be used again
11277 we have to point it back to where it
11279 if (AOP_SIZE(result) > 1 &&
11280 !OP_SYMBOL(left)->remat &&
11281 ( OP_SYMBOL(left)->liveTo > ic->seq ||
11283 int size = AOP_SIZE(result) - 1;
11285 pic16_emitcode("dec","%s",rname);
11290 pic16_freeAsmop(result,NULL,ic,TRUE);
11295 /*-----------------------------------------------------------------*/
11296 /* genFarPointerGet - gget value from far space */
11297 /*-----------------------------------------------------------------*/
11298 static void genFarPointerGet (operand *left,
11299 operand *result, iCode *ic)
11302 sym_link *retype = getSpec(operandType(result));
11304 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11306 pic16_aopOp(left,ic,FALSE);
11308 /* if the operand is already in dptr
11309 then we do nothing else we move the value to dptr */
11310 if (AOP_TYPE(left) != AOP_STR) {
11311 /* if this is remateriazable */
11312 if (AOP_TYPE(left) == AOP_IMMD)
11313 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11314 else { /* we need to get it byte by byte */
11315 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11316 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11317 if (options.model == MODEL_FLAT24)
11319 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11323 /* so dptr know contains the address */
11324 pic16_freeAsmop(left,NULL,ic,TRUE);
11325 pic16_aopOp(result,ic,FALSE);
11327 /* if bit then unpack */
11328 if (IS_BITFIELD(retype))
11329 genUnpackBits(result,left,"dptr",FPOINTER);
11331 size = AOP_SIZE(result);
11335 pic16_emitcode("movx","a,@dptr");
11336 pic16_aopPut(AOP(result),"a",offset++);
11338 pic16_emitcode("inc","dptr");
11342 pic16_freeAsmop(result,NULL,ic,TRUE);
11346 /*-----------------------------------------------------------------*/
11347 /* genCodePointerGet - get value from code space */
11348 /*-----------------------------------------------------------------*/
11349 static void genCodePointerGet (operand *left,
11350 operand *result, iCode *ic)
11353 sym_link *retype = getSpec(operandType(result));
11355 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11357 pic16_aopOp(left,ic,FALSE);
11359 /* if the operand is already in dptr
11360 then we do nothing else we move the value to dptr */
11361 if (AOP_TYPE(left) != AOP_STR) {
11362 /* if this is remateriazable */
11363 if (AOP_TYPE(left) == AOP_IMMD)
11364 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11365 else { /* we need to get it byte by byte */
11366 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11367 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11368 if (options.model == MODEL_FLAT24)
11370 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11374 /* so dptr know contains the address */
11375 pic16_freeAsmop(left,NULL,ic,TRUE);
11376 pic16_aopOp(result,ic,FALSE);
11378 /* if bit then unpack */
11379 if (IS_BITFIELD(retype))
11380 genUnpackBits(result,left,"dptr",CPOINTER);
11382 size = AOP_SIZE(result);
11386 pic16_emitcode("clr","a");
11387 pic16_emitcode("movc","a,@a+dptr");
11388 pic16_aopPut(AOP(result),"a",offset++);
11390 pic16_emitcode("inc","dptr");
11394 pic16_freeAsmop(result,NULL,ic,TRUE);
11399 /*-----------------------------------------------------------------*/
11400 /* genGenPointerGet - gget value from generic pointer space */
11401 /*-----------------------------------------------------------------*/
11402 static void genGenPointerGet (operand *left,
11403 operand *result, iCode *ic)
11405 int size, offset, lit;
11406 sym_link *retype = getSpec(operandType(result));
11408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11409 pic16_aopOp(left,ic,FALSE);
11410 pic16_aopOp(result,ic,FALSE);
11411 size = AOP_SIZE(result);
11413 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11415 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11417 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11418 // load FSR0 from immediate
11419 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11421 // pic16_loadFSR0( left );
11426 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11428 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11435 else { /* we need to get it byte by byte */
11436 // set up FSR0 with address from left
11437 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11438 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11444 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11446 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11453 /* if bit then unpack */
11454 if (IS_BITFIELD(retype))
11455 genUnpackBits(result,left,"BAD",GPOINTER);
11458 pic16_freeAsmop(left,NULL,ic,TRUE);
11459 pic16_freeAsmop(result,NULL,ic,TRUE);
11465 /*-----------------------------------------------------------------*/
11466 /* genGenPointerGet - gget value from generic pointer space */
11467 /*-----------------------------------------------------------------*/
11468 static void genGenPointerGet (operand *left,
11469 operand *result, iCode *ic)
11471 int size, offset, lit;
11472 sym_link *retype = getSpec(operandType(result));
11475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11476 pic16_aopOp(left,ic,FALSE);
11477 pic16_aopOp(result,ic,FALSE);
11478 size = AOP_SIZE(result);
11480 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11482 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11484 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11485 // load FSR0 from immediate
11486 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11488 werror(W_POSSBUG2, __FILE__, __LINE__);
11493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11495 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11502 } else { /* we need to get it byte by byte */
11504 /* set up WREG:PRODL:FSR0L with address from left */
11505 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11506 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11510 case 1: strcpy(fgptrget, "__gptrget1"); break;
11511 case 2: strcpy(fgptrget, "__gptrget2"); break;
11512 case 3: strcpy(fgptrget, "__gptrget3"); break;
11513 case 4: strcpy(fgptrget, "__gptrget4"); break;
11515 werror(W_POSSBUG2, __FILE__, __LINE__);
11519 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
11521 assignResultValue(result, 1);
11526 sym = newSymbol( fgptrget, 0 );
11527 strcpy(sym->rname, fgptrget);
11528 checkAddSym(&externs, sym);
11530 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
11536 /* if bit then unpack */
11537 if (IS_BITFIELD(retype))
11538 genUnpackBits(result,left,"BAD",GPOINTER);
11541 pic16_freeAsmop(left,NULL,ic,TRUE);
11542 pic16_freeAsmop(result,NULL,ic,TRUE);
11545 /*-----------------------------------------------------------------*/
11546 /* genConstPointerGet - get value from const generic pointer space */
11547 /*-----------------------------------------------------------------*/
11548 static void genConstPointerGet (operand *left,
11549 operand *result, iCode *ic)
11551 //sym_link *retype = getSpec(operandType(result));
11552 // symbol *albl = newiTempLabel(NULL); // patch 15
11553 // symbol *blbl = newiTempLabel(NULL); //
11554 // PIC_OPCODE poc; // patch 15
11558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11559 pic16_aopOp(left,ic,FALSE);
11560 pic16_aopOp(result,ic,TRUE);
11561 size = AOP_SIZE(result);
11563 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11565 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11567 // set up table pointer
11568 if( (AOP_TYPE(left) == AOP_PCODE)
11569 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11570 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11572 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11573 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11574 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11575 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11576 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11577 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11579 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11580 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11581 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11585 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11586 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11590 pic16_freeAsmop(left,NULL,ic,TRUE);
11591 pic16_freeAsmop(result,NULL,ic,TRUE);
11595 /*-----------------------------------------------------------------*/
11596 /* genPointerGet - generate code for pointer get */
11597 /*-----------------------------------------------------------------*/
11598 static void genPointerGet (iCode *ic)
11600 operand *left, *result ;
11601 sym_link *type, *etype;
11606 left = IC_LEFT(ic);
11607 result = IC_RESULT(ic) ;
11609 /* depending on the type of pointer we need to
11610 move it to the correct pointer register */
11611 type = operandType(left);
11612 etype = getSpec(type);
11615 if (IS_PTR_CONST(type))
11617 if (IS_CODEPTR(type))
11619 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11621 /* if left is of type of pointer then it is simple */
11622 if (IS_PTR(type) && !IS_FUNC(type->next))
11623 p_type = DCL_TYPE(type);
11625 /* we have to go by the storage class */
11626 p_type = PTR_TYPE(SPEC_OCLS(etype));
11628 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11630 if (SPEC_OCLS(etype)->codesp ) {
11631 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11632 //p_type = CPOINTER ;
11634 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11635 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11636 /*p_type = FPOINTER ;*/
11638 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11639 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11640 /* p_type = PPOINTER; */
11642 if (SPEC_OCLS(etype) == idata ) {
11643 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11644 /* p_type = IPOINTER; */
11646 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11647 /* p_type = POINTER ; */
11651 /* now that we have the pointer type we assign
11652 the pointer values */
11656 genNearPointerGet (left,result,ic);
11660 genPagedPointerGet(left,result,ic);
11664 genFarPointerGet (left,result,ic);
11668 genConstPointerGet (left,result,ic);
11669 //pic16_emitcodePointerGet (left,result,ic);
11674 if (IS_PTR_CONST(type))
11675 genConstPointerGet (left,result,ic);
11678 genGenPointerGet (left,result,ic);
11682 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11683 "genPointerGet: illegal pointer type");
11688 /*-----------------------------------------------------------------*/
11689 /* genPackBits - generates code for packed bit storage */
11690 /*-----------------------------------------------------------------*/
11691 static void genPackBits (sym_link *etype , operand *result,
11693 char *rname, int p_type)
11702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11703 blen = SPEC_BLEN(etype);
11704 bstr = SPEC_BSTR(etype);
11706 retype = getSpec(operandType(right));
11708 if(AOP_TYPE(right) == AOP_LIT) {
11709 if((blen == 1) && (bstr < 8)) {
11711 /* it is a single bit, so use the appropriate bit instructions */
11713 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11715 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11716 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11717 if((p_type == POINTER) && (result)) {
11718 /* workaround to reduce the extra lfsr instruction */
11720 pic16_emitpcode(POC_BSF,
11721 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11723 pic16_emitpcode(POC_BCF,
11724 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11727 pic16_loadFSR0( result );
11729 pic16_emitpcode(POC_BSF,
11730 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11732 pic16_emitpcode(POC_BCF,
11733 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11740 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11743 if(IS_BITFIELD(retype)
11744 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11748 rblen = SPEC_BLEN( retype );
11749 rbstr = SPEC_BSTR( retype );
11752 if(IS_BITFIELD(etype)) {
11753 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11754 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11756 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11759 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11761 if(IS_BITFIELD(etype)) {
11762 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11764 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11767 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11771 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11773 /* if the bit lenth is less than or */
11774 /* it exactly fits a byte then */
11775 if((shCnt=SPEC_BSTR(etype))
11776 || SPEC_BLEN(etype) <= 8 ) {
11778 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11780 /* shift left acc */
11783 /* using PRODL as a temporary register here */
11784 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11789 pic16_loadFSR0( result );
11790 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11791 // pic16_emitcode ("mov","b,a");
11792 // pic16_emitcode("mov","a,@%s",rname);
11796 werror(W_POSSBUG2, __FILE__, __LINE__);
11801 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11802 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11803 (unsigned char)(0xff >> (8-bstr))) ));
11804 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11805 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11812 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11813 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11818 if ( SPEC_BLEN(etype) <= 8 )
11821 pic16_emitcode("inc","%s",rname);
11822 rLen = SPEC_BLEN(etype) ;
11826 /* now generate for lengths greater than one byte */
11829 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11839 pic16_emitcode("mov","@%s,a",rname);
11841 pic16_emitcode("mov","@%s,%s",rname,l);
11846 pic16_emitcode("movx","@dptr,a");
11851 DEBUGpic16_emitcode(";lcall","__gptrput");
11854 pic16_emitcode ("inc","%s",rname);
11859 /* last last was not complete */
11861 /* save the byte & read byte */
11864 pic16_emitcode ("mov","b,a");
11865 pic16_emitcode("mov","a,@%s",rname);
11869 pic16_emitcode ("mov","b,a");
11870 pic16_emitcode("movx","a,@dptr");
11874 pic16_emitcode ("push","b");
11875 pic16_emitcode ("push","acc");
11876 pic16_emitcode ("lcall","__gptrget");
11877 pic16_emitcode ("pop","b");
11881 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11882 pic16_emitcode ("orl","a,b");
11885 if (p_type == GPOINTER)
11886 pic16_emitcode("pop","b");
11891 pic16_emitcode("mov","@%s,a",rname);
11895 pic16_emitcode("movx","@dptr,a");
11899 DEBUGpic16_emitcode(";lcall","__gptrput");
11903 /*-----------------------------------------------------------------*/
11904 /* genDataPointerSet - remat pointer to data space */
11905 /*-----------------------------------------------------------------*/
11906 static void genDataPointerSet(operand *right,
11910 int size, offset = 0, resoffset=0 ;
11912 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11913 pic16_aopOp(right,ic,FALSE);
11915 size = AOP_SIZE(right);
11917 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11920 if ( AOP_TYPE(result) == AOP_PCODE) {
11921 fprintf(stderr,"genDataPointerSet %s, %d\n",
11922 AOP(result)->aopu.pcop->name,
11923 (AOP(result)->aopu.pcop->type == PO_DIR)?
11924 PCOR(AOP(result)->aopu.pcop)->instance:
11925 PCOI(AOP(result)->aopu.pcop)->offset);
11929 if(AOP(result)->aopu.pcop->type == PO_DIR)
11930 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11933 if (AOP_TYPE(right) == AOP_LIT) {
11936 if(!IS_FLOAT(operandType( right )))
11937 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11940 unsigned long lit_int;
11944 /* take care if literal is a float */
11945 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11946 lit = info.lit_int;
11949 lit = lit >> (8*offset);
11951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11954 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11957 pic16_mov2w(AOP(right), offset);
11958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11964 pic16_freeAsmop(right,NULL,ic,TRUE);
11969 /*-----------------------------------------------------------------*/
11970 /* genNearPointerSet - pic16_emitcode for near pointer put */
11971 /*-----------------------------------------------------------------*/
11972 static void genNearPointerSet (operand *right,
11979 sym_link *ptype = operandType(result);
11980 sym_link *resetype;
11982 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11983 retype= getSpec(operandType(right));
11984 resetype = getSpec(operandType(result));
11986 pic16_aopOp(result,ic,FALSE);
11988 /* if the result is rematerializable &
11989 * in data space & not a bit variable */
11991 /* and result is not a bit variable */
11992 if (AOP_TYPE(result) == AOP_PCODE
11993 // && AOP_TYPE(result) == AOP_IMMD
11994 && DCL_TYPE(ptype) == POINTER
11995 && !IS_BITFIELD(retype)
11996 && !IS_BITFIELD(resetype)) {
11998 genDataPointerSet (right,result,ic);
11999 pic16_freeAsmop(result,NULL,ic,TRUE);
12003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12004 pic16_aopOp(right,ic,FALSE);
12005 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12007 /* if the value is already in a pointer register
12008 * then don't need anything more */
12009 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
12010 /* otherwise get a free pointer register */
12011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12013 // if( (AOP_TYPE(result) == AOP_PCODE)
12014 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
12015 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
12016 if(is_LitAOp( AOP(result) ))
12018 if(!IS_BITFIELD(resetype))
12019 pic16_loadFSR0( result ); // patch 10
12021 if(!IS_BITFIELD(resetype)) {
12022 // set up FSR0 with address of result
12023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
12024 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
12030 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12034 // pic16_loadFSR0( result );
12036 /* if bitfield then unpack the bits */
12037 if (IS_BITFIELD(resetype)) {
12038 genPackBits (resetype, result, right, NULL, POINTER);
12040 /* we have can just get the values */
12041 int size = AOP_SIZE(right);
12044 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12046 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12049 //pic16_emitcode("mov","@%s,a",rname);
12050 pic16_emitcode("movf","indf0,w ;1");
12053 if (AOP_TYPE(right) == AOP_LIT) {
12054 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12056 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12058 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12060 } else { // no literal
12062 pic16_emitpcode(POC_MOVFF,
12063 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12064 pic16_popCopyReg(&pic16_pc_postinc0)));
12066 pic16_emitpcode(POC_MOVFF,
12067 pic16_popGet2p(pic16_popGet(AOP(right),offset),
12068 pic16_popCopyReg(&pic16_pc_indf0)));
12076 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12077 /* now some housekeeping stuff */
12079 /* we had to allocate for this iCode */
12080 pic16_freeAsmop(NULL,aop,ic,TRUE);
12082 /* we did not allocate which means left
12083 * already in a pointer register, then
12084 * if size > 0 && this could be used again
12085 * we have to point it back to where it
12087 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12088 if (AOP_SIZE(right) > 1
12089 && !OP_SYMBOL(result)->remat
12090 && ( OP_SYMBOL(result)->liveTo > ic->seq
12093 int size = AOP_SIZE(right) - 1;
12096 pic16_emitcode("decf","fsr0,f");
12097 //pic16_emitcode("dec","%s",rname);
12101 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12104 pic16_freeAsmop(right,NULL,ic,TRUE);
12105 pic16_freeAsmop(result,NULL,ic,TRUE);
12108 /*-----------------------------------------------------------------*/
12109 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
12110 /*-----------------------------------------------------------------*/
12111 static void genPagedPointerSet (operand *right,
12116 regs *preg = NULL ;
12120 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12122 retype= getSpec(operandType(right));
12124 pic16_aopOp(result,ic,FALSE);
12126 /* if the value is already in a pointer register
12127 then don't need anything more */
12128 if (!AOP_INPREG(AOP(result))) {
12129 /* otherwise get a free pointer register */
12131 preg = getFreePtr(ic,&aop,FALSE);
12132 pic16_emitcode("mov","%s,%s",
12134 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12135 rname = preg->name ;
12137 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12139 pic16_freeAsmop(result,NULL,ic,TRUE);
12140 pic16_aopOp (right,ic,FALSE);
12142 /* if bitfield then unpack the bits */
12143 if (IS_BITFIELD(retype))
12144 genPackBits (retype,result,right,rname,PPOINTER);
12146 /* we have can just get the values */
12147 int size = AOP_SIZE(right);
12151 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12154 pic16_emitcode("movx","@%s,a",rname);
12157 pic16_emitcode("inc","%s",rname);
12163 /* now some housekeeping stuff */
12165 /* we had to allocate for this iCode */
12166 pic16_freeAsmop(NULL,aop,ic,TRUE);
12168 /* we did not allocate which means left
12169 already in a pointer register, then
12170 if size > 0 && this could be used again
12171 we have to point it back to where it
12173 if (AOP_SIZE(right) > 1 &&
12174 !OP_SYMBOL(result)->remat &&
12175 ( OP_SYMBOL(result)->liveTo > ic->seq ||
12177 int size = AOP_SIZE(right) - 1;
12179 pic16_emitcode("dec","%s",rname);
12184 pic16_freeAsmop(right,NULL,ic,TRUE);
12189 /*-----------------------------------------------------------------*/
12190 /* genFarPointerSet - set value from far space */
12191 /*-----------------------------------------------------------------*/
12192 static void genFarPointerSet (operand *right,
12193 operand *result, iCode *ic)
12196 sym_link *retype = getSpec(operandType(right));
12198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12199 pic16_aopOp(result,ic,FALSE);
12201 /* if the operand is already in dptr
12202 then we do nothing else we move the value to dptr */
12203 if (AOP_TYPE(result) != AOP_STR) {
12204 /* if this is remateriazable */
12205 if (AOP_TYPE(result) == AOP_IMMD)
12206 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12207 else { /* we need to get it byte by byte */
12208 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12209 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12210 if (options.model == MODEL_FLAT24)
12212 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12216 /* so dptr know contains the address */
12217 pic16_freeAsmop(result,NULL,ic,TRUE);
12218 pic16_aopOp(right,ic,FALSE);
12220 /* if bit then unpack */
12221 if (IS_BITFIELD(retype))
12222 genPackBits(retype,result,right,"dptr",FPOINTER);
12224 size = AOP_SIZE(right);
12228 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12230 pic16_emitcode("movx","@dptr,a");
12232 pic16_emitcode("inc","dptr");
12236 pic16_freeAsmop(right,NULL,ic,TRUE);
12239 /*-----------------------------------------------------------------*/
12240 /* genGenPointerSet - set value from generic pointer space */
12241 /*-----------------------------------------------------------------*/
12243 static void genGenPointerSet (operand *right,
12244 operand *result, iCode *ic)
12246 int i, size, offset, lit;
12247 sym_link *retype = getSpec(operandType(right));
12249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12251 pic16_aopOp(result,ic,FALSE);
12252 pic16_aopOp(right,ic,FALSE);
12253 size = AOP_SIZE(right);
12256 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12258 /* if the operand is already in dptr
12259 then we do nothing else we move the value to dptr */
12260 if (AOP_TYPE(result) != AOP_STR) {
12261 /* if this is remateriazable */
12262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12263 // WARNING: anythig until "else" is untested!
12264 if (AOP_TYPE(result) == AOP_IMMD) {
12265 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12266 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12267 // load FSR0 from immediate
12268 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12272 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12274 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12280 else { /* we need to get it byte by byte */
12281 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12282 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12284 // set up FSR0 with address of result
12285 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12286 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12288 /* hack hack! see if this the FSR. If so don't load W */
12289 if(AOP_TYPE(right) != AOP_ACC) {
12291 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12293 if(AOP_TYPE(right) == AOP_LIT)
12296 // note: pic16_popGet handles sign extension
12297 for(i=0;i<size;i++) {
12298 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12300 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12302 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12307 for(i=0;i<size;i++) {
12309 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12310 pic16_popCopyReg(&pic16_pc_postinc0)));
12312 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12313 pic16_popCopyReg(&pic16_pc_indf0)));
12319 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12320 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12322 } // if (AOP_TYPE(result) != AOP_IMMD)
12324 } // if (AOP_TYPE(result) != AOP_STR)
12325 /* so dptr know contains the address */
12328 /* if bit then unpack */
12329 if (IS_BITFIELD(retype))
12330 genPackBits(retype,result,right,"dptr",GPOINTER);
12332 size = AOP_SIZE(right);
12335 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12337 // set up FSR0 with address of result
12338 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12339 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12342 if (AOP_TYPE(right) == AOP_LIT) {
12343 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12345 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12347 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12349 } else { // no literal
12351 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12353 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12361 pic16_freeAsmop(right,NULL,ic,TRUE);
12362 pic16_freeAsmop(result,NULL,ic,TRUE);
12366 static void genGenPointerSet (operand *right,
12367 operand *result, iCode *ic)
12370 sym_link *retype = getSpec(operandType(right));
12373 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12375 pic16_aopOp(result,ic,FALSE);
12376 pic16_aopOp(right,ic,FALSE);
12377 size = AOP_SIZE(right);
12379 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12382 /* if bit then unpack */
12383 if (IS_BITFIELD(retype)) {
12384 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12385 genPackBits(retype,result,right,"dptr",GPOINTER);
12389 size = AOP_SIZE(right);
12391 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12395 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12397 /* value of right+0 is placed on stack, which will be retrieved
12398 * by the support function this restoring the stack. The important
12399 * thing is that there is no need to manually restore stack pointer
12401 pushaop(AOP(right), 0);
12402 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12403 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12404 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12405 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12407 /* load address to write to in WREG:FSR0H:FSR0L */
12408 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12409 pic16_popCopyReg(&pic16_pc_fsr0l)));
12410 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12411 pic16_popCopyReg(&pic16_pc_prodl)));
12412 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12415 /* put code here */
12417 case 1: strcpy(fgptrput, "__gptrput1"); break;
12418 case 2: strcpy(fgptrput, "__gptrput2"); break;
12419 case 3: strcpy(fgptrput, "__gptrput3"); break;
12420 case 4: strcpy(fgptrput, "__gptrput4"); break;
12422 werror(W_POSSBUG2, __FILE__, __LINE__);
12426 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
12431 sym = newSymbol( fgptrput, 0 );
12432 strcpy(sym->rname, fgptrput);
12433 checkAddSym(&externs, sym);
12437 pic16_freeAsmop(right,NULL,ic,TRUE);
12438 pic16_freeAsmop(result,NULL,ic,TRUE);
12441 /*-----------------------------------------------------------------*/
12442 /* genPointerSet - stores the value into a pointer location */
12443 /*-----------------------------------------------------------------*/
12444 static void genPointerSet (iCode *ic)
12446 operand *right, *result ;
12447 sym_link *type, *etype;
12452 right = IC_RIGHT(ic);
12453 result = IC_RESULT(ic) ;
12455 /* depending on the type of pointer we need to
12456 move it to the correct pointer register */
12457 type = operandType(result);
12458 etype = getSpec(type);
12459 /* if left is of type of pointer then it is simple */
12460 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12461 p_type = DCL_TYPE(type);
12464 /* we have to go by the storage class */
12465 p_type = PTR_TYPE(SPEC_OCLS(etype));
12467 /* if (SPEC_OCLS(etype)->codesp ) { */
12468 /* p_type = CPOINTER ; */
12471 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12472 /* p_type = FPOINTER ; */
12474 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12475 /* p_type = PPOINTER ; */
12477 /* if (SPEC_OCLS(etype) == idata ) */
12478 /* p_type = IPOINTER ; */
12480 /* p_type = POINTER ; */
12483 /* now that we have the pointer type we assign
12484 the pointer values */
12488 genNearPointerSet (right,result,ic);
12492 genPagedPointerSet (right,result,ic);
12496 genFarPointerSet (right,result,ic);
12500 genGenPointerSet (right,result,ic);
12504 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12505 "genPointerSet: illegal pointer type");
12509 /*-----------------------------------------------------------------*/
12510 /* genIfx - generate code for Ifx statement */
12511 /*-----------------------------------------------------------------*/
12512 static void genIfx (iCode *ic, iCode *popIc)
12514 operand *cond = IC_COND(ic);
12519 pic16_aopOp(cond,ic,FALSE);
12521 /* get the value into acc */
12522 if (AOP_TYPE(cond) != AOP_CRY)
12523 pic16_toBoolean(cond);
12526 /* the result is now in the accumulator */
12527 pic16_freeAsmop(cond,NULL,ic,TRUE);
12529 /* if there was something to be popped then do it */
12533 /* if the condition is a bit variable */
12534 if (isbit && IS_ITEMP(cond) &&
12536 genIfxJump(ic,"c");
12537 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12539 if (isbit && !IS_ITEMP(cond))
12540 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12542 genIfxJump(ic,"a");
12547 /*-----------------------------------------------------------------*/
12548 /* genAddrOf - generates code for address of */
12549 /*-----------------------------------------------------------------*/
12550 static void genAddrOf (iCode *ic)
12552 operand *result, *left;
12554 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12555 pCodeOp *pcop0, *pcop1, *pcop2;
12559 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12561 sym = OP_SYMBOL( IC_LEFT(ic) );
12564 /* get address of symbol on stack */
12565 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12567 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12568 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12571 // operands on stack are accessible via "FSR2 + index" with index
12572 // starting at 2 for arguments and growing from 0 downwards for
12573 // local variables (index == 0 is not assigned so we add one here)
12575 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12577 assert (soffs < 0);
12580 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12581 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12582 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12583 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12584 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12585 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12586 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12592 // if(pic16_debug_verbose) {
12593 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12594 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12597 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12598 size = AOP_SIZE(IC_RESULT(ic));
12600 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12601 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12602 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12605 pic16_emitpcode(POC_MOVLW, pcop0);
12606 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12607 pic16_emitpcode(POC_MOVLW, pcop1);
12608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12609 pic16_emitpcode(POC_MOVLW, pcop2);
12610 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12613 pic16_emitpcode(POC_MOVLW, pcop0);
12614 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12615 pic16_emitpcode(POC_MOVLW, pcop1);
12616 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12618 pic16_emitpcode(POC_MOVLW, pcop0);
12619 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12622 pic16_freeAsmop(left, NULL, ic, FALSE);
12624 pic16_freeAsmop(result,NULL,ic,TRUE);
12629 /*-----------------------------------------------------------------*/
12630 /* genFarFarAssign - assignment when both are in far space */
12631 /*-----------------------------------------------------------------*/
12632 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12634 int size = AOP_SIZE(right);
12637 /* first push the right side on to the stack */
12639 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12641 pic16_emitcode ("push","acc");
12644 pic16_freeAsmop(right,NULL,ic,FALSE);
12645 /* now assign DPTR to result */
12646 pic16_aopOp(result,ic,FALSE);
12647 size = AOP_SIZE(result);
12649 pic16_emitcode ("pop","acc");
12650 pic16_aopPut(AOP(result),"a",--offset);
12652 pic16_freeAsmop(result,NULL,ic,FALSE);
12657 /*-----------------------------------------------------------------*/
12658 /* genAssign - generate code for assignment */
12659 /*-----------------------------------------------------------------*/
12660 static void genAssign (iCode *ic)
12662 operand *result, *right;
12663 int size, offset,know_W;
12664 unsigned long lit = 0L;
12666 result = IC_RESULT(ic);
12667 right = IC_RIGHT(ic) ;
12671 /* if they are the same */
12672 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12675 /* reversed order operands are aopOp'ed so that result operand
12676 * is effective in case right is a stack symbol. This maneauver
12677 * allows to use the _G.resDirect flag later */
12678 pic16_aopOp(result,ic,TRUE);
12679 pic16_aopOp(right,ic,FALSE);
12681 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12683 /* if they are the same registers */
12684 if (pic16_sameRegs(AOP(right),AOP(result)))
12687 /* if the result is a bit */
12688 if (AOP_TYPE(result) == AOP_CRY) {
12689 /* if the right size is a literal then
12690 we know what the value is */
12691 if (AOP_TYPE(right) == AOP_LIT) {
12693 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12694 pic16_popGet(AOP(result),0));
12696 if (((int) operandLitValue(right)))
12697 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12698 AOP(result)->aopu.aop_dir,
12699 AOP(result)->aopu.aop_dir);
12701 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12702 AOP(result)->aopu.aop_dir,
12703 AOP(result)->aopu.aop_dir);
12707 /* the right is also a bit variable */
12708 if (AOP_TYPE(right) == AOP_CRY) {
12709 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12710 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12711 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12713 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12714 AOP(result)->aopu.aop_dir,
12715 AOP(result)->aopu.aop_dir);
12716 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12717 AOP(right)->aopu.aop_dir,
12718 AOP(right)->aopu.aop_dir);
12719 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12720 AOP(result)->aopu.aop_dir,
12721 AOP(result)->aopu.aop_dir);
12725 /* we need to or */
12726 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12727 pic16_toBoolean(right);
12729 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12730 //pic16_aopPut(AOP(result),"a",0);
12734 /* bit variables done */
12736 size = AOP_SIZE(result);
12739 if(AOP_TYPE(right) == AOP_LIT) {
12740 if(!IS_FLOAT(operandType( right )))
12741 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12744 unsigned long lit_int;
12748 /* take care if literal is a float */
12749 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12750 lit = info.lit_int;
12754 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12755 // sizeof(unsigned long int), sizeof(float));
12758 if (AOP_TYPE(right) == AOP_REG) {
12759 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12762 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12767 if(AOP_TYPE(right) != AOP_LIT
12768 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12769 && !IS_FUNC(OP_SYM_TYPE(right))
12771 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12772 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12774 // set up table pointer
12775 if(is_LitOp(right)) {
12776 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12777 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12778 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12779 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12780 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12781 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12782 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12784 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12785 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12786 pic16_popCopyReg(&pic16_pc_tblptrl)));
12787 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12788 pic16_popCopyReg(&pic16_pc_tblptrh)));
12789 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12790 pic16_popCopyReg(&pic16_pc_tblptru)));
12793 size = min(AOP_SIZE(right), AOP_SIZE(result));
12795 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12796 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12797 pic16_popGet(AOP(result),offset)));
12801 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12802 size = AOP_SIZE(result) - AOP_SIZE(right);
12804 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12814 /* VR - What is this?! */
12815 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12816 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12817 if(aopIdx(AOP(result),0) == 4) {
12819 /* this is a workaround to save value of right into wreg too,
12820 * value of wreg is going to be used later */
12821 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12823 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12827 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12833 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12834 if(AOP_TYPE(right) == AOP_LIT) {
12836 if(know_W != (lit&0xff))
12837 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12839 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12841 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12845 } else if (AOP_TYPE(right) == AOP_CRY) {
12846 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12848 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12849 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12850 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12852 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12853 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12856 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12858 if(!_G.resDirect) /* use this aopForSym feature */
12859 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12866 pic16_freeAsmop (right,NULL,ic,FALSE);
12867 pic16_freeAsmop (result,NULL,ic,TRUE);
12870 /*-----------------------------------------------------------------*/
12871 /* genJumpTab - generates code for jump table */
12872 /*-----------------------------------------------------------------*/
12873 static void genJumpTab (iCode *ic)
12878 pCodeOp *jt_offs_hi;
12883 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12884 /* get the condition into accumulator */
12885 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12887 /* multiply by three */
12888 pic16_emitcode("add","a,acc");
12889 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12891 jtab = newiTempLabel(NULL);
12892 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12893 pic16_emitcode("jmp","@a+dptr");
12894 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12897 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12898 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12900 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12901 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12902 pic16_emitpLabel(jtab->key);
12906 jt_offs = pic16_popGetTempReg(0);
12907 jt_offs_hi = pic16_popGetTempReg(1);
12908 jt_label = pic16_popGetLabel (jtab->key);
12909 //fprintf (stderr, "Creating jump table...\n");
12911 // calculate offset into jump table (idx * sizeof (GOTO))
12912 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12913 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12914 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12915 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12916 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12917 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12918 pic16_emitpcode(POC_MOVWF , jt_offs);
12920 // prepare PCLATx (set to first entry in jump table)
12921 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12922 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12923 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12924 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12925 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12927 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12928 pic16_emitpcode(POC_ADDWF , jt_offs);
12929 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12930 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12932 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12934 // release temporaries and prepare jump into table (new PCL --> WREG)
12935 pic16_emitpcode(POC_MOVFW , jt_offs);
12936 pic16_popReleaseTempReg (jt_offs_hi, 1);
12937 pic16_popReleaseTempReg (jt_offs, 0);
12939 // jump into the table
12940 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12942 pic16_emitpLabelFORCE(jtab->key);
12945 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12947 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12948 /* now generate the jump labels */
12949 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12950 jtab = setNextItem(IC_JTLABELS(ic))) {
12951 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12952 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12955 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12959 /*-----------------------------------------------------------------*/
12960 /* genMixedOperation - gen code for operators between mixed types */
12961 /*-----------------------------------------------------------------*/
12963 TSD - Written for the PIC port - but this unfortunately is buggy.
12964 This routine is good in that it is able to efficiently promote
12965 types to different (larger) sizes. Unfortunately, the temporary
12966 variables that are optimized out by this routine are sometimes
12967 used in other places. So until I know how to really parse the
12968 iCode tree, I'm going to not be using this routine :(.
12970 static int genMixedOperation (iCode *ic)
12973 operand *result = IC_RESULT(ic);
12974 sym_link *ctype = operandType(IC_LEFT(ic));
12975 operand *right = IC_RIGHT(ic);
12981 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12983 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12989 nextright = IC_RIGHT(nextic);
12990 nextleft = IC_LEFT(nextic);
12991 nextresult = IC_RESULT(nextic);
12993 pic16_aopOp(right,ic,FALSE);
12994 pic16_aopOp(result,ic,FALSE);
12995 pic16_aopOp(nextright, nextic, FALSE);
12996 pic16_aopOp(nextleft, nextic, FALSE);
12997 pic16_aopOp(nextresult, nextic, FALSE);
12999 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13001 operand *t = right;
13005 pic16_emitcode(";remove right +","");
13007 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13009 operand *t = right;
13013 pic16_emitcode(";remove left +","");
13017 big = AOP_SIZE(nextleft);
13018 small = AOP_SIZE(nextright);
13020 switch(nextic->op) {
13023 pic16_emitcode(";optimize a +","");
13024 /* if unsigned or not an integral type */
13025 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13026 pic16_emitcode(";add a bit to something","");
13029 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13031 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13032 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13033 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13035 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13043 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13044 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13045 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13048 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13050 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13051 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13052 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13053 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13054 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13057 pic16_emitcode("rlf","known_zero,w");
13064 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13065 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13066 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13068 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13078 pic16_freeAsmop(right,NULL,ic,TRUE);
13079 pic16_freeAsmop(result,NULL,ic,TRUE);
13080 pic16_freeAsmop(nextright,NULL,ic,TRUE);
13081 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13083 nextic->generated = 1;
13090 /*-----------------------------------------------------------------*/
13091 /* genCast - gen code for casting */
13092 /*-----------------------------------------------------------------*/
13093 static void genCast (iCode *ic)
13095 operand *result = IC_RESULT(ic);
13096 sym_link *ctype = operandType(IC_LEFT(ic));
13097 sym_link *rtype = operandType(IC_RIGHT(ic));
13098 sym_link *restype = operandType(IC_RESULT(ic));
13099 operand *right = IC_RIGHT(ic);
13105 /* if they are equivalent then do nothing */
13106 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13109 pic16_aopOp(right,ic,FALSE) ;
13110 pic16_aopOp(result,ic,FALSE);
13112 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13115 /* if the result is a bit */
13116 if (AOP_TYPE(result) == AOP_CRY) {
13118 /* if the right size is a literal then
13119 * we know what the value is */
13120 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13122 if (AOP_TYPE(right) == AOP_LIT) {
13123 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13124 pic16_popGet(AOP(result),0));
13126 if (((int) operandLitValue(right)))
13127 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13128 AOP(result)->aopu.aop_dir,
13129 AOP(result)->aopu.aop_dir);
13131 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13132 AOP(result)->aopu.aop_dir,
13133 AOP(result)->aopu.aop_dir);
13137 /* the right is also a bit variable */
13138 if (AOP_TYPE(right) == AOP_CRY) {
13140 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13142 pic16_emitcode("clrc","");
13143 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13144 AOP(right)->aopu.aop_dir,
13145 AOP(right)->aopu.aop_dir);
13146 pic16_aopPut(AOP(result),"c",0);
13150 /* we need to or */
13151 if (AOP_TYPE(right) == AOP_REG) {
13152 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
13153 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13154 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
13156 pic16_toBoolean(right);
13157 pic16_aopPut(AOP(result),"a",0);
13161 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13164 size = AOP_SIZE(result);
13166 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13168 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
13169 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
13170 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
13173 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13178 if(IS_BITFIELD(getSpec(restype))
13179 && IS_BITFIELD(getSpec(rtype))) {
13180 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13183 /* if they are the same size : or less */
13184 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13186 /* if they are in the same place */
13187 if (pic16_sameRegs(AOP(right),AOP(result)))
13190 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13192 if (IS_PTR_CONST(rtype))
13194 if (IS_CODEPTR(rtype))
13196 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13199 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13201 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13203 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13206 if(AOP_TYPE(right) == AOP_IMMD) {
13207 pCodeOp *pcop0, *pcop1, *pcop2;
13208 symbol *sym = OP_SYMBOL( right );
13210 size = AOP_SIZE(result);
13212 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13214 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13216 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13219 pic16_emitpcode(POC_MOVLW, pcop0);
13220 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13221 pic16_emitpcode(POC_MOVLW, pcop1);
13222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13223 pic16_emitpcode(POC_MOVLW, pcop2);
13224 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13227 pic16_emitpcode(POC_MOVLW, pcop0);
13228 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13229 pic16_emitpcode(POC_MOVLW, pcop1);
13230 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13232 pic16_emitpcode(POC_MOVLW, pcop0);
13233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13237 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13238 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13239 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13240 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13242 if(AOP_SIZE(result) <2)
13243 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13245 /* if they in different places then copy */
13246 size = AOP_SIZE(result);
13249 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13250 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13257 /* if the result is of type pointer */
13258 if (IS_PTR(ctype)) {
13260 sym_link *type = operandType(right);
13261 sym_link *etype = getSpec(type);
13263 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
13265 /* pointer to generic pointer */
13266 if (IS_GENPTR(ctype)) {
13270 p_type = DCL_TYPE(type);
13272 /* we have to go by the storage class */
13273 p_type = PTR_TYPE(SPEC_OCLS(etype));
13275 /* if (SPEC_OCLS(etype)->codesp ) */
13276 /* p_type = CPOINTER ; */
13278 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13279 /* p_type = FPOINTER ; */
13281 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13282 /* p_type = PPOINTER; */
13284 /* if (SPEC_OCLS(etype) == idata ) */
13285 /* p_type = IPOINTER ; */
13287 /* p_type = POINTER ; */
13290 /* the first two bytes are known */
13291 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13292 size = GPTRSIZE - 1;
13295 if(offset < AOP_SIZE(right)) {
13296 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13297 mov2f(AOP(result), AOP(right), offset);
13299 if ((AOP_TYPE(right) == AOP_PCODE) &&
13300 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13301 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13302 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13305 pic16_aopPut(AOP(result),
13306 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13311 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13314 /* the last byte depending on type */
13318 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13320 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13324 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13328 pic16_emitcode(";BUG!? ","%d",__LINE__);
13332 pic16_emitcode(";BUG!? ","%d",__LINE__);
13337 if (GPTRSIZE > AOP_SIZE(right)) {
13338 // assume data pointer... THIS MIGHT BE WRONG!
13339 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13340 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13342 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13347 /* this should never happen */
13348 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13349 "got unknown pointer type");
13352 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13356 /* just copy the pointers */
13357 size = AOP_SIZE(result);
13360 pic16_aopPut(AOP(result),
13361 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13370 /* so we now know that the size of destination is greater
13371 than the size of the source.
13372 Now, if the next iCode is an operator then we might be
13373 able to optimize the operation without performing a cast.
13375 if(genMixedOperation(ic))
13378 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13380 /* we move to result for the size of source */
13381 size = AOP_SIZE(right);
13384 mov2f(AOP(result), AOP(right), offset);
13388 /* now depending on the sign of the destination */
13389 size = AOP_SIZE(result) - AOP_SIZE(right);
13390 /* if unsigned or not an integral type */
13391 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13393 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13395 /* we need to extend the sign :( */
13398 /* Save one instruction of casting char to int */
13399 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13400 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13401 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
13403 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13406 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13408 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13410 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13413 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13418 pic16_freeAsmop(right,NULL,ic,TRUE);
13419 pic16_freeAsmop(result,NULL,ic,TRUE);
13423 /*-----------------------------------------------------------------*/
13424 /* genDjnz - generate decrement & jump if not zero instrucion */
13425 /*-----------------------------------------------------------------*/
13426 static int genDjnz (iCode *ic, iCode *ifx)
13428 symbol *lbl, *lbl1;
13429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13434 /* if the if condition has a false label
13435 then we cannot save */
13439 /* if the minus is not of the form
13441 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13442 !IS_OP_LITERAL(IC_RIGHT(ic)))
13445 if (operandLitValue(IC_RIGHT(ic)) != 1)
13448 /* if the size of this greater than one then no
13450 if (getSize(operandType(IC_RESULT(ic))) > 1)
13453 /* otherwise we can save BIG */
13454 lbl = newiTempLabel(NULL);
13455 lbl1= newiTempLabel(NULL);
13457 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13459 if (IS_AOP_PREG(IC_RESULT(ic))) {
13460 pic16_emitcode("dec","%s",
13461 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13462 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13463 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13467 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13468 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13470 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13471 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13475 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13476 ifx->generated = 1;
13480 /*-----------------------------------------------------------------*/
13481 /* genReceive - generate code for a receive iCode */
13482 /*-----------------------------------------------------------------*/
13483 static void genReceive (iCode *ic)
13489 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13490 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13492 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13494 if (isOperandInFarSpace(IC_RESULT(ic))
13495 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13496 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13498 int size = getSize(operandType(IC_RESULT(ic)));
13499 int offset = pic16_fReturnSizePic - size;
13503 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13504 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13508 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13510 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13511 size = AOP_SIZE(IC_RESULT(ic));
13514 pic16_emitcode ("pop","acc");
13515 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13518 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13520 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13523 /* set pseudo stack pointer to where it should be - dw*/
13524 GpsuedoStkPtr = ic->parmBytes;
13526 /* setting GpsuedoStkPtr has side effects here: */
13527 assignResultValue(IC_RESULT(ic), 0);
13530 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13533 /*-----------------------------------------------------------------*/
13534 /* genDummyRead - generate code for dummy read of volatiles */
13535 /*-----------------------------------------------------------------*/
13537 genDummyRead (iCode * ic)
13539 pic16_emitcode ("; genDummyRead","");
13540 pic16_emitcode ("; not implemented","");
13545 /*-----------------------------------------------------------------*/
13546 /* genpic16Code - generate code for pic16 based controllers */
13547 /*-----------------------------------------------------------------*/
13549 * At this point, ralloc.c has gone through the iCode and attempted
13550 * to optimize in a way suitable for a PIC. Now we've got to generate
13551 * PIC instructions that correspond to the iCode.
13553 * Once the instructions are generated, we'll pass through both the
13554 * peep hole optimizer and the pCode optimizer.
13555 *-----------------------------------------------------------------*/
13557 void genpic16Code (iCode *lic)
13562 lineHead = lineCurr = NULL;
13564 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13565 pic16_addpBlock(pb);
13568 /* if debug information required */
13569 if (options.debug && currFunc) {
13571 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13576 for (ic = lic ; ic ; ic = ic->next ) {
13578 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13579 if ( cln != ic->lineno ) {
13580 if ( options.debug ) {
13581 debugFile->writeCLine (ic);
13584 if(!options.noCcodeInAsm) {
13585 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13586 printCLine(ic->filename, ic->lineno)));
13592 if(options.iCodeInAsm) {
13595 /* insert here code to print iCode as comment */
13596 l = Safe_strdup(printILine(ic));
13597 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13600 /* if the result is marked as
13601 * spilt and rematerializable or code for
13602 * this has already been generated then
13604 if (resultRemat(ic) || ic->generated )
13607 /* depending on the operation */
13626 /* IPOP happens only when trying to restore a
13627 * spilt live range, if there is an ifx statement
13628 * following this pop then the if statement might
13629 * be using some of the registers being popped which
13630 * would destroy the contents of the register so
13631 * we need to check for this condition and handle it */
13633 && ic->next->op == IFX
13634 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13635 genIfx (ic->next,ic);
13653 genEndFunction (ic);
13669 pic16_genPlus (ic) ;
13673 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13674 pic16_genMinus (ic);
13690 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13694 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13700 /* note these two are xlated by algebraic equivalence
13701 * during parsing SDCC.y */
13702 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13703 "got '>=' or '<=' shouldn't have come here");
13707 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13719 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13723 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13727 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13751 genRightShift (ic);
13754 case GET_VALUE_AT_ADDRESS:
13759 if (POINTER_SET(ic))
13786 addSet(&_G.sendSet,ic);
13789 case DUMMY_READ_VOLATILE:
13799 /* now we are ready to call the
13800 peep hole optimizer */
13801 if (!options.nopeep)
13802 peepHole (&lineHead);
13804 /* now do the actual printing */
13805 printLine (lineHead, codeOutFile);
13808 DFPRINTF((stderr,"printing pBlock\n\n"));
13809 pic16_printpBlock(stdout,pb);