1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2f(asmop *dst, asmop *src, int offset);
61 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
62 static pCodeOp *pic16_popRegFromIdx(int rIdx);
64 //static int aopIdx (asmop *aop, int offset);
66 int pic16_labelOffset=0;
67 extern int pic16_debug_verbose;
68 static int optimized_for_speed = 0;
76 /* max_key keeps track of the largest label number used in
77 a function. This is then used to adjust the label offset
78 for the next function.
81 static int GpsuedoStkPtr=0;
83 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
85 unsigned int pic16aopLiteral (value *val, int offset);
86 const char *pic16_AopType(short type);
87 static iCode *ifxForOp ( operand *op, iCode *ic );
89 void pic16_pushpCodeOp(pCodeOp *pcop);
90 void pic16_poppCodeOp(pCodeOp *pcop);
92 static bool is_LitOp(operand *op);
93 static bool is_LitAOp(asmop *aop);
96 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
98 /* set the following macro to 1 to enable passing the
99 * first byte of functions parameters via WREG */
100 #define USE_WREG_IN_FUNC_PARAMS 0
103 /* this is the down and dirty file with all kinds of
104 kludgy & hacky stuff. This is what it is all about
105 CODE GENERATION for a specific MCU . some of the
106 routines may be reusable, will have to see */
108 static char *zero = "#0x00";
109 static char *one = "#0x01";
110 //static char *spname = "sp";
114 * Function return value policy (MSB-->LSB):
116 * 16 bits -> PRODL:WREG
117 * 24 bits -> PRODH:PRODL:WREG
118 * 32 bits -> FSR0L:PRODH:PRODL:WREG
119 * >32 bits -> on stack, and FSR0 points to the beginning
124 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
125 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
126 static char **fReturn = fReturnpic16;
128 static char *accUse[] = {"WREG"};
130 //static short rbank = -1;
146 int stack_lat; /* stack offset latency */
148 int useWreg; /* flag when WREG is used to pass function parameter */
151 /* Resolved ifx structure. This structure stores information
152 about an iCode ifx that makes it easier to generate code.
154 typedef struct resolvedIfx {
155 symbol *lbl; /* pointer to a label */
156 int condition; /* true or false ifx */
157 int generated; /* set true when the code associated with the ifx
161 extern int pic16_ptrRegReq ;
162 extern int pic16_nRegs;
163 extern FILE *codeOutFile;
164 //static void saverbank (int, iCode *,bool);
166 static lineNode *lineHead = NULL;
167 static lineNode *lineCurr = NULL;
169 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
170 0xE0, 0xC0, 0x80, 0x00};
171 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
172 0x07, 0x03, 0x01, 0x00};
176 /*-----------------------------------------------------------------*/
177 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
178 /* exponent of 2 is returned, otherwise -1 is */
180 /* note that this is similar to the function `powof2' in SDCCsymt */
184 /*-----------------------------------------------------------------*/
185 int pic16_my_powof2 (unsigned long num)
188 if( (num & (num-1)) == 0) {
201 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
203 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
205 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
206 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
207 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
208 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
209 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
210 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
211 ((result) ? AOP_SIZE(result) : 0));
214 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
217 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
219 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
220 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
221 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
222 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
223 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
224 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
228 void pic16_emitpcomment (char *fmt, ...)
231 char lb[INITIAL_INLINEASM];
237 vsprintf(lb+1,fmt,ap);
239 while (isspace(*lbp)) lbp++;
242 lineCurr = (lineCurr ?
243 connectLine(lineCurr,newLineNode(lb)) :
244 (lineHead = newLineNode(lb)));
245 lineCurr->isInline = _G.inLine;
246 lineCurr->isDebug = _G.debugLine;
248 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
251 // fprintf(stderr, "%s\n", lb);
254 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
257 char lb[INITIAL_INLINEASM];
260 if(!pic16_debug_verbose)
267 sprintf(lb,"%s\t",inst);
269 sprintf(lb,"%s",inst);
270 vsprintf(lb+(strlen(lb)),fmt,ap);
274 while (isspace(*lbp)) lbp++;
277 lineCurr = (lineCurr ?
278 connectLine(lineCurr,newLineNode(lb)) :
279 (lineHead = newLineNode(lb)));
280 lineCurr->isInline = _G.inLine;
281 lineCurr->isDebug = _G.debugLine;
283 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
286 // fprintf(stderr, "%s\n", lb);
291 void pic16_emitpLabel(int key)
293 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
296 void pic16_emitpLabelFORCE(int key)
298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
301 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
305 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
307 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
310 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
313 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
315 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
318 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
321 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
327 #define pic16_emitcode DEBUGpic16_emitcode
329 /*-----------------------------------------------------------------*/
330 /* pic16_emitcode - writes the code into a file : for now it is simple */
331 /*-----------------------------------------------------------------*/
332 void pic16_emitcode (char *inst,char *fmt, ...)
335 char lb[INITIAL_INLINEASM];
342 sprintf(lb,"%s\t",inst);
344 sprintf(lb,"%s",inst);
345 vsprintf(lb+(strlen(lb)),fmt,ap);
349 while (isspace(*lbp)) lbp++;
352 lineCurr = (lineCurr ?
353 connectLine(lineCurr,newLineNode(lb)) :
354 (lineHead = newLineNode(lb)));
355 lineCurr->isInline = _G.inLine;
356 lineCurr->isDebug = _G.debugLine;
358 // VR fprintf(stderr, "lb = <%s>\n", lbp);
360 // if(pic16_debug_verbose)
361 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
368 /*-----------------------------------------------------------------*/
369 /* pic16_emitDebuggerSymbol - associate the current code location */
370 /* with a debugger symbol */
371 /*-----------------------------------------------------------------*/
373 pic16_emitDebuggerSymbol (char * debugSym)
376 pic16_emitcode (";", "%s ==.", debugSym);
381 /*-----------------------------------------------------------------*/
382 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
383 /*-----------------------------------------------------------------*/
384 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
386 // bool r0iu = FALSE , r1iu = FALSE;
387 // bool r0ou = FALSE , r1ou = FALSE;
388 bool fsr0iu = FALSE, fsr0ou;
389 bool fsr2iu = FALSE, fsr2ou;
391 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
394 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
395 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
397 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
398 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
400 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
401 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
402 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
405 if(!fsr0iu && !fsr0ou) {
406 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
407 (*aopp)->type = AOP_FSR0;
409 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
411 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
415 /* no usage of FSR2 */
416 if(!fsr2iu && !fsr2ou) {
417 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
418 (*aopp)->type = AOP_FSR2;
420 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
424 /* now we know they both have usage */
425 /* if fsr0 not used in this instruction */
427 if (!_G.fsr0Pushed) {
428 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
429 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
433 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
434 (*aopp)->type = AOP_FSR0;
436 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
438 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
442 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
447 /* the logic: if r0 & r1 used in the instruction
448 then we are in trouble otherwise */
450 /* first check if r0 & r1 are used by this
451 instruction, in which case we are in trouble */
452 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
453 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
458 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
459 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
461 /* if no usage of r0 then return it */
462 if (!r0iu && !r0ou) {
463 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
464 (*aopp)->type = AOP_R0;
466 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
469 /* if no usage of r1 then return it */
470 if (!r1iu && !r1ou) {
471 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
472 (*aopp)->type = AOP_R1;
474 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
477 /* now we know they both have usage */
478 /* if r0 not used in this instruction */
480 /* push it if not already pushed */
482 //pic16_emitcode ("push","%s",
483 // pic16_regWithIdx(R0_IDX)->dname);
487 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
488 (*aopp)->type = AOP_R0;
490 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
493 /* if r1 not used then */
496 /* push it if not already pushed */
498 //pic16_emitcode ("push","%s",
499 // pic16_regWithIdx(R1_IDX)->dname);
503 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
504 (*aopp)->type = AOP_R1;
505 return pic16_regWithIdx(R1_IDX);
509 /* I said end of world but not quite end of world yet */
510 /* if this is a result then we can push it on the stack*/
512 (*aopp)->type = AOP_STK;
516 /* other wise this is true end of the world */
517 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
518 "getFreePtr should never reach here");
523 /*-----------------------------------------------------------------*/
524 /* newAsmop - creates a new asmOp */
525 /*-----------------------------------------------------------------*/
526 static asmop *newAsmop (short type)
530 aop = Safe_calloc(1,sizeof(asmop));
535 static void genSetDPTR(int n)
539 pic16_emitcode(";", "Select standard DPTR");
540 pic16_emitcode("mov", "dps, #0x00");
544 pic16_emitcode(";", "Select alternate DPTR");
545 pic16_emitcode("mov", "dps, #0x01");
549 /*-----------------------------------------------------------------*/
550 /* resolveIfx - converts an iCode ifx into a form more useful for */
551 /* generating code */
552 /*-----------------------------------------------------------------*/
553 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
557 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
563 resIfx->condition = 1; /* assume that the ifx is true */
564 resIfx->generated = 0; /* indicate that the ifx has not been used */
567 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
570 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
571 __FUNCTION__,__LINE__,resIfx->lbl->key);
576 resIfx->lbl = IC_TRUE(ifx);
578 resIfx->lbl = IC_FALSE(ifx);
579 resIfx->condition = 0;
584 DEBUGpic16_emitcode("; +++","ifx true is non-null");
586 DEBUGpic16_emitcode("; +++","ifx true is null");
588 DEBUGpic16_emitcode("; +++","ifx false is non-null");
590 DEBUGpic16_emitcode("; +++","ifx false is null");
594 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
598 /*-----------------------------------------------------------------*/
599 /* pointerCode - returns the code for a pointer type */
600 /*-----------------------------------------------------------------*/
601 static int pointerCode (sym_link *etype)
604 return PTR_TYPE(SPEC_OCLS(etype));
609 /*-----------------------------------------------------------------*/
610 /* aopForSym - for a true symbol */
611 /*-----------------------------------------------------------------*/
612 static asmop *aopForSym (iCode *ic, operand *op, bool result)
614 symbol *sym=OP_SYMBOL(op);
616 memmap *space= SPEC_OCLS(sym->etype);
620 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
622 // sym = OP_SYMBOL(op);
624 /* if already has one */
626 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
631 /* if symbol was initially placed onStack then we must re-place it
632 * to direct memory, since pic16 does not have a specific stack */
634 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
639 /* assign depending on the storage class */
640 /* if it is on the stack or indirectly addressable */
641 /* space we need to assign either r0 or r1 to it */
642 if (sym->onStack || sym->iaccess) {
646 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
647 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
649 /* acquire a temporary register -- it is saved in function */
651 sym->aop = aop = newAsmop(AOP_STA);
652 aop->aopu.stk.stk = sym->stack;
653 aop->size = getSize(sym->type);
656 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
657 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
658 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
659 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
661 for(i=0;i<aop->size;i++)
662 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
663 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
665 for(i=0;i<aop->size;i++) {
666 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
667 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
671 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
674 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
677 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
680 for(i=0;i<aop->size;i++) {
682 /* initialise for stack access via frame pointer */
683 // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
684 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((sym->stack + 1 + i /*+ _G.stack_lat*/)));
685 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
686 pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
690 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
697 /* now assign the address of the variable to
698 the pointer register */
699 if (aop->type != AOP_STK) {
703 pic16_emitcode("push","acc");
705 pic16_emitcode("mov","a,_bp");
706 pic16_emitcode("add","a,#0x%02x",
708 ((char)(sym->stack - _G.nRegsSaved )) :
709 ((char)sym->stack)) & 0xff);
710 pic16_emitcode("mov","%s,a",
711 aop->aopu.aop_ptr->name);
714 pic16_emitcode("pop","acc");
716 pic16_emitcode("mov","%s,#%s",
717 aop->aopu.aop_ptr->name,
719 aop->paged = space->paged;
721 aop->aopu.aop_stk = sym->stack;
729 if (sym->onStack && options.stack10bit)
731 /* It's on the 10 bit stack, which is located in
735 //DEBUGpic16_emitcode(";","%d",__LINE__);
738 pic16_emitcode("push","acc");
740 pic16_emitcode("mov","a,_bp");
741 pic16_emitcode("add","a,#0x%02x",
743 ((char)(sym->stack - _G.nRegsSaved )) :
744 ((char)sym->stack)) & 0xff);
747 pic16_emitcode ("mov","dpx1,#0x40");
748 pic16_emitcode ("mov","dph1,#0x00");
749 pic16_emitcode ("mov","dpl1, a");
753 pic16_emitcode("pop","acc");
755 sym->aop = aop = newAsmop(AOP_DPTR2);
756 aop->size = getSize(sym->type);
762 /* special case for a function */
763 if (IS_FUNC(sym->type)) {
764 sym->aop = aop = newAsmop(AOP_PCODE);
765 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
766 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
767 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
768 PCOI(aop->aopu.pcop)->index = 0;
769 aop->size = FPTRSIZE;
770 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
777 //DEBUGpic16_emitcode(";","%d",__LINE__);
778 /* if in bit space */
779 if (IN_BITSPACE(space)) {
780 sym->aop = aop = newAsmop (AOP_CRY);
781 aop->aopu.aop_dir = sym->rname ;
782 aop->size = getSize(sym->type);
783 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
786 /* if it is in direct space */
787 if (IN_DIRSPACE(space)) {
788 sym->aop = aop = newAsmop (AOP_DIR);
789 aop->aopu.aop_dir = sym->rname ;
790 aop->size = getSize(sym->type);
791 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
792 pic16_allocDirReg( IC_LEFT(ic) );
797 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
798 sym->aop = aop = newAsmop (AOP_DIR);
799 aop->aopu.aop_dir = sym->rname ;
800 aop->size = getSize(sym->type);
801 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
802 pic16_allocDirReg( IC_LEFT(ic) );
807 /* only remaining is far space */
808 sym->aop = aop = newAsmop(AOP_PCODE);
810 /* change the next if to 1 to revert to good old immediate code */
811 if(IN_CODESPACE(space)) {
812 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
813 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
814 PCOI(aop->aopu.pcop)->index = 0;
816 /* try to allocate via direct register */
817 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
818 // aop->size = getSize( sym->type );
821 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
822 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
825 if(!pic16_allocDirReg (IC_LEFT(ic)))
829 if(IN_DIRSPACE( space ))
831 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
832 aop->size = FPTRSIZE;
833 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
834 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
835 else if(sym->onStack) {
841 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
843 /* if it is in code space */
844 if (IN_CODESPACE(space))
850 /*-----------------------------------------------------------------*/
851 /* aopForRemat - rematerialzes an object */
852 /*-----------------------------------------------------------------*/
853 static asmop *aopForRemat (operand *op) // x symbol *sym)
855 symbol *sym = OP_SYMBOL(op);
857 iCode *ic = NULL, *oldic;
858 asmop *aop = newAsmop(AOP_PCODE);
865 ic = sym->rematiCode;
867 if(IS_OP_POINTER(op)) {
868 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
874 // pic16_emitpcomment("ic: %s\n", printILine(ic));
877 val += (int) operandLitValue(IC_RIGHT(ic));
878 } else if (ic->op == '-') {
879 val -= (int) operandLitValue(IC_RIGHT(ic));
883 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
886 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
889 if(!op->isaddr)viaimmd++; else viaimmd=0;
891 /* set the following if to 1 to revert to good old immediate code */
892 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
895 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
897 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
900 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
902 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
905 PCOI(aop->aopu.pcop)->index = val;
907 aop->size = getSize( sym->type );
909 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
911 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
912 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
914 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
918 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
919 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
921 val, IS_PTR_CONST(operandType(op)));
923 val, IS_CODEPTR(operandType(op)));
926 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
928 pic16_allocDirReg (IC_LEFT(ic));
930 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
937 static int aopIdx (asmop *aop, int offset)
942 if(aop->type != AOP_REG)
945 return aop->aopu.aop_reg[offset]->rIdx;
950 /*-----------------------------------------------------------------*/
951 /* regsInCommon - two operands have some registers in common */
952 /*-----------------------------------------------------------------*/
953 static bool regsInCommon (operand *op1, operand *op2)
958 /* if they have registers in common */
959 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
962 sym1 = OP_SYMBOL(op1);
963 sym2 = OP_SYMBOL(op2);
965 if (sym1->nRegs == 0 || sym2->nRegs == 0)
968 for (i = 0 ; i < sym1->nRegs ; i++) {
973 for (j = 0 ; j < sym2->nRegs ;j++ ) {
977 if (sym2->regs[j] == sym1->regs[i])
985 /*-----------------------------------------------------------------*/
986 /* operandsEqu - equivalent */
987 /*-----------------------------------------------------------------*/
988 static bool operandsEqu ( operand *op1, operand *op2)
992 /* if they not symbols */
993 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
996 sym1 = OP_SYMBOL(op1);
997 sym2 = OP_SYMBOL(op2);
999 /* if both are itemps & one is spilt
1000 and the other is not then false */
1001 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1002 sym1->isspilt != sym2->isspilt )
1005 /* if they are the same */
1009 if (sym1->rname[0] && sym2->rname[0]
1010 && strcmp (sym1->rname, sym2->rname) == 0)
1014 /* if left is a tmp & right is not */
1015 if (IS_ITEMP(op1) &&
1018 (sym1->usl.spillLoc == sym2))
1021 if (IS_ITEMP(op2) &&
1025 (sym2->usl.spillLoc == sym1))
1031 /*-----------------------------------------------------------------*/
1032 /* pic16_sameRegs - two asmops have the same registers */
1033 /*-----------------------------------------------------------------*/
1034 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1041 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1042 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1044 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1046 if (aop1->type != AOP_REG ||
1047 aop2->type != AOP_REG )
1050 if (aop1->size != aop2->size )
1053 for (i = 0 ; i < aop1->size ; i++ ) {
1054 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1056 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1057 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1064 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1066 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1067 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1069 if(aop1 == aop2)return TRUE;
1070 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1072 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1078 /*-----------------------------------------------------------------*/
1079 /* pic16_aopOp - allocates an asmop for an operand : */
1080 /*-----------------------------------------------------------------*/
1081 void pic16_aopOp (operand *op, iCode *ic, bool result)
1090 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1092 /* if this a literal */
1093 if (IS_OP_LITERAL(op)) {
1094 op->aop = aop = newAsmop(AOP_LIT);
1095 aop->aopu.aop_lit = op->operand.valOperand;
1096 aop->size = getSize(operandType(op));
1101 sym_link *type = operandType(op);
1103 if(IS_PTR_CONST(type))
1105 if(IS_CODEPTR(type))
1107 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1110 /* if already has a asmop then continue */
1114 /* if the underlying symbol has a aop */
1115 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1116 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1117 op->aop = OP_SYMBOL(op)->aop;
1121 /* if this is a true symbol */
1122 if (IS_TRUE_SYMOP(op)) {
1123 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1124 op->aop = aopForSym(ic, op, result);
1128 /* this is a temporary : this has
1134 e) can be a return use only */
1136 sym = OP_SYMBOL(op);
1138 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1139 /* if the type is a conditional */
1140 if (sym->regType == REG_CND) {
1141 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1146 /* if it is spilt then two situations
1148 b) has a spill location */
1149 if (sym->isspilt || sym->nRegs == 0) {
1151 DEBUGpic16_emitcode(";","%d",__LINE__);
1152 /* rematerialize it NOW */
1155 sym->aop = op->aop = aop = aopForRemat (op);
1156 // aop->size = getSize(sym->type);
1157 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1164 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1165 aop->size = getSize(sym->type);
1166 for ( i = 0 ; i < 1 ; i++ ) {
1167 aop->aopu.aop_str[i] = accUse[i];
1168 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1170 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1171 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1179 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1180 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1181 //pic16_allocDirReg (IC_LEFT(ic));
1182 aop->size = getSize(sym->type);
1187 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1188 aop->size = getSize(sym->type);
1189 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1190 aop->aopu.aop_str[i] = fReturn[i];
1192 DEBUGpic16_emitcode(";","%d",__LINE__);
1196 /* else spill location */
1197 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1198 /* force a new aop if sizes differ */
1199 sym->usl.spillLoc->aop = NULL;
1203 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1204 __FUNCTION__,__LINE__,
1205 sym->usl.spillLoc->rname,
1206 sym->rname, sym->usl.spillLoc->offset);
1209 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1210 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1211 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1213 sym->usl.spillLoc->offset, op);
1214 aop->size = getSize(sym->type);
1220 sym_link *type = operandType(op);
1222 if(IS_PTR_CONST(type))
1224 if(IS_CODEPTR(type))
1226 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1229 /* must be in a register */
1230 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1231 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1232 aop->size = sym->nRegs;
1233 for ( i = 0 ; i < sym->nRegs ;i++)
1234 aop->aopu.aop_reg[i] = sym->regs[i];
1237 /*-----------------------------------------------------------------*/
1238 /* pic16_freeAsmop - free up the asmop given to an operand */
1239 /*----------------------------------------------------------------*/
1240 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1257 /* depending on the asmop type only three cases need work AOP_RO
1258 , AOP_R1 && AOP_STK */
1260 switch (aop->type) {
1262 if (_G.fsr0Pushed ) {
1264 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1265 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1266 // pic16_emitcode ("pop","ar0");
1270 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1274 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1280 pic16_emitcode ("pop","ar0");
1284 bitVectUnSetBit(ic->rUsed,R0_IDX);
1290 pic16_emitcode ("pop","ar1");
1294 bitVectUnSetBit(ic->rUsed,R1_IDX);
1301 /* we must store the result on stack */
1302 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1303 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1304 for(i=0;i<aop->size;i++) {
1305 /* initialise for stack access via frame pointer */
1306 // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
1307 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((OP_SYMBOL(IC_RESULT(ic))->stack + 1 + i /*+ _G.stack_lat*/)));
1308 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1309 aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1312 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1316 for(i=0;i<aop->size;i++)
1317 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1326 int stk = aop->aopu.aop_stk + aop->size;
1327 bitVectUnSetBit(ic->rUsed,R0_IDX);
1328 bitVectUnSetBit(ic->rUsed,R1_IDX);
1330 getFreePtr(ic,&aop,FALSE);
1332 if (options.stack10bit)
1334 /* I'm not sure what to do here yet... */
1337 "*** Warning: probably generating bad code for "
1338 "10 bit stack mode.\n");
1342 pic16_emitcode ("mov","a,_bp");
1343 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1344 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1346 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1350 pic16_emitcode("pop","acc");
1351 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1353 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1356 pic16_freeAsmop(op,NULL,ic,TRUE);
1358 pic16_emitcode("pop","ar0");
1363 pic16_emitcode("pop","ar1");
1373 /* all other cases just dealloc */
1377 OP_SYMBOL(op)->aop = NULL;
1378 /* if the symbol has a spill */
1380 SPIL_LOC(op)->aop = NULL;
1385 /*-----------------------------------------------------------------*/
1386 /* pic16_aopGet - for fetching value of the aop */
1387 /*-----------------------------------------------------------------*/
1388 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1393 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1395 /* offset is greater than size then zero */
1396 if (offset > (aop->size - 1) &&
1397 aop->type != AOP_LIT)
1400 /* depending on type */
1401 switch (aop->type) {
1405 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1406 rs = Safe_calloc(1, strlen(s)+1);
1411 /* if we need to increment it */
1412 while (offset > aop->coff)
1414 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1418 while (offset < aop->coff)
1420 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1426 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1427 return (dname ? "acc" : "a");
1429 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1430 rs = Safe_calloc (1, strlen (s) + 1);
1438 sprintf (s,"%s",aop->aopu.aop_immd);
1441 sprintf(s,"(%s >> %d)",
1446 aop->aopu.aop_immd);
1447 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1448 rs = Safe_calloc(1,strlen(s)+1);
1454 sprintf(s,"(%s + %d)",
1457 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1459 sprintf(s,"%s",aop->aopu.aop_dir);
1460 rs = Safe_calloc(1,strlen(s)+1);
1466 // return aop->aopu.aop_reg[offset]->dname;
1468 return aop->aopu.aop_reg[offset]->name;
1471 //pic16_emitcode(";","%d",__LINE__);
1472 return aop->aopu.aop_dir;
1475 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1476 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1478 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1479 rs = Safe_strdup("WREG");
1483 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1484 rs = Safe_calloc(1,strlen(s)+1);
1489 aop->coff = offset ;
1490 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1493 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1495 return aop->aopu.aop_str[offset];
1499 pCodeOp *pcop = aop->aopu.pcop;
1500 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1502 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1503 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1505 pic16_emitpcomment ("; =!= %s:%d: changed from %s to (%s + %d)", __FUNCTION__, __LINE__, pcop->name, pcop->name, offset);
1506 sprintf(s,"(%s + %d)", pcop->name, offset);
1508 sprintf(s,"%s", pcop->name);
1511 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1514 rs = Safe_calloc(1,strlen(s)+1);
1519 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1523 // pCodeOp *pcop = aop->aop
1528 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1529 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1530 "aopget got unsupported aop->type");
1536 /* lock has the following meaning: When allocating temporary registers
1537 * for stack variables storage, the value of the temporary register is
1538 * saved on stack. Its value is restored at the end. This procedure is
1539 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1540 * a possibility that before a call to pic16_aopOp, a temporary register
1541 * is allocated for a while and it is freed after some time, this will
1542 * mess the stack and values will not be restored properly. So use lock=1
1543 * to allocate temporary registers used internally by the programmer, and
1544 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1545 * to inform the compiler developer about a possible bug. This is an internal
1546 * feature for developing the compiler -- VR */
1548 int _TempReg_lock = 0;
1549 /*-----------------------------------------------------------------*/
1550 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1551 /*-----------------------------------------------------------------*/
1552 pCodeOp *pic16_popGetTempReg(int lock)
1557 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1559 // werror(W_POSSBUG2, __FILE__, __LINE__);
1562 _TempReg_lock += lock;
1567 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1568 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1569 PCOR(pcop)->r->wasUsed=1;
1570 PCOR(pcop)->r->isFree=0;
1572 /* push value on stack */
1573 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1581 /*-----------------------------------------------------------------*/
1582 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1583 /* don't save if inside v */
1584 /*-----------------------------------------------------------------*/
1585 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1590 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1593 // werror(W_POSSBUG2, __FILE__, __LINE__);
1596 _TempReg_lock += lock;
1601 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1602 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1603 PCOR(pcop)->r->wasUsed=1;
1604 PCOR(pcop)->r->isFree=0;
1606 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1607 /* push value on stack */
1608 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1618 /*-----------------------------------------------------------------*/
1619 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1620 /*-----------------------------------------------------------------*/
1621 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1623 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1625 _TempReg_lock -= lock;
1627 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1628 PCOR(pcop)->r->isFree = 1;
1629 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1632 /*-----------------------------------------------------------------*/
1633 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1634 /*-----------------------------------------------------------------*/
1635 pCodeOp *pic16_popGetLabel(unsigned int key)
1638 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1643 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1646 /*-----------------------------------------------------------------*/
1647 /* pic16_popCopyReg - copy a pcode operator */
1648 /*-----------------------------------------------------------------*/
1649 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1653 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1654 pcor->pcop.type = pc->pcop.type;
1656 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1657 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1659 pcor->pcop.name = NULL;
1662 pcor->rIdx = pc->rIdx;
1664 pcor->instance = pc->instance;
1666 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1671 /*-----------------------------------------------------------------*/
1672 /* pic16_popGetLit - asm operator to pcode operator conversion */
1673 /*-----------------------------------------------------------------*/
1674 pCodeOp *pic16_popGetLit(int lit)
1676 return pic16_newpCodeOpLit(lit);
1679 /*-----------------------------------------------------------------*/
1680 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1684 return pic16_newpCodeOpLit2(lit, arg2);
1688 /*-----------------------------------------------------------------*/
1689 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1690 /*-----------------------------------------------------------------*/
1691 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1693 return pic16_newpCodeOpImmd(name, offset,index, 0);
1697 /*-----------------------------------------------------------------*/
1698 /* pic16_popGet - asm operator to pcode operator conversion */
1699 /*-----------------------------------------------------------------*/
1700 pCodeOp *pic16_popGetWithString(char *str)
1706 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1710 pcop = pic16_newpCodeOp(str,PO_STR);
1715 /*-----------------------------------------------------------------*/
1716 /* pic16_popRegFromString - */
1717 /*-----------------------------------------------------------------*/
1718 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1721 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1722 pcop->type = PO_DIR;
1724 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1725 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1730 pcop->name = Safe_calloc(1,strlen(str)+1);
1731 strcpy(pcop->name,str);
1733 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1735 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1737 /* make sure that register doesn't exist,
1738 * and operand isn't NULL
1739 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1740 if((PCOR(pcop)->r == NULL)
1742 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1743 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1744 // __FUNCTION__, __LINE__, str, size, offset);
1746 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1747 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1750 PCOR(pcop)->instance = offset;
1755 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1759 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1761 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1762 PCOR(pcop)->rIdx = rIdx;
1763 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1765 PCOR(pcop)->r->isFree = 0;
1766 PCOR(pcop)->r->wasUsed = 1;
1768 pcop->type = PCOR(pcop)->r->pc_type;
1773 /*---------------------------------------------------------------------------------*/
1774 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1776 /*---------------------------------------------------------------------------------*/
1777 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1782 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1784 /* comment the following check, so errors to throw up */
1785 // if(!pcop2)return NULL;
1787 temp = pic16_popGet(aop_dst, offset);
1788 pcop2->pcop2 = temp;
1795 /*--------------------------------------------------------------------------------.-*/
1796 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1797 /* VR 030601 , adapted by Hans Dorn */
1798 /*--------------------------------------------------------------------------------.-*/
1799 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1803 pcop2 = (pCodeOpReg2 *)src;
1811 /*---------------------------------------------------------------------------------*/
1812 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1813 /* movff instruction */
1814 /*---------------------------------------------------------------------------------*/
1815 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1820 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1821 pcop2->pcop2 = pic16_popCopyReg(dst);
1823 /* the pCodeOp may be already allocated */
1824 pcop2 = (pCodeOpReg2 *)(src);
1825 pcop2->pcop2 = (pCodeOp *)(dst);
1832 /*-----------------------------------------------------------------*/
1833 /* pic16_popGet - asm operator to pcode operator conversion */
1834 /*-----------------------------------------------------------------*/
1835 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1837 //char *s = buffer ;
1842 /* offset is greater than
1845 // if (offset > (aop->size - 1) &&
1846 // aop->type != AOP_LIT)
1847 // return NULL; //zero;
1849 /* depending on type */
1850 switch (aop->type) {
1856 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1857 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1864 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1865 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1866 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1867 PCOR(pcop)->r->wasUsed = 1;
1868 PCOR(pcop)->r->isFree = 0;
1870 PCOR(pcop)->instance = offset;
1871 pcop->type = PCOR(pcop)->r->pc_type;
1875 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1876 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1879 /* pCodeOp is already allocated from aopForSym */
1880 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1881 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1887 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1889 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1891 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1893 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1894 PCOR(pcop)->rIdx = rIdx;
1895 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1896 PCOR(pcop)->r->wasUsed=1;
1897 PCOR(pcop)->r->isFree=0;
1899 PCOR(pcop)->instance = offset;
1900 pcop->type = PCOR(pcop)->r->pc_type;
1901 // rs = aop->aopu.aop_reg[offset]->name;
1902 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1906 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1907 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1913 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1914 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1919 assert (aop && aop->aopu.aop_reg[offset] != NULL);
1920 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1922 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1924 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1925 // pcop->type = PO_GPR_REGISTER;
1926 PCOR(pcop)->rIdx = rIdx;
1927 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1928 PCOR(pcop)->r->wasUsed=1;
1929 PCOR(pcop)->r->isFree=0;
1931 PCOR(pcop)->instance = offset;
1932 pcop->type = PCOR(pcop)->r->pc_type;
1934 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1935 rs = aop->aopu.aop_reg[offset]->name;
1936 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1941 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1943 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1944 PCOR(pcop)->instance = offset;
1945 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1946 //if(PCOR(pcop)->r == NULL)
1947 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1951 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1952 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1955 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1956 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1959 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1960 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1961 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1962 pcop->type = PCOR(pcop)->r->pc_type;
1963 pcop->name = PCOR(pcop)->r->name;
1969 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1971 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1972 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1974 switch( aop->aopu.pcop->type ) {
1975 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1976 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1978 assert( 0 ); /* should never reach here */;
1981 PCOI(pcop)->offset = offset;
1986 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1987 "pic16_popGet got unsupported aop->type");
1990 /*-----------------------------------------------------------------*/
1991 /* pic16_aopPut - puts a string for a aop */
1992 /*-----------------------------------------------------------------*/
1993 void pic16_aopPut (asmop *aop, char *s, int offset)
2000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2002 if (aop->size && offset > ( aop->size - 1)) {
2003 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2004 "pic16_aopPut got offset > aop->size");
2008 /* will assign value to value */
2009 /* depending on where it is ofcourse */
2010 switch (aop->type) {
2013 sprintf(d,"(%s + %d)",
2014 aop->aopu.aop_dir,offset);
2015 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2018 sprintf(d,"%s",aop->aopu.aop_dir);
2021 DEBUGpic16_emitcode(";","%d",__LINE__);
2023 pic16_emitcode("movf","%s,w",s);
2024 pic16_emitcode("movwf","%s",d);
2027 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2028 if(offset >= aop->size) {
2029 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2032 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2035 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2042 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2043 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2046 strcmp(s,"r0") == 0 ||
2047 strcmp(s,"r1") == 0 ||
2048 strcmp(s,"r2") == 0 ||
2049 strcmp(s,"r3") == 0 ||
2050 strcmp(s,"r4") == 0 ||
2051 strcmp(s,"r5") == 0 ||
2052 strcmp(s,"r6") == 0 ||
2053 strcmp(s,"r7") == 0 )
2054 pic16_emitcode("mov","%s,%s ; %d",
2055 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2059 if(strcmp(s,"W")==0 )
2060 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2062 pic16_emitcode("movwf","%s",
2063 aop->aopu.aop_reg[offset]->name);
2065 if(strcmp(s,zero)==0) {
2066 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2068 } else if(strcmp(s,"W")==0) {
2069 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2070 pcop->type = PO_GPR_REGISTER;
2072 PCOR(pcop)->rIdx = -1;
2073 PCOR(pcop)->r = NULL;
2075 DEBUGpic16_emitcode(";","%d",__LINE__);
2076 pcop->name = Safe_strdup(s);
2077 pic16_emitpcode(POC_MOVFW,pcop);
2078 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2079 } else if(strcmp(s,one)==0) {
2080 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2081 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2083 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2091 if (aop->type == AOP_DPTR2)
2097 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2098 "pic16_aopPut writting to code space");
2102 while (offset > aop->coff) {
2104 pic16_emitcode ("inc","dptr");
2107 while (offset < aop->coff) {
2109 pic16_emitcode("lcall","__decdptr");
2114 /* if not in accumulater */
2117 pic16_emitcode ("movx","@dptr,a");
2119 if (aop->type == AOP_DPTR2)
2127 while (offset > aop->coff) {
2129 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2131 while (offset < aop->coff) {
2133 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2139 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2144 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2146 if (strcmp(s,"r0") == 0 ||
2147 strcmp(s,"r1") == 0 ||
2148 strcmp(s,"r2") == 0 ||
2149 strcmp(s,"r3") == 0 ||
2150 strcmp(s,"r4") == 0 ||
2151 strcmp(s,"r5") == 0 ||
2152 strcmp(s,"r6") == 0 ||
2153 strcmp(s,"r7") == 0 ) {
2155 sprintf(buffer,"a%s",s);
2156 pic16_emitcode("mov","@%s,%s",
2157 aop->aopu.aop_ptr->name,buffer);
2159 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2164 if (strcmp(s,"a") == 0)
2165 pic16_emitcode("push","acc");
2167 pic16_emitcode("push","%s",s);
2172 /* if bit variable */
2173 if (!aop->aopu.aop_dir) {
2174 pic16_emitcode("clr","a");
2175 pic16_emitcode("rlc","a");
2178 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2181 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2184 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2186 lbl = newiTempLabel(NULL);
2188 if (strcmp(s,"a")) {
2191 pic16_emitcode("clr","c");
2192 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2193 pic16_emitcode("cpl","c");
2194 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2195 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2202 if (strcmp(aop->aopu.aop_str[offset],s))
2203 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2208 if (!offset && (strcmp(s,"acc") == 0))
2211 if (strcmp(aop->aopu.aop_str[offset],s))
2212 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2216 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2217 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2218 // "pic16_aopPut got unsupported aop->type");
2224 /*-----------------------------------------------------------------*/
2225 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2226 /*-----------------------------------------------------------------*/
2227 void pic16_mov2w (asmop *aop, int offset)
2229 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2232 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2234 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2237 static void mov2f(asmop *dst, asmop *src, int offset)
2239 if(is_LitAOp(src)) {
2240 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2241 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2243 if(pic16_sameRegsOfs(src, dst, offset))return;
2244 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2245 pic16_popGet(dst, offset)));
2249 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2251 if(is_LitAOp(src)) {
2252 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2253 pic16_emitpcode(POC_MOVWF, dst);
2255 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2259 void pic16_testStackOverflow(void)
2261 #define GSTACK_TEST_NAME "__gstack_test"
2263 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2268 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2269 strcpy(sym->rname, GSTACK_TEST_NAME);
2270 checkAddSym(&externs, sym);
2275 /* push pcop into stack */
2276 void pic16_pushpCodeOp(pCodeOp *pcop)
2278 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2279 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2280 if(pic16_options.gstack)
2281 pic16_testStackOverflow();
2285 /* pop pcop from stack */
2286 void pic16_poppCodeOp(pCodeOp *pcop)
2288 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2289 if(pic16_options.gstack)
2290 pic16_testStackOverflow();
2294 /*-----------------------------------------------------------------*/
2295 /* pushw - pushes wreg to stack */
2296 /*-----------------------------------------------------------------*/
2299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2300 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2301 if(pic16_options.gstack)
2302 pic16_testStackOverflow();
2306 /*-----------------------------------------------------------------*/
2307 /* pushaop - pushes aop to stack */
2308 /*-----------------------------------------------------------------*/
2309 void pushaop(asmop *aop, int offset)
2311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2313 if(is_LitAOp(aop)) {
2314 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2315 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2317 pic16_emitpcode(POC_MOVFF,
2318 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2321 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2322 if(pic16_options.gstack)
2323 pic16_testStackOverflow();
2326 /*-----------------------------------------------------------------*/
2327 /* popaop - pops aop from stack */
2328 /*-----------------------------------------------------------------*/
2329 void popaop(asmop *aop, int offset)
2331 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2332 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2333 if(pic16_options.gstack)
2334 pic16_testStackOverflow();
2337 void popaopidx(asmop *aop, int offset, int index)
2341 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2343 if(STACK_MODEL_LARGE)ofs++;
2345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2346 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2347 if(pic16_options.gstack)
2348 pic16_testStackOverflow();
2351 /*-----------------------------------------------------------------*/
2352 /* reAdjustPreg - points a register back to where it should */
2353 /*-----------------------------------------------------------------*/
2354 static void reAdjustPreg (asmop *aop)
2358 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2360 if ((size = aop->size) <= 1)
2363 switch (aop->type) {
2367 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2371 if (aop->type == AOP_DPTR2)
2377 pic16_emitcode("lcall","__decdptr");
2380 if (aop->type == AOP_DPTR2)
2392 /*-----------------------------------------------------------------*/
2393 /* opIsGptr: returns non-zero if the passed operand is */
2394 /* a generic pointer type. */
2395 /*-----------------------------------------------------------------*/
2396 static int opIsGptr(operand *op)
2398 sym_link *type = operandType(op);
2400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2401 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2409 /*-----------------------------------------------------------------*/
2410 /* pic16_getDataSize - get the operand data size */
2411 /*-----------------------------------------------------------------*/
2412 int pic16_getDataSize(operand *op)
2414 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2417 return AOP_SIZE(op);
2419 // tsd- in the pic port, the genptr size is 1, so this code here
2420 // fails. ( in the 8051 port, the size was 4).
2423 size = AOP_SIZE(op);
2424 if (size == GPTRSIZE)
2426 sym_link *type = operandType(op);
2427 if (IS_GENPTR(type))
2429 /* generic pointer; arithmetic operations
2430 * should ignore the high byte (pointer type).
2433 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2440 /*-----------------------------------------------------------------*/
2441 /* pic16_outAcc - output Acc */
2442 /*-----------------------------------------------------------------*/
2443 void pic16_outAcc(operand *result)
2446 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2447 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2450 size = pic16_getDataSize(result);
2452 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2455 /* unsigned or positive */
2457 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2462 /*-----------------------------------------------------------------*/
2463 /* pic16_outBitC - output a bit C */
2464 /* Move to result the value of Carry flag -- VR */
2465 /*-----------------------------------------------------------------*/
2466 void pic16_outBitC(operand *result)
2470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2472 /* if the result is bit */
2473 if (AOP_TYPE(result) == AOP_CRY) {
2474 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2475 pic16_aopPut(AOP(result),"c",0);
2478 i = AOP_SIZE(result);
2480 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2482 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2486 /*-----------------------------------------------------------------*/
2487 /* pic16_outBitOp - output a bit from Op */
2488 /* Move to result the value of set/clr op -- VR */
2489 /*-----------------------------------------------------------------*/
2490 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2494 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2496 /* if the result is bit */
2497 if (AOP_TYPE(result) == AOP_CRY) {
2498 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2499 pic16_aopPut(AOP(result),"c",0);
2502 i = AOP_SIZE(result);
2504 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2506 pic16_emitpcode(POC_RRCF, pcop);
2507 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2511 /*-----------------------------------------------------------------*/
2512 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2513 /*-----------------------------------------------------------------*/
2514 void pic16_toBoolean(operand *oper)
2516 int size = AOP_SIZE(oper) - 1;
2519 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2521 if ( AOP_TYPE(oper) != AOP_ACC) {
2522 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2525 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2530 #if !defined(GEN_Not)
2531 /*-----------------------------------------------------------------*/
2532 /* genNot - generate code for ! operation */
2533 /*-----------------------------------------------------------------*/
2534 static void pic16_genNot (iCode *ic)
2540 /* assign asmOps to operand & result */
2541 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2542 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2544 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2545 /* if in bit space then a special case */
2546 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2547 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2548 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2549 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2551 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2552 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2553 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2558 size = AOP_SIZE(IC_LEFT(ic));
2560 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2561 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2562 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2565 pic16_toBoolean(IC_LEFT(ic));
2567 tlbl = newiTempLabel(NULL);
2568 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2569 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2570 pic16_outBitC(IC_RESULT(ic));
2573 /* release the aops */
2574 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2575 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2580 #if !defined(GEN_Cpl)
2581 /*-----------------------------------------------------------------*/
2582 /* genCpl - generate code for complement */
2583 /*-----------------------------------------------------------------*/
2584 static void pic16_genCpl (iCode *ic)
2590 /* assign asmOps to operand & result */
2591 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2592 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2594 /* if both are in bit space then
2596 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2597 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2599 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2600 pic16_emitcode("cpl","c");
2601 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2605 size = AOP_SIZE(IC_RESULT(ic));
2608 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2610 pic16_emitcode("cpl","a");
2611 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2613 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2614 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2616 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2617 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2625 /* release the aops */
2626 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2627 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2631 /*-----------------------------------------------------------------*/
2632 /* genUminusFloat - unary minus for floating points */
2633 /*-----------------------------------------------------------------*/
2634 static void genUminusFloat(operand *op,operand *result)
2636 int size ,offset =0 ;
2639 /* for this we just need to flip the
2640 first it then copy the rest in place */
2641 size = AOP_SIZE(op);
2644 mov2f(AOP(result), AOP(op), offset);
2648 /* toggle the MSB's highest bit */
2649 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2652 /*-----------------------------------------------------------------*/
2653 /* genUminus - unary minus code generation */
2654 /*-----------------------------------------------------------------*/
2655 static void genUminus (iCode *ic)
2658 sym_link *optype, *rtype;
2663 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2664 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2666 /* if both in bit space then special case */
2667 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2668 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2670 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2671 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2672 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2676 optype = operandType(IC_LEFT(ic));
2677 rtype = operandType(IC_RESULT(ic));
2679 /* if float then do float stuff */
2680 if (IS_FLOAT(optype)) {
2681 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2685 /* otherwise subtract from zero by taking the 2's complement */
2686 size = AOP_SIZE(IC_LEFT(ic));
2688 for(i=0; i<size; i++) {
2689 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2690 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2692 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2697 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2698 for(i=1; i<size; i++) {
2700 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2704 /* release the aops */
2705 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2706 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2710 /*-----------------------------------------------------------------*/
2711 /* saveRegisters - will look for a call and save the registers */
2712 /*-----------------------------------------------------------------*/
2713 static void saveRegisters(iCode *lic)
2720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2722 for (ic = lic ; ic ; ic = ic->next)
2723 if (ic->op == CALL || ic->op == PCALL)
2727 fprintf(stderr,"found parameter push with no function call\n");
2731 /* if the registers have been saved already then
2733 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2736 /* find the registers in use at this time
2737 and push them away to safety */
2738 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2742 if (options.useXstack) {
2743 if (bitVectBitValue(rsave,R0_IDX))
2744 pic16_emitcode("mov","b,r0");
2745 pic16_emitcode("mov","r0,%s",spname);
2746 for (i = 0 ; i < pic16_nRegs ; i++) {
2747 if (bitVectBitValue(rsave,i)) {
2749 pic16_emitcode("mov","a,b");
2751 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2752 pic16_emitcode("movx","@r0,a");
2753 pic16_emitcode("inc","r0");
2756 pic16_emitcode("mov","%s,r0",spname);
2757 if (bitVectBitValue(rsave,R0_IDX))
2758 pic16_emitcode("mov","r0,b");
2760 //for (i = 0 ; i < pic16_nRegs ; i++) {
2761 // if (bitVectBitValue(rsave,i))
2762 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2765 dtype = operandType(IC_LEFT(ic));
2766 if (currFunc && dtype &&
2767 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2768 IFFUNC_ISISR(currFunc->type) &&
2771 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2774 /*-----------------------------------------------------------------*/
2775 /* unsaveRegisters - pop the pushed registers */
2776 /*-----------------------------------------------------------------*/
2777 static void unsaveRegisters (iCode *ic)
2782 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2783 /* find the registers in use at this time
2784 and push them away to safety */
2785 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2788 if (options.useXstack) {
2789 pic16_emitcode("mov","r0,%s",spname);
2790 for (i = pic16_nRegs ; i >= 0 ; i--) {
2791 if (bitVectBitValue(rsave,i)) {
2792 pic16_emitcode("dec","r0");
2793 pic16_emitcode("movx","a,@r0");
2795 pic16_emitcode("mov","b,a");
2797 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2801 pic16_emitcode("mov","%s,r0",spname);
2802 if (bitVectBitValue(rsave,R0_IDX))
2803 pic16_emitcode("mov","r0,b");
2805 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2806 // if (bitVectBitValue(rsave,i))
2807 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2814 /*-----------------------------------------------------------------*/
2816 /*-----------------------------------------------------------------*/
2817 static void pushSide(operand * oper, int size)
2820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2822 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2823 if (AOP_TYPE(oper) != AOP_REG &&
2824 AOP_TYPE(oper) != AOP_DIR &&
2826 pic16_emitcode("mov","a,%s",l);
2827 pic16_emitcode("push","acc");
2829 pic16_emitcode("push","%s",l);
2834 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2836 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2837 pic16_emitpcode(POC_MOVFW, src);
2838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2840 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2841 src, pic16_popGet(AOP(op), offset)));
2846 /*-----------------------------------------------------------------*/
2847 /* assignResultValue - assign results to oper, rescall==1 is */
2848 /* called from genCall() or genPcall() */
2849 /*-----------------------------------------------------------------*/
2850 static void assignResultValue(operand * oper, int rescall)
2852 int size = AOP_SIZE(oper);
2856 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2857 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2860 /* assign result from a call/pcall function() */
2862 /* function results are stored in a special order,
2863 * see top of file with Function return policy, or manual */
2866 /* 8-bits, result in WREG */
2867 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2870 /* 16-bits, result in PRODL:WREG */
2871 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2875 /* 24-bits, result in PRODH:PRODL:WREG */
2876 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2880 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2881 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2885 /* >32-bits, result on stack, and FSR0 points to beginning.
2886 * Fix stack when done */
2888 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2890 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2891 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2893 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2898 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2899 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2900 if(STACK_MODEL_LARGE) {
2902 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2906 int areg = 0; /* matching argument register */
2908 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2909 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2912 /* its called from genReceive (probably) -- VR */
2913 /* I hope this code will not be called from somewhere else in the future!
2914 * We manually set the pseudo stack pointer in genReceive. - dw
2916 if(!GpsuedoStkPtr && _G.useWreg) {
2917 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2919 /* The last byte in the assignment is in W */
2920 if(areg <= GpsuedoStkPtr) {
2922 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2924 // debugf("receive from WREG\n", 0);
2926 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2929 _G.stack_lat = AOP_SIZE(oper)-1;
2934 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2935 // debugf("receive from STACK\n", 0);
2942 /*-----------------------------------------------------------------*/
2943 /* genIpush - generate code for pushing this gets a little complex */
2944 /*-----------------------------------------------------------------*/
2945 static void genIpush (iCode *ic)
2947 // int size, offset=0;
2950 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2953 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2955 /* send to stack as normal */
2956 addSet(&_G.sendSet,ic);
2957 // addSetHead(&_G.sendSet,ic);
2958 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2963 int size, offset = 0 ;
2967 /* if this is not a parm push : ie. it is spill push
2968 and spill push is always done on the local stack */
2969 if (!ic->parmPush) {
2971 /* and the item is spilt then do nothing */
2972 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2975 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2976 size = AOP_SIZE(IC_LEFT(ic));
2977 /* push it on the stack */
2979 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2984 pic16_emitcode("push","%s",l);
2989 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2993 /*-----------------------------------------------------------------*/
2994 /* genIpop - recover the registers: can happen only for spilling */
2995 /*-----------------------------------------------------------------*/
2996 static void genIpop (iCode *ic)
2999 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3004 /* if the temp was not pushed then */
3005 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3008 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3009 size = AOP_SIZE(IC_LEFT(ic));
3012 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3015 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3020 /*-----------------------------------------------------------------*/
3021 /* unsaverbank - restores the resgister bank from stack */
3022 /*-----------------------------------------------------------------*/
3023 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3025 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3033 if (options.useXstack) {
3035 r = getFreePtr(ic,&aop,FALSE);
3038 pic16_emitcode("mov","%s,_spx",r->name);
3039 pic16_emitcode("movx","a,@%s",r->name);
3040 pic16_emitcode("mov","psw,a");
3041 pic16_emitcode("dec","%s",r->name);
3044 pic16_emitcode ("pop","psw");
3047 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3048 if (options.useXstack) {
3049 pic16_emitcode("movx","a,@%s",r->name);
3050 //pic16_emitcode("mov","(%s+%d),a",
3051 // regspic16[i].base,8*bank+regspic16[i].offset);
3052 pic16_emitcode("dec","%s",r->name);
3055 pic16_emitcode("pop",""); //"(%s+%d)",
3056 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3059 if (options.useXstack) {
3061 pic16_emitcode("mov","_spx,%s",r->name);
3062 pic16_freeAsmop(NULL,aop,ic,TRUE);
3068 /*-----------------------------------------------------------------*/
3069 /* saverbank - saves an entire register bank on the stack */
3070 /*-----------------------------------------------------------------*/
3071 static void saverbank (int bank, iCode *ic, bool pushPsw)
3073 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3079 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3080 if (options.useXstack) {
3083 r = getFreePtr(ic,&aop,FALSE);
3084 pic16_emitcode("mov","%s,_spx",r->name);
3088 for (i = 0 ; i < pic16_nRegs ;i++) {
3089 if (options.useXstack) {
3090 pic16_emitcode("inc","%s",r->name);
3091 //pic16_emitcode("mov","a,(%s+%d)",
3092 // regspic16[i].base,8*bank+regspic16[i].offset);
3093 pic16_emitcode("movx","@%s,a",r->name);
3095 pic16_emitcode("push","");// "(%s+%d)",
3096 //regspic16[i].base,8*bank+regspic16[i].offset);
3100 if (options.useXstack) {
3101 pic16_emitcode("mov","a,psw");
3102 pic16_emitcode("movx","@%s,a",r->name);
3103 pic16_emitcode("inc","%s",r->name);
3104 pic16_emitcode("mov","_spx,%s",r->name);
3105 pic16_freeAsmop (NULL,aop,ic,TRUE);
3108 pic16_emitcode("push","psw");
3110 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3118 static int wparamCmp(void *p1, void *p2)
3120 return (!strcmp((char *)p1, (char *)p2));
3123 int inWparamList(char *s)
3125 return isinSetWith(wparamList, s, wparamCmp);
3129 /*-----------------------------------------------------------------*/
3130 /* genCall - generates a call statement */
3131 /*-----------------------------------------------------------------*/
3132 static void genCall (iCode *ic)
3142 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3143 /* if caller saves & we have not saved then */
3144 // if (!ic->regsSaved)
3145 // saveRegisters(ic);
3147 /* initialise stackParms for IPUSH pushes */
3148 // stackParms = psuedoStkPtr;
3149 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3150 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3151 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3154 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3157 /* if send set is not empty the assign */
3160 int psuedoStkPtr=-1;
3161 int firstTimeThruLoop = 1;
3164 /* reverse sendSet if function is not reentrant */
3165 if(!IFFUNC_ISREENT(ftype))
3166 _G.sendSet = reverseSet(_G.sendSet);
3168 /* First figure how many parameters are getting passed */
3172 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3176 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3177 size = AOP_SIZE(IC_LEFT(sic));
3181 /* pass the last byte through WREG */
3185 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3186 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3187 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3189 if(!firstTimeThruLoop) {
3190 /* If this is not the first time we've been through the loop
3191 * then we need to save the parameter in a temporary
3192 * register. The last byte of the last parameter is
3196 // --psuedoStkPtr; // sanity check
3200 firstTimeThruLoop=0;
3202 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3207 /* all arguments are passed via stack */
3211 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3212 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3213 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3215 // pushaop(AOP(IC_LEFT(sic)), size);
3216 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3221 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3225 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3226 pushw(); /* save last parameter to stack if functions has varargs */
3230 } else use_wreg = 0;
3232 _G.stackRegSet = _G.sendSet;
3237 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3241 /* if we need to assign a result value */
3242 if ((IS_ITEMP(IC_RESULT(ic))
3243 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3244 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3245 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3248 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3251 assignResultValue(IC_RESULT(ic), 1);
3253 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3254 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3256 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3259 if(!stackParms && ic->parmBytes) {
3260 stackParms = ic->parmBytes;
3263 stackParms -= use_wreg;
3266 if(stackParms == 1) {
3267 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3269 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3270 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3272 if(STACK_MODEL_LARGE) {
3274 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3279 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3282 /* adjust the stack for parameters if required */
3283 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3286 /* if register bank was saved then pop them */
3288 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3290 /* if we hade saved some registers then unsave them */
3291 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3292 unsaveRegisters (ic);
3298 /*-----------------------------------------------------------------*/
3299 /* genPcall - generates a call by pointer statement */
3300 /* new version, created from genCall - HJD */
3301 /*-----------------------------------------------------------------*/
3302 static void genPcall (iCode *ic)
3304 sym_link *ftype, *fntype;
3306 symbol *retlbl = newiTempLabel(NULL);
3307 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3311 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3312 fntype = operandType( IC_LEFT(ic) )->next;
3314 /* if send set is not empty the assign */
3317 int psuedoStkPtr=-1;
3319 /* reverse sendSet if function is not reentrant */
3320 if(!IFFUNC_ISREENT(fntype))
3321 _G.sendSet = reverseSet(_G.sendSet);
3325 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3328 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329 size = AOP_SIZE(IC_LEFT(sic));
3332 /* all parameters are passed via stack, since WREG is clobbered
3333 * by the calling sequence */
3335 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3336 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3337 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3339 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3343 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3346 _G.stackRegSet = _G.sendSet;
3350 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3352 // push return address
3353 // push $ on return stack, then replace with retlbl
3355 pic16_emitpcodeNULLop(POC_PUSH);
3357 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3358 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3359 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3360 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3361 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3362 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3364 /* make the call by writing the pointer into pc */
3365 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3366 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3368 // note: MOVFF to PCL not allowed
3369 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3370 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3373 /* return address is here: (X) */
3374 pic16_emitpLabelFORCE(retlbl->key);
3376 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3379 /* if we need assign a result value */
3380 if ((IS_ITEMP(IC_RESULT(ic))
3381 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3382 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3383 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3386 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3389 assignResultValue(IC_RESULT(ic), 1);
3391 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3392 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3394 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3397 // stackParms -= use_wreg;
3400 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3401 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3402 if(STACK_MODEL_LARGE) {
3403 /* this implies that stackParms < 256 !!! -- VR */
3405 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3410 /*-----------------------------------------------------------------*/
3411 /* resultRemat - result is rematerializable */
3412 /*-----------------------------------------------------------------*/
3413 static int resultRemat (iCode *ic)
3415 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3416 if (SKIP_IC(ic) || ic->op == IFX)
3419 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3420 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3421 if (sym->remat && !POINTER_SET(ic))
3428 #if defined(__BORLANDC__) || defined(_MSC_VER)
3429 #define STRCASECMP stricmp
3431 #define STRCASECMP strcasecmp
3435 /*-----------------------------------------------------------------*/
3436 /* inExcludeList - return 1 if the string is in exclude Reg list */
3437 /*-----------------------------------------------------------------*/
3438 static bool inExcludeList(char *s)
3440 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3444 if (options.excludeRegs[i] &&
3445 STRCASECMP(options.excludeRegs[i],"none") == 0)
3448 for ( i = 0 ; options.excludeRegs[i]; i++) {
3449 if (options.excludeRegs[i] &&
3450 STRCASECMP(s,options.excludeRegs[i]) == 0)
3457 /*-----------------------------------------------------------------*/
3458 /* genFunction - generated code for function entry */
3459 /*-----------------------------------------------------------------*/
3460 static void genFunction (iCode *ic)
3466 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3468 pic16_labelOffset += (max_key+4);
3473 ftype = operandType(IC_LEFT(ic));
3474 sym = OP_SYMBOL(IC_LEFT(ic));
3476 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3477 /* create an absolute section at the interrupt vector:
3478 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3486 sym = OP_SYMBOL( IC_LEFT(ic));
3488 if(interrupts[i]->name
3489 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3496 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3497 __FILE__, __LINE__, sym->name);
3500 _G.interruptvector = found;
3503 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3504 asym = newSymbol(asymname, 0);
3506 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3507 pic16_addpBlock( apb );
3509 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3510 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3511 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3513 /* mark the end of this tiny function */
3514 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3519 abSym = Safe_calloc(1, sizeof(absSym));
3520 strcpy(abSym->name, asymname);
3522 switch( _G.interruptvector ) {
3523 case 0: abSym->address = 0x000000; break;
3524 case 1: abSym->address = 0x000008; break;
3525 case 2: abSym->address = 0x000018; break;
3528 /* relocate interrupt vectors if needed */
3529 abSym->address += pic16_options.ivt_loc;
3531 addSet(&absSymSet, abSym);
3535 /* create the function header */
3536 pic16_emitcode(";","-----------------------------------------");
3537 pic16_emitcode(";"," function %s",sym->name);
3538 pic16_emitcode(";","-----------------------------------------");
3540 pic16_emitcode("","%s:",sym->rname);
3541 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3547 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3548 if(!strcmp(ab->name, sym->rname)) {
3549 pic16_pBlockConvert2Absolute(pb);
3556 if(IFFUNC_ISNAKED(ftype)) {
3557 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3561 /* if critical function then turn interrupts off */
3562 if (IFFUNC_ISCRITICAL(ftype)) {
3563 //pic16_emitcode("clr","ea");
3566 _G.fregsUsed = sym->regsUsed;
3568 /* if this is an interrupt service routine then
3569 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3570 if (IFFUNC_ISISR(sym->type)) {
3571 _G.usefastretfie = 1; /* use shadow registers by default */
3573 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3574 if(!(_G.interruptvector == 1)) {
3575 /* do not save WREG,STATUS,BSR for high priority interrupts
3576 * because they are stored in the hardware shadow registers already */
3577 _G.usefastretfie = 0;
3578 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3579 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3580 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3583 /* these should really be optimized somehow, because not all
3584 * interrupt handlers modify them */
3585 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3586 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3587 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3588 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3590 // pic16_pBlockConvert2ISR(pb);
3594 /* emit code to setup stack frame if user enabled,
3595 * and function is not main() */
3597 //fprintf(stderr, "function name: %s\n", sym->name);
3598 if(strcmp(sym->name, "main")) {
3599 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3600 /* setup the stack frame */
3601 if(STACK_MODEL_LARGE)
3602 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3603 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3604 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3605 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3606 if(STACK_MODEL_LARGE)
3607 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3611 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3614 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3616 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3617 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3619 pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3622 if(inWparamList(sym->name)) {
3623 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3630 /* if callee-save to be used for this function
3631 * then save the registers being used in this function */
3632 // if (IFFUNC_CALLEESAVES(sym->type))
3636 /* if any registers used */
3637 if (sym->regsUsed) {
3638 /* save the registers used */
3639 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3640 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3641 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3642 if (bitVectBitValue(sym->regsUsed,i)) {
3643 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3646 if(!pic16_regWithIdx(i)->wasUsed) {
3647 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3648 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3649 pic16_regWithIdx(i)->wasUsed = 1;
3653 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3657 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3658 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3661 /*-----------------------------------------------------------------*/
3662 /* genEndFunction - generates epilogue for functions */
3663 /*-----------------------------------------------------------------*/
3664 static void genEndFunction (iCode *ic)
3666 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3670 if(IFFUNC_ISNAKED(sym->type)) {
3671 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3677 /* add code for ISCRITICAL */
3678 if(IFFUNC_ISCRITICAL(sym->type)) {
3679 /* if critical function, turn on interrupts */
3681 /* TODO: add code here -- VR */
3684 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3686 if (sym->stack == 1) {
3687 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
3688 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3690 // we have to add more than one...
3691 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
3692 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3693 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3695 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3696 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3697 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
3701 // sym->regsUsed = _G.fregsUsed;
3703 /* now we need to restore the registers */
3704 /* if any registers used */
3705 if (sym->regsUsed) {
3708 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3709 /* restore registers used */
3710 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3711 for ( i = sym->regsUsed->size; i >= 0; i--) {
3712 if (bitVectBitValue(sym->regsUsed,i)) {
3713 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3717 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3721 if(strcmp(sym->name, "main")) {
3722 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3723 /* restore stack frame */
3724 if(STACK_MODEL_LARGE)
3725 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3726 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3727 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3728 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3734 if (IFFUNC_ISISR(sym->type)) {
3735 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3736 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3737 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3738 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3740 if(!(_G.interruptvector == 1)) {
3741 /* do not restore interrupt vector for WREG,STATUS,BSR
3742 * for high priority interrupt, see genFunction */
3743 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3744 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3745 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3747 _G.interruptvector = 0; /* sanity check */
3750 /* if debug then send end of function */
3751 /* if (options.debug && currFunc) */
3753 debugFile->writeEndFunction (currFunc, ic, 1);
3756 if(_G.usefastretfie)
3757 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3759 pic16_emitpcodeNULLop(POC_RETFIE);
3761 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3763 _G.usefastretfie = 0;
3767 if (IFFUNC_ISCRITICAL(sym->type)) {
3768 pic16_emitcode("setb","ea");
3771 /* if debug then send end of function */
3773 debugFile->writeEndFunction (currFunc, ic, 1);
3776 /* insert code to restore stack frame, if user enabled it
3777 * and function is not main() */
3780 pic16_emitpcodeNULLop(POC_RETURN);
3782 /* Mark the end of a function */
3783 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3787 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3790 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3792 pic16_emitpcode(POC_CLRF, dest);
3794 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3795 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3798 if(dest->type == PO_WREG && (offset == 0)) {
3799 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3802 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3806 /*-----------------------------------------------------------------*/
3807 /* genRet - generate code for return statement */
3808 /*-----------------------------------------------------------------*/
3809 static void genRet (iCode *ic)
3815 /* if we have no return value then
3816 * just generate the "ret" */
3821 /* we have something to return then
3822 * move the return value into place */
3823 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3824 size = AOP_SIZE(IC_LEFT(ic));
3828 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3829 // pic16_emitpcode(POC_MOVFF,
3830 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3833 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3834 // pic16_emitpcode(POC_MOVFF,
3835 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3838 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3839 // pic16_emitpcode(POC_MOVFF,
3840 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3843 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3845 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3846 // pic16_emitpcode(POC_MOVFF,
3847 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3850 /* >32-bits, setup stack and FSR0 */
3852 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3853 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3855 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3857 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3862 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3863 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3865 if(STACK_MODEL_LARGE) {
3866 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3867 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3869 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3874 /* old code, left here for reference -- VR */
3878 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3880 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3881 pic16_emitpcomment("push %s",l);
3884 DEBUGpic16_emitcode(";", "%d", __LINE__);
3885 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3886 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3888 if (strcmp(fReturn[offset],l)) {
3889 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3890 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3891 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3897 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3907 if (strcmp(fReturn[pushed],"a"))
3908 pic16_emitcode("pop",fReturn[pushed]);
3910 pic16_emitcode("pop","acc");
3916 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3919 /* generate a jump to the return label
3920 * if the next is not the return statement */
3921 if (!(ic->next && ic->next->op == LABEL
3922 && IC_LABEL(ic->next) == returnLabel)) {
3924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3925 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3929 /*-----------------------------------------------------------------*/
3930 /* genLabel - generates a label */
3931 /*-----------------------------------------------------------------*/
3932 static void genLabel (iCode *ic)
3936 /* special case never generate */
3937 if (IC_LABEL(ic) == entryLabel)
3940 pic16_emitpLabel(IC_LABEL(ic)->key);
3941 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3944 /*-----------------------------------------------------------------*/
3945 /* genGoto - generates a goto */
3946 /*-----------------------------------------------------------------*/
3948 static void genGoto (iCode *ic)
3951 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3952 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3956 /*-----------------------------------------------------------------*/
3957 /* genMultbits :- multiplication of bits */
3958 /*-----------------------------------------------------------------*/
3959 static void genMultbits (operand *left,
3965 if(!pic16_sameRegs(AOP(result),AOP(right)))
3966 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3968 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3969 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3970 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3975 /*-----------------------------------------------------------------*/
3976 /* genMultOneByte : 8 bit multiplication & division */
3977 /*-----------------------------------------------------------------*/
3978 static void genMultOneByte (operand *left,
3984 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3985 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3987 /* (if two literals, the value is computed before) */
3988 /* if one literal, literal on the right */
3989 if (AOP_TYPE(left) == AOP_LIT){
3995 /* size is already checked in genMult == 1 */
3996 // size = AOP_SIZE(result);
3998 if (AOP_TYPE(right) == AOP_LIT){
3999 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4000 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4001 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4002 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4004 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4005 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4006 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4007 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4010 pic16_genMult8X8_8 (left, right,result);
4013 /*-----------------------------------------------------------------*/
4014 /* genMultOneWord : 16 bit multiplication */
4015 /*-----------------------------------------------------------------*/
4016 static void genMultOneWord (operand *left,
4021 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4022 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4024 /* (if two literals, the value is computed before)
4025 * if one literal, literal on the right */
4026 if (AOP_TYPE(left) == AOP_LIT){
4032 /* size is checked already == 2 */
4033 // size = AOP_SIZE(result);
4035 if (AOP_TYPE(right) == AOP_LIT) {
4036 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4037 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4038 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4039 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4041 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4042 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4043 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4044 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4047 pic16_genMult16X16_16(left, right,result);
4050 /*-----------------------------------------------------------------*/
4051 /* genMultOneLong : 32 bit multiplication */
4052 /*-----------------------------------------------------------------*/
4053 static void genMultOneLong (operand *left,
4058 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4059 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4061 /* (if two literals, the value is computed before)
4062 * if one literal, literal on the right */
4063 if (AOP_TYPE(left) == AOP_LIT){
4069 /* size is checked already == 4 */
4070 // size = AOP_SIZE(result);
4072 if (AOP_TYPE(right) == AOP_LIT) {
4073 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4074 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4075 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4076 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4078 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4079 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4080 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4081 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4084 pic16_genMult32X32_32(left, right,result);
4089 /*-----------------------------------------------------------------*/
4090 /* genMult - generates code for multiplication */
4091 /*-----------------------------------------------------------------*/
4092 static void genMult (iCode *ic)
4094 operand *left = IC_LEFT(ic);
4095 operand *right = IC_RIGHT(ic);
4096 operand *result= IC_RESULT(ic);
4099 /* assign the amsops */
4100 pic16_aopOp (left,ic,FALSE);
4101 pic16_aopOp (right,ic,FALSE);
4102 pic16_aopOp (result,ic,TRUE);
4104 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4106 /* special cases first *
4108 if (AOP_TYPE(left) == AOP_CRY
4109 && AOP_TYPE(right)== AOP_CRY) {
4110 genMultbits(left,right,result);
4114 /* if both are of size == 1 */
4115 if(AOP_SIZE(left) == 1
4116 && AOP_SIZE(right) == 1) {
4117 genMultOneByte(left,right,result);
4121 /* if both are of size == 2 */
4122 if(AOP_SIZE(left) == 2
4123 && AOP_SIZE(right) == 2) {
4124 genMultOneWord(left, right, result);
4128 /* if both are of size == 4 */
4129 if(AOP_SIZE(left) == 4
4130 && AOP_SIZE(right) == 4) {
4131 genMultOneLong(left, right, result);
4135 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4138 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4139 /* should have been converted to function call */
4143 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4144 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4145 pic16_freeAsmop(result,NULL,ic,TRUE);
4148 /*-----------------------------------------------------------------*/
4149 /* genDivbits :- division of bits */
4150 /*-----------------------------------------------------------------*/
4151 static void genDivbits (operand *left,
4158 /* the result must be bit */
4159 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4160 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4164 pic16_emitcode("div","ab");
4165 pic16_emitcode("rrc","a");
4166 pic16_aopPut(AOP(result),"c",0);
4169 /*-----------------------------------------------------------------*/
4170 /* genDivOneByte : 8 bit division */
4171 /*-----------------------------------------------------------------*/
4172 static void genDivOneByte (operand *left,
4176 sym_link *opetype = operandType(result);
4181 /* result = divident / divisor
4182 * - divident may be a register or a literal,
4183 * - divisor may be a register or a literal,
4184 * so there are 3 cases (literal / literal is optimized
4185 * by the front-end) to handle.
4186 * In addition we must handle signed and unsigned, which
4187 * result in 6 final different cases -- VR */
4191 size = AOP_SIZE(result) - 1;
4193 /* signed or unsigned */
4194 if (SPEC_USIGN(opetype)) {
4195 pCodeOp *pct1, /* count */
4198 symbol *label1, *label2, *label3;;
4201 /* unsigned is easy */
4203 pct1 = pic16_popGetTempReg(1);
4204 pct2 = pic16_popGetTempReg(1);
4205 pct3 = pic16_popGetTempReg(1);
4207 label1 = newiTempLabel(NULL);
4208 label2 = newiTempLabel(NULL);
4209 label3 = newiTempLabel(NULL);
4211 /* the following algorithm is extracted from divuint.c */
4213 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4214 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4216 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4220 pic16_emitpLabel(label1->key);
4223 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4227 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4231 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4233 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4234 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4236 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4237 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4238 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4240 pic16_emitpLabel( label3->key );
4241 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4242 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4246 pic16_emitpLabel(label2->key);
4247 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4248 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4249 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4251 /* result is in wreg */
4252 if(AOP_TYPE(result) != AOP_ACC)
4253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4255 pic16_popReleaseTempReg( pct3, 1);
4256 pic16_popReleaseTempReg( pct2, 1);
4257 pic16_popReleaseTempReg( pct1, 1);
4262 /* signed is a little bit more difficult */
4264 /* save the signs of the operands */
4265 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4267 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4268 pic16_emitcode("push","acc"); /* save it on the stack */
4270 /* now sign adjust for both left & right */
4271 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4273 lbl = newiTempLabel(NULL);
4274 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4275 pic16_emitcode("cpl","a");
4276 pic16_emitcode("inc","a");
4277 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4278 pic16_emitcode("mov","b,a");
4280 /* sign adjust left side */
4281 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4284 lbl = newiTempLabel(NULL);
4285 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4286 pic16_emitcode("cpl","a");
4287 pic16_emitcode("inc","a");
4288 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4290 /* now the division */
4291 pic16_emitcode("div","ab");
4292 /* we are interested in the lower order
4294 pic16_emitcode("mov","b,a");
4295 lbl = newiTempLabel(NULL);
4296 pic16_emitcode("pop","acc");
4297 /* if there was an over flow we don't
4298 adjust the sign of the result */
4299 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4300 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4302 pic16_emitcode("clr","a");
4303 pic16_emitcode("subb","a,b");
4304 pic16_emitcode("mov","b,a");
4305 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4307 /* now we are done */
4308 pic16_aopPut(AOP(result),"b",0);
4310 pic16_emitcode("mov","c,b.7");
4311 pic16_emitcode("subb","a,acc");
4314 pic16_aopPut(AOP(result),"a",offset++);
4318 /*-----------------------------------------------------------------*/
4319 /* genDiv - generates code for division */
4320 /*-----------------------------------------------------------------*/
4321 static void genDiv (iCode *ic)
4323 operand *left = IC_LEFT(ic);
4324 operand *right = IC_RIGHT(ic);
4325 operand *result= IC_RESULT(ic);
4328 /* Division is a very lengthy algorithm, so it is better
4329 * to call support routines than inlining algorithm.
4330 * Division functions written here just in case someone
4331 * wants to inline and not use the support libraries -- VR */
4335 /* assign the amsops */
4336 pic16_aopOp (left,ic,FALSE);
4337 pic16_aopOp (right,ic,FALSE);
4338 pic16_aopOp (result,ic,TRUE);
4340 /* special cases first */
4342 if (AOP_TYPE(left) == AOP_CRY &&
4343 AOP_TYPE(right)== AOP_CRY) {
4344 genDivbits(left,right,result);
4348 /* if both are of size == 1 */
4349 if (AOP_SIZE(left) == 1 &&
4350 AOP_SIZE(right) == 1 ) {
4351 genDivOneByte(left,right,result);
4355 /* should have been converted to function call */
4358 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4359 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360 pic16_freeAsmop(result,NULL,ic,TRUE);
4363 /*-----------------------------------------------------------------*/
4364 /* genModbits :- modulus of bits */
4365 /*-----------------------------------------------------------------*/
4366 static void genModbits (operand *left,
4374 werror(W_POSSBUG2, __FILE__, __LINE__);
4375 /* the result must be bit */
4376 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4377 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4381 pic16_emitcode("div","ab");
4382 pic16_emitcode("mov","a,b");
4383 pic16_emitcode("rrc","a");
4384 pic16_aopPut(AOP(result),"c",0);
4387 /*-----------------------------------------------------------------*/
4388 /* genModOneByte : 8 bit modulus */
4389 /*-----------------------------------------------------------------*/
4390 static void genModOneByte (operand *left,
4394 sym_link *opetype = operandType(result);
4399 werror(W_POSSBUG2, __FILE__, __LINE__);
4401 /* signed or unsigned */
4402 if (SPEC_USIGN(opetype)) {
4403 /* unsigned is easy */
4404 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4405 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4407 pic16_emitcode("div","ab");
4408 pic16_aopPut(AOP(result),"b",0);
4412 /* signed is a little bit more difficult */
4414 /* save the signs of the operands */
4415 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4418 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4419 pic16_emitcode("push","acc"); /* save it on the stack */
4421 /* now sign adjust for both left & right */
4422 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4425 lbl = newiTempLabel(NULL);
4426 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4427 pic16_emitcode("cpl","a");
4428 pic16_emitcode("inc","a");
4429 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4430 pic16_emitcode("mov","b,a");
4432 /* sign adjust left side */
4433 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4436 lbl = newiTempLabel(NULL);
4437 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4438 pic16_emitcode("cpl","a");
4439 pic16_emitcode("inc","a");
4440 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4442 /* now the multiplication */
4443 pic16_emitcode("div","ab");
4444 /* we are interested in the lower order
4446 lbl = newiTempLabel(NULL);
4447 pic16_emitcode("pop","acc");
4448 /* if there was an over flow we don't
4449 adjust the sign of the result */
4450 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4451 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4453 pic16_emitcode("clr","a");
4454 pic16_emitcode("subb","a,b");
4455 pic16_emitcode("mov","b,a");
4456 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4458 /* now we are done */
4459 pic16_aopPut(AOP(result),"b",0);
4463 /*-----------------------------------------------------------------*/
4464 /* genMod - generates code for division */
4465 /*-----------------------------------------------------------------*/
4466 static void genMod (iCode *ic)
4468 operand *left = IC_LEFT(ic);
4469 operand *right = IC_RIGHT(ic);
4470 operand *result= IC_RESULT(ic);
4474 /* assign the amsops */
4475 pic16_aopOp (left,ic,FALSE);
4476 pic16_aopOp (right,ic,FALSE);
4477 pic16_aopOp (result,ic,TRUE);
4479 /* special cases first */
4481 if (AOP_TYPE(left) == AOP_CRY &&
4482 AOP_TYPE(right)== AOP_CRY) {
4483 genModbits(left,right,result);
4487 /* if both are of size == 1 */
4488 if (AOP_SIZE(left) == 1 &&
4489 AOP_SIZE(right) == 1 ) {
4490 genModOneByte(left,right,result);
4494 /* should have been converted to function call */
4498 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4500 pic16_freeAsmop(result,NULL,ic,TRUE);
4503 /*-----------------------------------------------------------------*/
4504 /* genIfxJump :- will create a jump depending on the ifx */
4505 /*-----------------------------------------------------------------*/
4507 note: May need to add parameter to indicate when a variable is in bit space.
4509 static void genIfxJump (iCode *ic, char *jval)
4513 /* if true label then we jump if condition
4515 if ( IC_TRUE(ic) ) {
4517 if(strcmp(jval,"a") == 0)
4519 else if (strcmp(jval,"c") == 0)
4522 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4523 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4526 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4527 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4531 /* false label is present */
4532 if(strcmp(jval,"a") == 0)
4534 else if (strcmp(jval,"c") == 0)
4537 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4538 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4541 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4542 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4547 /* mark the icode as generated */
4554 /*-----------------------------------------------------------------*/
4556 /*-----------------------------------------------------------------*/
4557 static void genSkip(iCode *ifx,int status_bit)
4559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4563 if ( IC_TRUE(ifx) ) {
4564 switch(status_bit) {
4579 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4580 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4584 switch(status_bit) {
4598 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4599 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4606 /*-----------------------------------------------------------------*/
4608 /*-----------------------------------------------------------------*/
4609 static void genSkipc(resolvedIfx *rifx)
4611 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4621 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4622 rifx->generated = 1;
4625 /*-----------------------------------------------------------------*/
4627 /*-----------------------------------------------------------------*/
4628 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4630 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4635 if( (rifx->condition ^ invert_condition) & 1)
4640 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4641 rifx->generated = 1;
4645 /*-----------------------------------------------------------------*/
4647 /*-----------------------------------------------------------------*/
4648 static void genSkipz(iCode *ifx, int condition)
4659 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4661 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4664 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4666 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4671 /*-----------------------------------------------------------------*/
4673 /*-----------------------------------------------------------------*/
4674 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4680 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4682 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4685 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4686 rifx->generated = 1;
4690 /*-----------------------------------------------------------------*/
4691 /* genChkZeroes :- greater or less than comparison */
4692 /* For each byte in a literal that is zero, inclusive or the */
4693 /* the corresponding byte in the operand with W */
4694 /* returns true if any of the bytes are zero */
4695 /*-----------------------------------------------------------------*/
4696 static int genChkZeroes(operand *op, int lit, int size)
4703 i = (lit >> (size*8)) & 0xff;
4707 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4709 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4718 /*-----------------------------------------------------------------*/
4719 /* genCmp :- greater or less than comparison */
4720 /*-----------------------------------------------------------------*/
4724 static void genCmp (operand *left,operand *right,
4725 operand *result, iCode *ifx, int sign)
4727 int size; //, offset = 0 ;
4728 unsigned long lit = 0L,i = 0;
4729 resolvedIfx rFalseIfx;
4730 // resolvedIfx rTrueIfx;
4732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4735 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4736 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4742 resolveIfx(&rFalseIfx,ifx);
4743 truelbl = newiTempLabel(NULL);
4744 size = max(AOP_SIZE(left),AOP_SIZE(right));
4746 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4750 /* if literal is on the right then swap with left */
4751 if ((AOP_TYPE(right) == AOP_LIT)) {
4752 operand *tmp = right ;
4753 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4754 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4757 lit = (lit - 1) & mask;
4760 rFalseIfx.condition ^= 1;
4763 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4764 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4768 //if(IC_TRUE(ifx) == NULL)
4769 /* if left & right are bit variables */
4770 if (AOP_TYPE(left) == AOP_CRY &&
4771 AOP_TYPE(right) == AOP_CRY ) {
4772 assert (0 && "bit variables used in genCmp");
4773 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4774 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4776 /* subtract right from left if at the
4777 end the carry flag is set then we know that
4778 left is greater than right */
4780 symbol *lbl = newiTempLabel(NULL);
4783 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4784 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4788 if(AOP_TYPE(right) == AOP_LIT) {
4790 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4792 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4799 genSkipCond(&rFalseIfx,left,size-1,7);
4801 /* no need to compare to 0...*/
4802 /* NOTE: this is a de-generate compare that most certainly
4803 * creates some dead code. */
4804 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4806 if(ifx) ifx->generated = 1;
4813 //i = (lit >> (size*8)) & 0xff;
4814 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4816 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4818 i = ((0-lit) & 0xff);
4821 /* lit is 0x7f, all signed chars are less than
4822 * this except for 0x7f itself */
4823 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4824 genSkipz2(&rFalseIfx,0);
4826 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4827 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4828 genSkipc(&rFalseIfx);
4833 genSkipz2(&rFalseIfx,1);
4835 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4836 genSkipc(&rFalseIfx);
4840 if(ifx) ifx->generated = 1;
4844 /* chars are out of the way. now do ints and longs */
4847 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4854 genSkipCond(&rFalseIfx,left,size,7);
4855 if(ifx) ifx->generated = 1;
4860 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4862 //rFalseIfx.condition ^= 1;
4863 //genSkipCond(&rFalseIfx,left,size,7);
4864 //rFalseIfx.condition ^= 1;
4866 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4867 if(rFalseIfx.condition)
4868 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4870 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4872 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4873 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4874 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4877 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4879 if(rFalseIfx.condition) {
4881 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4887 genSkipc(&rFalseIfx);
4888 pic16_emitpLabel(truelbl->key);
4889 if(ifx) ifx->generated = 1;
4896 if( (lit & 0xff) == 0) {
4897 /* lower byte is zero */
4898 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4899 i = ((lit >> 8) & 0xff) ^0x80;
4900 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4901 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4902 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4903 genSkipc(&rFalseIfx);
4906 if(ifx) ifx->generated = 1;
4911 /* Special cases for signed longs */
4912 if( (lit & 0xffffff) == 0) {
4913 /* lower byte is zero */
4914 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4915 i = ((lit >> 8*3) & 0xff) ^0x80;
4916 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4917 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4918 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4919 genSkipc(&rFalseIfx);
4922 if(ifx) ifx->generated = 1;
4930 if(lit & (0x80 << (size*8))) {
4931 /* lit is negative */
4932 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4934 //genSkipCond(&rFalseIfx,left,size,7);
4936 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4938 if(rFalseIfx.condition)
4939 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4941 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4945 /* lit is positive */
4946 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4947 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4948 if(rFalseIfx.condition)
4949 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4951 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4956 This works, but is only good for ints.
4957 It also requires a "known zero" register.
4958 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4959 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4960 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4961 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4962 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4963 genSkipc(&rFalseIfx);
4965 pic16_emitpLabel(truelbl->key);
4966 if(ifx) ifx->generated = 1;
4970 /* There are no more special cases, so perform a general compare */
4972 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4973 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4977 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4979 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4981 //rFalseIfx.condition ^= 1;
4982 genSkipc(&rFalseIfx);
4984 pic16_emitpLabel(truelbl->key);
4986 if(ifx) ifx->generated = 1;
4993 /* sign is out of the way. So now do an unsigned compare */
4994 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4997 /* General case - compare to an unsigned literal on the right.*/
4999 i = (lit >> (size*8)) & 0xff;
5000 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5001 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5003 i = (lit >> (size*8)) & 0xff;
5006 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5008 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5010 /* this byte of the lit is zero,
5011 *if it's not the last then OR in the variable */
5013 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5018 pic16_emitpLabel(lbl->key);
5019 // pic16_emitpLabel(truelbl->key);
5020 //if(emitFinalCheck)
5021 genSkipc(&rFalseIfx);
5023 pic16_emitpLabel(truelbl->key);
5025 if(ifx) ifx->generated = 1;
5032 if(AOP_TYPE(left) == AOP_LIT) {
5033 //symbol *lbl = newiTempLabel(NULL);
5035 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5038 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5041 if((lit == 0) && (sign == 0)){
5044 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5046 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5048 genSkipz2(&rFalseIfx,0);
5049 if(ifx) ifx->generated = 1;
5056 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5057 /* degenerate compare can never be true */
5058 if(rFalseIfx.condition == 0)
5059 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5061 if(ifx) ifx->generated = 1;
5066 /* signed comparisons to a literal byte */
5068 int lp1 = (lit+1) & 0xff;
5070 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5073 rFalseIfx.condition ^= 1;
5074 genSkipCond(&rFalseIfx,right,0,7);
5077 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5078 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5079 genSkipz2(&rFalseIfx,1);
5082 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5083 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5084 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5085 rFalseIfx.condition ^= 1;
5086 genSkipc(&rFalseIfx);
5090 /* unsigned comparisons to a literal byte */
5092 switch(lit & 0xff ) {
5094 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5095 genSkipz2(&rFalseIfx,0);
5098 rFalseIfx.condition ^= 1;
5099 genSkipCond(&rFalseIfx,right,0,7);
5103 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5104 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5105 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5106 rFalseIfx.condition ^= 1;
5107 if (AOP_TYPE(result) == AOP_CRY)
5108 genSkipc(&rFalseIfx);
5110 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5111 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5117 if(ifx) ifx->generated = 1;
5118 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5124 /* Size is greater than 1 */
5132 /* this means lit = 0xffffffff, or -1 */
5135 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5136 rFalseIfx.condition ^= 1;
5137 genSkipCond(&rFalseIfx,right,size,7);
5138 if(ifx) ifx->generated = 1;
5140 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5149 if(rFalseIfx.condition) {
5150 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5151 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5154 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5156 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5160 if(rFalseIfx.condition) {
5161 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5162 pic16_emitpLabel(truelbl->key);
5164 rFalseIfx.condition ^= 1;
5165 genSkipCond(&rFalseIfx,right,s,7);
5168 if(ifx) ifx->generated = 1;
5170 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5176 if((size == 1) && (0 == (lp1&0xff))) {
5177 /* lower byte of signed word is zero */
5178 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5179 i = ((lp1 >> 8) & 0xff) ^0x80;
5180 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5181 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5182 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5184 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5186 if(ifx) ifx->generated = 1;
5189 rFalseIfx.condition ^= 1;
5190 genSkipc(&rFalseIfx);
5191 if(ifx) ifx->generated = 1;
5197 if(lit & (0x80 << (size*8))) {
5198 /* Lit is less than zero */
5199 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5200 //rFalseIfx.condition ^= 1;
5201 //genSkipCond(&rFalseIfx,left,size,7);
5202 //rFalseIfx.condition ^= 1;
5203 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5204 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5206 if(rFalseIfx.condition)
5207 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5209 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5213 /* Lit is greater than or equal to zero */
5214 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5215 //rFalseIfx.condition ^= 1;
5216 //genSkipCond(&rFalseIfx,right,size,7);
5217 //rFalseIfx.condition ^= 1;
5219 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5220 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5222 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5223 if(rFalseIfx.condition)
5224 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5226 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5230 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5231 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5235 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5237 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5239 rFalseIfx.condition ^= 1;
5240 //rFalseIfx.condition = 1;
5241 genSkipc(&rFalseIfx);
5243 pic16_emitpLabel(truelbl->key);
5245 if(ifx) ifx->generated = 1;
5248 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5255 /* compare word or long to an unsigned literal on the right.*/
5260 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5263 break; /* handled above */
5266 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5268 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5269 genSkipz2(&rFalseIfx,0);
5273 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5275 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5278 if(rFalseIfx.condition)
5279 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5281 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5284 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5285 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5287 rFalseIfx.condition ^= 1;
5288 genSkipc(&rFalseIfx);
5291 pic16_emitpLabel(truelbl->key);
5293 if(ifx) ifx->generated = 1;
5295 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5303 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5304 i = (lit >> (size*8)) & 0xff;
5306 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5307 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5310 i = (lit >> (size*8)) & 0xff;
5313 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5315 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5317 /* this byte of the lit is zero,
5318 * if it's not the last then OR in the variable */
5320 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5325 pic16_emitpLabel(lbl->key);
5327 rFalseIfx.condition ^= 1;
5329 genSkipc(&rFalseIfx);
5333 pic16_emitpLabel(truelbl->key);
5334 if(ifx) ifx->generated = 1;
5336 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5342 /* Compare two variables */
5344 DEBUGpic16_emitcode(";sign","%d",sign);
5348 /* Sigh. thus sucks... */
5352 pctemp = pic16_popGetTempReg(1);
5353 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5354 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5355 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5356 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5357 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5358 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5359 pic16_popReleaseTempReg(pctemp, 1);
5361 /* Signed char comparison */
5362 /* Special thanks to Nikolai Golovchenko for this snippet */
5363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5364 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5365 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5366 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5367 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5368 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5370 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5371 genSkipc(&rFalseIfx);
5373 if(ifx) ifx->generated = 1;
5375 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5383 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5384 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5388 /* The rest of the bytes of a multi-byte compare */
5392 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5395 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5396 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5401 pic16_emitpLabel(lbl->key);
5403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5404 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5405 (AOP_TYPE(result) == AOP_REG)) {
5406 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5407 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5409 genSkipc(&rFalseIfx);
5411 //genSkipc(&rFalseIfx);
5412 if(ifx) ifx->generated = 1;
5415 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5423 if ((AOP_TYPE(result) != AOP_CRY)
5424 && AOP_SIZE(result)) {
5425 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5427 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5429 pic16_outBitC(result);
5431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5432 /* if the result is used in the next
5433 ifx conditional branch then generate
5434 code a little differently */
5436 genIfxJump (ifx,"c");
5438 pic16_outBitC(result);
5439 /* leave the result in acc */
5444 #else /* old version of genCmp() */ /* } else { */
5446 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5447 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5448 operand *result, int offset, int invert_op)
5452 /* check condition, > or < ?? */
5453 if(rIfx->condition != 0)invert_op ^= 1;
5455 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5457 if(!ifx)invert_op ^= 1;
5459 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5460 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5463 if(!invert_op)return POC_CPFSGT;
5464 else return POC_CPFSLT;
5467 static int compareAopfirstpass=1;
5469 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5470 operand *oper, int offset, operand *result,
5471 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5477 /* invert if there is a result to be loaded, in order to fit,
5478 * SETC/CLRC sequence */
5479 if(AOP_SIZE(result))invert_op ^= 1;
5481 // if(sign && !offset)invert_op ^= 1;
5483 // if(sign)invert_op ^= 1;
5485 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5487 if(AOP_SIZE(result) && compareAopfirstpass) {
5490 pic16_emitpcode(POC_SETF, pcop2);
5495 pic16_emitpcode(POC_CLRF, pcop2);
5501 compareAopfirstpass = 0;
5503 /* there is a bug when comparing operands with size > 1,
5504 * because higher bytes can be equal and test should be performed
5505 * to the next lower byte, current algorithm, considers operands
5506 * inequal in these cases! -- VR 20041107 */
5510 pic16_emitpcode(op, pcop);
5512 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5515 if((!sign || !offset) && AOP_SIZE(result)) {
5518 pic16_emitpcode(POC_CLRF, pcop2);
5523 pic16_emitpcode(POC_SETF, pcop2);
5528 /* don't emit final branch (offset == 0) */
5532 pic16_emitpcode(POC_RRCF, pcop2);
5534 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5537 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5538 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5539 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5541 truelbl = newiTempLabel( NULL );
5542 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5543 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5544 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5546 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5547 pic16_emitpLabel(truelbl->key);
5549 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5558 static void genCmp (operand *left, operand *right,
5559 operand *result, iCode *ifx, int sign)
5563 resolvedIfx rFalseIfx;
5564 symbol *falselbl, *tlbl;
5568 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5570 resolveIfx(&rFalseIfx, ifx);
5571 size = max(AOP_SIZE(left), AOP_SIZE(right));
5573 /* if left & right are bit variables */
5574 if(AOP_TYPE(left) == AOP_CRY
5575 && AOP_TYPE(right) == AOP_CRY ) {
5577 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5578 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5580 werror(W_POSSBUG2, __FILE__, __LINE__);
5584 /* if literal is on the right then swap with left */
5585 if((AOP_TYPE(right) == AOP_LIT)) {
5586 operand *tmp = right ;
5587 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5589 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5591 // lit = (lit - 1) & mask;
5594 rFalseIfx.condition ^= 1; /* reverse compare */
5596 if ((AOP_TYPE(left) == AOP_LIT)) {
5597 /* float compares are handled by support functions */
5598 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5601 /* actual comparing algorithm */
5602 // size = AOP_SIZE( right );
5604 falselbl = newiTempLabel( NULL );
5605 if(AOP_TYPE(left) == AOP_LIT) {
5606 /* compare to literal */
5607 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5610 pCodeOp *pct, *pct2;
5613 /* signed compare */
5614 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5616 pct = pic16_popCopyReg(&pic16_pc_prodl);
5617 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5618 tlbl = newiTempLabel( NULL );
5620 /* first compare signs:
5621 * a. if both are positive, compare just like unsigned
5622 * b. if both are negative, invert cmpop, compare just like unsigned
5623 * c. if different signs, determine the result directly */
5629 tlbl1 = newiTempLabel( NULL );
5630 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5634 /* literal is zero or positive:
5635 * a. if carry is zero, too, continue compare,
5636 * b. if carry is set, then continue depending on cmpop ^ condition:
5637 * 1. '<' return false (literal < variable),
5638 * 2. '>' return true (literal > variable) */
5639 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5640 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5643 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5644 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5648 /* literal is negative:
5649 * a. if carry is set, too, continue compare,
5650 * b. if carry is zero, then continue depending on cmpop ^ condition:
5651 * 1. '<' return true (literal < variable),
5652 * 2. '>' return false (literal > variable) */
5653 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5654 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5656 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5657 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5662 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5664 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5665 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5670 pic16_emitpLabel( tlbl1->key );
5673 compareAopfirstpass=1;
5674 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5675 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5676 // pic16_emitpcode(POC_MOVWF, pct);
5678 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5679 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5680 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5681 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5685 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5686 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5687 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5688 // pic16_emitpcode(POC_MOVWF, pct);
5690 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5692 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5693 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5694 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5698 if(ifx)ifx->generated = 1;
5700 if(AOP_SIZE(result)) {
5701 pic16_emitpLabel(tlbl->key);
5702 pic16_emitpLabel(falselbl->key);
5703 pic16_outBitOp( result, pct2 );
5705 pic16_emitpLabel(tlbl->key);
5710 /* unsigned compare */
5711 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5713 compareAopfirstpass=1;
5716 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5717 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5721 if(ifx)ifx->generated = 1;
5724 if(AOP_SIZE(result)) {
5725 pic16_emitpLabel(falselbl->key);
5726 pic16_outBitC( result );
5731 /* compare registers */
5732 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5736 pCodeOp *pct, *pct2;
5738 /* signed compare */
5739 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5741 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
5742 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
5743 tlbl = newiTempLabel( NULL );
5745 compareAopfirstpass=1;
5748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5749 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5750 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5751 pic16_emitpcode(POC_MOVWF, pct);
5753 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5754 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5755 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5757 /* WREG already holds left + 0x80 */
5758 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5761 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5762 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5763 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5764 pic16_emitpcode(POC_MOVWF, pct);
5766 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5767 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5768 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5770 /* WREG already holds left + 0x80 */
5771 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5772 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5775 if(ifx)ifx->generated = 1;
5777 if(AOP_SIZE(result)) {
5778 pic16_emitpLabel(tlbl->key);
5779 pic16_emitpLabel(falselbl->key);
5780 pic16_outBitOp( result, pct2 );
5782 pic16_emitpLabel(tlbl->key);
5786 /* unsigned compare */
5787 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5789 compareAopfirstpass=1;
5792 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5793 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5797 if(ifx)ifx->generated = 1;
5798 if(AOP_SIZE(result)) {
5800 pic16_emitpLabel(falselbl->key);
5801 pic16_outBitC( result );
5808 #else /* } else { */
5810 /* new version of genCmp -- VR 20041012 */
5811 static void genCmp (operand *left,operand *right,
5812 operand *result, iCode *ifx, int sign)
5814 int size; //, offset = 0 ;
5815 unsigned long lit = 0L,i = 0;
5816 resolvedIfx rFalseIfx;
5817 int willCheckCarry=0;
5818 // resolvedIfx rTrueIfx;
5824 * subtract right from left if at the end the carry flag is set then we
5825 * know that left is greater than right */
5827 resolveIfx(&rFalseIfx,ifx);
5828 truelbl = newiTempLabel(NULL);
5829 size = max(AOP_SIZE(left),AOP_SIZE(right));
5831 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5833 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5834 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5837 /* if literal is on the right then swap with left */
5838 if ((AOP_TYPE(right) == AOP_LIT)) {
5839 operand *tmp = right ;
5840 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5842 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5844 // lit = (lit - 1) & mask;
5847 rFalseIfx.condition ^= 1; /* reverse compare */
5849 if ((AOP_TYPE(left) == AOP_LIT)) {
5850 /* float compares are handled by support functions */
5851 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5855 //if(IC_TRUE(ifx) == NULL)
5856 /* if left & right are bit variables */
5857 if (AOP_TYPE(left) == AOP_CRY &&
5858 AOP_TYPE(right) == AOP_CRY ) {
5860 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5861 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5864 symbol *lbl = newiTempLabel(NULL);
5866 if(AOP_TYPE(left) == AOP_LIT) {
5867 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5869 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5871 else willCheckCarry = 0;
5874 if((lit == 0) && (sign == 0)) {
5875 /* unsigned compare to 0 */
5876 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5879 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5881 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5883 genSkipz2(&rFalseIfx,0);
5884 if(ifx)ifx->generated = 1;
5891 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5892 /* degenerate compare can never be true */
5893 if(rFalseIfx.condition == 0)
5894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5896 if(ifx) ifx->generated = 1;
5901 /* signed comparisons to a literal byte */
5902 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5904 int lp1 = (lit+1) & 0xff;
5906 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5909 rFalseIfx.condition ^= 1;
5910 genSkipCond(&rFalseIfx,right,0,7);
5913 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5914 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5915 genSkipz2(&rFalseIfx,1);
5918 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5920 if(rFalseIfx.condition)
5921 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5923 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5925 if(willCheckCarry) {
5926 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5927 else { emitSETC; emitCLRC; }
5930 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5933 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5934 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5935 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5936 rFalseIfx.condition ^= 1;
5937 genSkipc(&rFalseIfx);
5942 /* unsigned comparisons to a literal byte */
5943 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5945 switch(lit & 0xff ) {
5948 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5949 genSkipz2(&rFalseIfx,0);
5952 rFalseIfx.condition ^= 1;
5953 genSkipCond(&rFalseIfx,right,0,7);
5956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5957 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5958 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5959 rFalseIfx.condition ^= 1;
5960 if (AOP_TYPE(result) == AOP_CRY)
5961 genSkipc(&rFalseIfx);
5963 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5964 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5970 if(ifx) ifx->generated = 1;
5971 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5977 /* Size is greater than 1 */
5985 /* this means lit = 0xffffffff, or -1 */
5988 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5989 rFalseIfx.condition ^= 1;
5990 genSkipCond(&rFalseIfx,right,size,7);
5991 if(ifx) ifx->generated = 1;
5998 if(rFalseIfx.condition) {
5999 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6000 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6003 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6005 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6009 if(rFalseIfx.condition) {
6010 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6011 pic16_emitpLabel(truelbl->key);
6013 rFalseIfx.condition ^= 1;
6014 genSkipCond(&rFalseIfx,right,s,7);
6017 if(ifx) ifx->generated = 1;
6021 if((size == 1) && (0 == (lp1&0xff))) {
6022 /* lower byte of signed word is zero */
6023 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6024 i = ((lp1 >> 8) & 0xff) ^0x80;
6025 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6026 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6027 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6028 rFalseIfx.condition ^= 1;
6029 genSkipc(&rFalseIfx);
6032 if(ifx) ifx->generated = 1;
6036 if(lit & (0x80 << (size*8))) {
6037 /* Lit is less than zero */
6038 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6039 //rFalseIfx.condition ^= 1;
6040 //genSkipCond(&rFalseIfx,left,size,7);
6041 //rFalseIfx.condition ^= 1;
6042 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6043 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6045 if(rFalseIfx.condition)
6046 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6048 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6052 /* Lit is greater than or equal to zero */
6053 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6054 //rFalseIfx.condition ^= 1;
6055 //genSkipCond(&rFalseIfx,right,size,7);
6056 //rFalseIfx.condition ^= 1;
6058 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6059 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6061 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6062 if(rFalseIfx.condition)
6063 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6065 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6071 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6075 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6077 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6079 rFalseIfx.condition ^= 1;
6080 //rFalseIfx.condition = 1;
6081 genSkipc(&rFalseIfx);
6083 pic16_emitpLabel(truelbl->key);
6085 if(ifx) ifx->generated = 1;
6090 /* compare word or long to an unsigned literal on the right.*/
6095 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6098 break; /* handled above */
6101 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6103 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6104 genSkipz2(&rFalseIfx,0);
6108 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6110 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6113 if(rFalseIfx.condition)
6114 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6116 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6119 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6120 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6122 rFalseIfx.condition ^= 1;
6123 genSkipc(&rFalseIfx);
6126 pic16_emitpLabel(truelbl->key);
6128 if(ifx) ifx->generated = 1;
6134 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6135 i = (lit >> (size*8)) & 0xff;
6137 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6138 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6141 i = (lit >> (size*8)) & 0xff;
6144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6146 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6148 /* this byte of the lit is zero,
6149 * if it's not the last then OR in the variable */
6151 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6156 pic16_emitpLabel(lbl->key);
6158 rFalseIfx.condition ^= 1;
6160 genSkipc(&rFalseIfx);
6164 pic16_emitpLabel(truelbl->key);
6165 if(ifx) ifx->generated = 1;
6169 /* Compare two variables */
6171 DEBUGpic16_emitcode(";sign","%d",sign);
6175 /* Sigh. thus sucks... */
6179 pctemp = pic16_popGetTempReg(1);
6180 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6181 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6182 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6183 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6184 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6185 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6186 pic16_popReleaseTempReg(pctemp, 1);
6188 /* Signed char comparison */
6189 /* Special thanks to Nikolai Golovchenko for this snippet */
6190 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6191 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6192 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6193 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6194 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6195 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6198 genSkipc(&rFalseIfx);
6200 if(ifx) ifx->generated = 1;
6206 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6207 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6211 /* The rest of the bytes of a multi-byte compare */
6215 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6219 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6224 pic16_emitpLabel(lbl->key);
6226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6227 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6228 (AOP_TYPE(result) == AOP_REG)) {
6229 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6230 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6232 genSkipc(&rFalseIfx);
6234 //genSkipc(&rFalseIfx);
6235 if(ifx) ifx->generated = 1;
6242 if ((AOP_TYPE(result) != AOP_CRY)
6243 && AOP_SIZE(result)) {
6244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6246 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6248 pic16_outBitC(result);
6250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6251 /* if the result is used in the next
6252 ifx conditional branch then generate
6253 code a little differently */
6255 genIfxJump (ifx,"c");
6257 pic16_outBitC(result);
6258 /* leave the result in acc */
6269 /*-----------------------------------------------------------------*/
6270 /* genCmpGt :- greater than comparison */
6271 /*-----------------------------------------------------------------*/
6272 static void genCmpGt (iCode *ic, iCode *ifx)
6274 operand *left, *right, *result;
6275 sym_link *letype , *retype;
6281 right= IC_RIGHT(ic);
6282 result = IC_RESULT(ic);
6284 letype = getSpec(operandType(left));
6285 retype =getSpec(operandType(right));
6286 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6287 /* assign the amsops */
6288 pic16_aopOp (left,ic,FALSE);
6289 pic16_aopOp (right,ic,FALSE);
6290 pic16_aopOp (result,ic,TRUE);
6292 genCmp(right, left, result, ifx, sign);
6294 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296 pic16_freeAsmop(result,NULL,ic,TRUE);
6299 /*-----------------------------------------------------------------*/
6300 /* genCmpLt - less than comparisons */
6301 /*-----------------------------------------------------------------*/
6302 static void genCmpLt (iCode *ic, iCode *ifx)
6304 operand *left, *right, *result;
6305 sym_link *letype , *retype;
6311 right= IC_RIGHT(ic);
6312 result = IC_RESULT(ic);
6314 letype = getSpec(operandType(left));
6315 retype =getSpec(operandType(right));
6316 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6318 /* assign the amsops */
6319 pic16_aopOp (left,ic,FALSE);
6320 pic16_aopOp (right,ic,FALSE);
6321 pic16_aopOp (result,ic,TRUE);
6323 genCmp(left, right, result, ifx, sign);
6325 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6327 pic16_freeAsmop(result,NULL,ic,TRUE);
6332 // FIXME reenable literal optimisation when the pic16 port is stable
6334 /*-----------------------------------------------------------------*/
6335 /* genc16bit2lit - compare a 16 bit value to a literal */
6336 /*-----------------------------------------------------------------*/
6337 static void genc16bit2lit(operand *op, int lit, int offset)
6341 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6342 if( (lit&0xff) == 0)
6347 switch( BYTEofLONG(lit,i)) {
6349 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6352 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6355 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6358 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6364 switch( BYTEofLONG(lit,i)) {
6366 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6370 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6374 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6377 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6379 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6388 /*-----------------------------------------------------------------*/
6389 /* gencjneshort - compare and jump if not equal */
6390 /*-----------------------------------------------------------------*/
6391 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6393 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6395 int res_offset = 0; /* the result may be a different size then left or right */
6396 int res_size = AOP_SIZE(result);
6398 symbol *lbl, *lbl_done;
6400 unsigned long lit = 0L;
6401 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6404 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6406 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6407 resolveIfx(&rIfx,ifx);
6408 lbl = newiTempLabel(NULL);
6409 lbl_done = newiTempLabel(NULL);
6412 /* if the left side is a literal or
6413 if the right is in a pointer register and left
6415 if ((AOP_TYPE(left) == AOP_LIT) ||
6416 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6421 if(AOP_TYPE(right) == AOP_LIT)
6422 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6424 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6425 preserve_result = 1;
6427 if(result && !preserve_result)
6430 for(i = 0; i < AOP_SIZE(result); i++)
6431 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6435 /* if the right side is a literal then anything goes */
6436 if (AOP_TYPE(right) == AOP_LIT &&
6437 AOP_TYPE(left) != AOP_DIR ) {
6440 genc16bit2lit(left, lit, 0);
6442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6448 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6451 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6457 if(res_offset < res_size-1)
6465 /* if the right side is in a register or in direct space or
6466 if the left is a pointer register & right is not */
6467 else if (AOP_TYPE(right) == AOP_REG ||
6468 AOP_TYPE(right) == AOP_DIR ||
6469 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6470 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6471 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6472 int lbl_key = lbl->key;
6475 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6476 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6478 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6479 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6480 __FUNCTION__,__LINE__);
6484 /* switch(size) { */
6486 /* genc16bit2lit(left, lit, 0); */
6488 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6493 if((AOP_TYPE(left) == AOP_DIR) &&
6494 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6496 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6499 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6501 switch (lit & 0xff) {
6503 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6507 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6512 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6519 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6525 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6528 if(AOP_TYPE(result) == AOP_CRY) {
6529 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6534 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6536 /* fix me. probably need to check result size too */
6537 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6542 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6543 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6550 if(res_offset < res_size-1)
6555 } else if(AOP_TYPE(right) == AOP_REG &&
6556 AOP_TYPE(left) != AOP_DIR){
6559 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6560 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6561 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6566 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6568 if(res_offset < res_size-1)
6573 /* right is a pointer reg need both a & b */
6575 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6577 pic16_emitcode("mov","b,%s",l);
6578 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6579 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6584 if(result && preserve_result)
6587 for(i = 0; i < AOP_SIZE(result); i++)
6588 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6591 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6593 if(result && preserve_result)
6594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6599 pic16_emitpLabel(lbl->key);
6601 if(result && preserve_result)
6604 for(i = 0; i < AOP_SIZE(result); i++)
6605 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6607 pic16_emitpLabel(lbl_done->key);
6610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6618 /*-----------------------------------------------------------------*/
6619 /* gencjne - compare and jump if not equal */
6620 /*-----------------------------------------------------------------*/
6621 static void gencjne(operand *left, operand *right, iCode *ifx)
6623 symbol *tlbl = newiTempLabel(NULL);
6625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6626 gencjneshort(left, right, lbl);
6628 pic16_emitcode("mov","a,%s",one);
6629 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6630 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6631 pic16_emitcode("clr","a");
6632 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6634 pic16_emitpLabel(lbl->key);
6635 pic16_emitpLabel(tlbl->key);
6641 /*-----------------------------------------------------------------*/
6642 /* is_LitOp - check if operand has to be treated as literal */
6643 /*-----------------------------------------------------------------*/
6644 static bool is_LitOp(operand *op)
6646 return ((AOP_TYPE(op) == AOP_LIT)
6647 || ( (AOP_TYPE(op) == AOP_PCODE)
6648 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6649 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6652 /*-----------------------------------------------------------------*/
6653 /* is_LitAOp - check if operand has to be treated as literal */
6654 /*-----------------------------------------------------------------*/
6655 static bool is_LitAOp(asmop *aop)
6657 return ((aop->type == AOP_LIT)
6658 || ( (aop->type == AOP_PCODE)
6659 && ( (aop->aopu.pcop->type == PO_LITERAL)
6660 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6665 /*-----------------------------------------------------------------*/
6666 /* genCmpEq - generates code for equal to */
6667 /*-----------------------------------------------------------------*/
6668 static void genCmpEq (iCode *ic, iCode *ifx)
6670 operand *left, *right, *result;
6671 symbol *falselbl = newiTempLabel(NULL);
6672 symbol *donelbl = newiTempLabel(NULL);
6674 int preserve_result = 0;
6675 int generate_result = 0;
6680 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6681 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6682 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6684 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6686 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6688 werror(W_POSSBUG2, __FILE__, __LINE__);
6689 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6690 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6694 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6696 operand *tmp = right ;
6701 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6702 preserve_result = 1;
6704 if(result && AOP_SIZE(result))
6705 generate_result = 1;
6707 if(generate_result && !preserve_result)
6709 for(i = 0; i < AOP_SIZE(result); i++)
6710 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6713 for(i=0; i < AOP_SIZE(left); i++)
6715 if(AOP_TYPE(left) != AOP_ACC)
6718 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6720 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6723 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6725 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6727 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6732 if(generate_result && preserve_result)
6734 for(i = 0; i < AOP_SIZE(result); i++)
6735 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6739 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6741 if(generate_result && preserve_result)
6742 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6744 if(ifx && IC_TRUE(ifx))
6745 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6747 if(ifx && IC_FALSE(ifx))
6748 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6750 pic16_emitpLabel(falselbl->key);
6754 if(ifx && IC_FALSE(ifx))
6755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6757 if(generate_result && preserve_result)
6759 for(i = 0; i < AOP_SIZE(result); i++)
6760 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6763 pic16_emitpLabel(donelbl->key);
6769 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6770 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6771 pic16_freeAsmop(result,NULL,ic,TRUE);
6777 // old version kept for reference
6779 /*-----------------------------------------------------------------*/
6780 /* genCmpEq - generates code for equal to */
6781 /*-----------------------------------------------------------------*/
6782 static void genCmpEq (iCode *ic, iCode *ifx)
6784 operand *left, *right, *result;
6785 unsigned long lit = 0L;
6787 symbol *falselbl = newiTempLabel(NULL);
6790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6793 DEBUGpic16_emitcode ("; ifx is non-null","");
6795 DEBUGpic16_emitcode ("; ifx is null","");
6797 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6798 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6799 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6801 size = max(AOP_SIZE(left),AOP_SIZE(right));
6803 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6805 /* if literal, literal on the right or
6806 if the right is in a pointer register and left
6808 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6809 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6810 operand *tmp = right ;
6816 if(ifx && !AOP_SIZE(result)){
6818 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6819 /* if they are both bit variables */
6820 if (AOP_TYPE(left) == AOP_CRY &&
6821 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6822 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6823 if(AOP_TYPE(right) == AOP_LIT){
6824 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6826 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6827 pic16_emitcode("cpl","c");
6828 } else if(lit == 1L) {
6829 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6831 pic16_emitcode("clr","c");
6833 /* AOP_TYPE(right) == AOP_CRY */
6835 symbol *lbl = newiTempLabel(NULL);
6836 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6837 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6838 pic16_emitcode("cpl","c");
6839 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6841 /* if true label then we jump if condition
6843 tlbl = newiTempLabel(NULL);
6844 if ( IC_TRUE(ifx) ) {
6845 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6846 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6848 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6849 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6851 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6854 /* left and right are both bit variables, result is carry */
6857 resolveIfx(&rIfx,ifx);
6859 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6860 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6861 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6862 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6867 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6869 /* They're not both bit variables. Is the right a literal? */
6870 if(AOP_TYPE(right) == AOP_LIT) {
6871 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6876 switch(lit & 0xff) {
6878 if ( IC_TRUE(ifx) ) {
6879 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6881 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6883 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6884 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6888 if ( IC_TRUE(ifx) ) {
6889 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6893 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6898 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6900 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6905 /* end of size == 1 */
6909 genc16bit2lit(left,lit,offset);
6912 /* end of size == 2 */
6917 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6918 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6919 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6920 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6923 /* search for patterns that can be optimized */
6925 genc16bit2lit(left,lit,0);
6929 emitSKPZ; // if hi word unequal
6931 emitSKPNZ; // if hi word equal
6933 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6934 genc16bit2lit(left,lit,2);
6937 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6938 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6942 pic16_emitpLabel(falselbl->key);
6951 } else if(AOP_TYPE(right) == AOP_CRY ) {
6952 /* we know the left is not a bit, but that the right is */
6953 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6954 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6955 pic16_popGet(AOP(right),offset));
6956 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6958 /* if the two are equal, then W will be 0 and the Z bit is set
6959 * we could test Z now, or go ahead and check the high order bytes if
6960 * the variable we're comparing is larger than a byte. */
6963 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6965 if ( IC_TRUE(ifx) ) {
6967 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6968 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6971 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6972 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6976 /* They're both variables that are larger than bits */
6979 tlbl = newiTempLabel(NULL);
6982 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6983 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6985 if ( IC_TRUE(ifx) ) {
6989 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6991 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6992 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6996 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6999 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7000 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7005 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7007 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7008 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7012 if(s>1 && IC_TRUE(ifx)) {
7013 pic16_emitpLabel(tlbl->key);
7014 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7018 /* mark the icode as generated */
7023 /* if they are both bit variables */
7024 if (AOP_TYPE(left) == AOP_CRY &&
7025 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7026 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7027 if(AOP_TYPE(right) == AOP_LIT){
7028 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7030 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7031 pic16_emitcode("cpl","c");
7032 } else if(lit == 1L) {
7033 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7035 pic16_emitcode("clr","c");
7037 /* AOP_TYPE(right) == AOP_CRY */
7039 symbol *lbl = newiTempLabel(NULL);
7040 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7041 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7042 pic16_emitcode("cpl","c");
7043 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7046 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7047 pic16_outBitC(result);
7051 genIfxJump (ifx,"c");
7054 /* if the result is used in an arithmetic operation
7055 then put the result in place */
7056 pic16_outBitC(result);
7059 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7060 gencjne(left,right,result,ifx);
7063 gencjne(left,right,newiTempLabel(NULL));
7065 if(IC_TRUE(ifx)->key)
7066 gencjne(left,right,IC_TRUE(ifx)->key);
7068 gencjne(left,right,IC_FALSE(ifx)->key);
7072 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7073 pic16_aopPut(AOP(result),"a",0);
7078 genIfxJump (ifx,"a");
7082 /* if the result is used in an arithmetic operation
7083 then put the result in place */
7085 if (AOP_TYPE(result) != AOP_CRY)
7086 pic16_outAcc(result);
7088 /* leave the result in acc */
7092 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7093 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7094 pic16_freeAsmop(result,NULL,ic,TRUE);
7098 /*-----------------------------------------------------------------*/
7099 /* ifxForOp - returns the icode containing the ifx for operand */
7100 /*-----------------------------------------------------------------*/
7101 static iCode *ifxForOp ( operand *op, iCode *ic )
7105 /* if true symbol then needs to be assigned */
7106 if (IS_TRUE_SYMOP(op))
7109 /* if this has register type condition and
7110 the next instruction is ifx with the same operand
7111 and live to of the operand is upto the ifx only then */
7113 && ic->next->op == IFX
7114 && IC_COND(ic->next)->key == op->key
7115 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7117 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7123 ic->next->op == IFX &&
7124 IC_COND(ic->next)->key == op->key) {
7125 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7130 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7132 ic->next->op == IFX)
7133 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7136 ic->next->op == IFX &&
7137 IC_COND(ic->next)->key == op->key) {
7138 DEBUGpic16_emitcode ("; "," key is okay");
7139 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7140 OP_SYMBOL(op)->liveTo,
7145 /* the code below is completely untested
7146 * it just allows ulong2fs.c compile -- VR */
7149 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7150 __FILE__, __FUNCTION__, __LINE__);
7152 /* if this has register type condition and
7153 the next instruction is ifx with the same operand
7154 and live to of the operand is upto the ifx only then */
7156 ic->next->op == IFX &&
7157 IC_COND(ic->next)->key == op->key &&
7158 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7162 ic->next->op == IFX &&
7163 IC_COND(ic->next)->key == op->key) {
7164 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7168 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7169 __FILE__, __FUNCTION__, __LINE__);
7171 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7176 /*-----------------------------------------------------------------*/
7177 /* genAndOp - for && operation */
7178 /*-----------------------------------------------------------------*/
7179 static void genAndOp (iCode *ic)
7181 operand *left,*right, *result;
7186 /* note here that && operations that are in an
7187 if statement are taken away by backPatchLabels
7188 only those used in arthmetic operations remain */
7189 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7190 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7191 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7193 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7195 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7196 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7199 /* if both are bit variables */
7200 /* if (AOP_TYPE(left) == AOP_CRY && */
7201 /* AOP_TYPE(right) == AOP_CRY ) { */
7202 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7203 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7204 /* pic16_outBitC(result); */
7206 /* tlbl = newiTempLabel(NULL); */
7207 /* pic16_toBoolean(left); */
7208 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7209 /* pic16_toBoolean(right); */
7210 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7211 /* pic16_outBitAcc(result); */
7214 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7215 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7216 pic16_freeAsmop(result,NULL,ic,TRUE);
7220 /*-----------------------------------------------------------------*/
7221 /* genOrOp - for || operation */
7222 /*-----------------------------------------------------------------*/
7225 modified this code, but it doesn't appear to ever get called
7228 static void genOrOp (iCode *ic)
7230 operand *left,*right, *result;
7235 /* note here that || operations that are in an
7236 if statement are taken away by backPatchLabels
7237 only those used in arthmetic operations remain */
7238 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7239 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7240 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7242 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7244 /* if both are bit variables */
7245 if (AOP_TYPE(left) == AOP_CRY &&
7246 AOP_TYPE(right) == AOP_CRY ) {
7247 pic16_emitcode("clrc","");
7248 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7249 AOP(left)->aopu.aop_dir,
7250 AOP(left)->aopu.aop_dir);
7251 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7252 AOP(right)->aopu.aop_dir,
7253 AOP(right)->aopu.aop_dir);
7254 pic16_emitcode("setc","");
7257 tlbl = newiTempLabel(NULL);
7258 pic16_toBoolean(left);
7260 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7261 pic16_toBoolean(right);
7262 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7264 pic16_outBitAcc(result);
7267 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7268 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7269 pic16_freeAsmop(result,NULL,ic,TRUE);
7272 /*-----------------------------------------------------------------*/
7273 /* isLiteralBit - test if lit == 2^n */
7274 /*-----------------------------------------------------------------*/
7275 static int isLiteralBit(unsigned long lit)
7277 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7278 0x100L,0x200L,0x400L,0x800L,
7279 0x1000L,0x2000L,0x4000L,0x8000L,
7280 0x10000L,0x20000L,0x40000L,0x80000L,
7281 0x100000L,0x200000L,0x400000L,0x800000L,
7282 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7283 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7287 for(idx = 0; idx < 32; idx++)
7293 /*-----------------------------------------------------------------*/
7294 /* continueIfTrue - */
7295 /*-----------------------------------------------------------------*/
7296 static void continueIfTrue (iCode *ic)
7300 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7304 /*-----------------------------------------------------------------*/
7306 /*-----------------------------------------------------------------*/
7307 static void jumpIfTrue (iCode *ic)
7311 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7315 /*-----------------------------------------------------------------*/
7316 /* jmpTrueOrFalse - */
7317 /*-----------------------------------------------------------------*/
7318 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7320 // ugly but optimized by peephole
7323 symbol *nlbl = newiTempLabel(NULL);
7324 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7325 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7326 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7327 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7329 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7330 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7335 /*-----------------------------------------------------------------*/
7336 /* genAnd - code for and */
7337 /*-----------------------------------------------------------------*/
7338 static void genAnd (iCode *ic, iCode *ifx)
7340 operand *left, *right, *result;
7342 unsigned long lit = 0L;
7348 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7349 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7350 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7352 resolveIfx(&rIfx,ifx);
7354 /* if left is a literal & right is not then exchange them */
7355 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7356 AOP_NEEDSACC(left)) {
7357 operand *tmp = right ;
7362 /* if result = right then exchange them */
7363 if(pic16_sameRegs(AOP(result),AOP(right))){
7364 operand *tmp = right ;
7369 /* if right is bit then exchange them */
7370 if (AOP_TYPE(right) == AOP_CRY &&
7371 AOP_TYPE(left) != AOP_CRY){
7372 operand *tmp = right ;
7376 if(AOP_TYPE(right) == AOP_LIT)
7377 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7379 size = AOP_SIZE(result);
7381 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7384 // result = bit & yy;
7385 if (AOP_TYPE(left) == AOP_CRY){
7386 // c = bit & literal;
7387 if(AOP_TYPE(right) == AOP_LIT){
7389 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7392 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7395 if(size && (AOP_TYPE(result) == AOP_CRY)){
7396 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7399 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7403 pic16_emitcode("clr","c");
7406 if (AOP_TYPE(right) == AOP_CRY){
7408 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7409 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7412 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7414 pic16_emitcode("rrc","a");
7415 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421 pic16_outBitC(result);
7423 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7424 genIfxJump(ifx, "c");
7428 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7429 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7430 if((AOP_TYPE(right) == AOP_LIT) &&
7431 (AOP_TYPE(result) == AOP_CRY) &&
7432 (AOP_TYPE(left) != AOP_CRY)){
7433 int posbit = isLiteralBit(lit);
7437 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7440 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7446 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7447 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7449 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7450 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7453 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7454 size = AOP_SIZE(left);
7457 int bp = posbit, ofs=0;
7464 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7465 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7469 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7470 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7472 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7479 symbol *tlbl = newiTempLabel(NULL);
7480 int sizel = AOP_SIZE(left);
7486 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7488 /* patch provided by Aaron Colwell */
7489 if((posbit = isLiteralBit(bytelit)) != 0) {
7490 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7491 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7492 (posbit-1),0, PO_GPR_REGISTER));
7494 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7495 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7497 if (bytelit == 0xff) {
7498 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7499 * a peephole could optimize it out -- VR */
7500 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7502 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7503 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7506 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7507 pic16_popGetLabel(tlbl->key));
7511 /* old code, left here for reference -- VR 09/2004 */
7512 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7514 if((posbit = isLiteralBit(bytelit)) != 0)
7515 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7517 if(bytelit != 0x0FFL)
7518 pic16_emitcode("anl","a,%s",
7519 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7520 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7526 // bit = left & literal
7529 pic16_emitpLabel(tlbl->key);
7531 // if(left & literal)
7534 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7537 pic16_emitpLabel(tlbl->key);
7542 pic16_outBitC(result);
7546 /* if left is same as result */
7547 if(pic16_sameRegs(AOP(result),AOP(left))){
7549 for(;size--; offset++,lit>>=8) {
7550 if(AOP_TYPE(right) == AOP_LIT){
7551 switch(lit & 0xff) {
7553 /* and'ing with 0 has clears the result */
7554 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7555 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7558 /* and'ing with 0xff is a nop when the result and left are the same */
7563 int p = pic16_my_powof2( (~lit) & 0xff );
7565 /* only one bit is set in the literal, so use a bcf instruction */
7566 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7567 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7570 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7571 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7572 if(know_W != (lit&0xff))
7573 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7575 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7580 if (AOP_TYPE(left) == AOP_ACC) {
7581 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7583 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7584 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7591 // left & result in different registers
7592 if(AOP_TYPE(result) == AOP_CRY){
7594 // if(size), result in bit
7595 // if(!size && ifx), conditional oper: if(left & right)
7596 symbol *tlbl = newiTempLabel(NULL);
7597 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7599 pic16_emitcode("setb","c");
7601 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7602 pic16_emitcode("anl","a,%s",
7603 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7604 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7609 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7610 pic16_outBitC(result);
7612 jmpTrueOrFalse(ifx, tlbl);
7614 for(;(size--);offset++) {
7616 // result = left & right
7617 if(AOP_TYPE(right) == AOP_LIT){
7618 int t = (lit >> (offset*8)) & 0x0FFL;
7621 pic16_emitcode("clrf","%s",
7622 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7623 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7626 pic16_emitcode("movf","%s,w",
7627 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7628 pic16_emitcode("movwf","%s",
7629 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7630 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7631 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7634 pic16_emitcode("movlw","0x%x",t);
7635 pic16_emitcode("andwf","%s,w",
7636 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7637 pic16_emitcode("movwf","%s",
7638 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7641 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7642 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7647 if (AOP_TYPE(left) == AOP_ACC) {
7648 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7649 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7651 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7652 pic16_emitcode("andwf","%s,w",
7653 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7655 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7657 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7658 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7664 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7665 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7666 pic16_freeAsmop(result,NULL,ic,TRUE);
7669 /*-----------------------------------------------------------------*/
7670 /* genOr - code for or */
7671 /*-----------------------------------------------------------------*/
7672 static void genOr (iCode *ic, iCode *ifx)
7674 operand *left, *right, *result;
7676 unsigned long lit = 0L;
7678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7680 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7681 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7682 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7684 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7686 /* if left is a literal & right is not then exchange them */
7687 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7688 AOP_NEEDSACC(left)) {
7689 operand *tmp = right ;
7694 /* if result = right then exchange them */
7695 if(pic16_sameRegs(AOP(result),AOP(right))){
7696 operand *tmp = right ;
7701 /* if right is bit then exchange them */
7702 if (AOP_TYPE(right) == AOP_CRY &&
7703 AOP_TYPE(left) != AOP_CRY){
7704 operand *tmp = right ;
7709 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7711 if(AOP_TYPE(right) == AOP_LIT)
7712 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7714 size = AOP_SIZE(result);
7718 if (AOP_TYPE(left) == AOP_CRY){
7719 if(AOP_TYPE(right) == AOP_LIT){
7720 // c = bit & literal;
7722 // lit != 0 => result = 1
7723 if(AOP_TYPE(result) == AOP_CRY){
7725 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7726 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7727 // AOP(result)->aopu.aop_dir,
7728 // AOP(result)->aopu.aop_dir);
7730 continueIfTrue(ifx);
7734 // lit == 0 => result = left
7735 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7737 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7740 if (AOP_TYPE(right) == AOP_CRY){
7741 if(pic16_sameRegs(AOP(result),AOP(left))){
7743 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7744 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7745 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7747 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7748 AOP(result)->aopu.aop_dir,
7749 AOP(result)->aopu.aop_dir);
7750 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7751 AOP(right)->aopu.aop_dir,
7752 AOP(right)->aopu.aop_dir);
7753 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7754 AOP(result)->aopu.aop_dir,
7755 AOP(result)->aopu.aop_dir);
7757 if( AOP_TYPE(result) == AOP_ACC) {
7758 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7759 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7760 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7761 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7765 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7766 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7767 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7768 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7770 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7771 AOP(result)->aopu.aop_dir,
7772 AOP(result)->aopu.aop_dir);
7773 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7774 AOP(right)->aopu.aop_dir,
7775 AOP(right)->aopu.aop_dir);
7776 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7777 AOP(left)->aopu.aop_dir,
7778 AOP(left)->aopu.aop_dir);
7779 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7780 AOP(result)->aopu.aop_dir,
7781 AOP(result)->aopu.aop_dir);
7786 symbol *tlbl = newiTempLabel(NULL);
7787 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7790 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7791 if( AOP_TYPE(right) == AOP_ACC) {
7792 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7794 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7795 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7800 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7801 pic16_emitcode(";XXX setb","c");
7802 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7803 AOP(left)->aopu.aop_dir,tlbl->key+100);
7804 pic16_toBoolean(right);
7805 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7806 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7807 jmpTrueOrFalse(ifx, tlbl);
7811 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7818 pic16_outBitC(result);
7820 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7821 genIfxJump(ifx, "c");
7825 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7826 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7827 if((AOP_TYPE(right) == AOP_LIT) &&
7828 (AOP_TYPE(result) == AOP_CRY) &&
7829 (AOP_TYPE(left) != AOP_CRY)){
7831 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7834 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7836 continueIfTrue(ifx);
7839 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7840 // lit = 0, result = boolean(left)
7842 pic16_emitcode(";XXX setb","c");
7843 pic16_toBoolean(right);
7845 symbol *tlbl = newiTempLabel(NULL);
7846 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7848 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7850 genIfxJump (ifx,"a");
7854 pic16_outBitC(result);
7858 /* if left is same as result */
7859 if(pic16_sameRegs(AOP(result),AOP(left))){
7861 for(;size--; offset++,lit>>=8) {
7862 if(AOP_TYPE(right) == AOP_LIT){
7863 if((lit & 0xff) == 0)
7864 /* or'ing with 0 has no effect */
7867 int p = pic16_my_powof2(lit & 0xff);
7869 /* only one bit is set in the literal, so use a bsf instruction */
7870 pic16_emitpcode(POC_BSF,
7871 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7873 if(know_W != (lit & 0xff))
7874 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7875 know_W = lit & 0xff;
7876 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7881 if (AOP_TYPE(left) == AOP_ACC) {
7882 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7883 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7885 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7886 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7888 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7889 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7895 // left & result in different registers
7896 if(AOP_TYPE(result) == AOP_CRY){
7898 // if(size), result in bit
7899 // if(!size && ifx), conditional oper: if(left | right)
7900 symbol *tlbl = newiTempLabel(NULL);
7901 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7902 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7906 pic16_emitcode(";XXX setb","c");
7908 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7909 pic16_emitcode(";XXX orl","a,%s",
7910 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7911 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7916 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7917 pic16_outBitC(result);
7919 jmpTrueOrFalse(ifx, tlbl);
7920 } else for(;(size--);offset++){
7922 // result = left & right
7923 if(AOP_TYPE(right) == AOP_LIT){
7924 int t = (lit >> (offset*8)) & 0x0FFL;
7927 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7928 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7930 pic16_emitcode("movf","%s,w",
7931 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7932 pic16_emitcode("movwf","%s",
7933 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7936 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7937 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7940 pic16_emitcode("movlw","0x%x",t);
7941 pic16_emitcode("iorwf","%s,w",
7942 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7943 pic16_emitcode("movwf","%s",
7944 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7950 // faster than result <- left, anl result,right
7951 // and better if result is SFR
7952 if (AOP_TYPE(left) == AOP_ACC) {
7953 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7954 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7956 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7957 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7959 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7960 pic16_emitcode("iorwf","%s,w",
7961 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7964 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7969 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7970 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7971 pic16_freeAsmop(result,NULL,ic,TRUE);
7974 /*-----------------------------------------------------------------*/
7975 /* genXor - code for xclusive or */
7976 /*-----------------------------------------------------------------*/
7977 static void genXor (iCode *ic, iCode *ifx)
7979 operand *left, *right, *result;
7981 unsigned long lit = 0L;
7983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7985 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7986 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7987 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7989 /* if left is a literal & right is not ||
7990 if left needs acc & right does not */
7991 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7992 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7993 operand *tmp = right ;
7998 /* if result = right then exchange them */
7999 if(pic16_sameRegs(AOP(result),AOP(right))){
8000 operand *tmp = right ;
8005 /* if right is bit then exchange them */
8006 if (AOP_TYPE(right) == AOP_CRY &&
8007 AOP_TYPE(left) != AOP_CRY){
8008 operand *tmp = right ;
8012 if(AOP_TYPE(right) == AOP_LIT)
8013 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8015 size = AOP_SIZE(result);
8019 if (AOP_TYPE(left) == AOP_CRY){
8020 if(AOP_TYPE(right) == AOP_LIT){
8021 // c = bit & literal;
8023 // lit>>1 != 0 => result = 1
8024 if(AOP_TYPE(result) == AOP_CRY){
8026 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8027 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8029 continueIfTrue(ifx);
8032 pic16_emitcode("setb","c");
8036 // lit == 0, result = left
8037 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8039 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8041 // lit == 1, result = not(left)
8042 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8043 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8044 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8045 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8048 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8049 pic16_emitcode("cpl","c");
8056 symbol *tlbl = newiTempLabel(NULL);
8057 if (AOP_TYPE(right) == AOP_CRY){
8059 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8062 int sizer = AOP_SIZE(right);
8064 // if val>>1 != 0, result = 1
8065 pic16_emitcode("setb","c");
8067 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8069 // test the msb of the lsb
8070 pic16_emitcode("anl","a,#0xfe");
8071 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8075 pic16_emitcode("rrc","a");
8077 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8078 pic16_emitcode("cpl","c");
8079 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8084 pic16_outBitC(result);
8086 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8087 genIfxJump(ifx, "c");
8091 if(pic16_sameRegs(AOP(result),AOP(left))){
8092 /* if left is same as result */
8093 for(;size--; offset++) {
8094 if(AOP_TYPE(right) == AOP_LIT){
8095 int t = (lit >> (offset*8)) & 0x0FFL;
8099 if (IS_AOP_PREG(left)) {
8100 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8101 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8102 pic16_aopPut(AOP(result),"a",offset);
8104 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8105 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8106 pic16_emitcode("xrl","%s,%s",
8107 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8108 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8111 if (AOP_TYPE(left) == AOP_ACC)
8112 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8115 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8117 if (IS_AOP_PREG(left)) {
8118 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119 pic16_aopPut(AOP(result),"a",offset);
8121 pic16_emitcode("xrl","%s,a",
8122 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8128 // left & result in different registers
8129 if(AOP_TYPE(result) == AOP_CRY){
8131 // if(size), result in bit
8132 // if(!size && ifx), conditional oper: if(left ^ right)
8133 symbol *tlbl = newiTempLabel(NULL);
8134 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8136 pic16_emitcode("setb","c");
8138 if((AOP_TYPE(right) == AOP_LIT) &&
8139 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8140 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8142 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8143 pic16_emitcode("xrl","a,%s",
8144 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8146 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8151 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8152 pic16_outBitC(result);
8154 jmpTrueOrFalse(ifx, tlbl);
8155 } else for(;(size--);offset++){
8157 // result = left & right
8158 if(AOP_TYPE(right) == AOP_LIT){
8159 int t = (lit >> (offset*8)) & 0x0FFL;
8162 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8163 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8164 pic16_emitcode("movf","%s,w",
8165 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8166 pic16_emitcode("movwf","%s",
8167 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8170 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8171 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8172 pic16_emitcode("comf","%s,w",
8173 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174 pic16_emitcode("movwf","%s",
8175 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8178 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8179 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181 pic16_emitcode("movlw","0x%x",t);
8182 pic16_emitcode("xorwf","%s,w",
8183 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8184 pic16_emitcode("movwf","%s",
8185 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191 // faster than result <- left, anl result,right
8192 // and better if result is SFR
8193 if (AOP_TYPE(left) == AOP_ACC) {
8194 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8195 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8197 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8198 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8199 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8200 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8202 if ( AOP_TYPE(result) != AOP_ACC){
8203 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8204 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8210 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8211 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8212 pic16_freeAsmop(result,NULL,ic,TRUE);
8215 /*-----------------------------------------------------------------*/
8216 /* genInline - write the inline code out */
8217 /*-----------------------------------------------------------------*/
8218 static void genInline (iCode *ic)
8220 char *buffer, *bp, *bp1;
8222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8224 _G.inLine += (!options.asmpeep);
8226 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8227 strcpy(buffer,IC_INLINE(ic));
8229 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8231 /* emit each line as a code */
8237 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8245 /* print label, use this special format with NULL directive
8246 * to denote that the argument should not be indented with tab */
8247 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8254 if ((bp1 != bp) && *bp1)
8255 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8260 _G.inLine -= (!options.asmpeep);
8263 /*-----------------------------------------------------------------*/
8264 /* genRRC - rotate right with carry */
8265 /*-----------------------------------------------------------------*/
8266 static void genRRC (iCode *ic)
8268 operand *left , *result ;
8269 int size, offset = 0, same;
8271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8273 /* rotate right with carry */
8275 result=IC_RESULT(ic);
8276 pic16_aopOp (left,ic,FALSE);
8277 pic16_aopOp (result,ic,FALSE);
8279 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8281 same = pic16_sameRegs(AOP(result),AOP(left));
8283 size = AOP_SIZE(result);
8285 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8287 /* get the lsb and put it into the carry */
8288 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8295 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8297 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8298 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8304 pic16_freeAsmop(left,NULL,ic,TRUE);
8305 pic16_freeAsmop(result,NULL,ic,TRUE);
8308 /*-----------------------------------------------------------------*/
8309 /* genRLC - generate code for rotate left with carry */
8310 /*-----------------------------------------------------------------*/
8311 static void genRLC (iCode *ic)
8313 operand *left , *result ;
8314 int size, offset = 0;
8317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8318 /* rotate right with carry */
8320 result=IC_RESULT(ic);
8321 pic16_aopOp (left,ic,FALSE);
8322 pic16_aopOp (result,ic,FALSE);
8324 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8326 same = pic16_sameRegs(AOP(result),AOP(left));
8328 /* move it to the result */
8329 size = AOP_SIZE(result);
8331 /* get the msb and put it into the carry */
8332 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8339 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8341 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8342 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8349 pic16_freeAsmop(left,NULL,ic,TRUE);
8350 pic16_freeAsmop(result,NULL,ic,TRUE);
8354 /* gpasm can get the highest order bit with HIGH/UPPER
8355 * so the following probably is not needed -- VR */
8357 /*-----------------------------------------------------------------*/
8358 /* genGetHbit - generates code get highest order bit */
8359 /*-----------------------------------------------------------------*/
8360 static void genGetHbit (iCode *ic)
8362 operand *left, *result;
8364 result=IC_RESULT(ic);
8365 pic16_aopOp (left,ic,FALSE);
8366 pic16_aopOp (result,ic,FALSE);
8368 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8369 /* get the highest order byte into a */
8370 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8371 if(AOP_TYPE(result) == AOP_CRY){
8372 pic16_emitcode("rlc","a");
8373 pic16_outBitC(result);
8376 pic16_emitcode("rl","a");
8377 pic16_emitcode("anl","a,#0x01");
8378 pic16_outAcc(result);
8382 pic16_freeAsmop(left,NULL,ic,TRUE);
8383 pic16_freeAsmop(result,NULL,ic,TRUE);
8387 /*-----------------------------------------------------------------*/
8388 /* AccRol - rotate left accumulator by known count */
8389 /*-----------------------------------------------------------------*/
8390 static void AccRol (int shCount)
8392 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8393 shCount &= 0x0007; // shCount : 0..7
8398 pic16_emitcode("rl","a");
8401 pic16_emitcode("rl","a");
8402 pic16_emitcode("rl","a");
8405 pic16_emitcode("swap","a");
8406 pic16_emitcode("rr","a");
8409 pic16_emitcode("swap","a");
8412 pic16_emitcode("swap","a");
8413 pic16_emitcode("rl","a");
8416 pic16_emitcode("rr","a");
8417 pic16_emitcode("rr","a");
8420 pic16_emitcode("rr","a");
8426 /*-----------------------------------------------------------------*/
8427 /* AccLsh - left shift accumulator by known count */
8428 /*-----------------------------------------------------------------*/
8429 static void AccLsh (int shCount)
8431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8437 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8440 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8441 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8445 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8451 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8452 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8455 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8456 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8459 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8466 /*-----------------------------------------------------------------*/
8467 /* AccRsh - right shift accumulator by known count */
8468 /*-----------------------------------------------------------------*/
8469 static void AccRsh (int shCount, int andmask)
8471 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8476 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8479 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8480 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8483 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8484 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8490 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8491 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8494 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8495 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8498 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8503 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8505 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8509 /*-----------------------------------------------------------------*/
8510 /* AccSRsh - signed right shift accumulator by known count */
8511 /*-----------------------------------------------------------------*/
8512 static void AccSRsh (int shCount)
8515 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8518 pic16_emitcode("mov","c,acc.7");
8519 pic16_emitcode("rrc","a");
8520 } else if(shCount == 2){
8521 pic16_emitcode("mov","c,acc.7");
8522 pic16_emitcode("rrc","a");
8523 pic16_emitcode("mov","c,acc.7");
8524 pic16_emitcode("rrc","a");
8526 tlbl = newiTempLabel(NULL);
8527 /* rotate right accumulator */
8528 AccRol(8 - shCount);
8529 /* and kill the higher order bits */
8530 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8531 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8532 pic16_emitcode("orl","a,#0x%02x",
8533 (unsigned char)~SRMask[shCount]);
8534 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8540 /*-----------------------------------------------------------------*/
8541 /* shiftR1Left2Result - shift right one byte from left to result */
8542 /*-----------------------------------------------------------------*/
8543 static void shiftR1Left2ResultSigned (operand *left, int offl,
8544 operand *result, int offr,
8549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8551 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8555 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8557 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8559 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8560 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8566 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8568 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8570 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8571 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8573 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8574 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8580 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8582 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8583 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8586 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8587 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8588 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8590 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8591 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8593 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8597 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8598 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8599 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8600 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8601 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8605 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8607 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8610 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8611 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8612 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8613 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8614 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8619 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8620 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8621 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8622 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8623 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8626 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8627 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8628 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8629 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8630 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8636 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8637 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8638 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8639 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8641 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8643 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8651 /*-----------------------------------------------------------------*/
8652 /* shiftR1Left2Result - shift right one byte from left to result */
8653 /*-----------------------------------------------------------------*/
8654 static void shiftR1Left2Result (operand *left, int offl,
8655 operand *result, int offr,
8656 int shCount, int sign)
8660 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8662 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8664 /* Copy the msb into the carry if signed. */
8666 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8676 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8678 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8679 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8685 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8687 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8703 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8704 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8710 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8715 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8716 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8717 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8719 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8724 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8725 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8726 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8727 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8728 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8733 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8734 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8735 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8744 /*-----------------------------------------------------------------*/
8745 /* shiftL1Left2Result - shift left one byte from left to result */
8746 /*-----------------------------------------------------------------*/
8747 static void shiftL1Left2Result (operand *left, int offl,
8748 operand *result, int offr, int shCount)
8753 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8755 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8756 DEBUGpic16_emitcode ("; ***","same = %d",same);
8757 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8759 /* shift left accumulator */
8760 //AccLsh(shCount); // don't comment out just yet...
8761 // pic16_aopPut(AOP(result),"a",offr);
8765 /* Shift left 1 bit position */
8766 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8768 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8770 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8775 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8776 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8777 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8783 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8789 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8790 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8793 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8794 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8795 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8799 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8800 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8801 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8802 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8803 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8806 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8807 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8808 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8812 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8817 /*-----------------------------------------------------------------*/
8818 /* movLeft2Result - move byte from left to result */
8819 /*-----------------------------------------------------------------*/
8820 static void movLeft2Result (operand *left, int offl,
8821 operand *result, int offr)
8824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8825 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8826 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8828 if (*l == '@' && (IS_AOP_PREG(result))) {
8829 pic16_emitcode("mov","a,%s",l);
8830 pic16_aopPut(AOP(result),"a",offr);
8832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8833 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8838 /*-----------------------------------------------------------------*/
8839 /* shiftL2Left2Result - shift left two bytes from left to result */
8840 /*-----------------------------------------------------------------*/
8841 static void shiftL2Left2Result (operand *left, int offl,
8842 operand *result, int offr, int shCount)
8844 int same = pic16_sameRegs(AOP(result), AOP(left));
8847 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8849 if (same && (offl != offr)) { // shift bytes
8852 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8853 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8855 } else { // just treat as different later on
8868 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8874 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8881 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8882 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8883 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8884 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8886 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8889 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8890 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8894 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8895 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8896 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8897 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8898 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8899 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8900 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8902 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8903 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8906 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8907 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8909 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8910 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8920 /* note, use a mov/add for the shift since the mov has a
8921 chance of getting optimized out */
8922 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8924 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8925 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8930 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8931 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8937 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8938 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8940 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8943 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8948 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8954 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8962 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8964 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8968 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8969 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8970 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8977 /*-----------------------------------------------------------------*/
8978 /* shiftR2Left2Result - shift right two bytes from left to result */
8979 /*-----------------------------------------------------------------*/
8980 static void shiftR2Left2Result (operand *left, int offl,
8981 operand *result, int offr,
8982 int shCount, int sign)
8984 int same = pic16_sameRegs(AOP(result), AOP(left));
8986 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8988 if (same && (offl != offr)) { // shift right bytes
8991 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8992 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8994 } else { // just treat as different later on
9006 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9011 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9012 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9015 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9017 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9026 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9034 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9039 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9043 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9044 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9046 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9047 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9048 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9049 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9050 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9054 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9055 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9060 pic16_emitpcode(POC_BTFSC,
9061 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9062 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9070 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9071 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9073 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9074 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9075 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9076 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9078 pic16_emitpcode(POC_BTFSC,
9079 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9080 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9082 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9084 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9087 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9088 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9089 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9090 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9091 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9092 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9093 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9094 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9096 pic16_emitpcode(POC_BTFSC,
9097 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9098 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9100 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9101 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9108 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9109 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9110 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9116 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9121 /*-----------------------------------------------------------------*/
9122 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9123 /*-----------------------------------------------------------------*/
9124 static void shiftLLeftOrResult (operand *left, int offl,
9125 operand *result, int offr, int shCount)
9127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9129 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9130 /* shift left accumulator */
9132 /* or with result */
9133 /* back to result */
9134 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9137 /*-----------------------------------------------------------------*/
9138 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9139 /*-----------------------------------------------------------------*/
9140 static void shiftRLeftOrResult (operand *left, int offl,
9141 operand *result, int offr, int shCount)
9143 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9145 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9146 /* shift right accumulator */
9148 /* or with result */
9149 /* back to result */
9150 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9153 /*-----------------------------------------------------------------*/
9154 /* genlshOne - left shift a one byte quantity by known count */
9155 /*-----------------------------------------------------------------*/
9156 static void genlshOne (operand *result, operand *left, int shCount)
9158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9159 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9162 /*-----------------------------------------------------------------*/
9163 /* genlshTwo - left shift two bytes by known amount != 0 */
9164 /*-----------------------------------------------------------------*/
9165 static void genlshTwo (operand *result,operand *left, int shCount)
9169 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9170 size = pic16_getDataSize(result);
9172 /* if shCount >= 8 */
9178 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9180 movLeft2Result(left, LSB, result, MSB16);
9182 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9185 /* 1 <= shCount <= 7 */
9188 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9190 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9194 /*-----------------------------------------------------------------*/
9195 /* shiftLLong - shift left one long from left to result */
9196 /* offr = LSB or MSB16 */
9197 /*-----------------------------------------------------------------*/
9198 static void shiftLLong (operand *left, operand *result, int offr )
9200 int size = AOP_SIZE(result);
9201 int same = pic16_sameRegs(AOP(left),AOP(result));
9204 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9206 if (same && (offr == MSB16)) { //shift one byte
9207 for(i=size-1;i>=MSB16;i--) {
9208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9209 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9212 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9215 if (size > LSB+offr ){
9217 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9219 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9220 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9224 if(size > MSB16+offr){
9226 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9228 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9229 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9233 if(size > MSB24+offr){
9235 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9237 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9238 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9242 if(size > MSB32+offr){
9244 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9246 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9247 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9251 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9255 /*-----------------------------------------------------------------*/
9256 /* genlshFour - shift four byte by a known amount != 0 */
9257 /*-----------------------------------------------------------------*/
9258 static void genlshFour (operand *result, operand *left, int shCount)
9262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9263 size = AOP_SIZE(result);
9265 /* if shifting more that 3 bytes */
9266 if (shCount >= 24 ) {
9269 /* lowest order of left goes to the highest
9270 order of the destination */
9271 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9273 movLeft2Result(left, LSB, result, MSB32);
9275 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9276 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9277 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9282 /* more than two bytes */
9283 else if ( shCount >= 16 ) {
9284 /* lower order two bytes goes to higher order two bytes */
9286 /* if some more remaining */
9288 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9290 movLeft2Result(left, MSB16, result, MSB32);
9291 movLeft2Result(left, LSB, result, MSB24);
9293 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9294 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9298 /* if more than 1 byte */
9299 else if ( shCount >= 8 ) {
9300 /* lower order three bytes goes to higher order three bytes */
9304 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9306 movLeft2Result(left, LSB, result, MSB16);
9308 else{ /* size = 4 */
9310 movLeft2Result(left, MSB24, result, MSB32);
9311 movLeft2Result(left, MSB16, result, MSB24);
9312 movLeft2Result(left, LSB, result, MSB16);
9313 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9315 else if(shCount == 1)
9316 shiftLLong(left, result, MSB16);
9318 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9319 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9320 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9321 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9326 /* 1 <= shCount <= 7 */
9327 else if(shCount <= 3)
9329 shiftLLong(left, result, LSB);
9330 while(--shCount >= 1)
9331 shiftLLong(result, result, LSB);
9333 /* 3 <= shCount <= 7, optimize */
9335 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9336 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9337 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9341 /*-----------------------------------------------------------------*/
9342 /* genLeftShiftLiteral - left shifting by known count */
9343 /*-----------------------------------------------------------------*/
9344 void pic16_genLeftShiftLiteral (operand *left,
9349 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9353 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9354 pic16_freeAsmop(right,NULL,ic,TRUE);
9356 pic16_aopOp(left,ic,FALSE);
9357 pic16_aopOp(result,ic,FALSE);
9359 size = getSize(operandType(result));
9362 pic16_emitcode("; shift left ","result %d, left %d",size,
9366 /* I suppose that the left size >= result size */
9369 movLeft2Result(left, size, result, size);
9373 else if(shCount >= (size * 8))
9375 pic16_aopPut(AOP(result),zero,size);
9379 genlshOne (result,left,shCount);
9384 genlshTwo (result,left,shCount);
9388 genlshFour (result,left,shCount);
9392 pic16_freeAsmop(left,NULL,ic,TRUE);
9393 pic16_freeAsmop(result,NULL,ic,TRUE);
9396 /*-----------------------------------------------------------------*
9397 * genMultiAsm - repeat assembly instruction for size of register.
9398 * if endian == 1, then the high byte (i.e base address + size of
9399 * register) is used first else the low byte is used first;
9400 *-----------------------------------------------------------------*/
9401 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9406 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9419 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9424 /*-----------------------------------------------------------------*/
9425 /* genLeftShift - generates code for left shifting */
9426 /*-----------------------------------------------------------------*/
9427 static void genLeftShift (iCode *ic)
9429 operand *left,*right, *result;
9432 symbol *tlbl , *tlbl1;
9435 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9437 right = IC_RIGHT(ic);
9439 result = IC_RESULT(ic);
9441 pic16_aopOp(right,ic,FALSE);
9443 /* if the shift count is known then do it
9444 as efficiently as possible */
9445 if (AOP_TYPE(right) == AOP_LIT) {
9446 pic16_genLeftShiftLiteral (left,right,result,ic);
9450 /* shift count is unknown then we have to form
9451 * a loop. Get the loop count in WREG : Note: we take
9452 * only the lower order byte since shifting
9453 * more than 32 bits make no sense anyway, ( the
9454 * largest size of an object can be only 32 bits ) */
9456 pic16_aopOp(left,ic,FALSE);
9457 pic16_aopOp(result,ic,FALSE);
9459 /* now move the left to the result if they are not the
9460 * same, and if size > 1,
9461 * and if right is not same to result (!!!) -- VR */
9462 if (!pic16_sameRegs(AOP(left),AOP(result))
9463 && (AOP_SIZE(result) > 1)) {
9465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9467 size = AOP_SIZE(result);
9472 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9473 if (*l == '@' && (IS_AOP_PREG(result))) {
9475 pic16_emitcode("mov","a,%s",l);
9476 pic16_aopPut(AOP(result),"a",offset);
9480 /* we don't know if left is a literal or a register, take care -- VR */
9481 mov2f(AOP(result), AOP(left), offset);
9487 size = AOP_SIZE(result);
9489 /* if it is only one byte then */
9491 if(optimized_for_speed) {
9492 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9493 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9494 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9495 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9496 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9497 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9498 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9499 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9500 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9501 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9502 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9503 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9506 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9508 tlbl = newiTempLabel(NULL);
9511 /* this is already done, why change it? */
9512 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9513 mov2f(AOP(result), AOP(left), 0);
9517 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9518 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9519 pic16_emitpLabel(tlbl->key);
9520 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9521 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9523 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9528 if (pic16_sameRegs(AOP(left),AOP(result))) {
9530 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9532 tlbl = newiTempLabel(NULL);
9533 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9534 genMultiAsm(POC_RRCF, result, size,1);
9535 pic16_emitpLabel(tlbl->key);
9536 genMultiAsm(POC_RLCF, result, size,0);
9537 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9539 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9543 //tlbl = newiTempLabel(NULL);
9545 //tlbl1 = newiTempLabel(NULL);
9547 //reAdjustPreg(AOP(result));
9549 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9550 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9551 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9553 //pic16_emitcode("add","a,acc");
9554 //pic16_aopPut(AOP(result),"a",offset++);
9556 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9558 // pic16_emitcode("rlc","a");
9559 // pic16_aopPut(AOP(result),"a",offset++);
9561 //reAdjustPreg(AOP(result));
9563 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9564 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9567 tlbl = newiTempLabel(NULL);
9568 tlbl1= newiTempLabel(NULL);
9570 size = AOP_SIZE(result);
9573 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9575 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9577 /* offset should be 0, 1 or 3 */
9579 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9581 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9583 pic16_emitpcode(POC_MOVWF, pctemp);
9586 pic16_emitpLabel(tlbl->key);
9589 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9591 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9593 pic16_emitpcode(POC_DECFSZ, pctemp);
9594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9595 pic16_emitpLabel(tlbl1->key);
9597 pic16_popReleaseTempReg(pctemp,1);
9601 pic16_freeAsmop (right,NULL,ic,TRUE);
9602 pic16_freeAsmop(left,NULL,ic,TRUE);
9603 pic16_freeAsmop(result,NULL,ic,TRUE);
9609 #error old code (left here for reference)
9610 /*-----------------------------------------------------------------*/
9611 /* genLeftShift - generates code for left shifting */
9612 /*-----------------------------------------------------------------*/
9613 static void genLeftShift (iCode *ic)
9615 operand *left,*right, *result;
9618 symbol *tlbl , *tlbl1;
9621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9623 right = IC_RIGHT(ic);
9625 result = IC_RESULT(ic);
9627 pic16_aopOp(right,ic,FALSE);
9629 /* if the shift count is known then do it
9630 as efficiently as possible */
9631 if (AOP_TYPE(right) == AOP_LIT) {
9632 pic16_genLeftShiftLiteral (left,right,result,ic);
9636 /* shift count is unknown then we have to form
9637 a loop get the loop count in B : Note: we take
9638 only the lower order byte since shifting
9639 more that 32 bits make no sense anyway, ( the
9640 largest size of an object can be only 32 bits ) */
9643 pic16_aopOp(left,ic,FALSE);
9644 pic16_aopOp(result,ic,FALSE);
9646 /* now move the left to the result if they are not the
9648 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9649 AOP_SIZE(result) > 1) {
9651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9653 size = AOP_SIZE(result);
9656 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9657 if (*l == '@' && (IS_AOP_PREG(result))) {
9659 pic16_emitcode("mov","a,%s",l);
9660 pic16_aopPut(AOP(result),"a",offset);
9663 /* we don't know if left is a literal or a register, take care -- VR */
9664 mov2f(AOP(result), AOP(left), offset);
9670 size = AOP_SIZE(result);
9672 /* if it is only one byte then */
9674 if(optimized_for_speed) {
9675 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9676 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9677 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9678 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9679 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9680 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9681 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9682 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9684 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9685 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9686 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9689 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9691 tlbl = newiTempLabel(NULL);
9692 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9693 mov2f(AOP(result), AOP(left), 0);
9695 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9696 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9699 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9700 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9701 pic16_emitpLabel(tlbl->key);
9702 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9703 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9710 if (pic16_sameRegs(AOP(left),AOP(result))) {
9712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9714 tlbl = newiTempLabel(NULL);
9715 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9716 genMultiAsm(POC_RRCF, result, size,1);
9717 pic16_emitpLabel(tlbl->key);
9718 genMultiAsm(POC_RLCF, result, size,0);
9719 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9721 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9725 //tlbl = newiTempLabel(NULL);
9727 //tlbl1 = newiTempLabel(NULL);
9729 //reAdjustPreg(AOP(result));
9731 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9732 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9733 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9735 //pic16_emitcode("add","a,acc");
9736 //pic16_aopPut(AOP(result),"a",offset++);
9738 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9740 // pic16_emitcode("rlc","a");
9741 // pic16_aopPut(AOP(result),"a",offset++);
9743 //reAdjustPreg(AOP(result));
9745 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9746 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9749 tlbl = newiTempLabel(NULL);
9750 tlbl1= newiTempLabel(NULL);
9752 size = AOP_SIZE(result);
9755 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9759 /* offset should be 0, 1 or 3 */
9761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9763 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9765 pic16_emitpcode(POC_MOVWF, pctemp);
9768 pic16_emitpLabel(tlbl->key);
9771 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9773 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9775 pic16_emitpcode(POC_DECFSZ, pctemp);
9776 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9777 pic16_emitpLabel(tlbl1->key);
9779 pic16_popReleaseTempReg(pctemp,1);
9783 pic16_freeAsmop (right,NULL,ic,TRUE);
9784 pic16_freeAsmop(left,NULL,ic,TRUE);
9785 pic16_freeAsmop(result,NULL,ic,TRUE);
9789 /*-----------------------------------------------------------------*/
9790 /* genrshOne - right shift a one byte quantity by known count */
9791 /*-----------------------------------------------------------------*/
9792 static void genrshOne (operand *result, operand *left,
9793 int shCount, int sign)
9795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9796 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9799 /*-----------------------------------------------------------------*/
9800 /* genrshTwo - right shift two bytes by known amount != 0 */
9801 /*-----------------------------------------------------------------*/
9802 static void genrshTwo (operand *result,operand *left,
9803 int shCount, int sign)
9805 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9806 /* if shCount >= 8 */
9810 shiftR1Left2Result(left, MSB16, result, LSB,
9813 movLeft2Result(left, MSB16, result, LSB);
9815 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9818 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9819 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9823 /* 1 <= shCount <= 7 */
9825 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9828 /*-----------------------------------------------------------------*/
9829 /* shiftRLong - shift right one long from left to result */
9830 /* offl = LSB or MSB16 */
9831 /*-----------------------------------------------------------------*/
9832 static void shiftRLong (operand *left, int offl,
9833 operand *result, int sign)
9835 int size = AOP_SIZE(result);
9836 int same = pic16_sameRegs(AOP(left),AOP(result));
9838 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9840 if (same && (offl == MSB16)) { //shift one byte right
9841 for(i=MSB16;i<size;i++) {
9842 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9843 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9848 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9854 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9856 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9861 /* add sign of "a" */
9862 pic16_addSign(result, MSB32, sign);
9866 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9868 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9869 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9873 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9875 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9876 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9880 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9883 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9884 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9889 /*-----------------------------------------------------------------*/
9890 /* genrshFour - shift four byte by a known amount != 0 */
9891 /*-----------------------------------------------------------------*/
9892 static void genrshFour (operand *result, operand *left,
9893 int shCount, int sign)
9895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9896 /* if shifting more that 3 bytes */
9897 if(shCount >= 24 ) {
9900 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9902 movLeft2Result(left, MSB32, result, LSB);
9904 pic16_addSign(result, MSB16, sign);
9906 else if(shCount >= 16){
9909 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9911 movLeft2Result(left, MSB24, result, LSB);
9912 movLeft2Result(left, MSB32, result, MSB16);
9914 pic16_addSign(result, MSB24, sign);
9916 else if(shCount >= 8){
9919 shiftRLong(left, MSB16, result, sign);
9920 else if(shCount == 0){
9921 movLeft2Result(left, MSB16, result, LSB);
9922 movLeft2Result(left, MSB24, result, MSB16);
9923 movLeft2Result(left, MSB32, result, MSB24);
9924 pic16_addSign(result, MSB32, sign);
9926 else{ //shcount >= 2
9927 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9928 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9929 /* the last shift is signed */
9930 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9931 pic16_addSign(result, MSB32, sign);
9934 else{ /* 1 <= shCount <= 7 */
9936 shiftRLong(left, LSB, result, sign);
9938 shiftRLong(result, LSB, result, sign);
9941 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9942 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9943 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9948 /*-----------------------------------------------------------------*/
9949 /* genRightShiftLiteral - right shifting by known count */
9950 /*-----------------------------------------------------------------*/
9951 static void genRightShiftLiteral (operand *left,
9957 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9960 pic16_freeAsmop(right,NULL,ic,TRUE);
9962 pic16_aopOp(left,ic,FALSE);
9963 pic16_aopOp(result,ic,FALSE);
9965 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9968 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9972 lsize = pic16_getDataSize(left);
9973 res_size = pic16_getDataSize(result);
9974 /* test the LEFT size !!! */
9976 /* I suppose that the left size >= result size */
9979 movLeft2Result(left, lsize, result, res_size);
9982 else if(shCount >= (lsize * 8)){
9985 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9987 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9988 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9994 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9995 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10002 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10007 switch (res_size) {
10009 genrshOne (result,left,shCount,sign);
10013 genrshTwo (result,left,shCount,sign);
10017 genrshFour (result,left,shCount,sign);
10025 pic16_freeAsmop(left,NULL,ic,TRUE);
10026 pic16_freeAsmop(result,NULL,ic,TRUE);
10029 /*-----------------------------------------------------------------*/
10030 /* genSignedRightShift - right shift of signed number */
10031 /*-----------------------------------------------------------------*/
10032 static void genSignedRightShift (iCode *ic)
10034 operand *right, *left, *result;
10037 symbol *tlbl, *tlbl1 ;
10040 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10042 /* we do it the hard way put the shift count in b
10043 and loop thru preserving the sign */
10044 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10046 right = IC_RIGHT(ic);
10047 left = IC_LEFT(ic);
10048 result = IC_RESULT(ic);
10050 pic16_aopOp(right,ic,FALSE);
10051 pic16_aopOp(left,ic,FALSE);
10052 pic16_aopOp(result,ic,FALSE);
10055 if ( AOP_TYPE(right) == AOP_LIT) {
10056 genRightShiftLiteral (left,right,result,ic,1);
10059 /* shift count is unknown then we have to form
10060 a loop get the loop count in B : Note: we take
10061 only the lower order byte since shifting
10062 more that 32 bits make no sense anyway, ( the
10063 largest size of an object can be only 32 bits ) */
10065 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10066 //pic16_emitcode("inc","b");
10067 //pic16_freeAsmop (right,NULL,ic,TRUE);
10068 //pic16_aopOp(left,ic,FALSE);
10069 //pic16_aopOp(result,ic,FALSE);
10071 /* now move the left to the result if they are not the
10073 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10074 AOP_SIZE(result) > 1) {
10076 size = AOP_SIZE(result);
10080 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10081 if (*l == '@' && IS_AOP_PREG(result)) {
10083 pic16_emitcode("mov","a,%s",l);
10084 pic16_aopPut(AOP(result),"a",offset);
10086 pic16_aopPut(AOP(result),l,offset);
10088 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10089 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10095 /* mov the highest order bit to OVR */
10096 tlbl = newiTempLabel(NULL);
10097 tlbl1= newiTempLabel(NULL);
10099 size = AOP_SIZE(result);
10102 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10104 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10106 /* offset should be 0, 1 or 3 */
10107 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10109 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10111 pic16_emitpcode(POC_MOVWF, pctemp);
10114 pic16_emitpLabel(tlbl->key);
10116 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10117 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10120 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10123 pic16_emitpcode(POC_DECFSZ, pctemp);
10124 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10125 pic16_emitpLabel(tlbl1->key);
10127 pic16_popReleaseTempReg(pctemp,1);
10129 size = AOP_SIZE(result);
10131 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10132 pic16_emitcode("rlc","a");
10133 pic16_emitcode("mov","ov,c");
10134 /* if it is only one byte then */
10136 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10138 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10139 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10140 pic16_emitcode("mov","c,ov");
10141 pic16_emitcode("rrc","a");
10142 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10143 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10144 pic16_aopPut(AOP(result),"a",0);
10148 reAdjustPreg(AOP(result));
10149 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10150 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10151 pic16_emitcode("mov","c,ov");
10153 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10155 pic16_emitcode("rrc","a");
10156 pic16_aopPut(AOP(result),"a",offset--);
10158 reAdjustPreg(AOP(result));
10159 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10160 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10165 pic16_freeAsmop(left,NULL,ic,TRUE);
10166 pic16_freeAsmop(result,NULL,ic,TRUE);
10167 pic16_freeAsmop(right,NULL,ic,TRUE);
10170 /*-----------------------------------------------------------------*/
10171 /* genRightShift - generate code for right shifting */
10172 /*-----------------------------------------------------------------*/
10173 static void genRightShift (iCode *ic)
10175 operand *right, *left, *result;
10179 symbol *tlbl, *tlbl1 ;
10181 /* if signed then we do it the hard way preserve the
10182 sign bit moving it inwards */
10183 letype = getSpec(operandType(IC_LEFT(ic)));
10184 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10186 if (!SPEC_USIGN(letype)) {
10187 genSignedRightShift (ic);
10191 /* signed & unsigned types are treated the same : i.e. the
10192 signed is NOT propagated inwards : quoting from the
10193 ANSI - standard : "for E1 >> E2, is equivalent to division
10194 by 2**E2 if unsigned or if it has a non-negative value,
10195 otherwise the result is implementation defined ", MY definition
10196 is that the sign does not get propagated */
10198 right = IC_RIGHT(ic);
10199 left = IC_LEFT(ic);
10200 result = IC_RESULT(ic);
10202 pic16_aopOp(right,ic,FALSE);
10204 /* if the shift count is known then do it
10205 as efficiently as possible */
10206 if (AOP_TYPE(right) == AOP_LIT) {
10207 genRightShiftLiteral (left,right,result,ic, 0);
10211 /* shift count is unknown then we have to form
10212 a loop get the loop count in B : Note: we take
10213 only the lower order byte since shifting
10214 more that 32 bits make no sense anyway, ( the
10215 largest size of an object can be only 32 bits ) */
10217 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10218 pic16_emitcode("inc","b");
10219 pic16_aopOp(left,ic,FALSE);
10220 pic16_aopOp(result,ic,FALSE);
10222 /* now move the left to the result if they are not the
10224 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10225 AOP_SIZE(result) > 1) {
10227 size = AOP_SIZE(result);
10230 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10231 if (*l == '@' && IS_AOP_PREG(result)) {
10233 pic16_emitcode("mov","a,%s",l);
10234 pic16_aopPut(AOP(result),"a",offset);
10236 pic16_aopPut(AOP(result),l,offset);
10241 tlbl = newiTempLabel(NULL);
10242 tlbl1= newiTempLabel(NULL);
10243 size = AOP_SIZE(result);
10246 /* if it is only one byte then */
10249 tlbl = newiTempLabel(NULL);
10250 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10251 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10252 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10255 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10256 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10257 pic16_emitpLabel(tlbl->key);
10258 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10259 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10261 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10266 reAdjustPreg(AOP(result));
10267 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10268 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10271 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10273 pic16_emitcode("rrc","a");
10274 pic16_aopPut(AOP(result),"a",offset--);
10276 reAdjustPreg(AOP(result));
10278 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10279 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10282 pic16_freeAsmop(left,NULL,ic,TRUE);
10283 pic16_freeAsmop (right,NULL,ic,TRUE);
10284 pic16_freeAsmop(result,NULL,ic,TRUE);
10288 void pic16_loadFSR0(operand *op)
10290 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10293 /*-----------------------------------------------------------------*/
10294 /* genUnpackBits - generates code for unpacking bits */
10295 /*-----------------------------------------------------------------*/
10296 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10300 sym_link *etype, *letype;
10301 int blen=0, bstr=0;
10305 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10306 etype = getSpec(operandType(result));
10307 letype = getSpec(operandType(left));
10309 // if(IS_BITFIELD(etype)) {
10310 blen = SPEC_BLEN(etype);
10311 bstr = SPEC_BSTR(etype);
10314 lbstr = SPEC_BSTR( letype );
10317 if((blen == 1) && (bstr < 8)) {
10318 /* it is a single bit, so use the appropriate bit instructions */
10319 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10321 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10323 if((ptype == POINTER) && (result)) {
10324 /* workaround to reduce the extra lfsr instruction */
10325 pic16_emitpcode(POC_BTFSC,
10326 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10328 pic16_emitpcode(POC_BTFSC,
10329 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10332 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10334 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10340 /* the following call to pic16_loadFSR0 is temporary until
10341 * optimization to handle single bit assignments is added
10342 * to the function. Until then use the old safe way! -- VR */
10343 pic16_loadFSR0( left );
10345 /* read the first byte */
10352 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10355 pic16_emitcode("clr","a");
10356 pic16_emitcode("movc","a","@a+dptr");
10361 /* if we have bitdisplacement then it fits */
10362 /* into this byte completely or if length is */
10363 /* less than a byte */
10364 if ((shCnt = SPEC_BSTR(etype)) ||
10365 (SPEC_BLEN(etype) <= 8)) {
10367 /* shift right acc */
10370 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10371 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10373 /* VR -- normally I would use the following, but since we use the hack,
10374 * to avoid the masking from AccRsh, why not mask it right now? */
10377 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10380 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10386 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10387 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10390 /* bit field did not fit in a byte */
10391 rlen = SPEC_BLEN(etype) - 8;
10392 pic16_aopPut(AOP(result),"a",offset++);
10399 pic16_emitcode("inc","%s",rname);
10400 pic16_emitcode("mov","a,@%s",rname);
10404 pic16_emitcode("inc","%s",rname);
10405 pic16_emitcode("movx","a,@%s",rname);
10409 pic16_emitcode("inc","dptr");
10410 pic16_emitcode("movx","a,@dptr");
10414 pic16_emitcode("clr","a");
10415 pic16_emitcode("inc","dptr");
10416 pic16_emitcode("movc","a","@a+dptr");
10420 pic16_emitcode("inc","dptr");
10421 pic16_emitcode("lcall","__gptrget");
10426 /* if we are done */
10430 pic16_aopPut(AOP(result),"a",offset++);
10435 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10436 pic16_aopPut(AOP(result),"a",offset);
10443 static void genDataPointerGet(operand *left,
10447 int size, offset = 0, leoffset=0 ;
10449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10450 pic16_aopOp(result, ic, FALSE);
10452 size = AOP_SIZE(result);
10453 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10457 /* The following tests may save a redudant movff instruction when
10458 * accessing unions */
10460 /* if they are the same */
10461 if (operandsEqu (left, result)) {
10462 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10468 /* if they are the same registers */
10469 if (pic16_sameRegs(AOP(left),AOP(result))) {
10470 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10476 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10477 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10478 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10485 if ( AOP_TYPE(left) == AOP_PCODE) {
10486 fprintf(stderr,"genDataPointerGet %s, %d\n",
10487 AOP(left)->aopu.pcop->name,
10488 (AOP(left)->aopu.pcop->type == PO_DIR)?
10489 PCOR(AOP(left)->aopu.pcop)->instance:
10490 PCOI(AOP(left)->aopu.pcop)->offset);
10494 if(AOP(left)->aopu.pcop->type == PO_DIR)
10495 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10497 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10500 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10502 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10503 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10504 pic16_mov2w(AOP(left), offset); // patch 8
10505 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10507 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10508 pic16_popGet(AOP(left), offset), //patch 8
10509 pic16_popGet(AOP(result), offset)));
10517 pic16_freeAsmop(result,NULL,ic,TRUE);
10522 /*-----------------------------------------------------------------*/
10523 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10524 /*-----------------------------------------------------------------*/
10525 static void genNearPointerGet (operand *left,
10530 //regs *preg = NULL ;
10531 sym_link *rtype, *retype;
10532 sym_link *ltype = operandType(left);
10536 rtype = operandType(result);
10537 retype= getSpec(rtype);
10539 pic16_aopOp(left,ic,FALSE);
10541 // pic16_DumpOp("(left)",left);
10542 // pic16_DumpOp("(result)",result);
10544 /* if left is rematerialisable and
10545 * result is not bit variable type and
10546 * the left is pointer to data space i.e
10547 * lower 128 bytes of space */
10549 if (AOP_TYPE(left) == AOP_PCODE
10550 && !IS_BITFIELD(retype)
10551 && DCL_TYPE(ltype) == POINTER) {
10553 genDataPointerGet (left,result,ic);
10554 pic16_freeAsmop(left, NULL, ic, TRUE);
10558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10560 /* if the value is already in a pointer register
10561 * then don't need anything more */
10562 if (!AOP_INPREG(AOP(left))) {
10563 /* otherwise get a free pointer register */
10564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10566 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10567 /* bitfields will be handled by genUnpackBits */
10568 if(!IS_BITFIELD(retype)) {
10570 if(is_LitAOp( AOP(left) )) {
10571 pic16_loadFSR0( left );
10573 // set up FSR0 with address from left
10574 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10575 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10580 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10582 pic16_aopOp (result,ic,FALSE);
10584 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10586 /* if bitfield then unpack the bits */
10587 if (IS_BITFIELD(retype))
10588 genUnpackBits (result, left, NULL, POINTER);
10590 /* we have can just get the values */
10591 int size = AOP_SIZE(result);
10594 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10596 /* fsr0 is loaded already -- VR */
10597 // pic16_loadFSR0( left );
10599 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10600 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10603 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10604 pic16_popGet(AOP(result), offset++)));
10606 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10607 pic16_popGet(AOP(result), offset++)));
10611 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10612 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10614 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10618 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10620 pic16_emitcode("mov","a,@%s",rname);
10621 pic16_aopPut(AOP(result),"a",offset);
10623 sprintf(buffer,"@%s",rname);
10624 pic16_aopPut(AOP(result),buffer,offset);
10628 pic16_emitcode("inc","%s",rname);
10633 /* now some housekeeping stuff */
10635 /* we had to allocate for this iCode */
10636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10637 pic16_freeAsmop(NULL,aop,ic,TRUE);
10639 /* we did not allocate which means left
10640 * already in a pointer register, then
10641 * if size > 0 && this could be used again
10642 * we have to point it back to where it
10644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10645 if (AOP_SIZE(result) > 1
10646 && !OP_SYMBOL(left)->remat
10647 && ( OP_SYMBOL(left)->liveTo > ic->seq
10649 // int size = AOP_SIZE(result) - 1;
10651 // pic16_emitcode("dec","%s",rname);
10656 pic16_freeAsmop(left,NULL,ic,TRUE);
10657 pic16_freeAsmop(result,NULL,ic,TRUE);
10660 /*-----------------------------------------------------------------*/
10661 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10662 /*-----------------------------------------------------------------*/
10663 static void genPagedPointerGet (operand *left,
10668 regs *preg = NULL ;
10670 sym_link *rtype, *retype;
10672 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10674 rtype = operandType(result);
10675 retype= getSpec(rtype);
10677 pic16_aopOp(left,ic,FALSE);
10679 /* if the value is already in a pointer register
10680 then don't need anything more */
10681 if (!AOP_INPREG(AOP(left))) {
10682 /* otherwise get a free pointer register */
10684 preg = getFreePtr(ic,&aop,FALSE);
10685 pic16_emitcode("mov","%s,%s",
10687 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10688 rname = preg->name ;
10690 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10692 pic16_freeAsmop(left,NULL,ic,TRUE);
10693 pic16_aopOp (result,ic,FALSE);
10695 /* if bitfield then unpack the bits */
10696 if (IS_BITFIELD(retype))
10697 genUnpackBits (result,left,rname,PPOINTER);
10699 /* we have can just get the values */
10700 int size = AOP_SIZE(result);
10705 pic16_emitcode("movx","a,@%s",rname);
10706 pic16_aopPut(AOP(result),"a",offset);
10711 pic16_emitcode("inc","%s",rname);
10715 /* now some housekeeping stuff */
10717 /* we had to allocate for this iCode */
10718 pic16_freeAsmop(NULL,aop,ic,TRUE);
10720 /* we did not allocate which means left
10721 already in a pointer register, then
10722 if size > 0 && this could be used again
10723 we have to point it back to where it
10725 if (AOP_SIZE(result) > 1 &&
10726 !OP_SYMBOL(left)->remat &&
10727 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10729 int size = AOP_SIZE(result) - 1;
10731 pic16_emitcode("dec","%s",rname);
10736 pic16_freeAsmop(result,NULL,ic,TRUE);
10741 /*-----------------------------------------------------------------*/
10742 /* genFarPointerGet - gget value from far space */
10743 /*-----------------------------------------------------------------*/
10744 static void genFarPointerGet (operand *left,
10745 operand *result, iCode *ic)
10748 sym_link *retype = getSpec(operandType(result));
10750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10752 pic16_aopOp(left,ic,FALSE);
10754 /* if the operand is already in dptr
10755 then we do nothing else we move the value to dptr */
10756 if (AOP_TYPE(left) != AOP_STR) {
10757 /* if this is remateriazable */
10758 if (AOP_TYPE(left) == AOP_IMMD)
10759 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10760 else { /* we need to get it byte by byte */
10761 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10762 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10763 if (options.model == MODEL_FLAT24)
10765 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10769 /* so dptr know contains the address */
10770 pic16_freeAsmop(left,NULL,ic,TRUE);
10771 pic16_aopOp(result,ic,FALSE);
10773 /* if bit then unpack */
10774 if (IS_BITFIELD(retype))
10775 genUnpackBits(result,left,"dptr",FPOINTER);
10777 size = AOP_SIZE(result);
10781 pic16_emitcode("movx","a,@dptr");
10782 pic16_aopPut(AOP(result),"a",offset++);
10784 pic16_emitcode("inc","dptr");
10788 pic16_freeAsmop(result,NULL,ic,TRUE);
10791 /*-----------------------------------------------------------------*/
10792 /* genCodePointerGet - get value from code space */
10793 /*-----------------------------------------------------------------*/
10794 static void genCodePointerGet (operand *left,
10795 operand *result, iCode *ic)
10798 sym_link *retype = getSpec(operandType(result));
10800 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10802 pic16_aopOp(left,ic,FALSE);
10804 /* if the operand is already in dptr
10805 then we do nothing else we move the value to dptr */
10806 if (AOP_TYPE(left) != AOP_STR) {
10807 /* if this is remateriazable */
10808 if (AOP_TYPE(left) == AOP_IMMD)
10809 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10810 else { /* we need to get it byte by byte */
10811 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10812 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10813 if (options.model == MODEL_FLAT24)
10815 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10819 /* so dptr know contains the address */
10820 pic16_freeAsmop(left,NULL,ic,TRUE);
10821 pic16_aopOp(result,ic,FALSE);
10823 /* if bit then unpack */
10824 if (IS_BITFIELD(retype))
10825 genUnpackBits(result,left,"dptr",CPOINTER);
10827 size = AOP_SIZE(result);
10831 pic16_emitcode("clr","a");
10832 pic16_emitcode("movc","a,@a+dptr");
10833 pic16_aopPut(AOP(result),"a",offset++);
10835 pic16_emitcode("inc","dptr");
10839 pic16_freeAsmop(result,NULL,ic,TRUE);
10843 /*-----------------------------------------------------------------*/
10844 /* genGenPointerGet - gget value from generic pointer space */
10845 /*-----------------------------------------------------------------*/
10846 static void genGenPointerGet (operand *left,
10847 operand *result, iCode *ic)
10849 int size, offset, lit;
10850 sym_link *retype = getSpec(operandType(result));
10852 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10853 pic16_aopOp(left,ic,FALSE);
10854 pic16_aopOp(result,ic,FALSE);
10855 size = AOP_SIZE(result);
10857 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10859 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10861 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10862 // load FSR0 from immediate
10863 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10865 // pic16_loadFSR0( left );
10870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10872 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10879 else { /* we need to get it byte by byte */
10880 // set up FSR0 with address from left
10881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10888 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10890 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10897 /* if bit then unpack */
10898 if (IS_BITFIELD(retype))
10899 genUnpackBits(result,left,"BAD",GPOINTER);
10902 pic16_freeAsmop(left,NULL,ic,TRUE);
10903 pic16_freeAsmop(result,NULL,ic,TRUE);
10909 /*-----------------------------------------------------------------*/
10910 /* genGenPointerGet - gget value from generic pointer space */
10911 /*-----------------------------------------------------------------*/
10912 static void genGenPointerGet (operand *left,
10913 operand *result, iCode *ic)
10915 int size, offset, lit;
10916 sym_link *retype = getSpec(operandType(result));
10919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10920 pic16_aopOp(left,ic,FALSE);
10921 pic16_aopOp(result,ic,FALSE);
10922 size = AOP_SIZE(result);
10924 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10926 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10928 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10929 // load FSR0 from immediate
10930 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10932 werror(W_POSSBUG2, __FILE__, __LINE__);
10937 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10939 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10946 } else { /* we need to get it byte by byte */
10948 /* set up WREG:PRODL:FSR0L with address from left */
10949 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10950 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10951 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10954 case 1: strcpy(fgptrget, "__gptrget1"); break;
10955 case 2: strcpy(fgptrget, "__gptrget2"); break;
10956 case 3: strcpy(fgptrget, "__gptrget3"); break;
10957 case 4: strcpy(fgptrget, "__gptrget4"); break;
10959 werror(W_POSSBUG2, __FILE__, __LINE__);
10963 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10965 assignResultValue(result, 1);
10970 sym = newSymbol( fgptrget, 0 );
10971 strcpy(sym->rname, fgptrget);
10972 checkAddSym(&externs, sym);
10974 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10980 /* if bit then unpack */
10981 if (IS_BITFIELD(retype))
10982 genUnpackBits(result,left,"BAD",GPOINTER);
10985 pic16_freeAsmop(left,NULL,ic,TRUE);
10986 pic16_freeAsmop(result,NULL,ic,TRUE);
10989 /*-----------------------------------------------------------------*/
10990 /* genConstPointerGet - get value from const generic pointer space */
10991 /*-----------------------------------------------------------------*/
10992 static void genConstPointerGet (operand *left,
10993 operand *result, iCode *ic)
10995 //sym_link *retype = getSpec(operandType(result));
10996 // symbol *albl = newiTempLabel(NULL); // patch 15
10997 // symbol *blbl = newiTempLabel(NULL); //
10998 // PIC_OPCODE poc; // patch 15
11002 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11003 pic16_aopOp(left,ic,FALSE);
11004 pic16_aopOp(result,ic,TRUE);
11005 size = AOP_SIZE(result);
11007 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11009 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11011 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11012 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11013 pic16_emitpLabel(albl->key);
11015 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11017 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11018 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11019 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11020 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11021 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11023 pic16_emitpLabel(blbl->key);
11025 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11029 // set up table pointer
11030 if( (AOP_TYPE(left) == AOP_PCODE)
11031 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11032 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
11034 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11035 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11036 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11037 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11038 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11039 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11043 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11045 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11051 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11052 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11056 pic16_freeAsmop(left,NULL,ic,TRUE);
11057 pic16_freeAsmop(result,NULL,ic,TRUE);
11062 /*-----------------------------------------------------------------*/
11063 /* genPointerGet - generate code for pointer get */
11064 /*-----------------------------------------------------------------*/
11065 static void genPointerGet (iCode *ic)
11067 operand *left, *result ;
11068 sym_link *type, *etype;
11073 left = IC_LEFT(ic);
11074 result = IC_RESULT(ic) ;
11076 /* depending on the type of pointer we need to
11077 move it to the correct pointer register */
11078 type = operandType(left);
11079 etype = getSpec(type);
11082 if (IS_PTR_CONST(type))
11084 if (IS_CODEPTR(type))
11086 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11088 /* if left is of type of pointer then it is simple */
11089 if (IS_PTR(type) && !IS_FUNC(type->next))
11090 p_type = DCL_TYPE(type);
11092 /* we have to go by the storage class */
11093 p_type = PTR_TYPE(SPEC_OCLS(etype));
11095 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11097 if (SPEC_OCLS(etype)->codesp ) {
11098 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11099 //p_type = CPOINTER ;
11102 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11103 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11104 /*p_type = FPOINTER ;*/
11106 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11107 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11108 /* p_type = PPOINTER; */
11110 if (SPEC_OCLS(etype) == idata )
11111 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11112 /* p_type = IPOINTER; */
11114 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11115 /* p_type = POINTER ; */
11118 /* now that we have the pointer type we assign
11119 the pointer values */
11124 genNearPointerGet (left,result,ic);
11128 genPagedPointerGet(left,result,ic);
11132 genFarPointerGet (left,result,ic);
11136 genConstPointerGet (left,result,ic);
11137 //pic16_emitcodePointerGet (left,result,ic);
11142 if (IS_PTR_CONST(type))
11143 genConstPointerGet (left,result,ic);
11146 genGenPointerGet (left,result,ic);
11150 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11151 "genPointerGet: illegal pointer type");
11157 /*-----------------------------------------------------------------*/
11158 /* genPackBits - generates code for packed bit storage */
11159 /*-----------------------------------------------------------------*/
11160 static void genPackBits (sym_link *etype , operand *result,
11162 char *rname, int p_type)
11171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11172 blen = SPEC_BLEN(etype);
11173 bstr = SPEC_BSTR(etype);
11175 retype = getSpec(operandType(right));
11177 if(AOP_TYPE(right) == AOP_LIT) {
11178 if((blen == 1) && (bstr < 8)) {
11180 /* it is a single bit, so use the appropriate bit instructions */
11182 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11184 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11185 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11186 if((p_type == POINTER) && (result)) {
11187 /* workaround to reduce the extra lfsr instruction */
11189 pic16_emitpcode(POC_BSF,
11190 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11192 pic16_emitpcode(POC_BCF,
11193 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11196 pic16_loadFSR0( result );
11198 pic16_emitpcode(POC_BSF,
11199 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11201 pic16_emitpcode(POC_BCF,
11202 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11209 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11212 if(IS_BITFIELD(retype)
11213 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11217 rblen = SPEC_BLEN( retype );
11218 rbstr = SPEC_BSTR( retype );
11221 if(IS_BITFIELD(etype)) {
11222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11223 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11225 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11228 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11230 if(IS_BITFIELD(etype)) {
11231 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11233 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11236 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11240 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11242 /* if the bit lenth is less than or */
11243 /* it exactly fits a byte then */
11244 if((shCnt=SPEC_BSTR(etype))
11245 || SPEC_BLEN(etype) <= 8 ) {
11247 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11249 /* shift left acc */
11252 /* using PRODL as a temporary register here */
11253 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11258 pic16_loadFSR0( result );
11259 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11260 // pic16_emitcode ("mov","b,a");
11261 // pic16_emitcode("mov","a,@%s",rname);
11265 werror(W_POSSBUG2, __FILE__, __LINE__);
11270 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11271 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11272 (unsigned char)(0xff >> (8-bstr))) ));
11273 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11274 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11281 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11282 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11287 if ( SPEC_BLEN(etype) <= 8 )
11290 pic16_emitcode("inc","%s",rname);
11291 rLen = SPEC_BLEN(etype) ;
11295 /* now generate for lengths greater than one byte */
11298 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11308 pic16_emitcode("mov","@%s,a",rname);
11310 pic16_emitcode("mov","@%s,%s",rname,l);
11315 pic16_emitcode("movx","@dptr,a");
11320 DEBUGpic16_emitcode(";lcall","__gptrput");
11323 pic16_emitcode ("inc","%s",rname);
11328 /* last last was not complete */
11330 /* save the byte & read byte */
11333 pic16_emitcode ("mov","b,a");
11334 pic16_emitcode("mov","a,@%s",rname);
11338 pic16_emitcode ("mov","b,a");
11339 pic16_emitcode("movx","a,@dptr");
11343 pic16_emitcode ("push","b");
11344 pic16_emitcode ("push","acc");
11345 pic16_emitcode ("lcall","__gptrget");
11346 pic16_emitcode ("pop","b");
11350 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11351 pic16_emitcode ("orl","a,b");
11354 if (p_type == GPOINTER)
11355 pic16_emitcode("pop","b");
11360 pic16_emitcode("mov","@%s,a",rname);
11364 pic16_emitcode("movx","@dptr,a");
11368 DEBUGpic16_emitcode(";lcall","__gptrput");
11372 /*-----------------------------------------------------------------*/
11373 /* genDataPointerSet - remat pointer to data space */
11374 /*-----------------------------------------------------------------*/
11375 static void genDataPointerSet(operand *right,
11379 int size, offset = 0, resoffset=0 ;
11381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11382 pic16_aopOp(right,ic,FALSE);
11384 size = AOP_SIZE(right);
11386 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11389 if ( AOP_TYPE(result) == AOP_PCODE) {
11390 fprintf(stderr,"genDataPointerSet %s, %d\n",
11391 AOP(result)->aopu.pcop->name,
11392 (AOP(result)->aopu.pcop->type == PO_DIR)?
11393 PCOR(AOP(result)->aopu.pcop)->instance:
11394 PCOI(AOP(result)->aopu.pcop)->offset);
11398 if(AOP(result)->aopu.pcop->type == PO_DIR)
11399 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11402 if (AOP_TYPE(right) == AOP_LIT) {
11405 if(!IS_FLOAT(operandType( right )))
11406 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11409 unsigned long lit_int;
11413 /* take care if literal is a float */
11414 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11415 lit = info.lit_int;
11418 lit = lit >> (8*offset);
11420 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11421 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11423 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11426 pic16_mov2w(AOP(right), offset);
11427 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11433 pic16_freeAsmop(right,NULL,ic,TRUE);
11438 /*-----------------------------------------------------------------*/
11439 /* genNearPointerSet - pic16_emitcode for near pointer put */
11440 /*-----------------------------------------------------------------*/
11441 static void genNearPointerSet (operand *right,
11448 sym_link *ptype = operandType(result);
11449 sym_link *resetype;
11451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11452 retype= getSpec(operandType(right));
11453 resetype = getSpec(operandType(result));
11455 pic16_aopOp(result,ic,FALSE);
11457 /* if the result is rematerializable &
11458 * in data space & not a bit variable */
11460 /* and result is not a bit variable */
11461 if (AOP_TYPE(result) == AOP_PCODE
11462 // && AOP_TYPE(result) == AOP_IMMD
11463 && DCL_TYPE(ptype) == POINTER
11464 && !IS_BITFIELD(retype)
11465 && !IS_BITFIELD(resetype)) {
11467 genDataPointerSet (right,result,ic);
11468 pic16_freeAsmop(result,NULL,ic,TRUE);
11472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11473 pic16_aopOp(right,ic,FALSE);
11474 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11476 /* if the value is already in a pointer register
11477 * then don't need anything more */
11478 if (!AOP_INPREG(AOP(result))) {
11479 /* otherwise get a free pointer register */
11480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11482 // if( (AOP_TYPE(result) == AOP_PCODE)
11483 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11484 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11485 if(is_LitAOp( AOP(result) ))
11487 if(!IS_BITFIELD(resetype))
11488 pic16_loadFSR0( result ); // patch 10
11490 if(!IS_BITFIELD(resetype)) {
11491 // set up FSR0 with address of result
11492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11493 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11499 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11501 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11503 // pic16_loadFSR0( result );
11505 /* if bitfield then unpack the bits */
11506 if (IS_BITFIELD(resetype)) {
11507 genPackBits (resetype, result, right, NULL, POINTER);
11509 /* we have can just get the values */
11510 int size = AOP_SIZE(right);
11513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11515 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11518 //pic16_emitcode("mov","@%s,a",rname);
11519 pic16_emitcode("movf","indf0,w ;1");
11522 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
11523 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
11525 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
11527 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
11529 } else { // no literal //
11531 pic16_emitpcode(POC_MOVFF, //
11532 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11533 pic16_popCopyReg(&pic16_pc_postinc0))); //
11535 pic16_emitpcode(POC_MOVFF, //
11536 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11537 pic16_popCopyReg(&pic16_pc_indf0))); //
11545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11546 /* now some housekeeping stuff */
11548 /* we had to allocate for this iCode */
11549 pic16_freeAsmop(NULL,aop,ic,TRUE);
11551 /* we did not allocate which means left
11552 * already in a pointer register, then
11553 * if size > 0 && this could be used again
11554 * we have to point it back to where it
11556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11557 if (AOP_SIZE(right) > 1
11558 && !OP_SYMBOL(result)->remat
11559 && ( OP_SYMBOL(result)->liveTo > ic->seq
11562 int size = AOP_SIZE(right) - 1;
11565 pic16_emitcode("decf","fsr0,f");
11566 //pic16_emitcode("dec","%s",rname);
11570 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11573 pic16_freeAsmop(right,NULL,ic,TRUE);
11574 pic16_freeAsmop(result,NULL,ic,TRUE);
11577 /*-----------------------------------------------------------------*/
11578 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11579 /*-----------------------------------------------------------------*/
11580 static void genPagedPointerSet (operand *right,
11585 regs *preg = NULL ;
11589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11591 retype= getSpec(operandType(right));
11593 pic16_aopOp(result,ic,FALSE);
11595 /* if the value is already in a pointer register
11596 then don't need anything more */
11597 if (!AOP_INPREG(AOP(result))) {
11598 /* otherwise get a free pointer register */
11600 preg = getFreePtr(ic,&aop,FALSE);
11601 pic16_emitcode("mov","%s,%s",
11603 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11604 rname = preg->name ;
11606 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11608 pic16_freeAsmop(result,NULL,ic,TRUE);
11609 pic16_aopOp (right,ic,FALSE);
11611 /* if bitfield then unpack the bits */
11612 if (IS_BITFIELD(retype))
11613 genPackBits (retype,result,right,rname,PPOINTER);
11615 /* we have can just get the values */
11616 int size = AOP_SIZE(right);
11620 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11623 pic16_emitcode("movx","@%s,a",rname);
11626 pic16_emitcode("inc","%s",rname);
11632 /* now some housekeeping stuff */
11634 /* we had to allocate for this iCode */
11635 pic16_freeAsmop(NULL,aop,ic,TRUE);
11637 /* we did not allocate which means left
11638 already in a pointer register, then
11639 if size > 0 && this could be used again
11640 we have to point it back to where it
11642 if (AOP_SIZE(right) > 1 &&
11643 !OP_SYMBOL(result)->remat &&
11644 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11646 int size = AOP_SIZE(right) - 1;
11648 pic16_emitcode("dec","%s",rname);
11653 pic16_freeAsmop(right,NULL,ic,TRUE);
11658 /*-----------------------------------------------------------------*/
11659 /* genFarPointerSet - set value from far space */
11660 /*-----------------------------------------------------------------*/
11661 static void genFarPointerSet (operand *right,
11662 operand *result, iCode *ic)
11665 sym_link *retype = getSpec(operandType(right));
11667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11668 pic16_aopOp(result,ic,FALSE);
11670 /* if the operand is already in dptr
11671 then we do nothing else we move the value to dptr */
11672 if (AOP_TYPE(result) != AOP_STR) {
11673 /* if this is remateriazable */
11674 if (AOP_TYPE(result) == AOP_IMMD)
11675 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11676 else { /* we need to get it byte by byte */
11677 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11678 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11679 if (options.model == MODEL_FLAT24)
11681 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11685 /* so dptr know contains the address */
11686 pic16_freeAsmop(result,NULL,ic,TRUE);
11687 pic16_aopOp(right,ic,FALSE);
11689 /* if bit then unpack */
11690 if (IS_BITFIELD(retype))
11691 genPackBits(retype,result,right,"dptr",FPOINTER);
11693 size = AOP_SIZE(right);
11697 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11699 pic16_emitcode("movx","@dptr,a");
11701 pic16_emitcode("inc","dptr");
11705 pic16_freeAsmop(right,NULL,ic,TRUE);
11708 /*-----------------------------------------------------------------*/
11709 /* genGenPointerSet - set value from generic pointer space */
11710 /*-----------------------------------------------------------------*/
11712 static void genGenPointerSet (operand *right,
11713 operand *result, iCode *ic)
11715 int i, size, offset, lit;
11716 sym_link *retype = getSpec(operandType(right));
11718 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11720 pic16_aopOp(result,ic,FALSE);
11721 pic16_aopOp(right,ic,FALSE);
11722 size = AOP_SIZE(right);
11725 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11727 /* if the operand is already in dptr
11728 then we do nothing else we move the value to dptr */
11729 if (AOP_TYPE(result) != AOP_STR) {
11730 /* if this is remateriazable */
11731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11732 // WARNING: anythig until "else" is untested!
11733 if (AOP_TYPE(result) == AOP_IMMD) {
11734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11735 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11736 // load FSR0 from immediate
11737 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11741 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11743 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11749 else { /* we need to get it byte by byte */
11750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11751 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11753 // set up FSR0 with address of result
11754 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11755 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11757 /* hack hack! see if this the FSR. If so don't load W */
11758 if(AOP_TYPE(right) != AOP_ACC) {
11760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11762 if(AOP_TYPE(right) == AOP_LIT)
11765 // note: pic16_popGet handles sign extension
11766 for(i=0;i<size;i++) {
11767 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11769 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11771 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11776 for(i=0;i<size;i++) {
11778 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11779 pic16_popCopyReg(&pic16_pc_postinc0)));
11781 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11782 pic16_popCopyReg(&pic16_pc_indf0)));
11788 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11789 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11791 } // if (AOP_TYPE(result) != AOP_IMMD)
11793 } // if (AOP_TYPE(result) != AOP_STR)
11794 /* so dptr know contains the address */
11797 /* if bit then unpack */
11798 if (IS_BITFIELD(retype))
11799 genPackBits(retype,result,right,"dptr",GPOINTER);
11801 size = AOP_SIZE(right);
11804 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11806 // set up FSR0 with address of result
11807 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11808 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11811 if (AOP_TYPE(right) == AOP_LIT) {
11812 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11814 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11816 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11818 } else { // no literal
11820 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11822 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11830 pic16_freeAsmop(right,NULL,ic,TRUE);
11831 pic16_freeAsmop(result,NULL,ic,TRUE);
11835 static void genGenPointerSet (operand *right,
11836 operand *result, iCode *ic)
11839 sym_link *retype = getSpec(operandType(right));
11842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11844 pic16_aopOp(result,ic,FALSE);
11845 pic16_aopOp(right,ic,FALSE);
11846 size = AOP_SIZE(right);
11848 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11851 /* if bit then unpack */
11852 if (IS_BITFIELD(retype)) {
11853 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11854 genPackBits(retype,result,right,"dptr",GPOINTER);
11858 size = AOP_SIZE(right);
11860 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11864 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11866 /* value of right+0 is placed on stack, which will be retrieved
11867 * by the support function this restoring the stack. The important
11868 * thing is that there is no need to manually restore stack pointer
11870 pushaop(AOP(right), 0);
11871 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11872 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11873 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11874 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11876 /* load address to write to in WREG:FSR0H:FSR0L */
11877 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11878 pic16_popCopyReg(&pic16_pc_fsr0l)));
11879 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11880 pic16_popCopyReg(&pic16_pc_prodl)));
11881 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11884 /* put code here */
11886 case 1: strcpy(fgptrput, "__gptrput1"); break;
11887 case 2: strcpy(fgptrput, "__gptrput2"); break;
11888 case 3: strcpy(fgptrput, "__gptrput3"); break;
11889 case 4: strcpy(fgptrput, "__gptrput4"); break;
11891 werror(W_POSSBUG2, __FILE__, __LINE__);
11895 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11900 sym = newSymbol( fgptrput, 0 );
11901 strcpy(sym->rname, fgptrput);
11902 checkAddSym(&externs, sym);
11906 pic16_freeAsmop(right,NULL,ic,TRUE);
11907 pic16_freeAsmop(result,NULL,ic,TRUE);
11910 /*-----------------------------------------------------------------*/
11911 /* genPointerSet - stores the value into a pointer location */
11912 /*-----------------------------------------------------------------*/
11913 static void genPointerSet (iCode *ic)
11915 operand *right, *result ;
11916 sym_link *type, *etype;
11921 right = IC_RIGHT(ic);
11922 result = IC_RESULT(ic) ;
11924 /* depending on the type of pointer we need to
11925 move it to the correct pointer register */
11926 type = operandType(result);
11927 etype = getSpec(type);
11928 /* if left is of type of pointer then it is simple */
11929 if (IS_PTR(type) && !IS_FUNC(type->next)) {
11930 p_type = DCL_TYPE(type);
11933 /* we have to go by the storage class */
11934 p_type = PTR_TYPE(SPEC_OCLS(etype));
11936 /* if (SPEC_OCLS(etype)->codesp ) { */
11937 /* p_type = CPOINTER ; */
11940 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11941 /* p_type = FPOINTER ; */
11943 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11944 /* p_type = PPOINTER ; */
11946 /* if (SPEC_OCLS(etype) == idata ) */
11947 /* p_type = IPOINTER ; */
11949 /* p_type = POINTER ; */
11952 /* now that we have the pointer type we assign
11953 the pointer values */
11958 genNearPointerSet (right,result,ic);
11962 genPagedPointerSet (right,result,ic);
11966 genFarPointerSet (right,result,ic);
11970 genGenPointerSet (right,result,ic);
11974 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11975 "genPointerSet: illegal pointer type");
11979 /*-----------------------------------------------------------------*/
11980 /* genIfx - generate code for Ifx statement */
11981 /*-----------------------------------------------------------------*/
11982 static void genIfx (iCode *ic, iCode *popIc)
11984 operand *cond = IC_COND(ic);
11989 pic16_aopOp(cond,ic,FALSE);
11991 /* get the value into acc */
11992 if (AOP_TYPE(cond) != AOP_CRY)
11993 pic16_toBoolean(cond);
11996 /* the result is now in the accumulator */
11997 pic16_freeAsmop(cond,NULL,ic,TRUE);
11999 /* if there was something to be popped then do it */
12003 /* if the condition is a bit variable */
12004 if (isbit && IS_ITEMP(cond) &&
12006 genIfxJump(ic,SPIL_LOC(cond)->rname);
12007 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12009 if (isbit && !IS_ITEMP(cond))
12010 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12012 genIfxJump(ic,"a");
12017 /*-----------------------------------------------------------------*/
12018 /* genAddrOf - generates code for address of */
12019 /*-----------------------------------------------------------------*/
12020 static void genAddrOf (iCode *ic)
12022 operand *result, *left;
12024 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12025 pCodeOp *pcop0, *pcop1, *pcop2;
12029 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12031 sym = OP_SYMBOL( IC_LEFT(ic) );
12034 /* get address of symbol on stack */
12035 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12037 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12038 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12041 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12042 pic16_popCopyReg(&pic16_pc_fsr2l),
12043 pic16_popGet(AOP(result), 0)));
12044 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12045 pic16_popCopyReg(&pic16_pc_fsr2h),
12046 pic16_popGet(AOP(result), 1)));
12048 // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
12049 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( - (OP_SYMBOL( IC_LEFT(ic))->stack + 1 ) /*+ _G.stack_lat*/));
12050 pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result), 0));
12052 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result), 1));
12057 // if(pic16_debug_verbose) {
12058 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12059 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12062 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12063 size = AOP_SIZE(IC_RESULT(ic));
12066 /* Assume that what we want the address of is in data space
12067 * since there is no stack on the PIC, yet! -- VR */
12069 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12070 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12071 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12074 pic16_emitpcode(POC_MOVLW, pcop0);
12075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12076 pic16_emitpcode(POC_MOVLW, pcop1);
12077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12078 pic16_emitpcode(POC_MOVLW, pcop2);
12079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12082 pic16_emitpcode(POC_MOVLW, pcop0);
12083 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12084 pic16_emitpcode(POC_MOVLW, pcop1);
12085 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12087 pic16_emitpcode(POC_MOVLW, pcop0);
12088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12091 pic16_freeAsmop(left, NULL, ic, FALSE);
12093 pic16_freeAsmop(result,NULL,ic,TRUE);
12098 /*-----------------------------------------------------------------*/
12099 /* genFarFarAssign - assignment when both are in far space */
12100 /*-----------------------------------------------------------------*/
12101 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12103 int size = AOP_SIZE(right);
12106 /* first push the right side on to the stack */
12108 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12110 pic16_emitcode ("push","acc");
12113 pic16_freeAsmop(right,NULL,ic,FALSE);
12114 /* now assign DPTR to result */
12115 pic16_aopOp(result,ic,FALSE);
12116 size = AOP_SIZE(result);
12118 pic16_emitcode ("pop","acc");
12119 pic16_aopPut(AOP(result),"a",--offset);
12121 pic16_freeAsmop(result,NULL,ic,FALSE);
12126 /*-----------------------------------------------------------------*/
12127 /* genAssign - generate code for assignment */
12128 /*-----------------------------------------------------------------*/
12129 static void genAssign (iCode *ic)
12131 operand *result, *right;
12132 int size, offset,know_W;
12133 unsigned long lit = 0L;
12135 result = IC_RESULT(ic);
12136 right = IC_RIGHT(ic) ;
12140 /* if they are the same */
12141 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12144 /* reversed order operands are aopOp'ed so that result operand
12145 * is effective in case right is a stack symbol. This maneauver
12146 * allows to use the _G.resDirect flag later */
12147 pic16_aopOp(result,ic,TRUE);
12148 pic16_aopOp(right,ic,FALSE);
12150 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12152 /* if they are the same registers */
12153 if (pic16_sameRegs(AOP(right),AOP(result)))
12156 /* if the result is a bit */
12157 if (AOP_TYPE(result) == AOP_CRY) {
12158 /* if the right size is a literal then
12159 we know what the value is */
12160 if (AOP_TYPE(right) == AOP_LIT) {
12162 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12163 pic16_popGet(AOP(result),0));
12165 if (((int) operandLitValue(right)))
12166 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12167 AOP(result)->aopu.aop_dir,
12168 AOP(result)->aopu.aop_dir);
12170 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12171 AOP(result)->aopu.aop_dir,
12172 AOP(result)->aopu.aop_dir);
12176 /* the right is also a bit variable */
12177 if (AOP_TYPE(right) == AOP_CRY) {
12178 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12179 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12180 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12182 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12183 AOP(result)->aopu.aop_dir,
12184 AOP(result)->aopu.aop_dir);
12185 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12186 AOP(right)->aopu.aop_dir,
12187 AOP(right)->aopu.aop_dir);
12188 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12189 AOP(result)->aopu.aop_dir,
12190 AOP(result)->aopu.aop_dir);
12194 /* we need to or */
12195 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12196 pic16_toBoolean(right);
12198 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12199 //pic16_aopPut(AOP(result),"a",0);
12203 /* bit variables done */
12205 size = AOP_SIZE(result);
12208 if(AOP_TYPE(right) == AOP_LIT) {
12209 if(!IS_FLOAT(operandType( right )))
12210 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12213 unsigned long lit_int;
12217 /* take care if literal is a float */
12218 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12219 lit = info.lit_int;
12223 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12224 // sizeof(unsigned long int), sizeof(float));
12227 if (AOP_TYPE(right) == AOP_REG) {
12228 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12231 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12236 if(AOP_TYPE(right) != AOP_LIT
12237 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12238 && !IS_FUNC(OP_SYM_TYPE(right))
12240 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12241 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12243 // set up table pointer
12244 if(is_LitOp(right)) {
12245 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12246 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12247 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12248 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12249 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12250 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12251 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12253 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12255 pic16_popCopyReg(&pic16_pc_tblptrl)));
12256 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12257 pic16_popCopyReg(&pic16_pc_tblptrh)));
12258 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12259 pic16_popCopyReg(&pic16_pc_tblptru)));
12262 size = min(AOP_SIZE(right), AOP_SIZE(result));
12264 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12266 pic16_popGet(AOP(result),offset)));
12270 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12271 size = AOP_SIZE(result) - AOP_SIZE(right);
12273 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12283 /* VR - What is this?! */
12284 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12285 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12286 if(aopIdx(AOP(result),0) == 4) {
12288 /* this is a workaround to save value of right into wreg too,
12289 * value of wreg is going to be used later */
12290 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12291 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12292 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12296 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12302 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12303 if(AOP_TYPE(right) == AOP_LIT) {
12305 if(know_W != (lit&0xff))
12306 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12308 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12310 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12314 } else if (AOP_TYPE(right) == AOP_CRY) {
12315 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12317 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12318 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12319 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12321 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12322 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12327 if(!_G.resDirect) /* use this aopForSym feature */
12328 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12335 pic16_freeAsmop (right,NULL,ic,FALSE);
12336 pic16_freeAsmop (result,NULL,ic,TRUE);
12339 /*-----------------------------------------------------------------*/
12340 /* genJumpTab - generates code for jump table */
12341 /*-----------------------------------------------------------------*/
12342 static void genJumpTab (iCode *ic)
12347 pCodeOp *jt_offs_hi;
12352 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12353 /* get the condition into accumulator */
12354 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12356 /* multiply by three */
12357 pic16_emitcode("add","a,acc");
12358 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12360 jtab = newiTempLabel(NULL);
12361 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12362 pic16_emitcode("jmp","@a+dptr");
12363 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12366 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12367 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12369 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12370 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12371 pic16_emitpLabel(jtab->key);
12375 jt_offs = pic16_popGetTempReg(0);
12376 jt_offs_hi = pic16_popGetTempReg(1);
12377 jt_label = pic16_popGetLabel (jtab->key);
12378 //fprintf (stderr, "Creating jump table...\n");
12380 // calculate offset into jump table (idx * sizeof (GOTO))
12381 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12382 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12383 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12384 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12385 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12386 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12387 pic16_emitpcode(POC_MOVWF , jt_offs);
12389 // prepare PCLATx (set to first entry in jump table)
12390 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12391 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12392 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12393 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12394 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12396 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12397 pic16_emitpcode(POC_ADDWF , jt_offs);
12398 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12399 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12401 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12403 // release temporaries and prepare jump into table (new PCL --> WREG)
12404 pic16_emitpcode(POC_MOVFW , jt_offs);
12405 pic16_popReleaseTempReg (jt_offs_hi, 1);
12406 pic16_popReleaseTempReg (jt_offs, 0);
12408 // jump into the table
12409 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12411 pic16_emitpLabelFORCE(jtab->key);
12414 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12416 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12417 /* now generate the jump labels */
12418 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12419 jtab = setNextItem(IC_JTLABELS(ic))) {
12420 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12421 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12424 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12428 /*-----------------------------------------------------------------*/
12429 /* genMixedOperation - gen code for operators between mixed types */
12430 /*-----------------------------------------------------------------*/
12432 TSD - Written for the PIC port - but this unfortunately is buggy.
12433 This routine is good in that it is able to efficiently promote
12434 types to different (larger) sizes. Unfortunately, the temporary
12435 variables that are optimized out by this routine are sometimes
12436 used in other places. So until I know how to really parse the
12437 iCode tree, I'm going to not be using this routine :(.
12439 static int genMixedOperation (iCode *ic)
12442 operand *result = IC_RESULT(ic);
12443 sym_link *ctype = operandType(IC_LEFT(ic));
12444 operand *right = IC_RIGHT(ic);
12450 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12452 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12458 nextright = IC_RIGHT(nextic);
12459 nextleft = IC_LEFT(nextic);
12460 nextresult = IC_RESULT(nextic);
12462 pic16_aopOp(right,ic,FALSE);
12463 pic16_aopOp(result,ic,FALSE);
12464 pic16_aopOp(nextright, nextic, FALSE);
12465 pic16_aopOp(nextleft, nextic, FALSE);
12466 pic16_aopOp(nextresult, nextic, FALSE);
12468 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12470 operand *t = right;
12474 pic16_emitcode(";remove right +","");
12476 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12478 operand *t = right;
12482 pic16_emitcode(";remove left +","");
12486 big = AOP_SIZE(nextleft);
12487 small = AOP_SIZE(nextright);
12489 switch(nextic->op) {
12492 pic16_emitcode(";optimize a +","");
12493 /* if unsigned or not an integral type */
12494 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12495 pic16_emitcode(";add a bit to something","");
12498 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12500 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12501 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12502 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12504 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12512 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12513 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12514 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12517 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12519 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12520 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12521 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12522 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12523 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12526 pic16_emitcode("rlf","known_zero,w");
12533 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12534 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12535 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12537 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12547 pic16_freeAsmop(right,NULL,ic,TRUE);
12548 pic16_freeAsmop(result,NULL,ic,TRUE);
12549 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12550 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12552 nextic->generated = 1;
12559 /*-----------------------------------------------------------------*/
12560 /* genCast - gen code for casting */
12561 /*-----------------------------------------------------------------*/
12562 static void genCast (iCode *ic)
12564 operand *result = IC_RESULT(ic);
12565 sym_link *ctype = operandType(IC_LEFT(ic));
12566 sym_link *rtype = operandType(IC_RIGHT(ic));
12567 sym_link *restype = operandType(IC_RESULT(ic));
12568 operand *right = IC_RIGHT(ic);
12574 /* if they are equivalent then do nothing */
12575 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12578 pic16_aopOp(right,ic,FALSE) ;
12579 pic16_aopOp(result,ic,FALSE);
12581 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12584 /* if the result is a bit */
12585 if (AOP_TYPE(result) == AOP_CRY) {
12587 /* if the right size is a literal then
12588 * we know what the value is */
12589 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12591 if (AOP_TYPE(right) == AOP_LIT) {
12592 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12593 pic16_popGet(AOP(result),0));
12595 if (((int) operandLitValue(right)))
12596 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12597 AOP(result)->aopu.aop_dir,
12598 AOP(result)->aopu.aop_dir);
12600 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12601 AOP(result)->aopu.aop_dir,
12602 AOP(result)->aopu.aop_dir);
12606 /* the right is also a bit variable */
12607 if (AOP_TYPE(right) == AOP_CRY) {
12609 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12611 pic16_emitcode("clrc","");
12612 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12613 AOP(right)->aopu.aop_dir,
12614 AOP(right)->aopu.aop_dir);
12615 pic16_aopPut(AOP(result),"c",0);
12619 /* we need to or */
12620 if (AOP_TYPE(right) == AOP_REG) {
12621 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12622 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12623 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12625 pic16_toBoolean(right);
12626 pic16_aopPut(AOP(result),"a",0);
12630 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12633 size = AOP_SIZE(result);
12635 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12637 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12638 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12639 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12642 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12647 if(IS_BITFIELD(getSpec(restype))
12648 && IS_BITFIELD(getSpec(rtype))) {
12649 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12652 /* if they are the same size : or less */
12653 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12655 /* if they are in the same place */
12656 if (pic16_sameRegs(AOP(right),AOP(result)))
12659 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12661 if (IS_PTR_CONST(rtype))
12663 if (IS_CODEPTR(rtype))
12665 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12668 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12670 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12672 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12675 if(AOP_TYPE(right) == AOP_IMMD) {
12676 pCodeOp *pcop0, *pcop1, *pcop2;
12677 symbol *sym = OP_SYMBOL( right );
12679 size = AOP_SIZE(result);
12681 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12683 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12685 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12688 pic16_emitpcode(POC_MOVLW, pcop0);
12689 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12690 pic16_emitpcode(POC_MOVLW, pcop1);
12691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12692 pic16_emitpcode(POC_MOVLW, pcop2);
12693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12696 pic16_emitpcode(POC_MOVLW, pcop0);
12697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12698 pic16_emitpcode(POC_MOVLW, pcop1);
12699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12701 pic16_emitpcode(POC_MOVLW, pcop0);
12702 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12706 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12707 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12709 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12710 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12711 if(AOP_SIZE(result) <2)
12712 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12714 /* if they in different places then copy */
12715 size = AOP_SIZE(result);
12718 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12719 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12726 /* if the result is of type pointer */
12727 if (IS_PTR(ctype)) {
12729 sym_link *type = operandType(right);
12730 sym_link *etype = getSpec(type);
12732 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12734 /* pointer to generic pointer */
12735 if (IS_GENPTR(ctype)) {
12739 p_type = DCL_TYPE(type);
12741 /* we have to go by the storage class */
12742 p_type = PTR_TYPE(SPEC_OCLS(etype));
12744 /* if (SPEC_OCLS(etype)->codesp ) */
12745 /* p_type = CPOINTER ; */
12747 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12748 /* p_type = FPOINTER ; */
12750 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12751 /* p_type = PPOINTER; */
12753 /* if (SPEC_OCLS(etype) == idata ) */
12754 /* p_type = IPOINTER ; */
12756 /* p_type = POINTER ; */
12759 /* the first two bytes are known */
12760 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12761 size = GPTRSIZE - 1;
12764 if(offset < AOP_SIZE(right)) {
12765 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12766 mov2f(AOP(result), AOP(right), offset);
12768 if ((AOP_TYPE(right) == AOP_PCODE) &&
12769 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12770 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12774 pic16_aopPut(AOP(result),
12775 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12780 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12783 /* the last byte depending on type */
12787 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12789 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12793 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12797 pic16_emitcode(";BUG!? ","%d",__LINE__);
12801 pic16_emitcode(";BUG!? ","%d",__LINE__);
12806 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12810 /* this should never happen */
12811 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12812 "got unknown pointer type");
12815 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12819 /* just copy the pointers */
12820 size = AOP_SIZE(result);
12823 pic16_aopPut(AOP(result),
12824 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12833 /* so we now know that the size of destination is greater
12834 than the size of the source.
12835 Now, if the next iCode is an operator then we might be
12836 able to optimize the operation without performing a cast.
12838 if(genMixedOperation(ic))
12841 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12843 /* we move to result for the size of source */
12844 size = AOP_SIZE(right);
12847 mov2f(AOP(result), AOP(right), offset);
12851 /* now depending on the sign of the destination */
12852 size = AOP_SIZE(result) - AOP_SIZE(right);
12853 /* if unsigned or not an integral type */
12854 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12856 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12858 /* we need to extend the sign :( */
12861 /* Save one instruction of casting char to int */
12862 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12863 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12864 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
12866 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12869 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12871 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12873 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
12876 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
12881 pic16_freeAsmop(right,NULL,ic,TRUE);
12882 pic16_freeAsmop(result,NULL,ic,TRUE);
12886 /*-----------------------------------------------------------------*/
12887 /* genDjnz - generate decrement & jump if not zero instrucion */
12888 /*-----------------------------------------------------------------*/
12889 static int genDjnz (iCode *ic, iCode *ifx)
12891 symbol *lbl, *lbl1;
12892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12897 /* if the if condition has a false label
12898 then we cannot save */
12902 /* if the minus is not of the form
12904 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12905 !IS_OP_LITERAL(IC_RIGHT(ic)))
12908 if (operandLitValue(IC_RIGHT(ic)) != 1)
12911 /* if the size of this greater than one then no
12913 if (getSize(operandType(IC_RESULT(ic))) > 1)
12916 /* otherwise we can save BIG */
12917 lbl = newiTempLabel(NULL);
12918 lbl1= newiTempLabel(NULL);
12920 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12922 if (IS_AOP_PREG(IC_RESULT(ic))) {
12923 pic16_emitcode("dec","%s",
12924 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12925 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12926 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12930 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12931 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12933 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12934 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12938 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12939 ifx->generated = 1;
12943 /*-----------------------------------------------------------------*/
12944 /* genReceive - generate code for a receive iCode */
12945 /*-----------------------------------------------------------------*/
12946 static void genReceive (iCode *ic)
12952 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12953 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12955 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12957 if (isOperandInFarSpace(IC_RESULT(ic))
12958 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12959 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12961 int size = getSize(operandType(IC_RESULT(ic)));
12962 int offset = pic16_fReturnSizePic - size;
12966 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12967 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12971 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
12973 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12974 size = AOP_SIZE(IC_RESULT(ic));
12977 pic16_emitcode ("pop","acc");
12978 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12981 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12983 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12986 /* set pseudo stack pointer to where it should be - dw*/
12987 GpsuedoStkPtr = ic->parmBytes;
12989 /* setting GpsuedoStkPtr has side effects here: */
12990 assignResultValue(IC_RESULT(ic), 0);
12993 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12996 /*-----------------------------------------------------------------*/
12997 /* genDummyRead - generate code for dummy read of volatiles */
12998 /*-----------------------------------------------------------------*/
13000 genDummyRead (iCode * ic)
13002 pic16_emitcode ("; genDummyRead","");
13003 pic16_emitcode ("; not implemented","");
13008 /*-----------------------------------------------------------------*/
13009 /* genpic16Code - generate code for pic16 based controllers */
13010 /*-----------------------------------------------------------------*/
13012 * At this point, ralloc.c has gone through the iCode and attempted
13013 * to optimize in a way suitable for a PIC. Now we've got to generate
13014 * PIC instructions that correspond to the iCode.
13016 * Once the instructions are generated, we'll pass through both the
13017 * peep hole optimizer and the pCode optimizer.
13018 *-----------------------------------------------------------------*/
13020 void genpic16Code (iCode *lic)
13025 lineHead = lineCurr = NULL;
13027 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13028 pic16_addpBlock(pb);
13031 /* if debug information required */
13032 if (options.debug && currFunc) {
13034 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13039 for (ic = lic ; ic ; ic = ic->next ) {
13041 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13042 if ( cln != ic->lineno ) {
13043 if ( options.debug ) {
13044 debugFile->writeCLine (ic);
13047 if(!options.noCcodeInAsm) {
13048 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13049 printCLine(ic->filename, ic->lineno)));
13055 if(options.iCodeInAsm) {
13058 /* insert here code to print iCode as comment */
13059 l = Safe_strdup(printILine(ic));
13060 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13063 /* if the result is marked as
13064 * spilt and rematerializable or code for
13065 * this has already been generated then
13067 if (resultRemat(ic) || ic->generated )
13070 /* depending on the operation */
13089 /* IPOP happens only when trying to restore a
13090 * spilt live range, if there is an ifx statement
13091 * following this pop then the if statement might
13092 * be using some of the registers being popped which
13093 * would destroy the contents of the register so
13094 * we need to check for this condition and handle it */
13096 && ic->next->op == IFX
13097 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13098 genIfx (ic->next,ic);
13116 genEndFunction (ic);
13132 pic16_genPlus (ic) ;
13136 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13137 pic16_genMinus (ic);
13153 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13157 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13163 /* note these two are xlated by algebraic equivalence
13164 * during parsing SDCC.y */
13165 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13166 "got '>=' or '<=' shouldn't have come here");
13170 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13182 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13186 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13190 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13214 genRightShift (ic);
13217 case GET_VALUE_AT_ADDRESS:
13222 if (POINTER_SET(ic))
13249 addSet(&_G.sendSet,ic);
13252 case DUMMY_READ_VOLATILE:
13262 /* now we are ready to call the
13263 peep hole optimizer */
13264 if (!options.nopeep)
13265 peepHole (&lineHead);
13267 /* now do the actual printing */
13268 printLine (lineHead, codeOutFile);
13271 DFPRINTF((stderr,"printing pBlock\n\n"));
13272 pic16_printpBlock(stdout,pb);